記一次頭鐵的病毒樣本分析過程
樣本

運行效果:

點擊確定后就無任何反應。
二 靜態分析
1、程序信息
MD5 fdd9fd0249d48d8c6d991741c67fcfeb
SHA-1 ff0181242825b5bb8cac1d4d17e8377352e3aa55
SHA-256 6a9bdabc4599618513de5c963972929de9322c486e84e101e177c0868e7c5fb7
File size 1.34 MB (1408512 bytes)

其中較為引人注目的就是winnet.dll、shell32.dll、advapi32.dll,這三者分別是對網絡,運行程序,注冊表進行操作的動態庫,說明程序存在運行外部程序和聯網操作。
字符串的話,通過Strings.exe查詢后沒發現任何敏感字符串,這里就不貼出來了。
2、在線查毒


3、進程行為監控:
通過火絨的監控發現其對注冊表進行了大量操作,不過并沒什么影響。


且運行了一個名為CrashReporter.exe的程序。

途中創建了一些文件:

首先是CrashReporter.exe,跳到目標目錄后發現其文件大小與樣本大小相同,故猜測此樣本運行后將自身轉移到新路徑后偽裝綠色運行,其次是txt,打開后發現內容為:
ABC
AAC
AAD
BBC
BAC
BAD
暫時不知什么意思,然后是WeiXinCR01,內容為:
D2 C2 7E AD 52 06 C4 93
這里根據后面的調試,發現內容含義為Crc32計算C盤的序列號的結果。
4、網絡行為

HttpDebuger無任何發現。
三 動靜態分析
首先分析原樣本,突破口可以從給MessageBoxA下斷后返回拿到關鍵點。

這里直接返回到call的位置,直接計算call地址的相對地址,然后扔進IDA進行分析。


這個樣本在靜態分析時之所以沒有看到敏感字符串是因為他的字符串都是以字符數組初始化的。

在分析的時候可以通過先轉義這些字符數組的內容,再去分析這個地方執行了什么。比如這里的字符數組為SetEvent error,那么說明調用SetEvent失敗。并且他這個樣本調用函數的方式是通過一個類似shellcode的方法獲取,然后把函數存放放到一個全局變量里。
我們來到調用了MessageBoxA后,直接到函數頭部進行一直交叉引用,最后來到了WinMain的最初調用處。

這個過程中會發現整個代碼中存在很多這種形式的代碼。

