Skip to content

setcontext构造rop链

· 852 字 · heap

用途比较大的一个办法 通常适用的是开启了沙盒的堆 然后用来构造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> mov rsp, [rdi+0A0h] 这一句 rsp寄存器的值由rdi寄存器决定的 rdi可太好控制了 我们执行free函数 rdi的值就是被释放的chunk的用户区地址 但是光控制rsp寄存器也没用 他不执行啊 还得再把rop链弹到rip寄存器里面 那就要用到ret指令了是吧 往下看一看 找到了 .text<00000000000520ce> push rcx 把rcx的值入栈 rcx能不能控制啊 能啊 .text<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 image.png