前不久,360安全中心率先发布了MBR木马——“隐魂”的预警,对木马入侵过程分析(史上反侦察力最强木马“隐魂”:撑起色情播放器百万推广陷阱http://bobao.360.cn/learning/detail/4238.html)后发现,“隐魂”的反侦察能力极高,堪称迄今最复杂的MBR木马。360安全中心随即对该木马展开了持续追踪,本篇是对其篡改主页的行为详细介绍。
1 摘要
首先,我们来进一步了解“隐魂”木马的反侦察能力和复杂性。
(1)隐蔽性极高:“隐魂”木马会通过挂钩磁盘底层驱动实现自我保护,普通的ARK工具或查杀类工具无法深入磁盘底层,难以有效检测到MBR被修改;同时,应用层代码在TimerQueue中调度,目前除了利用调试器进行反复测试外,根本没有其他方法能检测该系统触发机制;另外,内核LoadImage挂钩代码在Nt节的空白区域,这部分在未知内存区域执行的代码也是检测工具的一大盲区。
(2)对抗性极强:为了与检测工具及杀软对抗,“隐魂”使用签名和PDB文件名方式,禁止一系列驱动加载,即使加载成功相关功能函数也会被IAT挂钩。
(3)兼容性极高:“隐魂”是目前支持系统范围最广的MBR木马,从Windows XP到Win10X64位最新系统的均支持,兼容性远远超过2016年开始活跃的暗云Ⅲ木马。
其次,我们再来说一下“隐魂”木马在篡改主页时是如何清理犯罪现场的。
(1)声东击西:不同于直接在浏览器进程中添加参数的劫持方式,“隐魂”为了躲避查杀,采取了结束原浏览器进程——创建新的系统进程——再创建新浏览器进程的方式绕了个大圈才完成主页篡改。
(2)釜底抽薪:“隐魂”会把大多数杀软的正常挂钩全部抹掉,使得浏览器主页失去安全类软件的保护。
接下来,将从WindowsNt系统加载前 (BootKit) 、系统加载后(RootKit)、注入桌面进程explorer
改首页共三部分对木马的执行流程进行详细分析。
2 NT系统加载前
2.1 MBR部分
将自身代码拷贝到 0x600处执行。
图1
而后使用int 13 42扩展读功能读取0x1个扇区 到 0x7c00,
位置是由bp指定的。
图2
读取:
图3
而后跳转到 0x7c00处继续执行。
图4
跳转:
图5
并将自身代码再次拷贝到0x600处执行:
图6
这次相同位置连续读取 0x20个扇区:
图7
定位位置:
图8
读取20个扇区:
图9
然后将代码拷贝到 0x101000 大小为0x1400。
图10
而后跳转到 0x10100处执行:
图11
然后预留高端地址0x14 = 20KB页面 用来存放代码。
图12
将自身代码拷贝到高端地址:
图13
跳转到 0x9a400 处执行挂钩代码。
图14
然后挂钩int13中断:
图15
挂钩后:
图16
挂钩处代码为 0x9a400 + 45 = 0x9a445。
图17
2.2 Int13挂钩部分
Int13挂钩中断被执行,搜索硬编码并挂钩:
图18
挂钩函数为:
图19
挂钩后函数被修改为:
图20
2.3 BootMgr部分
当系统控制权交给BootMgr 16位代码后,
准备转移给32位代码执行时挂钩中断被执行。
相关函数为:
图21
跳转:
然后直接搜0x400000 地址 并挂钩
图22
从BootMgr PE节信息中搜可执行代码,自带反汇编引擎搜索ImgpLoadPEImage对 LdrRelocateImageWithBias的调用,然后Patch对该函数调用。
挂钩前该处调用为:
图23
特征码为:
图24
搜到后 特征码 0xc0000221 及 0x20B后,
找到下一个Call调用 机器码为0xE8且指令长度为5即为搜索成功。
图25
后挂钩 :
图26
挂钩后调用为:
图27
Winload挂钩函数为:
图28
2.4 WinLoad部分
当系统执行到bootmgr!BmpTransferExecution 将控制权转移给Winload时候,
挂钩函数HookWinLoad被执行。
先将 LdrRelocateImageWithBias 函数地址放置在堆栈上,等挂钩Winload函数执行完毕后就
调用LdrRelocateImageWithBias 接着执行原来的流程。
后续的挂钩执行都是如此,并未恢复原先代码。
图29
调用为:
图30
按系统分别挂钩:
图31
然后同样是搜索ImgpLoadPEImage对 LdrRelocateImageWithBias的调用,然后Patch对该函数调用,该部分代码同BootMgr一样。
挂钩后函数为:
图32
先将恢复对函数LdrRelocateImageWithBias的调用:
图33
而后将 0x9aa9a函数放置在堆栈上等待被调用:
图34
LdrRelocateImageWithBias调用完成后 HooNt函数被执行(0x9aa9a):
图35
先恢复堆栈 后续执行流程 将winload!ImgpLoadPEImage+0x67d 放置在返回地址处:
图36
通过反汇编引擎搜调用代码 搜IoInitSystem 对 IopInitializeBootDrivers的调用。
图37
3 NT系统加载后
3.1 加载ShellCode部分
当系统执行到 Nt 中 IoInitSystem 对 IopInitializeBootDrivers调用时候,恶意代码被执行。
先将函数 IopInitializeBootDrivers 放置堆栈上,然后关闭写保护恢复原始挂钩处代码,而后将后续加载木马代码函数地址(LoadTheShellCode)放置堆栈上。
图38
当函数IopInitializeBootDrivers 调用完成后, 再次将Nt正确函数返回地址放置堆栈上。
图39
而后将ShllCode1代码映射, 大小为0xca0。
图40
校验代码并执行。
3.2 ShellCode1部分
该部分功能为读取磁盘指定位置代码并加载ShellCode2。
先获取相关函数地址,
后读取磁盘数据 检测完整并获取大小, 大小为0x4a000。
图41
然后为第二块ShellCode申请内存 大小为 0x4c08。
申请后执行:
图42
3.3 ShellCode2部分
该部分主要为解压之前读取的资源数据并查找加载其中/bin/i386/bootmgr NE文件并加载。
校验完整性 ,并解压数据:
图43
然后为第三块NE 格式ShellCode申请空间 大小为0x1f00,准备执行,并将资源作为参数传入。
图44
3.4 ShellCode3部分
主要为加载 /bin/i386/kernel 到内存并执行,Kenel部分为内核关键代码部分。
图45
拷贝NE文件资源,大小为0x10380:
图46
而后帮第四块ShellCode修正导入表重定位并执行。
图47
3.5 ShellCode4部分
该部分为内核关键代码,包含注入代码挂钩LoadImage 反内核调试代码。
入口出先断开内核调试:
图48
而后读取磁盘数据并保存:
图49
创建设备跟应用层交互:
图50
而后重载内核获取一些导出符号,占满情况下,用于清理挂钩回调:
图51
设置LoadImage回调 主要后续用于APC注入svchost跟explorer用来修改用户主页。
将真正函数地址LoadImageNotify作为参数传入。
图52
查找节后面空闲区域 ,将自身挂钩代码拷贝过去。
图53
拷贝代码:
图54
代码为:
图55
其中AAAAAAAA 为占位后续将填入实际地址。
然后加载第五块ShellCode,并且挂钩:
图56
而该挂钩会反复被检测执行:
图57
挂钩函数为:
图58
LoadImage中判断svchost.exe进程创建:
图59
如果是svchost.exe进程创建:
图60
判断是否为指定的svchost.exe:
图 61
主要通过命令行方式判断:
图62
匹配命令行后准备注入代码:
图63
将APC NormalRoutine设置为Ne 入口点 得到执行:
图64
Exploer注入代码:
图65
3.6 ShellCode5部分
该内核块功能主要为防止被检出查杀。
获取签名公司列表信息:
图66
代码:
图67
而后调用ShellCode4中设置LoadImage回调函数。
图68
在回调中判断驱动是否有PDB信息,分三种情况Patch
1 如果没有PDB符号信息且匹配签名 则直接Patch入口点。
图69
2 如果有PDB信息,一些常见的工具,也Patch入口点,如gmer.pdb ,Win64AST.pdb。
图70
3 如果Pdb有 且hash 比对一致则导入表 Hook:
图71
还会IAT Hook文件操作函数,防止查杀类驱动读取文件恢复钩子。
ZwCreateFile:
图72
IofCallDriver:
图73
防止文件簇读取方式:
图74
获取文件保护列表函数:
图75
Patch函数:
图76
图 77
4 篡改主页部分
4.1 ShellCode1部分
APC注入Explorer.exe后,入口点修正导入表 ,创建线程并加载改首页模块。
图78
线程函数中申请执行空间,并将代码拷贝。
高端地址执行:
图79
然后修正导入表,重定位:
图 80
执行入口点函数:
图81
4.2 ShellCode2部分
初始化系统模块名字,挂钩时候使用:
图82
初始化恢复钩子列表,发现这些函数一旦被挂钩就直接恢复。
图83
将原始代码备份,并保存到链表中,头部指令最多长度为0x20。
图84
然后打开首页页面地址:
图 85
其中共享内存区数据为:
图86
然后枚举所有加载模块 IAT挂钩CreateProcessW函数。
图87
挂钩回调函数为:
图88
主要挂钩Shell32.dll对CreateProcessW函数调用。而后检测之前的初始化的系统函数是否被Hook,进行恢复。
图89
CreateProcessW挂钩中判断创建进程是否为浏览器列表之一:
图90
浏览器列表为:
图91
而后创建verclsid.exe 为傀儡进程,修改主页:
图92
而后创建傀儡进程:
图93
将代码映射到傀儡进程QueueUserAPC APC函数:
图94
4.3 ShellCode3部分
该部分代码为QueueUserAPC 注入到 verclsid.exe 中执行。
入口点为从PEB LDR中获取信息,修正重定位修正导入表:
图95
然后Patch傀儡进程入口点。
图96
而后在调用CreateProcessW创建带有命令行的浏览器进程
图97
完成修改主页:
图98
svshost部分
主要为创建TimerQueue中 回写LoadImage回调并回写MBR:
该部分代码难以有效检出。
创建:
图99
给驱动发送命令写入:
图100
5 尾声
“隐魂”木马创下了两周内攻击量上百万次的记录,可谓迄今传播速度最快的MBR木马。其高超的反侦察能力及复杂的利用技巧让不少检测手段力不从心,如今其攻势虽然放缓但远不曾停止,被推广利益驱使的作者很有可能继续兴风作浪,通过远程控制的方式实施对个人数据及财物的大规模攻击。
不过网民们也不用过分担心,360安全卫士不仅率先对“隐魂”木马展开了查杀,还可以完美拦截各类MBR顽固木马的攻击。目前,360安全中心也正在对“隐魂”木马进行持续追踪,如有新成果将第一时间与大家分享。
图101