setcontext
setcontext用于恢复寄存器和栈的一个函数,类似于srop中sigreturn
,主要利用setcontext+53的位置来伪造栈空间来构造rop链。即给rsp寄存器传参
libc-2.29之前setcontext是通过rdi来索引的,libc-2.29之后rdi变为rdx
利用
程序开启了沙箱,无法直接system("/bin/sh")
来获得shell,或者是需要构造rop链来实现orw获得flag时,可以考虑利用setcontext构造一个fake_stack
能知道heap_base的地址和libc_base的地址即可利用
先劫持free_hook,使其指向setcontext+53的位置
在堆中传入0xa0个填充字符+fake_stack的地址+返回地址
调用free,释放掉上述的堆块,此时rdi为上述堆块的地址,rdi+0xa0正好为fake_stack的地址,rdi+0xa8为返回地址
之后
mov rsp,[rdi+0xa0]
伪造出fake_stack,mov rcx,[rdi+0xa8];push rcx
使rcx为栈顶空间,之后再次ret,返回到rcx即rdi+0xa8
的地址位置fake_stack中的数据可写在另一个chunk中,这样知道了heap_base即可知道fake_stack的地址
实例
2024网鼎杯青龙组初赛pwn4
分析
main函数,禁用execve,开始需要输入用户名和密码,cmp中调用strlen()
来比较前几位字符,若前几位相同,则会打印Invalid username length
否则打印Invalid username
因此可以类似于爆破canary一样爆破username和password
结果
1 | username = "4dm1n" |
之后就是堆的部分,四功能齐全
在输入数据里会有一个加密,同样的,输出里也会有一个加密,free后会恢复加密。这就导致了如果利用UAF直接泄露地址,会泄露出加密的地址,如果edit伪造一个地址,也会被加密,导致成为一个非法地址
rc4加密
该题目的加密手法是rc4加密
rc4加密首先会有一个密钥,如图密钥为s4cur1ty_p4ssw0rd
之后会对密钥进行处理,来生成一个密钥流,利用密钥流对明文进行加密
rc4加密有以下特点
- rc4为对称加密,加密解密用一个密钥
- rc4甚至加密解密是同一个算法,意味着对同一组数据加密两次相当于没有进行加密
- 原文密文长度一样,若对密文的一部分进行解密,解密的结果仍是原文相对应的部分
可以利用python来辅助解密
1 | from Crypto.Cipher import ARC4 |
由于rc4的特性实际上两个函数一样,因此只需写一个即可
exp
1 | from pwn import* |
由于地址的随机性,导致有时候地址会被加密出\n
截断后续内容
原题中最后orw的flag是flag.txt