用途比较大的一个办法 通常适用的是开启了沙盒的堆 然后用来构造orw链 不过libc2.29是一个比较大的分水岭 前后的版本关于setcontext的利用不一样
libc2.27#
.text:0000000000052070 public setcontext ; weak.text:0000000000052070 setcontext proc near ; CODE XREF: sub_586B0+C↓p.text:0000000000052070 ; DATA XREF: LOAD:0000000000009018↑o.text:0000000000052070 ; __unwind {.text:0000000000052070 push rdi.text:0000000000052071 lea rsi, [rdi+128h] ; nset.text:0000000000052078 xor edx, edx ; oset.text:000000000005207A mov edi, 2 ; how.text:000000000005207F mov r10d, 8 ; sigsetsize.text:0000000000052085 mov eax, 0Eh.text:000000000005208A syscall ; LINUX - sys_rt_sigprocmask.text:000000000005208C pop rdi.text:000000000005208D cmp rax, 0FFFFFFFFFFFFF001h.text:0000000000052093 jnb short loc_520F0.text:0000000000052095 mov rcx, [rdi+0E0h].text:000000000005209C fldenv byte ptr [rcx].text:000000000005209E ldmxcsr dword ptr [rdi+1C0h].text:00000000000520A5 mov rsp, [rdi+0A0h].text:00000000000520AC mov rbx, [rdi+80h].text:00000000000520B3 mov rbp, [rdi+78h].text:00000000000520B7 mov r12, [rdi+48h].text:00000000000520BB mov r13, [rdi+50h].text:00000000000520BF mov r14, [rdi+58h].text:00000000000520C3 mov r15, [rdi+60h].text:00000000000520C7 mov rcx, [rdi+0A8h].text:00000000000520CE push rcx.text:00000000000520CF mov rsi, [rdi+70h].text:00000000000520D3 mov rdx, [rdi+88h].text:00000000000520DA mov rcx, [rdi+98h].text:00000000000520E1 mov r8, [rdi+28h].text:00000000000520E5 mov r9, [rdi+30h].text:00000000000520E9 mov rdi, [rdi+68h].text:00000000000520E9 ; } // starts at 52070.text:00000000000520ED ; __unwind {.text:00000000000520ED xor eax, eax.text:00000000000520EF retn你可以在libc文件中搜索函数setcontext找到这一串汇编 前面的指令没啥用 重点是 .text<00000000000520a5>00000000000520a5> mov rsp, [rdi+0A0h] 这一句 rsp寄存器的值由rdi寄存器决定的 rdi可太好控制了 我们执行free函数 rdi的值就是被释放的chunk的用户区地址 但是光控制rsp寄存器也没用 他不执行啊 还得再把rop链弹到rip寄存器里面 那就要用到ret指令了是吧 往下看一看 找到了 .text<00000000000520ce>00000000000520ce> push rcx 把rcx的值入栈 rcx能不能控制啊 能啊 .text<00000000000520c7>00000000000520c7> mov rcx, [rdi+0A8h] 那就意味着 我们可以利用这三行 实现一个栈迁移 劫持程序执行流 并且所需要的只是覆盖free_hook 演示的话 可以看一看wp分类里的Ciscn复现里的一题
libc2.29#
2.29对于setcontext进行了优化 不好利用了
.text:0000000000055E00 public setcontext ; weak.text:0000000000055E00 setcontext proc near ; CODE XREF: sub_5C160+C↓p.text:0000000000055E00 ; DATA XREF: LOAD:000000000000C6D8↑o.text:0000000000055E00 ; __unwind {.text:0000000000055E00 push rdi.text:0000000000055E01 lea rsi, [rdi+128h] ; nset.text:0000000000055E08 xor edx, edx ; oset.text:0000000000055E0A mov edi, 2 ; how.text:0000000000055E0F mov r10d, 8 ; sigsetsize.text:0000000000055E15 mov eax, 0Eh.text:0000000000055E1A syscall ; LINUX - sys_rt_sigprocmask.text:0000000000055E1C pop rdx.text:0000000000055E1D cmp rax, 0FFFFFFFFFFFFF001h.text:0000000000055E23 jnb short loc_55E80.text:0000000000055E25 mov rcx, [rdx+0E0h].text:0000000000055E2C fldenv byte ptr [rcx].text:0000000000055E2E ldmxcsr dword ptr [rdx+1C0h].text:0000000000055E35 mov rsp, [rdx+0A0h].text:0000000000055E3C mov rbx, [rdx+80h].text:0000000000055E43 mov rbp, [rdx+78h].text:0000000000055E47 mov r12, [rdx+48h].text:0000000000055E4B mov r13, [rdx+50h].text:0000000000055E4F mov r14, [rdx+58h].text:0000000000055E53 mov r15, [rdx+60h].text:0000000000055E57 mov rcx, [rdx+0A8h].text:0000000000055E5E push rcx.text:0000000000055E5F mov rsi, [rdx+70h].text:0000000000055E63 mov rdi, [rdx+68h].text:0000000000055E67 mov rcx, [rdx+98h].text:0000000000055E6E mov r8, [rdx+28h].text:0000000000055E72 mov r9, [rdx+30h].text:0000000000055E76 mov rdx, [rdx+88h].text:0000000000055E76 ; } // starts at 55E00.text:0000000000055E7D ; __unwind {.text:0000000000055E7D xor eax, eax.text:0000000000055E7F retn你可以看到 变成rdx寻址了 不过也不碍事 还是有办法解决 介绍一个新的工具 ropper 其可以查询libc文件中的一些gadget
ropper -f libc文件路径 --search '指令'就比如此时我们想要 可以修改rdx值的gadget
