9

Source code for both programs at the end of the post

So, I've working through Hacking: The Art Of Exploitation, and so far so good. I've managed to control EIP in the vulnerable program notesearch.c.

gdb-peda$ run $(perl -e 'print "a"x112 . "bbbb"')
Starting program: /root/hacking/booksrc/notesearch $(perl -e 'print "a"x112 . "bbbb"')
[DEBUG] found a 5 byte note for user id 0
[DEBUG] found a 7 byte note for user id 0
-------[ end of note data ]-------

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers----------------------------------    -]
EAX: 0x0 
EBX: 0x0 
ECX: 0xbffff300 ('a' <repeats 36 times>, "\003")
EDX: 0x0 
ESI: 0x2 
EDI: 0xb7fb5000 --> 0x1b3db0 
EBP: 0x0 
ESP: 0xbffff300 ('a' <repeats 36 times>, "\003")
EIP: 0x61616161 ('aaaa')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction     overflow)
[-------------------------------------code------------------------------------    -]
Invalid $PC address: 0x61616161
[------------------------------------stack------------------------------------    -]
0000| 0xbffff300 ('a' <repeats 36 times>, "\003")
0004| 0xbffff304 ('a' <repeats 32 times>, "\003")
0008| 0xbffff308 ('a' <repeats 28 times>, "\003")
0012| 0xbffff30c ('a' <repeats 24 times>, "\003")
0016| 0xbffff310 ('a' <repeats 20 times>, "\003")
0020| 0xbffff314 ('a' <repeats 16 times>, "\003")
0024| 0xbffff318 ('a' <repeats 12 times>, "\003")
0028| 0xbffff31c ("aaaaaaaa\003")
[-----------------------------------------------------------------------------    -]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x61616161 in ?? ()
gdb-peda$ 

However, once I write my own, very simple buggy code and try to control EIP, this happens

gdb-peda$ run
Starting program: /root/vulnerable 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbb

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0x41414141 ('AAAA')
EDX: 0xb7fb687c --> 0x0 
ESI: 0x1 
EDI: 0xb7fb5000 --> 0x1b3db0 
EBP: 0x41414141 ('AAAA')
ESP: 0x4141413d ('=AAA')
EIP: 0x804841d (<main+50>:  ret)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
   0x8048419 <main+46>: leave  
   0x804841a <main+47>: lea    esp,[ecx-0x4]
=> 0x804841d <main+50>: ret    
   0x804841e:   xchg   ax,ax
   0x8048420 <__libc_csu_init>: push   ebp
   0x8048421 <__libc_csu_init+1>:   push   edi
   0x8048422 <__libc_csu_init+2>:   push   esi
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x4141413d
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0804841d in main ()
gdb-peda$ p/x $eip
$1 = 0x804841d
gdb-peda$ 

I don't get anything, shouldn't ESP remain unchanged (as it isn't stored in the stack) and EIP get overwritten?

You can find notesearch.c @ https://github.com/intere/hacking Below is my alledgedly "exploitable" program.

Needless to say, I have ASLR disabled and the programs are compiled with -fno-stack-protector and -zexecstack flags. Should you need more info, drop a comment.

#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}
user3006498
  • 93
  • 1
  • 4

1 Answers1

9

Your code is wrong:

#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}

The char *buffer[64] creates an array of pointers to chars.

Try again with this:

#include <stdio.h>

int main(){
    char buffer[64];
    gets(buffer);
    return 0;
}

Run it at IDEone.


Actually, I can see quite a few reasons why this didn't work. Let's follow through your assembly:

   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]

Since ebp-0x4 is a location within your input buffer, ecx is loaded with 0x41414141.

   0x8048419 <main+46>: leave  

This clears the current stack frame, basically setting esp to ebp, then pops the top value off the stack into ebp to restore the previous frame pointer. You can again see that ebp was set to 0x41414141, because the top item in the stack was still part of your buffer.

   0x804841a <main+47>: lea    esp,[ecx-0x4]

This loads the effective address of ecx-0x4 into esp. Think of lea like a convenient pointer math instruction. In this case it's literally just doing esp = ecx - 0x4. This is why your esp value is 0x4141413d.

=> 0x804841d <main+50>: ret    

A ret instruction sets eip to the top value in the stack. The problem here is that your stack pointer is set to invalid memory. You overwrote it with 0x4141413d.

Why did this happen? Your payload is almost certainly too long, for a start, but there's a difference in the assembly between what your code does and what the example code did. However, there's a silver lining: you have control of the stack pointer immediately before a ret instruction. This means you only have to point esp at some memory you control, and you get eip control.

What you want to do is run the code until you get to <main+43>, then work out offset in your payload has been placed at ebp+0x4. You can make this a bit easier using a tool such as Metasploit's pattern_create.rb, but just observing the values in the stack should be sufficient to work it out manually.

So, let's imagine that 80 bytes into your payload is where the application reads that value from. Your payload now wants to start with 'A' * 80. After this, encode the address of the stack minus 8 bytes into the payload. So, if the stack pointer at that point was 0x4120EC40, subtract 8 to get 0x4120EC38, then place \x41\x20\xEC\x38 into your payload after all the A values.

When you next run the program, what should happen is this:

0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
; [ebp-0x4] contains an address slightly further up the stack (0x4120EC38)
; all the memory around this address contains 0x41414141
0x8048419 <main+46>: leave  
; leave the stack frame, setting esp and popping ebp
; both registers are trashed but it doesn't matter
0x804841a <main+47>: lea    esp,[ecx-0x4]
; subtract 4 from 0x4120EC38, giving us 0x4120EC34
; then set esp to this value - [esp] is now 0x41414141
0x804841d <main+50>: ret    
; pop the top value off the stack and set eip to it
; eip is now 0x41414141

You win.

As an addendum, you may run into the problem that you can't encode the stack address into your payload because it contaisn a null byte. You can get round this by shortening your payload so that it only partially overwrites the stack frame pointer, so you can change the least significant byte (or two bytes) allowing partial control over esp to point it further up the stack, rather than totally overwriting it.

Polynomial
  • 132,208
  • 43
  • 298
  • 379
  • Thanks. Did that, but still getting the same results. I can copypaste the peda-gdb output, but it's essentially the same as the one before. – user3006498 Apr 22 '16 at 17:46
  • @user3006498 I made some edits. Read through and have a try. – Polynomial Apr 22 '16 at 18:29
  • Thanks! this is quite a good explanation. However, I'm indeed having trouble with the encoding, I cant input \xa0 without the resulting stack values being all over the place. Could you give me a source to look into this? FWIW, the input I'm having trouble with now is perl -e 'print "A" x 70 . "\xa0\xf3\xff\xbf"'. I manage to overwrite eip with other values but this returns complete nonsense. – user3006498 Apr 23 '16 at 14:26
  • @user3006498 Unfortunately I can't really help much without an interactive session with your environment. My advice would be to trace through and look at exactly what gets put on the stack, and what code branches get taken when you change the values from 'A' to '\xA0'. – Polynomial Apr 24 '16 at 21:57