Flag: Tornado! Hurricane!

Blogs >> RolfRolles's Blog

Created: Tuesday, February 5 2008 15:33.02 CST Modified: Thursday, February 14 2008 14:40.44 CST
Printer Friendly ...
SpyShredder Malware Spammed on OpenRCE
Author: RolfRolles # Views: 9119

From time to time I notice an obvious spam account in the "Active in Last 5 Minutes" box or on the 'Users' page.  This one in particular caught my attention.  You can see several pages of links to useless things (such as "poster of vin diesel in shower"), with all of those links pointing to .cn domains.  I figured I'd be infected by malware if I visited one of the sites, so I opened up the link inside of a VM.

It was not at all surprising when the page ran a fake spyware scan and then urged me to install its anti-spyware product to get rid of all of the dangerous rootkits infecting my system.  The webpage serves you a small downloader which is packed with something I've never seen before.  All in all the packer is trivial, but it uses an anti-debug trick that I hadn't seen before:


.text:004042F7                 push    0
.text:004042F9                 call    dword ptr [eax] ; <- msvcrt!_CIacos
.text:004042FB                 mov     edx, eax        ; <- eax = 0x00321EA8
.text:004042FD                 imul    edx, 10000h     ; <- edx = 0x1EA80000

...

.text:004042D8                 push    0E1A8A200h
.text:004042DD                 pop     esi
.text:004042DE                 add     esi, edx        ; <- esi = 0x0050A200, read-only memory
.text:004042E0                 mov     edi, esi
.text:004042E2
.text:004042E2 loc_4042E2:
.text:004042E2                 lodsd
.text:004042E3                 xor     eax, 0C2EA41h
.text:004042E8                 stosd                   ; <- access violation writing to read-only memory
.text:004042E9                 loop    loc_4042E2