這些代碼看似是在獲取TEB和PEB操作,但是經過簡單分析后,發現這些其實就是垃圾代碼,只是為了通過增大代碼量,用來增加分析時間。
1、StartMainWork分析
在這個StartMainWork函數執行前,會執行幾個數據初始化的函數,包括有crc32和crc64表的生成,動態庫函數的獲取,還有樣本之后所需要用到的數據。這里crc32和64生成的函數很好識別,因為其算法固定,且帶有常量值,下面是樣本生成crc的關鍵代碼。
for ( i = 0; i < 256; ++i ) // 開始生成crc32表
{
crcValue = i;
for ( j = 0; j < 8; ++j )
{
......垃圾代碼........
if ( crcValue & 1 )
crcValue = (crcValue >> 1) ^ 0xEDB88320;// 搜索這個值,可以知道這里是CRC算法的常量值
else
crcValue = crcValue >> 1;
g_crc32Table[i] = crcValue;
}
}
for ( jj = 0; jj < 256; ++jj ) // 開始生成crc64表
{
v45 = jj;
for ( kk = 0; kk < 8; ++kk )
{
......垃圾代碼........
if ( v45 & 1 )
{
LODWORD(v0) = (v45 >> 1) ^ 0xAC4BC9B5; // 根據這個常量值,搜索后發現是crc64的常量值
HIDWORD(v0) = (v45 >> 1 >> 32) ^ 0x95AC9329;
v45 = v0;
}
else
{
v45 >>= 1;
}
g_crc64Table_Low[2 * jj] = v45;
g_crc64Table_Hight[2 * jj] = HIDWORD(v45);
然后比較有意思的就是動態庫函數的獲取了,該樣本采取了類似shellcode的方式獲取,通過Ldr來遍歷自身的dll模塊,然后通過都PE文件的解析尋找函數地址,并添加到全局函數表中。
該方式在《惡意代碼分析實戰》一書中第十九章的shellcode符號解析有講解,這里就不詳細解釋了,以下是關鍵代碼:
peb = readPEB();
*functionTable = peb;
if ( peb )
{
// 通過動態調試得知這里獲取的是Kernel32.dll地址,參數二為字符串Kernel32.dll通過crc32計算后的結果
ModuleBase = getModuleBaseByCrcValue(*functionTable, 0xF7784A01);
functionTable[1] = ModuleBase;
if ( KernelBase )
{
// 直接從目錄項里獲取參數三對應的函數地址
procCreateFileA = getProcAddrByDirArray(functionTable[1], -1, (int)&strCreateFileA, 0);
....往下的也是一樣
}
............
}
這里貼出它加載的所有函數:
$ ==> 757E3090 kernel32.CreateFileA $+4 757DDF70 kernel32.GetLastError $+8 757D83E0 kernel32.GetSystemDirectoryA $+C 757E22D0 kernel32.ExpandEnvironmentStringsA $+10 757E0BE0 kernel32.GetStartupInfoA $+14 757F2DA0 kernel32.CreateProcessA $+18 757E2E40 kernel32.CloseHandle $+1C 757E3030 kernel32.WaitForSingleObject $+20 757E3420 kernel32.ReadFile $+24 757D89C0 kernel32.lstrcat $+28 757E2DF0 kernel32.GetCurrentProcessId $+2C 757DDE70 kernel32.GetCurrentThreadId $+30 757E2300 kernel32.GetTickCount $+34 757E3510 kernel32.WriteFile $+38 757F2D80 kernel32.CreatePipe $+3C 75130000 "MZ?" $+40 75155840 user32.wsprintfA $+44 757C0000 "MZ?" $+48 757E0B30 kernel32.LoadLibraryA $+4C 757E0A40 kernel32.FreeLibrary $+50 757E0D90 kernel32.GetModuleFileNameA $+54 757DE010 kernel32.lstrlenW $+58 757DDF00 kernel32.SetLastError $+5C 7581F6A0 kernel32.lstrcpyW $+60 757E03A0 kernel32.lstrlenA $+64 757D8320 kernel32.lstrcpyA $+68 757DF440 kernel32.lstrcmp $+6C 757DF320 kernel32.VirtualAlloc $+70 757DF420 kernel32.VirtualFree $+74 757E0860 kernel32.GetModuleFileNameW $+78 757E3090 kernel32.CreateFileA $+7C 757E32C0 kernel32.GetFileSize $+80 757E3420 kernel32.ReadFile $+84 757E2E40 kernel32.CloseHandle $+88 757D88F0 kernel32.GetEnvironmentVariableA $+8C 757D89C0 kernel32.lstrcat $+90 757E3510 kernel32.WriteFile $+94 757DDF70 kernel32.GetLastError $+98 757E0E60 kernel32.Sleep $+9C 757E3030 kernel32.WaitForSingleObject $+A0 757E2E90 kernel32.CreateEventA $+A4 757E0E70 kernel32.CreateThread $+A8 757E2FE0 kernel32.SetEvent $+AC 757D92B0 kernel32.OutputDebugStringA $+B0 757E2300 kernel32.GetTickCount $+B4 757D2EB0 kernel32.FindResourceA $+B8 757E03E0 kernel32.SizeofResource $+BC 757DE7A0 kernel32.LoadResource $+C0 757DF2A0 kernel32.LockResource $+C4 757F4B10 kernel32.SetCurrentDirectoryA $+C8 7581CD60 kernel32.WinExec $+CC 757DF4B0 kernel32.GetProcAddress $+D0 757E2DF0 kernel32.GetCurrentProcessId $+D4 757DDE70 kernel32.GetCurrentThreadId $+D8 757F2D80 kernel32.CreatePipe $+DC 757E3010 kernel32.WaitForMultipleObjects $+E0 757E2FD0 kernel32.ResetEvent $+E4 757E0AF0 kernel32.ProcessIdToSessionId $+E8 757E1E10 kernel32.GetNativeSystemInfo $+EC 757E0640 kernel32.IsWow64Process $+F0 757E2DE0 kernel32.GetCurrentProcess $+F4 757F2DA0 kernel32.CreateProcessA $+F8 757D9870 kernel32.TerminateProcess $+FC 757F5000 kernel32.VirtualAllocEx $+100 757F5250 kernel32.WriteProcessMemory $+104 757F2E40 kernel32.CreateRemoteThread $+108 757E0590 kernel32.OpenProcess $+10C 757F4B70 kernel32.SetEnvironmentVariableA $+110 757F3550 kernel32.GetEnvironmentStrings $+114 757E3390 kernel32.GetVolumeInformationA $+118 757D8FE0 kernel32.GetComputerNameA $+11C 757E16C0 kernel32.GetVersionExA $+120 757E0BE0 kernel32.GetStartupInfoA $+124 757D83E0 kernel32.GetSystemDirectoryA $+128 757E34C0 kernel32.SetFilePointerEx $+12C 757E32D0 kernel32.GetFileSizeEx $+130 757E32E0 kernel32.GetFileTime $+134 757E34D0 kernel32.SetFileTime $+138 757E22D0 kernel32.ExpandEnvironmentStringsA $+13C 757E30C0 kernel32.DeleteFileA $+140 757E34B0 kernel32.SetFilePointer $+144 757E09C0 kernel32.GetModuleHandleA $+148 757E0DB0 kernel32.GetModuleHandleW $+14C 757E07C0 kernel32.GetEnvironmentVariableW $+150 757E1E40 kernel32.GetCommandLineA $+154 757D9420 kernel32.GetExitCodeProcess $+158 757E1850 kernel32.ResumeThread $+15C 757DF2F0 kernel32.GetSystemTimeAsFileTime $+160 757E2ED0 kernel32.CreateMutexA $+164 757D8AC0 kernel32.CopyFileA $+168 757E3060 kernel32.CreateDirectoryA $+16C 757E2040 kernel32.GetExitCodeThread $+170 757DF490 kernel32.LocalFree $+174 757DDF50 kernel32.WideCharToMultiByte $+178 75130000 "MZ?" $+17C 75155840 user32.wsprintfA $+180 76EE6640 ntdll.NtdllDefWindowProc_A $+184 7514F150 user32.RegisterClassA $+188 75155580 user32.CreateWindowExA $+18C 7516F7E0 user32.ShowWindow $+190 75161970 user32.UpdateWindow $+194 75150B90 user32.GetMessageA $+198 75167660 user32.TranslateMessage $+19C 75154EC0 user32.DispatchMessageA $+1A0 75159350 user32.CharUpperA $+1A4 751AD860 user32.MessageBoxA $+1A8 751527A0 user32.GetCursorPos $+1AC 751B7170 user32.FindWindowExA $+1B0 75167AF0 user32.GetWindowThreadProcessId $+1B4 75161ED0 user32.GetWindowRect $+1B8 751660B0 user32.ScreenToClient $+1BC 75162150 user32.GetClientRect $+1C0 75154080 user32.SetWindowTextA $+1C4 7516F040 user32.MoveWindow $+1C8 751525B0 user32.GetAsyncKeyState $+1CC 76580000 "MZ?" $+1D0 7659F620 advapi32.SetServiceStatus $+1D4 7659F8A0 advapi32.RegisterServiceCtrlHandlerW $+1D8 7659DF20 advapi32.OpenProcessToken $+1DC 765A3910 advapi32.LookupPrivilegeValueA $+1E0 7659EF80 advapi32.AdjustTokenPrivileges $+1E4 765B2990 advapi32.CreateProcessAsUserA $+1E8 7659E7E0 advapi32.InitializeSecurityDescriptor $+1EC 7659E7C0 advapi32.InitializeAcl $+1F0 765C45D0 advapi32.LookupAccountNameA $+1F4 7659E660 advapi32.AddAccessAllowedAce $+1F8 7659E640 advapi32.SetSecurityDescriptorDacl $+1FC 765A2840 advapi32.GetUserNameA $+200 75530000 "MZ?" $+204 755A59A0 msvcrt.sscanf $+208 755B94D0 msvcrt.memset $+20C 755B8CF0 msvcrt.memcpy $+210 755A4CB0 msvcrt.printf $+214 75596C30 msvcrt._beginthreadex $+218 755B9EF0 msvcrt.strtok $+21C 755B9E60 msvcrt.strstr $+220 755BF140 msvcrt._time64 $+224 7558C650 msvcrt.rand $+228 7558BAB0 "j\fh垜]u鐷\x11" $+22C 755774F0 msvcrt.malloc $+230 7558C680 msvcrt.srand $+234 75577310 msvcrt.free $+238 76E60000 "MZ?" $+23C 76EBE1D0 ntdll.RtlInitializeCriticalSection $+240 76E9E8E0 ntdll.RtlEnterCriticalSection $+244 76E9DE00 ntdll.RtlLeaveCriticalSection $+248 76EAF940 ntdll.RtlDeleteCriticalSection $+24C 746A0000 "MZ?" $+250 746A4FD0 wtsapi32.WTSEnumerateSessionsA $+254 746A53A0 wtsapi32.WTSQuerySessionInformationA $+258 746A24A0 wtsapi32.WTSFreeMemory $+25C 746A1930 wtsapi32.QueryUserToken $+260 75C60000 "MZ?" $+264 75DBA520 shell32.CommandLineToArgvW $+268 75E97CF0 shell32.ShellExecuteA $+26C 76250000 "MZ?" $+270 7626A1C0 shlwapi.PathFileExistsA $+274 73B20000 "MZ?" $+278 73DC1380 wininet.InternetOpenA $+27C 73DD8640 wininet.InternetQueryOptionA $+280 73DDA4B0 wininet.InternetSetOptionA $+284 73E27000 wininet.InternetConnectA $+288 73DD7D50 wininet.InternetReadFile $+28C 73DE2950 wininet.InternetCloseHandle $+290 73EC41F0 wininet.HttpOpenRequestA $+294 73DF00F0 wininet.HttpAddRequestHeadersA $+298 73E32B20 wininet.HttpSendRequestA $+29C 73DD9EE0 wininet.HttpQueryInfoA $+2A0 6F780000 "MZ?" $+2A4 6F7D19B0 dnsapi.DnsGetCacheDataTable $+2A8 6F7A1DE0 dnsapi.DnsFree $+2AC 6F793530 dnsapi.DnsQuery_W
最后初始化的是一個樣本之后用到的數據,包括有創建文件的路徑,自拷貝的路徑等等。該函數是直接賦值,這里直接貼出內容。
$ ==> 00000201 $+4 00000066 $+8 00000002 $+C 00000065 $+10 00000001 $+14 0123A601 $+18 02D91248 "D:\\Tencent\\WeChat\\v7.0D:\\Tencent\\WeChat\\v7.0%ProgramData%\\Tencent\\WeChat" $+1C 02D92448 "CrashReporter.exe" $+20 02D92478 "%PUBLIC%\\unlimit.flag" $+24 76ED9800 "鶅}\x08" $+28 00000000 $+2C 02D924A8 "%PUBLIC%\\Documents" $+30 02D924D8 "new.doc" $+34 76EA0100 ntdll.76EA0100 $+38 02D924F8 "%ProgramData%\\WeiXinCR01" $+3C 02D92530 "%ProgramData%\\WeiXinCR02" $+40 00000001 $+44 00000014 $+48 00000064 $+4C 02D92884 $+50 02D928A8 "Microsoft Word" $+54 02D928B7 $+58 00000064 $+5C 0000000A $+60 01200200 $+64 02D925E8 "127.0.0..0.0.127192.168.172.16.0.0.0.0255.255.255.255" $+68 02D92640 ".testtest." $+6C 00000000 $+70 00000000 $+74 00000001 $+78 00000301 $+7C 0001D4C0 $+80 00000000 $+84 00000BB8 $+88 00026000 $+8C 00000000 $+90 02D92668 "WeiXinCrashReporter" $+94 02D92698 "https://start.firefoxchina.cnhttps://www.msn.cn/zh-cn" $+98 02D928BC "http://39.99.57.67/grief-seed/ribbon-mummy.dathttp://39.99.57.67/grief-seed/marmaid-conductor.dathttp://39.99.57.67/grief-seed/candle-knight.dathttp://39.99.57.67/grief-seed/gramphone-witch.dat" $+9C 00001388 $+A0 00007530 $+A4 00000001 $+A8 02D92982 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.104 Safari/537.36 Edg/89.0.774.76" $+AC 02D92750 "###@@@WeiXin0099" $+B0 00000000 $+B4 00000000 $+B8 00000003 $+BC 02D92A06 $+C0 02D92A09 "0d8d26376410b051421adee91163c5a54a5d5095d47cdf05ae5351de7ba0a153382c6d5778c21726" $+C4 00EFF320 $+C8 00000FDC $+CC 00000000 $+D0 01200000 $+D4 00001F18 $+D8 00DEF000 $+DC 01200000 $+E0 00000000 $+E4 01200000 $+E8 00EFF390 $+EC 00001F18 $+F0 00001F18 $+F4 00001F18 $+F8 00DEF000 $+FC 00000000 $+100 00000000
這里可以看到存在協議頭,域名和IP列表,但是網絡工具并沒有監測到,說明樣本沒有觸發。
StartMainWork函數頭首先是一個調用ExpandEnvironmentStringsA函數,來獲取環境變量的值。

通過前面他初始化的字符串得知這里的環境值為 %PUBLIC%\unlimit.flag,因為這個文件一直不存在,所以緊接著的PathFileExistsA返回0,不進入代碼塊。

然后會對本層函數傳進來的參數進行判斷,因為打開程序時默認不帶有命令參數,所以CmdLine為NULL。又因為上面判斷flag文件不存在,所以對應的標志位也是為0。此處判斷不成立。往下走會判斷dataTable + 0x14位置的值是否為0。通過查看dataTable發現這個位置的值恒等于1,所以此處永遠是執行的狀態。

進行自我復制的操作。

因為v73在上面的if沒有成立,所以此處的值為默認的1,故此處調用的后兩個參數為1,0。然后整個WinMain的執行周期結束。明顯關鍵函數為**CopySelf_And_DoWork**,接下來進入分析。
2、CopySelf_And_DoWork分析

進入函數后首先會調用一個popMsgBox_DnsCache,這個函數的是跳出一個信息框然后進行DNS一些查詢操作。這里注意的是ida在這里顯示的是+0xE的作為參數一,可是在我調試的時候發現這里實際上是0x38,具體原因我也不清楚。

現在繼續往下看看還會執行什么。

這里會執行兩個函數,通過動態調試得知這里的參數內容如下:
pathTable = "D:\\Tencent\\WeChat\\v7.0D:\\Tencent\\WeChat\\v7.0%ProgramData%\\Tencent\\WeChat"
ExistPath = 上面一個函數創建new出來的地址,用于此處函數的out_buffer。
經過內部分析,這個函數作為為對參數一的路徑以\r分割,然后逐一判斷其是否存在,存在則返回到ExistPath。參數三的作用則是,傳入0就直接判斷路徑是否存在,不創建。
傳入1就是如果路徑不存在則創建。因為本人虛擬機只有C盤,故只有第三項路徑存在C:\ProgramData\\Tencent\\WeChat。如果所有路徑都不存在,則本層函數直接返回,反之執行下列代碼。





圖片可能有點亂,大概的流程就是:
if ( GetModuleFileNameA(0, ¤tPath, 259) )// 獲取當前運行時的路徑 { if ( lstrcmpA_0(&_crashReportPath, &_currentPath) )// 比較兩個文件運行的路徑 { // 這里是路徑不相同時的處理 if (CopyFileA(¤tPath, &CrashReportPath, 0) )// 將自身拷貝到目標路徑 { if ( PathFileExistsA(&CrashReportPath) ) { wsprintf(&v226, &v395, &CrashReportPath); //運行拷貝后的程序 if ( CreateProcessA(0, &v226, 0, 0, 0, 0, 0, 0, &lpStartupInfo, &lpProcessInformation) )// shellCmd { CloseHandle_0(lpProcessInformation); CloseHandle_0(v10); } } } } else { CrashReportMain((int)dataTable, a2, ExistFlag);// CrashReport.exe 執行的函數 } }
然后本層函數也執行完畢。現在就開始分析重中之中,CrashReportMain。
3、CrashReportMain分析

首先在x32dbg進行頭部下斷,查看一下該函數的參數。
參數1 = dataTable
參數2 = 1
參數3 = 0

函數進來后依舊是popMsgBox_DnsCache函數的調用,這個函數基本上不影響樣本功能,所以略過。

到了這里雖然里面有一個sub_511EB0函數,但是這個條件沒有成立,0x24的位置始終為0。這里先繼續往下走。


這里的話是判斷互斥體名稱是否存在,存在的話創建一個互斥體。

往下繼續分析,會看到這里會對上面的錯誤碼進行判斷,而且判斷的文本為Error : A downloader instance is already,由此可知,這個當前分析的這個CrashReporter樣本可能是一個下載器。


往下執行會執行到這個條件,因為這個sub_4C7B40內部存在sleep函數,單步跳過時會直接卡住。如果返回為true,則會執行下面的sub_5176C0,然后本層函數直接結束掉。這里就直接從sub_4C7B40開始分析。
4、sub_4C7B40分析

首先執行第一個函數,CheckMachineIsMatch_FileExist,這個函數會檢測是否存在文件C:\ProgramData\WeiXinCR02文件,該文件存放著C盤序列號的CRC32值。
如果文件不存在則函數返回0,如果存在則獲取C盤的序列號并且計算出CRC32值,然后與文件里的值對比,是否一致。這里由于文件是不存在的,所以返回的為0,下面0x40是1,條件成立直接執行下面的延遲函數。

safeSleep通過isMatch來計算需要延遲的時間,如果isMatch == true,則延遲2分鐘,反之延遲4分鐘。

這里因為為了分析直接先nop掉這個函數執行,并且讓返回值為1。

包括這里isMatch也是0,所以這里也需要改。

緊接著執行這個位置,函數直接返回1。

由于沒有文件WeiXinCR02,所有在函數尾部,創建了該文件,并寫入了C盤序列號的CRC32值,最后也返回1。這個函數整體大概是通過判斷文件WeiXinCR02的存在來進行樣本休眠,具體的作用可能為了躲過某些檢測。
5、sub_5176C0分析

進入頭部直接是一個urlList的初始化:

往下走會執行一個Requst函數,會對每一個url進行一個get請求和讀取源碼,之后會執行一個sub_5071A0,這里沒分析出具體是干嘛。看到一些加密或解密的函數,估計是在讀取網頁源碼的時候對內容進行解密然后形成shellcode?


網頁操作執行完后,就是文件下載了,這里通過查看數據表發現這里的字符串都是以url\filename的形式存在,然后下面只有一個函數在執行,所以這里基本上可以確定下面的函數是下載這些文件,在這里本人自己去訪問一下這些地址,發現已經無法訪問了,所以無法下載,這估計也是為什么該樣本運行時只有一個信息框彈出,就沒有其它反應了,這里進入downloader進行分析。
6、downloader分析

函數頭的字符串提示更加確定這是一個下載函數。


往下走后會看到樣本使用了strtok進行文本分割,然后傳入startDownLoad開始下載,下載同時會記錄下載的個數,當所有下載完成后,本層函數返回下載的總數。這里注意下上面CrashReporter函數中我少了一個函數沒分析,那個函數其實就是這個函數。

7、startDownLoad分析

這里定義了一個結構體變量,newMem_8,結構體內容如下:
struct unkown
{
int* urlField;
int* dataTable
};
之后會根據參數3進行啟動不同的下載線程。
8、sub_50C610分析

因為文件已經無法下載了,所以sub_5071A0本人沒法繼續跟入分析,因為此函數里,基本都是對下載的文件進行image,section校驗,且對部分數據進行處理。由于沒拿到原文件,所以本人無從下手。
9、openDoc_download分析

首先是對保存路徑初始化。


然后是對文件路徑判斷是否存在,如果存在則打開改文檔。

否則進行下載。

下載完成后創建路徑,然后再去打開文檔。同樣,由于文檔當前也是無法下載的,導致沒法進一步分析。
至此,該樣本分析基本完了,且據目前分析結果來看,該樣本也就是個下載器。
四 總結
長達一周的分析,終于結束了。因為該樣本添加了很多的垃圾代碼,導致分析的時候需要翻來翻去,有些關鍵代碼又夾在里面,分析的時候甚是頭疼,并且還有很多沒用的條件,看起來覺得它會執行,但是動態調試的時候就是不會執行。
又因為該樣本的下載文件地址全部失效,把樣本跑起來后整個虛擬機啥問題都沒有,監視工具也壓根就沒啥反應,壓根就是一個正常的程序,這更增加了分析難度。剛剛開始接手這個樣本時,運行起來和正常程序沒什么區別,完全沒有找到有關惡意代碼的地方,最后被迫無奈,直接從WinMain手撕。整個樣本,共106個函數,天天24小時肝。
由于壓根就沒看到有什么惡意代碼,使得產生自我懷疑,甚至產生了放棄的念頭,但是想到已經分析那么多了,還不如堅持下去。最后把70多個函數全部給分析了,然后已經看出了個大概,其余的就沒分析,只看了個流程。