3

I want to exploit a simple program

#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
    char buf[128];
    strcpy(buf, argv[1]);
    return 0;
}

The disassembly of main:

push %ebp
mov %esp, %ebp
and $0xfffffff0, %esp
... (and the rest follows)

My question is since esp's last 4bytes are getting null-ed, the actual location of the ebp with respect to buf[]'s starting address becomes RANDOM. So how am I supposed to know exactly after pushing how many characters I am supposed to reach ebp? &buf[0] on my computer is showing 0x2c(%esp) and the stack frame is occupying 0xb0 bytes. But just with this "fixed" information, how am I supposed to reach ebp? There remains a missing element...the initial content of esp. Please help me exploiting this basic program.

user257330
  • 33
  • 4
  • I would suggest making `buf` smaller than 128. It doesn't matter how large it is. You could make it 10 bytes and accomplish the same task. I'm not sure what you mean by *"the stack frame is occupying `0xb0` bytes"*. Also, are you saying that `0x2c` is the value of ESP? – RoraΖ Jun 23 '15 at 16:36
  • If I disassemble the program there is one statement ...sub 0xb0, %esp... So obviously the stack frame is 0xb0 bytes(I think). Also 0x2c is not the value of esp. A bit of analysis on the disassembly showed that it was the starting address of buf ...0x2c(%esp)... means ($esp+0x2c). They are the same. – user257330 Jun 24 '15 at 03:49

2 Answers2

1

I wrote that exact code into an overflow.c file, and got the following main(). I disassembled with objdump --disassemble overflow

0804846d <main>:
 804846d:       55                      push   %ebp
 804846e:       89 e5                   mov    %esp,%ebp
 8048470:       83 e4 f0                and    $0xfffffff0,%esp
 8048473:       81 ec a0 00 00 00       sub    $0xa0,%esp
 8048479:       8b 45 0c                mov    0xc(%ebp),%eax
 804847c:       89 44 24 0c             mov    %eax,0xc(%esp)
 8048480:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 8048486:       89 84 24 9c 00 00 00    mov    %eax,0x9c(%esp)
 804848d:       31 c0                   xor    %eax,%eax
 804848f:       8b 44 24 0c             mov    0xc(%esp),%eax
 8048493:       83 c0 04                add    $0x4,%eax
 8048496:       8b 00                   mov    (%eax),%eax
 8048498:       89 44 24 04             mov    %eax,0x4(%esp)
 804849c:       8d 44 24 1c             lea    0x1c(%esp),%eax
 80484a0:       89 04 24                mov    %eax,(%esp)
 80484a3:       e8 98 fe ff ff          call   8048340 <strcpy@plt>
 80484a8:       b8 00 00 00 00          mov    $0x0,%eax
 80484ad:       8b 94 24 9c 00 00 00    mov    0x9c(%esp),%edx
 80484b4:       65 33 15 14 00 00 00    xor    %gs:0x14,%edx
 80484bb:       74 05                   je     80484c2 <main+0x55>
 80484bd:       e8 6e fe ff ff          call   8048330 <__stack_chk_fail@plt>
 80484c2:       c9                      leave  
 80484c3:       c3                      ret   

Unfortunately I don't think there is a way for you to know how much the stack is going to be aligned at that point. You do know that it won't be more than 16 bytes. A dirty solution would be to write the 0x84 bytes to reach the alignment section. Then write the 4 byte value you want to overwrite EBP and/or the return address with 6 times. This would also smash the stack completely if the alignment was less than 16 bytes. But if you gain execution you could fix it up to a working state in your shellcode.


To go a bit further lets perform this same operation in a different function. Which would be a lot more likely of a scenario than a main(). So now we have the following:

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 int function(char **argv) {
  5     char buf[128];
  6 
  7     strcpy(buf, argv[1]);
  8 
  9     return 0;
 10 }
 11 
 12 int main(int argc, char **argv) {
 13     return function(argv);
 14 }

Which disassembles to:

0804846d <function>:
 804846d:       55                      push   %ebp
 804846e:       89 e5                   mov    %esp,%ebp
 8048470:       81 ec a8 00 00 00       sub    $0xa8,%esp
 8048476:       8b 45 08                mov    0x8(%ebp),%eax
 8048479:       89 85 64 ff ff ff       mov    %eax,-0x9c(%ebp)
 804847f:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 8048485:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048488:       31 c0                   xor    %eax,%eax
 804848a:       8b 85 64 ff ff ff       mov    -0x9c(%ebp),%eax
 8048490:       83 c0 04                add    $0x4,%eax
 8048493:       8b 00                   mov    (%eax),%eax
 8048495:       89 44 24 04             mov    %eax,0x4(%esp)
 8048499:       8d 85 74 ff ff ff       lea    -0x8c(%ebp),%eax
 804849f:       89 04 24                mov    %eax,(%esp)
 80484a2:       e8 99 fe ff ff          call   8048340 <strcpy@plt>
 80484a7:       b8 00 00 00 00          mov    $0x0,%eax
 80484ac:       8b 55 f4                mov    -0xc(%ebp),%edx
 80484af:       65 33 15 14 00 00 00    xor    %gs:0x14,%edx
 80484b6:       74 05                   je     80484bd <function+0x50>
 80484b8:       e8 73 fe ff ff          call   8048330 <__stack_chk_fail@plt>
 80484bd:       c9                      leave  
 80484be:       c3                      ret