[EDIT 02/14:  apparently the up arrow in the ; CODE XREF was causing problems with WoodMann's blog imports]

If, on line 004042DE, you modify the register esi to instead contain 0x0040A200 (e.g. subtract 0x00100000), unpacking proceeds as usual.  Therefore I surmised that msvcrt!CIacos(0) returns 0x00321E98 if a debugger is not present, 0x00321EA8 otherwise.  I wrote a small test application that confirms this behavior.  Comments on this point would be appreciated.

The downloader installs itself as an autorun in the registry, downloads a file off of some Californian webserver, runs it, and then writes out a hard-coded file called c:\Program Files\SpyShredder\SpyShredder.lic.  There's only three non-library functions inside of the downloader, so it makes for pretty quick work, although it's MSVC on high optimization settings so the instruction scheduling and inlined string operations are a bit hard to read.

At this point all of the "SpyShredder" references caught my attention, so I googled it and submitted the samples to VirusTotal.  I stopped analyzing when I saw that F-Secure has a pretty good write-up on it -- it's one of those trojans that pops up many official-looking nag windows warning you about the sky falling, and promises that the windows will go away if you pay up.  There's a technical term for that behavior.  The United States' Federal Trade Committee calls it "extortion".

The moral of the story?  Spamming malware onto a site for professional reverse engineers is plain stupid.


Blog Comments
neoxfx Posted: Tuesday, February 5 2008 21:28.18 CST
Hi RolfRolles,

you are right, try this too msvcrt!_CIasin().
it is an indirect NtGlobalFlag check.

RolfRolles Posted: Tuesday, February 5 2008 22:06.44 CST
I'll have to look into it ... it's strange to imagine that a trigonometric function would behave differently under a debugger, but that is indeed what is happening.  It has "heisenbug" written all over it.  Thanks for the pointer neoxfx, I'll be investigating it.

Kayaker Posted: Wednesday, February 6 2008 00:09.35 CST
Nice find Rolf.  I was thinking it was more related to the difference in heap allocations when a target is run under a debugger.  See here for reference:

http://www.openrce.org/forums/posts/594#1982

That magic value returned in the malware is directly related to TlsGetValue when used by _CIacos().  You can see the same effect in Notepad, which also uses msvcrt and ultimately some TlsGetValue calls.


For _CIacos that's here:

// msvcrt.dll WinXP
:77C39F25 sub_77C39F25    proc near
:77C39F25                 mov     edi, edi
:77C39F27                 push    esi
:77C39F28                 push    edi
:77C39F29                 call    ds:GetLastError
:77C39F2F                 push    dwTlsIndex      ; dwTlsIndex
:77C39F35                 mov     edi, eax
:77C39F37                 call    ds:TlsGetValue


TlsGetValue directly returns the value 0x00321E90 if a debugger is not present, 0x00321EA0 otherwise.  The extra "8" is added a little later to give the final values seen.

kernel32!TlsGetValue gives us:


:7C809750 TlsGetValue     proc near
:7C809750
:7C809750 dwTlsIndex      = dword ptr  8
:7C809750
:7C809750                 mov     edi, edi
:7C809752                 push    ebp
:7C809753                 mov     ebp, esp
:7C809755                 mov     eax, large fs:18h
:7C80975B                 mov     ecx, [ebp+dwTlsIndex]
:7C80975E                 cmp     ecx, 40h
:7C809761                 jnb     loc_7C84463F
:7C809767                 and     dword ptr [eax+34h], 0
:7C80976B                 mov     eax, [eax+ecx*4+0E10h] // TEB.TlsSlots
:7C809772
:7C809772                 pop     ebp
:7C809773                 retn    4
:7C809773 TlsGetValue     endp


[eax+ecx*4+0E10h] is TEB.TlsSlots.  The slot indexes appear to contain allocated memory block addresses.  

Now we know that TlsGetValue must have a corresponding TlsSetValue, so if you search around in msvcrt.dll you can see where the dll sets up Tls values as the returned value from calloc() through the lpParameter of CreateThread. For example:


:77C3A28E loc_77C3A28E:                           ; CODE XREF: _beginthread+E
:77C3A28E                 push    esi
:77C3A28F                 push    88h
:77C3A294                 push    1
:77C3A296                 call    calloc
:77C3A29B                 mov     esi, eax
...
:77C3A2A9                 mov     eax, [ebp+arg_8]
:77C3A2AC                 pop     ecx
:77C3A2AD                 push    esi             ; lpThreadId
:77C3A2AE                 push    4               ; dwCreationFlags
:77C3A2B0                 push    esi        ; lpParameter
:77C3A2B1                 push    offset StartAddress ; lpStartAddress
:77C3A2B6                 push    [ebp+dwStackSize] ; dwStackSize
:77C3A2B9                 mov     [esi+4Ch], edi
:77C3A2BC                 push    0               ; lpThreadAttributes
:77C3A2BE                 mov     [esi+50h], eax
:77C3A2C1                 call    ds:CreateThread


And if we check the beginning of the new thread at lpStartAddress, the first thing it does is to set the TlsValue as the calloc() mem allocation address from the lpParameter variable:


:77C3A1D7 StartAddress    proc near               ; DATA XREF: _beginthread+43
:77C3A1D7
:77C3A1D7 lpTlsValue      = dword ptr  8
:77C3A1D7
:77C3A1D7                 push    0Ch
:77C3A1D9                 push    offset stru_77C140C8
:77C3A1DE                 call    __SEH_prolog
:77C3A1E3                 push    dwTlsIndex      ; dwTlsIndex
:77C3A1E9                 call    ds:TlsGetValue
:77C3A1EF                 mov     esi, eax
:77C3A1F1                 test    esi, esi
:77C3A1F3                 jnz     short loc_77C3A212
:77C3A1F5                 mov     esi, [ebp+lpTlsValue]
:77C3A1F8                 push    esi             ; lpTlsValue
:77C3A1F9                 push    dwTlsIndex      ; dwTlsIndex
:77C3A1FF                 call    ds:TlsSetValue


So, that's how those TEB.TlsSlots values get in there and which the malware makes use of by indirectly calling TlsGetValue.


As for the address differences, when under a debugger (and debug heap allocations are used) the addresses are something like xx1EA0.  When not under a debugger (and heap allocations are of a regular type), the addresses are xx1E90.  The 0x10 difference in offset is likely due to the extra size of a debug heap allocation.

If you compare the calloc() allocations under Softice, with and without a ring3 debugger attached, you'll see the allocation begins with 0xABABABAB 0xABABABAB in the debug version, so there must be an extra 0x10 bytes padded to the start of the alloc.

Further details on that was provided be Ero in the thread I posted above and references the following article:
http://www.docsultant.com/site2/articles%5Cdebug_codes.html

Interestingly, the TlsValue itself (either debug/no debug case) points directly to the ThreadId of the new thread, which you can actually guess from the CreateThread code posted above, as esi is also used as the lpThreadId OUT variable.


Cheers,
Kayaker

GynvaelColdwind Posted: Wednesday, February 6 2008 00:21.54 CST
Huh... Now that is interesting ;> Nice find Rolf ;>

RolfRolles Posted: Wednesday, February 6 2008 01:28.58 CST
Thanks for the lucid explanation and reference links, Kayaker; now it's clear.  Would be nice if there was a wiki for anti-debug tricks so we don't keep reinventing the wheel on various messageboards and papers.

neoxfx Posted: Wednesday, February 6 2008 01:38.20 CST
Good detailed explanation kayaker.
flag NtGlobalFlag affects heap allocation

OllyAdvanced already takes care of this and turning off Debug heap.

check this
http://forum.exetools.com/showthread.php?t=7363
http://www.openrce.org/forums/posts/629

neoxfx Posted: Wednesday, February 6 2008 01:44.04 CST
Read this too https://www.blackhat.com/presentations/bh-usa-07/Yason/Presentation/bh-usa-07-yason.pdf
this presentation gives a detailed explanation about the flags which get affected by NtGlobalFlag (page 8)

dELTA Posted: Wednesday, February 6 2008 03:19.08 CST
Hey Rolf, nice post!

About your suggestion for a wiki for anti debug tricks, the almighty Collaborative RCE Tool Library (which essentially is a wiki, or rather has all advantages of a wiki while not having most of the disadvantages) of course already has a category called "Technical PoC Tools", for exactly this kind of thing. :) I also just added a subcategory of it called "Anti Debug PoC Tools", here:

http://www.woodmann.com/collaborative/tools/index.php/Category:Anti_Debug_PoC_Tools

So, you (and everyone else) are very welcome to submit all your anti debug trick PoCs + information there, which will make up a very nice collection of information for anti debug tricks and accompanying PoCs! Other types of PoC categories are also very welcome of course!

pedram Posted: Wednesday, February 6 2008 17:17.32 CST
Related to dELTA's note. If you want admin access to add to the Anti-RE section of OpenRCE here:

http://www.openrce.org/reference_library/anti_reversing

Let me know and I'll add you.



Add New Comment
Comment:









There are 31,314 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
hi!
Jul/01
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit