2

I want to try a buffer overflow on a c program. I compiled it like this gcc -fno-stack-protector -m32 buggy_program.c with gcc. If i run this program in gdb and i overflow the buffer, it should said 0x41414141, because i sent A's. But its saying 0x565561f5. Sorry for my bad english. Can somebody help me?

This is the source code:

#include <stdio.h>

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

    printf("Type in something: ");
    gets(buffer);
}
Starting program: /root/Downloads/a.out 
Type in something: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
0x565561f5 in main ()

I want to see this:

Starting program: /root/Downloads/a.out 
Type in something: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in main ()
microman
  • 73
  • 8
  • 1
    why do you think it is strange? whre is the code? – OznOg Jun 03 '19 at 16:36
  • All you showed here is the disassembly. This doesn't tell you where the function will return to. – interjay Jun 03 '19 at 16:39
  • Try to enable ASLR in gdb with `set disable-randomization off`. – ks1322 Jun 03 '19 at 17:33
  • regarding: `gets(buffer);` The function: `gets()` has been depreciated for years and completely removed from the latest versions of C. Your compiler should have told you this. Suggest using `fgets()` (which has different parameters from `gets()`) – user3629249 Jun 04 '19 at 01:34
  • the input of all those 'A's resulted in the overflow of the buffer: `char buffer[64];` overflowing the buffer results in undefined behavior. And that buffer is declared on the stack, so the stack is clobbered. So anything can happen. – user3629249 Jun 04 '19 at 01:42
  • But in other bof applications it is working perfectly, and I'm wondering what I've done wrong. This program is exact the same from www.exploit-exercises.com/protostar/stack5 (The site is currently down) with minimal changes. It should say 0x41414141. – microman Jun 04 '19 at 15:08

3 Answers3

1

Modern operating systems use address-space-layout-randomization ASLR to make this stuff not work quite so easily.

I remember the controversy when it was first started. ASLR was kind of a bad idea for 32 bit processes due to the number of other constraints it imposed on the system and dubious security benefit. On the other hand, it works great on 64 bit processes and almost everybody uses it now.

You don't know where the code is. You don't know where the heap is. You don't know where the stack is. Writing exploits is hard now.

Also, you tried to use 32 bit shellcode and documentation on a 64 bit process.

On reading the updated question: Your code is compiled with frame pointers (which is the default). This is causing the ret instruction itself to fault because esp is trashed. ASLR appears to still be in play most likely it doesn't really matter.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • And how can i get this to a 32bit process? – microman Jun 03 '19 at 17:05
  • @bitfriends: That's this question: https://stackoverflow.com/questions/1272357/how-to-compile-a-32-bit-binary-on-a-64-bit-linux-machine-with-gcc-cmake – Joshua Jun 03 '19 at 17:35
  • Thanks! But how can i get when i type AAAA the 0x41414141? Its says just the return adress: 0x565561f5. – microman Jun 03 '19 at 18:28
  • ASLR doesn't explain why the address causing the segfault is not `0x41414141` as the return address on the stack should have been overwritten with `0x41414141`. ASLR makes it hard to know where you want to jump to when you can overwrite `$EIP`. – Steve Jun 09 '19 at 14:25
  • @Steve: In v1 of the post, you can clearly see that `gdb` is reporting the address of the instruction that tried to return to unmapped memory. So anyway, the post has been edited away from my answer. – Joshua Jun 09 '19 at 14:33
  • I'm afraid that ASLR is not the answer from v1 of the post. It is a corrupted stack pointer which means that when the `ret` instruction is executed (which is essentially a `pop $eip`) the attempt to pop fails. – Steve Jun 09 '19 at 15:21
1

Looking at the address at which the process segfaulted shows the relevant line in the disassembled code:

gdb a.out <<EOF
set logging on
r < inp
disassemble main x/i $eip
p/x $esp

Produces the following output:

(gdb) Starting program: .../a.out < in