Since it's not a main function you don't have that pesky and esp, 0xfffffff0 operation in there. You can perform your subtraction just like you normally would have expected.

I hope this answers your question.

RoraΖ
  • 12,317
  • 4
  • 51
  • 83
  • First of all, I don't see stack is already aligned when I check esp's value just after second line (mov %esp, %ebp). I am losing about 8 bytes there. Second you tell I need to write 160 bytes, but why is that because the buf starts from address 0x1c(%esp) [in your case]. So the number of bytes necessary to fill b4 ebp should be 0xa0-0x1c+. The first 2 terms are more or less constant. Its the last term that's troubling me. In case you have exploited it in gdb pls do tell exactly how many bytes you used to reach ebp (It can not be 160). Thanks – user257330 Jun 25 '15 at 02:48
  • You're absolutely right. I see your issue now. Unfortunately I don't think there is a way for you to know how much the stack is going to be aligned at that point. You do know that it won't be more than 16 bytes. A dirty solution would be to write the 0x84 bytes to reach the alignment section. Then write the 4 byte value you want to overwrite EBP and/or the return address with 6 times. This would also smash the stack completely if the alignment was less than 16 bytes. But if you gain execution you could fix it up to a working state in your shellcode. – RoraΖ Jun 25 '15 at 12:38
  • Is there really no way to exploit this simple buffer overflow just because of this one line? But this line is very common! Please do tell what am I supposed to do. I can't even exploit this simplest program. Also if you can kindly consult the other professionals, what they do in this case, I would be highly grateful. Thanks for your time and effort. – user257330 Jun 25 '15 at 13:10
  • Also this repeated writing of 4 byte desired return address would work only if the stack was initially off by 4 bytes or 8 bytes or 12 bytes but not for any other cases. Well, one thing I just noted: can the stack be off by 3 bytes initially or 7 bytes (not a multiple of 4)? If it is not so then there is a high probability of exploiting it by repeated writing of desired return address. – user257330 Jun 25 '15 at 13:13
  • If your stack isn't 4 byte aligned then it's corrupt, and there are other issues at fault. This is highly unlikely, and what I was poorly eluding to when I said that your "stack should already be aligned" earlier. – RoraΖ Jun 25 '15 at 13:40
0

I don't know if I understand well, what you want. Let me know if I understand it bad. I will assume, you want to overwrite EBP with some your value. One of the way, how to do it, is find, where begin buffer and get its address. So in debugger fill buffer with some payload of 'A' like -

run AAAAAAAA

Set breakpoint after calling strcpy() function. I set it on leave instruction, then check, where begin your buffer (buf).

0xbfffef30: 0x41414141 0x41414141 0xbfffef60 0x0804823d

In this case, it means, our buffer begins on address 0xbfffef30. With this information, take this address, and subtract it from $ebp (because as we know, EBP is located on bottom of the actual frame, it mean = higher address)

(gdb) p $ebp - 0xbfffef30

$1 = (void *) 0x88

(gdb) p 0x88

$2 = 136

Now, next 4 bytes will overwrite our saved frame pointer.

(gdb) run python -c 'print "A" * 136 + "B" * 4'

Don't forget to set up breakpoint again. After it, you can see, we rewrite EBP with our own value. In this case with 'BBBB'.

(gdb) i r ebp

ebp 0x42424242 0x42424242

Maybe you know, what you'll overwrite with next 4 bytes - return address.

core2dump
  • 11
  • 2
  • No after you construct the payload and the shellcode, how do you make sure the essential 4 bytes will accurately overwrite the return address in a remote host's program(say)? The assumption that the number of 'A' is 136 is based on ...p $ebp - ($esp+0x2c)...output which will be different on different machine [sidenote:if you disassemble the program, a bit analysis will show buf is starting from 0x2c(%esp).] This is because of the randomness of stack starting point combineed with the effect of the instruction ...and 0xfffffff0, $esp... – user257330 Jun 24 '15 at 03:39
  • Even if stack address space was randomized, since ebp would always be located at a fixed distance from esp (or for that matter buf, which is also at a fixed distance from esp). But ...and 0xfffffff0, %esp... introduces randomness as because now the location of ebp from esp does not remain fixed but becomes a variable of the initial value of esp. If I cannot explain you this properly, please let me know. I will try to explain in more detail. And many thanks for your answer. – user257330 Jun 24 '15 at 03:46