投放代码
有ollvm+rolror等取值索引函数表的混淆,强混淆的情况下只去关注结果,可以在windows一些常被使用的api下断点,从堆栈调用里面找到调用链线索
载荷
一共有三个可执行段,其中两个RWX一个RX,其中一个RWX是dll反射展开shellcode,另一个是传参调用第一个RWX,所以极有可能载荷一开始加载的地方是直接传参调用,展开dllhost,RX的部分就是主要逻辑代码了
1.RWX 注入的shellcode
2.RWX 传参调用1.RWX
3.RX jmp rax的ollvm混淆+dllhost的主要逻辑
木马.exe -> 2.RWX(1.RWX(RX)) -> 展开RX运行
1 | __int64 (__fastcall **__fastcall DLLMain(__int64 a1))(_QWORD, _QWORD) |
最终载荷
dllhost.exe
可以通过定位注入时候的基地址然后附加提前下好断点,然后调试
先是一段RC4解密+自展开代码,然后调用展开后的PE
先经过一些初始化之后就是dllmain

前面是链接性的初始化

这部分是有自我防御性质的代码

检验过最后的进程id后,进入业务代码,获取进程id,为kernelThread的a1参数new kernelmanager

先看KernelManager_0

内部实现其实是在装载函数然后返回函数表

进入KernelThread,这里面还有一个kernelManager,这两个kernalManager实现的功能有差异,传入参数a1的kernelManager更偏向用户态,如文件操作,屏幕操作等

另一个KernelManager的主体功能主要在系统上,尤其是SysManager,里面细分了Logs,服务,驱动,注入,windows版本信息等
那么先看系统的KernelManager调用链
1 | __int64 KeyBoardManager() |
创建一个线程a -> 创建一个隐藏窗口 -> 挂全局键盘钩子
|———-> 线程a 创建一个剪贴板钩子
好,我们回到用户态KernelManager
1 | __int64 __fastcall MouseManager(__int64 *a1) |
一开始挂了一个鼠标钩子,再加上前面的两个函数,鼠标 键盘 剪贴板就都被监听了
然后判断a1[6]决定结果,而参数a1正是用户态的KernelManager v12 = 0; *(v2 + 6) = v12;
一开始是被赋值0的,那么就是顺着调用a1[9]
1 | __int64 __fastcall CreateThreadByFunc20(__int64 *a1) |
直接调用a1[20],然后等待响应
1 | v1 = a1[5]; |
先解密字符串,这里就是将管道通信需要的字符串设置好,然后调用a1[5][0]
不难猜测是连接,连接失败退出,那么先往后看
1 | memset(); |
qword_180076120 = ConnectManager();
第二个是尝试通过命名管道连接到本地某个服务,也是失败退出
1 | v6 = new_malloc_4(); |
最后都连接结束后,等待客户端消息,如果有消息,先用(v1)[2]处理,前文有v1 = a1[5],这里的(v1)[2]实际上是a1[5]里面的2函数
整理思路
1 | __int64 __fastcall GetConnectObj(__int64 a1, __int64 a2) |
这里把客户端消息加载在a2也就是前文的v6里面,然后去调用a1[16]
1 | __int64 __fastcall ToTask_4(__int64 *a1, __int64 *a2) |
这里a2是一个信号的类,根据信号去调用17 18 19
1 | __int64 __fastcall KernelManager17(__int64 *a1, __int64 a2) |
作用大概是给21做连接,然后21直接调用a1[10],里面用到v2[9],实现如下
1 | void __fastcall Make11a22(__int64 *a1, __int64 a2, __int64 a3) |
所以这里的结果就是,
v2[11] = a1[8];
v2[22] = a1;
然后调用a1[11],注意参数是v2了
1 | __int64 __fastcall KernelManager11(__int64 *a1) |
那么就是调用了v2[6],实现如下
1 | __int64 __fastcall CryEvent(__int64 rcx0, __int64 a2, unsigned int a3) |
这里就是处理一些数据,然后返回,返回后调用v2[3]
1 | __int64 __fastcall WorkEvent(__int64 a1) |
这里做的主要是网络连接的连接发送接收等,感觉是初始化的,比较底层不深究了,看另外两个方向
18的实现是将所有的windows消息发送给客户端
19负责实现ScreenManager
关于分析蓝屏部分:

检测进程名

设置进程属性导致蓝屏
一些用到的脚本
1 | import idc, idautils, idaapi |
1 | # IDA Python 脚本 |