Program received signal SIGSEGV, Segmentation fault. 0x08048482 in main (argc=, argv=) at tmp.c:10 10 } (gdb) Dump of assembler code for function main:
0x08048436 <+0>: lea 0x4(%esp),%ecx
0x0804843a <+4>: and $0xfffffff0,%esp
0x0804843d <+7>: pushl -0x4(%ecx)
0x08048440 <+10>: push %ebp
0x08048441 <+11>: mov %esp,%ebp
0x08048443 <+13>: push %ebx
0x08048444 <+14>: push %ecx
0x08048445 <+15>: sub $0x40,%esp
0x08048448 <+18>: call
0x8048370 <__x86.get_pc_thunk.bx>
0x0804844d <+23>: add $0x1bb3,%ebx
0x08048453 <+29>: sub $0xc,%esp
0x08048456 <+32>: lea -0x1af0(%ebx),%eax
0x0804845c <+38>: push %eax
0x0804845d <+39>: call 0x8048300
0x08048462 <+44>: add $0x10,%esp
0x08048465 <+47>: sub $0xc,%esp
0x08048468 <+50>: lea -0x48(%ebp),%eax
0x0804846b <+53>: push %eax
0x0804846c <+54>: call 0x8048310
0x08048471 <+59>: add $0x10,%esp
0x08048474 <+62>: mov $0x0,%eax
0x08048479 <+67>: lea -0x8(%ebp),%esp
0x0804847c <+70>: pop %ecx
0x0804847d <+71>: pop %ebx
0x0804847e <+72>: pop %ebp
0x0804847f <+73>: lea -0x4(%ecx),%esp
=> 0x08048482 <+76>: ret
End of assembler dump.
(gdb) => 0x8048482 : ret
(gdb) $1 = 0x4141413d
(gdb) quit

The failing statement is the ret at the end of main. The program fails, when ret attempts to load the return-address from the top of the stack. The produced executable stores the old value of esp on the stack, before aligning to word-boundaries. When main is completed, the program attempts to restore the esp from the stack and afterwards read the return-address. However the whole top of the stack is compromised, thus rendering the new value of the stack-pointer garbage ($1 = 0x4141413d). When ret is executed, it attempts to read a word from address 0x4141413d, which isn't allocated and produces as segfault.

Notes

The above disassembly was produced from the code in the question using the following compiler-options:

-m32 -fno-stack-protector -g -O0

  • Do I have to add $1 = 0x4141413d? – microman Jun 04 '19 at 19:18
  • @bitfriends no. That's the value of the esp-register when the program crashes. The problem is that the program as it is compiled attempts to restore the esp-registers value from the stack at the end of main. However the stack was compromised by the bufferoverflow. In the end this will most likely boil down to using an older compiler (I'm currently looking into that, but if anyone is faster, feel free to add the info either to the answer or as a comment). –  Jun 04 '19 at 19:23
  • So the compiler is the problem? – microman Jun 04 '19 at 19:25
  • @bitfriends yup. More specifically the configuration. The overflow messes with the alignment-functionality. –  Jun 04 '19 at 19:32
  • @bitfriends a general advice on the topic you're currently working: there are plenty of books about hacking that provide their own environment, which is already configured to avoid such issues as the above. –  Jun 04 '19 at 20:11
  • Here is a link: https://alternativeto.net/software/gnu-compiler-collection/ – microman Jun 05 '19 at 05:05
  • This is the right answer. ASLR is definitely not the cause of the problem here. The `ret` instruction effectively does `pop eip`. The `pop` instruction needs to read the memory at `esp` which has been corrupted. See: https://stackoverflow.com/questions/4292447/does-ret-instruction-cause-esp-register-added-by-4 – Steve Jun 09 '19 at 18:38
1

So guys, i found a solution: Just compile it with gcc 3.3.4 gcc -m32 buggy_program.c

microman
  • 73
  • 8