关于32位与64位程序切换
在写fullchain遇到个问题,浏览器程序是32位的,不能往64位的winlogon.exe注入shellcode。以前写过这类的题但没深入研究过,趁这个机会写篇blog。
简介
简答来说就是通过切换cs来切换状态,要知道内核代码都是64位的,32位程序调用api肯定要进内核,所以肯定会有状态切换,可以看我之前写的api从三环到0环调用里提到过。
关于32位程序调用64位代码的方法其实在ctf中就出现过几次
https://apeng.re/2020/03/11/2020npointer-3/#more
可以看阿鹏师傅写的这writeup。
这边附赠几个学习链接。
https://www.slideshare.net/YardenShafir/jumping-into-heavens-gate
https://www.youtube.com/watch?v=fEVdqOkbUtI
https://www.sentinelone.com/blog/deep-hooks-monitoring-native-execution-wow64-applications-part-1/
近期准备用这个出个题,恰点烂钱。
随便写写
通读了上面几篇文章大概可以了解。每个32位程序都会加载几个原生的64位dll
wow64.dll, wow64cpu.dll, wow64win.dll和一个64位的ntdll.dll
且在32位程序初始化时会尝试load一个wow64log.dll在system32目录下,如果找到,它会被加载到每个wow64进程中。目前wow64log.dll并没有被windows提供,其实这是一种比较好的注入方法。
如图所示,目前还可用,其实可以作为一种不错的驻留方式。
缺点就是他会劫持所有的32位进程,不可控。而且有可能该dll存在于system32目录中(默认不存在)。
后面提到的和想学的无关紧要,就忽略了
讲讲出题,最简单的就是直接retf
1 |
|
通过这样来切换位数。
但还有其他的办法比如jmp far
https://github.com/zzhouhe/x96_POC/blob/master/main.cpp
可以看这个样例,融合起来,相对逆向难度就大了些//比较恶心人
至于为什么cs不同位数也不同可以去查询intel手册,看cs寄存器他的标志位代表着当前位数。
关于出题
出题其实很简单
32位先切换成64位下面必须写机器码
比如说你有个check函数你先编译成64位的然后dump出来直接放进32位即可
一般不会出现不兼容的情况,函数默认开头会sub rsp xxx开辟一段栈帧给局部变量使用,如果引用到全局变量记得生成后手动patch一下
有几个注意点就是在编译的时候经尽量关闭地址随机化。否则全局变量重定位不可控。64位代码中引用到全局变量会gg。
吧check后的返回值保存在寄存器里,返回32位后验证下即可。
当然出题还是比较简单的。如果想要在32位里面调用64位api实现注入就稍微烦一些。
https://github.com/rwfpl/rewolf-wow64ext
这个项目里面都帮你写好了。就和32位调用api一样,先转换64位然后把参数按照64位fastcall进行布局然后直接调用。