malloc_assert


思维导图

基本原理

https://www.anquanke.com/post/id/235598

https://blog.wjhwjhn.com/posts/ciscn-2021-final-break%E7%8E%AF%E8%8A%82-pwn-writeup/

基本做法

  1. 在一片已知地址的内存空间中部署和house_of_apple2略有不同的fake_struct;

  2. 让stderr指向这片内存;

  3. 修改top_chunk的size使之很小不满足malloc需求,且不满足top_chunk的页对齐;

  4. malloc触发assert;

动态调试

当malloc等函数申请内存空间,且用到了top_chunk、而top_chunk的size较小不能满足需求的时候,就要重新分配空间,这个时候会查看top_chunk的size,判度胺是否页对齐,如果不对齐,就会触发__malloc_assert,则会有如下调用链:

__malloc_assert()
__fxprintf()
locked_vfxprintf()
__vfprintf_internal()

其中在__fxprintf+208的位置会有如下代码:

0x00007fee65e7e8d0 <+208>:	mov    rdi,QWORD PTR [rbx+0x88] ;这里是重点

后边就和house_of_apple的利用链一样了;

下面是__fxprintf函数的汇编代码:

Dump of assembler code for function __fxprintf:
=> 0x00007fee65e7e800 <+0>: endbr64
0x00007fee65e7e804 <+4>: push rbp
0x00007fee65e7e805 <+5>: push rbx
0x00007fee65e7e806 <+6>: mov rbx,rdi ;这里一个
0x00007fee65e7e809 <+9>: sub rsp,0xe8
0x00007fee65e7e810 <+16>: mov QWORD PTR [rsp+0x40],rdx
0x00007fee65e7e815 <+21>: mov QWORD PTR [rsp+0x48],rcx
0x00007fee65e7e81a <+26>: mov QWORD PTR [rsp+0x50],r8
0x00007fee65e7e81f <+31>: mov QWORD PTR [rsp+0x58],r9
0x00007fee65e7e824 <+36>: test al,al
0x00007fee65e7e826 <+38>: je 0x7fee65e7e862 <__fxprintf+98>
0x00007fee65e7e828 <+40>: movaps XMMWORD PTR [rsp+0x60],xmm0
0x00007fee65e7e82d <+45>: movaps XMMWORD PTR [rsp+0x70],xmm1
0x00007fee65e7e832 <+50>: movaps XMMWORD PTR [rsp+0x80],xmm2
0x00007fee65e7e83a <+58>: movaps XMMWORD PTR [rsp+0x90],xmm3
0x00007fee65e7e842 <+66>: movaps XMMWORD PTR [rsp+0xa0],xmm4
0x00007fee65e7e84a <+74>: movaps XMMWORD PTR [rsp+0xb0],xmm5
0x00007fee65e7e852 <+82>: movaps XMMWORD PTR [rsp+0xc0],xmm6
0x00007fee65e7e85a <+90>: movaps XMMWORD PTR [rsp+0xd0],xmm7
0x00007fee65e7e862 <+98>: mov rax,QWORD PTR fs:0x28
0x00007fee65e7e86b <+107>: mov QWORD PTR [rsp+0x28],rax
0x00007fee65e7e870 <+112>: xor eax,eax
0x00007fee65e7e872 <+114>: lea rax,[rsp+0x100]
0x00007fee65e7e87a <+122>: mov DWORD PTR [rsp+0x10],0x10
0x00007fee65e7e882 <+130>: mov QWORD PTR [rsp+0x18],rax
0x00007fee65e7e887 <+135>: lea rax,[rsp+0x30]
0x00007fee65e7e88c <+140>: mov DWORD PTR [rsp+0x14],0x30
0x00007fee65e7e894 <+148>: mov QWORD PTR [rsp+0x20],rax
0x00007fee65e7e899 <+153>: test rbx,rbx
0x00007fee65e7e89c <+156>: je 0x7fee65e7e950 <__fxprintf+336>
0x00007fee65e7e8a2 <+162>: mov eax,DWORD PTR [rbx]
0x00007fee65e7e8a4 <+164>: and eax,0x8000
0x00007fee65e7e8a9 <+169>: jne 0x7fee65e7e8df <__fxprintf+223>
0x00007fee65e7e8ab <+171>: mov rbp,QWORD PTR fs:0x10
0x00007fee65e7e8b4 <+180>: mov rdi,QWORD PTR [rbx+0x88]
0x00007fee65e7e8bb <+187>: cmp rbp,QWORD PTR [rdi+0x8]
0x00007fee65e7e8bf <+191>: je 0x7fee65e7e8db <__fxprintf+219>
0x00007fee65e7e8c1 <+193>: mov edx,0x1
0x00007fee65e7e8c6 <+198>: lock cmpxchg DWORD PTR [rdi],edx
0x00007fee65e7e8ca <+202>: jne 0x7fee65e7e960 <__fxprintf+352>
0x00007fee65e7e8d0 <+208>: mov rdi,QWORD PTR [rbx+0x88] ;这里是重点
0x00007fee65e7e8d7 <+215>: mov QWORD PTR [rdi+0x8],rbp
0x00007fee65e7e8db <+219>: add DWORD PTR [rdi+0x4],0x1
0x00007fee65e7e8df <+223>: xor ecx,ecx
0x00007fee65e7e8e1 <+225>: lea rdx,[rsp+0x10]
0x00007fee65e7e8e6 <+230>: mov rdi,rbx
0x00007fee65e7e8e9 <+233>: call 0x7fee65e7e560 <locked_vfxprintf>
0x00007fee65e7e8ee <+238>: test DWORD PTR [rbx],0x8000
0x00007fee65e7e8f4 <+244>: jne 0x7fee65e7e90a <__fxprintf+266>
0x00007fee65e7e8f6 <+246>: mov rdi,QWORD PTR [rbx+0x88]
0x00007fee65e7e8fd <+253>: mov ecx,DWORD PTR [rdi+0x4]
0x00007fee65e7e900 <+256>: lea edx,[rcx-0x1]
0x00007fee65e7e903 <+259>: mov DWORD PTR [rdi+0x4],edx
0x00007fee65e7e906 <+262>: test edx,edx
0x00007fee65e7e908 <+264>: je 0x7fee65e7e928 <__fxprintf+296>
0x00007fee65e7e90a <+266>: mov rdx,QWORD PTR [rsp+0x28]
0x00007fee65e7e90f <+271>: sub rdx,QWORD PTR fs:0x28
0x00007fee65e7e918 <+280>: jne 0x7fee65e7e974 <__fxprintf+372>
0x00007fee65e7e91a <+282>: add rsp,0xe8
0x00007fee65e7e921 <+289>: pop rbx
0x00007fee65e7e922 <+290>: pop rbp
0x00007fee65e7e923 <+291>: ret
0x00007fee65e7e924 <+292>: nop DWORD PTR [rax+0x0]
0x00007fee65e7e928 <+296>: mov QWORD PTR [rdi+0x8],0x0
0x00007fee65e7e930 <+304>: xchg DWORD PTR [rdi],edx
0x00007fee65e7e932 <+306>: cmp edx,0x1
0x00007fee65e7e935 <+309>: jle 0x7fee65e7e90a <__fxprintf+266>
0x00007fee65e7e937 <+311>: mov DWORD PTR [rsp+0x8],eax
0x00007fee65e7e93b <+315>: call 0x7fee65e91300 <__GI___lll_lock_wake_private>
0x00007fee65e7e940 <+320>: mov eax,DWORD PTR [rsp+0x8]
0x00007fee65e7e944 <+324>: jmp 0x7fee65e7e90a <__fxprintf+266>
0x00007fee65e7e946 <+326>: cs nop WORD PTR [rax+rax*1+0x0]
0x00007fee65e7e950 <+336>: mov rax,QWORD PTR [rip+0x19b551] # 0x7fee66019ea8
0x00007fee65e7e957 <+343>: mov rbx,QWORD PTR [rax];先调到这里来取_IO_2_1_stderr
0x00007fee65e7e95a <+346>: jmp 0x7fee65e7e8a2 <__fxprintf+162>
0x00007fee65e7e95f <+351>: nop
0x00007fee65e7e960 <+352>: mov QWORD PTR [rsp+0x8],rsi
0x00007fee65e7e965 <+357>: call 0x7fee65e91230 <__GI___lll_lock_wait_private>
0x00007fee65e7e96a <+362>: mov rsi,QWORD PTR [rsp+0x8]
0x00007fee65e7e96f <+367>: jmp 0x7fee65e7e8d0 <__fxprintf+208>
0x00007fee65e7e974 <+372>: call 0x7fee65f36550 <__stack_chk_fail>

关于stderr

在许多题目的经验中,我们会发现往往有两个stderr的诡异现象;

在2024年2月份的异常NSSCTF中,就遇到了这样的事情:

![]1707896656574](/images/1707896656574.png)

__fxprintf+343的地方rax使用的是elf空间的stderr;

针对这种情况,笔者的做法是将fake_strcut部署在了_IO_2_1_stderr_中,最终get_shell;


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录