关于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

image-20220406163608119

wow64.dll, wow64cpu.dll, wow64win.dll和一个64位的ntdll.dll

且在32位程序初始化时会尝试load一个wow64log.dll在system32目录下,如果找到,它会被加载到每个wow64进程中。目前wow64log.dll并没有被windows提供,其实这是一种比较好的注入方法。

image-20220406163908140

如图所示,目前还可用,其实可以作为一种不错的驻留方式。

缺点就是他会劫持所有的32位进程,不可控。而且有可能该dll存在于system32目录中(默认不存在)。

后面提到的和想学的无关紧要,就忽略了

讲讲出题,最简单的就是直接retf

1
2
3
4
push   cs           
call $+5
add dword [esp], 5
retf

通过这样来切换位数。

但还有其他的办法比如jmp far

https://github.com/zzhouhe/x96_POC/blob/master/main.cpp

可以看这个样例,融合起来,相对逆向难度就大了些//比较恶心人

至于为什么cs不同位数也不同可以去查询intel手册,看cs寄存器他的标志位代表着当前位数。

关于出题

出题其实很简单

32位先切换成64位下面必须写机器码

比如说你有个check函数你先编译成64位的然后dump出来直接放进32位即可

image-20220412131740694

一般不会出现不兼容的情况,函数默认开头会sub rsp xxx开辟一段栈帧给局部变量使用,如果引用到全局变量记得生成后手动patch一下

有几个注意点就是在编译的时候经尽量关闭地址随机化。否则全局变量重定位不可控。64位代码中引用到全局变量会gg。

吧check后的返回值保存在寄存器里,返回32位后验证下即可。

当然出题还是比较简单的。如果想要在32位里面调用64位api实现注入就稍微烦一些。

https://github.com/rwfpl/rewolf-wow64ext

这个项目里面都帮你写好了。就和32位调用api一样,先转换64位然后把参数按照64位fastcall进行布局然后直接调用。

文章目录
  1. 1. 简介
  2. 2. 随便写写
  3. 3. 关于出题
|