Transcript DLL

電腦攻擊與防禦
The Attack and Defense of Computers
Dr. 許 富 皓
1
Rootkit
2
for Windows by
[Bryce Cogswell et al. ]
3
Categories of Rootkits – Windows
User-mode Rootkits
 Kernel-mode Rootkits

4
User-mode Rootkits
5
Windows API [wikipedia]
The Windows API, informally WinAPI, is
the name given by Microsoft to the core
set of application programming
interfaces available in the Microsoft
Windows operating systems.
 It is designed for use by C/C++ programs
and is the most direct way to interact with
a Windows system for software
applications.

6
Windows API [developerfusion]

Windows can do lots of things:




Much of these functions are carried out by DLL files.
DLLs (Dynamic Linked Libraries) store functions, so
other programs can access them.


manage hardware
run programs
display icons
The advantage of using DLLs is that the same file can be
accessed at the same time by different programs.
The functions stored in the windows DLLs are called
Windows API.
7
Native API[wikipedia]

Lower level access to a Windows system,
mostly required for device drivers, is
provided by the Native API in current
versions of Windows.
8
Windows Library Files -user32.dll [processlibrary][answers.com]

user32.dll is a file that contains Windows API
functions related the Windows user interface,
such as:
 Window handling
 basic UI functions
…


and so forth.
It is a core file for several versions of the
Microsoft Windows operating system.
If this file is damaged or deleted, the operating
system will not work.
9
Windows Library Files -ntdll.dll [answers.com]
The Native API (with capitalized N) is
the publicly mostly undocumented
application programming interface used
internally by the Windows NT family of
operating systems.
 Most of them are in ntdll.dll and
ntoskrnl.exe (and it's variants).

10
Native Applications [answer]

Applications that are linked directly against a
Native API library are known as Native
Applications
 the
primary reason for their existence is to perform
low-level tasks such as direct disk I/O that cannot be
achieved through the documented Windows API.

Ordinary Windows applications are not linked
directly against a Native API library, but to one
or more of the WinAPI libraries with welldocumented APIs
 This
is to retain portability across Windows Platforms
among other reasons.
11
User-mode Rootkits – Utilizing
Windows APIs


A user-mode rootkit might intercept all calls to
the Windows FindFirstFile/FindNextFile
APIs, which are used by file system
exploration utilities, including Explorer and the
command prompt, to enumerate the contents
of file system directories.
When an application performs a directory listing
that would otherwise return results that contain
entries identifying the files associated with the
rootkit, the rootkit intercepts and modifies the
output to remove the entries.
12
API Hooking [craigheffner]


In Windows, all applications must communicate
with the kernel through API functions; as such,
these functions are critical to even the simplest
Windows application.
Thus, the ability to intercept, monitor, and
modify a program's API calls, commonly called
API hooking, effectively gives one full control
over that process.
13
Usage of API Hooking [craigheffner]

API Hooking can be useful for a multitude
of reasons, including
 debugging
 reverse
engineering
and
 hacking.
14
Intercept API Calls

While there are several methods which
can be used to
 intercept
 monitor
and
 modify
a program's API calls, one of them is DLL
redirection.
15
DLL Redirection [craigheffner]


Since an executable imports API functions from
DLL files, DLL redirection allows us to tell a
program that the DLLs it needs are located in a
different directory than the originals.
In this way we can create a DLL with the same
name as the original, which exports the same
function names as the original, but each function
may contain whatever code we like.
16
User-mode Rootkits – Utilizing
Windows Native APIs

More sophisticated user-mode rootkits intercept
 file system
 registry
and
 process enumeration functions
of the Native API.

This prevents their detection by scanners that
compare the results of a Windows API
enumeration with that returned by a Native API
enumeration.
17
Registry [Microsoft]

A central hierarchical database used in Microsoft




Windows 9x
Windows CE
Windows NT
and
Windows 2000
used to store information necessary to configure




the system for one or more users
applications
hardware devices.
Registry data is stored in binary files.
18
Information Contained in the
Registry [Microsoft]

The Registry contains information that Windows
continually references during operation, such as
 profiles
for each user
 the applications installed on the computer
 the types of documents that each application can
create
 property sheet settings for folders and application
icons
 what hardware exists on the system
 the ports that are being used.
19
Description of the Registry [Microsoft]

The Registry replaces most of the textbased .ini files used in Windows 3.x
and MS-DOS configuration files, such
as the Autoexec.bat and
Config.sys.

Although the Registry is common to
several Windows operating systems,
there are some differences among them.
20
What Does the Registry Look Like - [Tim Smith] ?

The Registry is stored on your hard disk in
several files but the only way to look at it and
make changes is to use the regedit program.
 To
access this, click on the Start Button and then on
the Run option.
 Type regedit into the box that appears and press
Enter.
 This will launch regedit and you will now have your
first sight of the Registry.
21
Organization of Registry [Tim Smith]


The Registry is organized much like the files on a
disk and will look familiar if you have ever used
the Folders view in Windows Explorer.
In the Registry, however, these folders are called
keys.
 To
open a key, simply click on the small plus (+) symbol
next to it.
 You will then see that each key contains either


more keys - called subkeys
or
values.
22
Key Overview [Tim Smith]
The keys are organized logically but there
are thousands of them, which can be
daunting the first time you sneak a peek at
the Registry.
 To simplify things, be aware that there are
five root keys and these are the basic
building blocks of the Registry.

23
Predefined Keys [Microsoft]

What follows is the predefined keys that are
used by the system.
 HKEY_CURRENT_USER
(abbr. HKCU)
 HKEY_USERS
(abbr. HKU)
 HKEY_LOCAL_MACHINE (abbr. HKLM)
 HKEY_CLASSES_ROOT
(abbr. HKCR)
 HKEY_CURRENT_CONFIG (abbr. HKCC)

The maximum size of a key name is 255
characters.
24
Key Value [wikipedia]



Each of the predefined keys is divided into
subkeys, which may contain further subkeys,
and so on.
Any key may contain values.
These values can be:
 String
Value
 Binary Value (0 and 1's)
 DWORD Value, a 32 bit unsigned integer (numbers
between 0 and 4,294,967,295 [232 – 1])
 Multi-String value
 Expandable String Value
25
Key Hierarchy [wikipedia]


Each key has a default value, which is in effect a
value with the same name as the key.
Registry keys and values are specified with a
syntax similar to Windows' filenames, using
backslashes to indicate levels of hierarchy.
 e.g.
HKEY_LOCAL_MACHINE\Software\Microsoft\Wi
ndows refers to the subkey "Windows" of the subkey
"Microsoft" of the subkey "Software" of the
HKEY_LOCAL_MACHINE key.
26
Example (1)
Each value has a name and a datum.
HKCU has subkeys and values. By pressing the
+ before the HKCU you can see its subkeys.
27
Example (2)
28
Key Specifying Applications to Run
When a User Logs in [wikipedia]


HKLM\Software\Microsoft\Windows\Curren
tVersion\Run (and the HKCU equivalent)
specifies applications to run whenever a user logs
in.
These can include desirable programs, such as
 printer
monitoring programs
or
 frequently-used tools.


But a lot of malware uses this registry key to
ensure it is automatically run.
This key is a good place to start looking for
evidence of malware if you think your computer
has been infected.
29
Example
30
Spyware and Registry [Tim Smith]

Spyware often installs values in the Registry to make
sure that it's launched to monitor your computer when
Windows starts up.



When looking for advice on how to remove these programs you
may be told to edit the Registry.
Always make sure that the advice is coming from a trustworthy
source such as Registry Guide for Windows or Systweak.com.
Sometimes the spyware also installs a small program to


monitor the Registry
and
replace keys that you delete,
so you should use software such as Spybot Search and
Destroy to clean your computer entirely.
31
Kernel-mode Rootkits
32
Why Kernel-mode Rootkits Are
More Powerful?

Kernel-mode rootkits can be even more
powerful since,
only can they intercept the Native API
in kernel-mode,
 but they can also directly manipulate kernelmode data structures.
 not
33
Example of Kernel-mode Rootkits


A common technique for hiding the presence of
a malware process is to remove the process
from the kernel's list of active processes.
Since process management APIs rely on the
contents of the list, the malware process will not
display in process management tools like
 Task
Manager
or
 Process Explorer.
34
Rootkit Techniques by [Ivo Ivanov]
35
Techniques Involved
Step 1: Injecting techniques
 Step 2: Interception Mechanisms

36
Injecting Techniques [Ivo Ivanov]
37
Injecting Techniques
Method 1: Registry
 Method 2: Global Windows Hooks
 Other Methods (omitted in this lecture)

DLL by using
CreateRemoteThread() API function
 Injecting
 Implanting
through BHO add-ins
 MS Office add-ins
38
Injecting Techniques - by Registry
39
Inject a DLL into Processes

In order to inject a DLL into processes that link with
USER32.DLL, you simply can add the DLL name to the
value of the following registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

Its value contains
a single DLL name
or
 group of DLLs separated either by comma or spaces.
 According to MSDN documentation, all DLLs specified by

the value of that key are loaded by each Windows-based
application running within the current logon session.
40
Invoke Registry Editor
41
Select the Appropriate Key
42
Edit the Selected Key
43
Load USER32-Related DLLs



It is interesting that the actual loading of these
DLLs occurs as a part of USER32's initialization.
USER32 reads the value of mentioned registry
key and calls LoadLibrary() for these DLLs
in its DllMain code.
Restrictions:
 However
this trick applies only to applications that
use USER32.DLL.
 Another restriction is that this built-in mechanism is
supported only by NT and 2K operating systems.
44
Shortcomings (1)


In order to activate/deactivate the injection process you
have to reboot Windows.
The DLL you want to inject will be mapped only into
these processes that use USER32.DLL, thus you cannot
expect to get your hook injected into console
applications, since they usually don't import functions
from USER32.DLL.
45
Shortcomings (2)



On the other hand you don't have any control over the
injection process.
It means that it is implanted into every single GUI
application, regardless you want it or not.
It is a redundant overhead especially if you intend to
hook few applications only.
46
Injecting Techniques
– by Hooks [Chris Cummings ] [MSDN]
47
What Are Hooks?

Put shortly, a hook is a function you can
create as part of
a
dll
or
 your application
to monitor the 'goings on' inside the
windows operating system.
48
Objectives of Hooks (1)

The idea is to write a function that is called
every time a certain event in windows occurs –
 for




example
when a user presses a key on the keyboard
or
moves the mouse.
Hooks were provided by Microsoft primarily to
help program writers with the debugging of their
applications.
But they can be put to use in many different
ways – for example,
 write
hidden key logging program to find out other
users’ passwords to the internet!
49
Objectives of Hooks (2)
The system supports many different types
of hooks.
 Each hook type provides access to a
different aspect of its message-handling
mechanism.

 For
example, an application can use the
WH_MOUSE Hook to monitor the message
traffic for mouse messages.
50
Categories of Hooks

There are 2 categories of hooks
 global
or
 local.
51
Global Hook

A global hook
 monitors
the entire system (all threads)
or
 monitors messages for all threads in the same
desktop as the calling thread.

A global hook procedure can be called in the
context of any application in the same desktop
as the calling thread, so the procedure must be
in a separate DLL module.
52
Local Hook (Thread-specific Hook )

A local hook (thread-specific hook) is one that
 monitors
things happening only for a specific program
(or thread)
or
 monitors messages for only an individual thread.

A thread-specific hook procedure is called only
in the context of the associated thread.
53
Hook Setup (1)


Both types of hooks are set up in the same way.
The main difference being that
 for
a local hook, the function to be called can be
within the program it is monitoring.
but
 with a global hook the function must be stored and
loaded from a separate dll.
54
Hook Setup (2)

If an application installs a hook procedure for
one of its own threads, the hook procedure can
be in either
 the
same module as the rest of the application's code
or
 in a DLL.

If the application installs a hook procedure for a
thread of a different application, the procedure
must be in a DLL.
55
Hook Chain [MSDN]



The system maintains a separate hook chain for
each type of hook.
A hook chain is a list of pointers to special,
application-defined callback functions called
hook procedures.
When a message occurs that is associated with
a particular type of hook, the system passes the
message to each hook procedure referenced in
the hook chain, one after the other.
56
Action Taken by a Hook Procedure

The action a hook procedure can take
depends on the type of hook involved.
 The
hook procedures for some types of hooks
can only monitor messages.
 Others can modify messages.
 The others can stop their progress through
the chain, preventing them from reaching the
next hook procedure or the destination
window.
57
Hook Procedures (Hook Functions)
[MSDN] (1)

To take advantage of a particular type of hook,
the developer provides a hook procedure
and uses the SetWindowsHookEx function
to install it into the chain associated with the
hook.
58
Hook Procedures (Hook Functions)
[MSDN] (2)
A hook procedure is the procedure to be
called by windows when the event we
specify happens.
 A hook for any event always takes the
same form, but the values passed to it by
windows can mean different things.

 For
example if the hook is type
WH_KEYBOARD, windows will pass
information to it relating to which key was
pressed.
59
Hook Procedure Syntax

A hook procedure must have the following
syntax:
LRESULT CALLBACK HookProc(
int nCode,
WPARAM wParam,
LPARAM lParam
);

HookProc is a placeholder for an
application-defined name.
60
Arguments of a Hook Procedure

Your hook procedure should accept the following
arguments:
nCode

The nCode parameter is a hook code that the hook
procedure uses to determine the action to perform.


The value of the hook code depends on the type of the hook; each
type has its own characteristic set of hook codes.
The values of the wParam and lParam parameters depend
on the hook code, but they typically contain information
about a message that was sent or posted.
61
The Return Value of a Hook
Procedure

A hook procedure returns a value of type
longword. What you should set it to depends
on
 the
type of hook
or
 you can just set it to the value that
CallNextHookEx returns.
62
Hook Function Example
LRESULT CALLBACK MouseProc(int node, WPARAM wParam, LPARAM lParam)
{
if (code<0)
{
return CallNextHookEx(HookHandle,code,wParam,lParam);
}
//Define a rectangle
POINT MousePos;
RECT UpperRightCorner=Rect(Screen->Width-2,0,Screen->Width,2);
//Get the mouse position
GetCursorPos(&MousePos);
//Check if the mouse is in the rectangle
if((PtInRect(&UpperRightCorner,MousePos))&&(IsInRect==false))
{
//if the mouse is in the rectangle, launch the screensaver
IsInRect=true;
SendMessage(GetDesktopWindow(),WM_SYSCOMMAND,SC_SCREENSAVE,0);
}
else IsInRect=false;
//Call the next hook in the chain
return CallNextHookEx(HookHandle,code,wParam,lParam);
}
63
Hook-related Functions
64
Installing Hook Procedures

You can install a hook procedure by calling
the SetWindowsHookEx function and
specifying
 the
type of hook calling the procedure
 whether the procedure should be associated
with all threads in the same desktop as the
calling thread or with a particular thread
and
 a pointer to the procedure entry point.
65
Installing a Global Hook (1)





You must place a global hook procedure in a DLL
separate from the application installing the hook
procedure.
The installing application must have the handle to the
DLL module before it can install the hook procedure.
To retrieve a handle to the DLL module, call the
LoadLibrary function with the name of the DLL.
After you have obtained the handle, you can call the
GetProcAddress function to retrieve a pointer to the
hook procedure.
Finally, use SetWindowsHookEx to install the hook
procedure address in the appropriate hook chain.
66
Installing a Global Hook (2)

SetWindowsHookEx passes
 the
module handle
 a pointer to the hook-procedure entry point
and
 0 for the thread identifier, indicating that the
hook procedure should be associated with all
threads in the same desktop as the calling
thread.
67
The SetWindowsHookEx Function

SetWindowsHookEx is the function provided by Microsoft to
install a hook. It accepts the following arguments:

SetWindowsHookEx returns a handle (i.e. an identifier) for
the current hook, so you can use UnhookWindowsHookEx to
remove the hook later on.
The SetWindowsHookEx function always installs a hook
procedure at the beginning of a hook chain.

68
SetWindowsHookEx Example [Michel
Leunen]
// Hood Function (Callback Procedure) Declaration
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam);
// Global variables
HHOOK HookHandle;
HINSTANCE DllInstance;
bool IsInRect=false;
bool InstallMouseHook()
{
HookHandle=SetWindowsHookEx(WH_MOUSE,
reinterpret_cast<HOOKPROC>(MouseProc),DllInstance,0);
if (HookHandle==NULL)
return false;
else
return true;
}
//-------------------------------------------------------------------bool RemoveMouseHook()
{ if(UnhookWindowsHookEx(HookHandle)==0)
return false;
else
return true;
}
69
Types of Hooks used in the idHook
Parameter of SetWindowsHookEx

Types of Hooks appearing in a hook
function.
70
The CallNextHookEx Function


This function is to do with hook chains.
When a hook is installed for a certain event,
there may be others like it already installed.
 For
example 2 programs at once might be trying to
log keyboard input.


When you install a hook with
SetWindowsHookEx it adds your hook
procedure to the front of a list of hook
procedures (hook chain).
CallNextHookEx simply calls the next
procedure in the list.
71
Execution of a Hook Procedure


When an event occurs that is monitored by a particular
type of hook, the system calls the procedure at the
beginning of the hook chain associated with the hook.
Each hook procedure in the chain determines whether to
pass the event to the next procedure.


A hook procedure passes an event to the next procedure by
calling the CallNextHookEx function.
Note that the hook procedures for some types of hooks
can only monitor messages. The system passes
messages to each hook procedure, regardless of
whether a particular procedure calls CallNextHookEx.
72
Parameters of the CallNextHookEx
Function

CallNextHookEx takes exactly the same
form as a hook procedure plus one extra –
handle returned by SetWindowsHookEx
identifying the hook.
 the
The other values you pass to it should be
the values your hook procedure was called
with.
 How you should use CallNextHookEx
depends on the type of hook.

73
The Return Value of a Hook
Procedure

When your hook procedure is finished, it
can run CallNextHookEx, and then
return
 the
value it gets from it
or
 a different one depending on the type of hook.
74
The UnhookWindowsHookEx
Function
This function simply removes your hook.
 The only argument you pass to it is the
hook handle returned by
SetWindowsHookEx.

75
Global Windows Hooks
76
Global Hooks
The global hook is slightly more
complicated than a local hook.
 To create a global hook you need 2 steps,

 to
make the executable file that executes
SetWindowsHookEx()
and
 to make a Dll to contain the hook
procedure.
77
System-wide Hooks

A system-wide hook is registered just once
when SetWindowsHookEx() is executed.

If no error occurs a handle to the hook is
returned.
 The
returned value is required at the end of
the custom hook function when a call to
CallNextHookEx() has to be made.
78
Result of a Successful Call to
SetWindowsHookEx()

After a successful call to
SetWindowsHookEx(), the operating
system injects the DLL automatically (but
not necessary immediately) into all
processes that meet the requirements for
this particular hook.
Processes that will encounter the same event as the one indicated in the hook
function.
79
Global Variables vs. Shared Data



Once an application installs a system-wide hook, the operating system maps the
DLL into the address space in each of its client processes.
Therefore global variables within the DLL will be per-process and cannot be
shared among the processes that have loaded the hook DLL.
All variables that contain shared data must be placed in a shared data section.
80
A Global Hook Is Loaded by Multiple Processes
That Don't Share the Same Address Space


For instance hook handle sg_hGetMsgHook, that is obtained
by SetWindowsHookEx() and is used as parameter in
CallNextHookEx() must be used virtually in all address
spaces.
It means that its value must be shared among hooked
processes as well as the hook Server application. In order to
make this variable "visible" to all processes we should store it in
the shared data section.
81
Define Variables Shared by All
Processes
82
Example

Installing a mouse hook.
83
Interception Mechanisms [Ivo Ivanov]
84
Interception Mechanisms
Injecting a DLL into the address space
of an external process is a key element
of a spying system.
 It provides an excellent opportunity to
have a control over process's thread
activities.
 However it is not sufficient to have the
DLL injected if you want to intercept API
function calls within the process.

85
Interception through Special Kinds
of Hooking

In terms of the level where the hook is
applied, there are two mechanisms for
API spying –
 Kernel

through NT Kernel Level Hooking
 User

level spying
level spying
Win32 User Level Hooking
86
The Module Relationships and Their Dependencies on
Windows 2K and Interception Points
87
NT Kernel Level Hooking
88
NT Kernel Level Hooking

There are several methods for achieving hooking
of NT system services in kernel mode.
 The
most popular interception mechanism was
originally demonstrated by Mark Russinovich and Bryce
Cogswell in their article "Windows NT System-Call
Hooking".



Their basic idea is to inject an interception mechanism for
monitoring NT system calls just bellow the user mode.
This technique is very powerful and provides an extremely
flexible method for hooking the point that all user-mode
threads pass through before they are serviced by the OS kernel.
However, all these hooking strategies remain out
of the scope of this course.
89
Win32 User Level Hooking
90
Win32 User Level Hooking

Proxy DLL (Trojan DLL)
Spying by altering of the Import Address
Table
 Other Approaches (not covered in this
lecture)

 Code
overwriting
 Spying by a debugger
 Windows sub-classing
91
Function Forwarder -- Mechanism Used by
Proxy DLL[Jeffrey Richter]
92
Define a Function Forwarder
Defined in a stub DLL (A stub DLL refers to an
entire DLL of unimplemented functions.)
// Function forwarders to functions in DllWork
#pragma comment(linker, "/ export:SomeFunc=DllWork.SomeFunc")


This pragma tells the linker that the stub DLL should
export a function called SomeFunc, but that the actual
implementation for the function is in a function
SomeFunc contained in the DllWork.dll.
You'll have to have one pragma line for each function
exported by your DllWork.dll for a program to call
your functions correctly.
93
Stub DLL and the Real DLL
stub DLL
The DLL
used by an
application
#pragma comment(linker, "/export:SomeFunc=DllWork.SomeFunc")
BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID p)
{
:
ShutdownLibrary();
:
return(TRUE);
}
The real
DLL
__declspec(dllexport) void ShutdownLibrary();
__declspec(dllexport) void SomeFunc();
void SomeFunc()
{ MessageBox(NULL, "Doing something", "SomeFunc in DllWork", MB_OK); }
LoadLibrary
loads the stub
DLL, then the
OS loader
automatically
loads your real
DLL.
void ShutdownLibrary()
{ // Notify the worker threads to shutdown
SetEvent(g_hEventTerminate); }
BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID fImpLoad)
{ int nThread;
:
}
94
_declspec



[wikipedia]
the _declspec keyword is a strange new
keyword that is not part of the ANSI C
standard, but that most compilers will
understand anyway.
_declspec allows a variety of non-standard
options to be specified, that will affect the way
a program runs.
Specifically, there are two _declspec
identifiers that we want to discuss:
 _declspec(dllexport)
 _declspec(dllimport)
95
Dllexport
[wikipedia]
When writing a DLL, we need to use the
dllexport keyword to denote functions
that are going to be available to other
programs.
 Functions without this keyword will only be
available for use from inside the library
itself.

96
DllMain
[wikipedia]
When Windows links a DLL to a program,
Windows calls the libraries' DllMain
function.
 This means that EVERY DLL needs to
have a DllMain function.

97
Function Forwarder Example
98
Function Forwarder Again [Ivo Ivanov]
 A function
forwarder is an entry in
a DLL's export table that redirects
a function call to another function in
another DLL.

You can accomplish this task by simply
using
#pragma comment
#pragma comment(linker, "/export:DoSomething=DllImpl.ActuallyDoSomething")
99
Function Forwarder Example

For example, if you run the Visual C++® DumpBin utility on the
Windows NT Kernel32.dll, you'll see a part of the output
that looks like this:
C:\winnt\system32>DumpBin -Exports Kernel32.dll
(some output omitted)
360 167 HeapAlloc (forwarded to NTDLL.RtlAllocateHeap)
361 168 HeapCompact (000128D9)
362 169 HeapCreate (000126EF)
363 16A HeapCreateTagsW (0001279E)
364 16B HeapDestroy (00012750)
365 16C HeapExtend (00012773)
366 16D HeapFree (forwarded to NTDLL.RtlFreeHeap)
367 16E HeapLock (000128ED)
368 16F HeapQueryTagW (000127B8)
369 170 HeapReAlloc (forwarded to NTDLL.RtlReAllocateHeap)
370 171 HeapSize (forwarded to NTDLL.RtlSizeHeap)
(remainder of output omitted)
100
How a Function Forwarder Forwards the
Execution of a Function to Another Function




This output of the previous slide shows four forwarded
functions.
Whenever your application calls HeapAlloc, HeapFree,
HeapReAlloc, or HeapSize, your executable is
dynamically linked with Kernel32.dll.
When you invoke your executable, the loader loads
Kernel32.dll and sees that there are forwarded
functions that are actually contained inside NTDLL.dll, so
the loader also loads the NTDLL.dll module.
When your executable calls HeapAlloc, it is actually calling
the RtlAllocateHeap function inside NTDLL.dll.

The HeapAlloc function does not actually exist anywhere in the
system!
101
Rootkits Utilizing Function Forwarders - Proxy DLL (Trojan DLL) Rootkits

An easy way for hacking API is just to
replace a DLL with one that has the same
name and exports all the symbols of the
original one.
 This
technique can be effortlessly implemented
using function forwarders.
 However, if you decide to employ the above
method, you should take the responsibility of
providing compatibilities with newer versions of
the original library.
102
Portable Executable (PE)
File Format [Ashkbiz Danehkar ]
103
Portable Executable (PE) File
Format

The Portable Executable file format was defined to
provide the best way for the Windows Operating System


to execute code
to store the essential data which is needed to run a program

for example:





constant data
variable data
import library links
resource data
It consists of




MS-DOS file information,
Windows NT file information,
Section Headers,
and
Section images.
104
Portable Executable File Format
Structure (1)
105
Portable Executable File Format
Structure Types
MS-DOS Information
IMAGE_DOS_HEADER
MS-DOS Stub Program
Windows NT Information
(IMAGE_NT_HEADERS)
Signature
IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER32
IMAGE_DATA_DIRECTORY[16]
IMAGE_SECTION_HEADER[0]
:
Sections Information
IMAGE_SECTION_HEADER[n]
SECTION[0]
:
SECTION[n]
106
Using Ordinal Numbers to Identify
DLL Procedures
In addition to a name, all DLL procedures
can be identified by an ordinal number
that specifies the procedure in the DLL.
 Some DLLs do not include the names of
their procedures and require you to use
ordinal numbers when declaring the
procedures they contain.

107
MS-DOS Information
offset
value
e_lfanew is the offset
which refers to the
position of the Windows
NT data.
108
Structure IMAGE_NT_HEADERS
typedef struct _IMAGE_NT_HEADERS
{
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;[1]
109
Access the MS-DOS header and
the Windows NT Header

If you assume that the pMem pointer relates the start point of the
memory space for a selected portable executable file, you can
retrieve the MS-DOS header and also the Windows NT header by
the following lines,
IMAGE_DOS_HEADER
image_dos_header;
IMAGE_NT_HEADERS
image_nt_headers;
PCHAR pMem;
...
memcpy(&image_dos_header, pMem, sizeof(IMAGE_DOS_HEADER));
memcpy(&image_nt_headers, pMem+image_dos_header.e_lfanew,
sizeof(IMAGE_NT_HEADERS));
110
Signature and IMAGE_FILE_HEADER of
Windows NT Information
111
Structure
IMAGE_OPTIONAL_HEADER
typedef struct _IMAGE_OPTIONAL_HEADER
{
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD AddressOfEntryPoint;
:
A pointer to the first IMAGE_DATA_DIRECTORY
DWORD ImageBase;
structure in the data directory.
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
112
AddressOfEntryPoint and
ImageBase

AddressOfEntryPoint
A pointer to the entry point function,
relative to the image base address.

ImageBase
 The
preferred address of the first byte of the
image when it is loaded in memory.
 This value is a multiple of 64K bytes.
The default value for DLLs is 0x10000000.
 The default value for applications is 0x00400000.

113
Remarks
The actual structure in Winnt.h is named
IMAGE_OPTIONAL_HEADER32.
 IMAGE_OPTIONAL_HEADER is defined as
IMAGE_OPTIONAL_HEADER32.
 However, if _WIN64 is defined, then
IMAGE_OPTIONAL_HEADER is defined as
IMAGE_OPTIONAL_HEADER64.

114
IMAGE_OPTIONAL_HEADER32 of Windows
NT Information
115
IMAGE_DATA_DIRECTORY


Represents the data directory.
typedef struct _IMAGE_DATA_DIRECTORY
{
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY,
*PIMAGE_DATA_DIRECTORY;
Members

VirtualAddress


The relative virtual address of the table.
Size

The size of the table, in bytes.
points to a
IMAGE_IMPORT_DESCRIPTOR
structure
116
A List of the Data Directories [MSDN]

Offsets are relative to the beginning of the optional header.
117
List of the Data Directories
118
IMAGE_DATA_DIRECTORY of Windows NT
Information
points to a IMAGE_IMPORT_DESCRIPTOR structure.
Each DLL file has a corresponding IMAGE_IMPORT_DESCRIPTOR structure.
type
119
Example [stinson]

If we have a PE that imports two modules, we'll have:




one IMAGE_DATA_DIRECTORY structure for the Import Symbols
(i.e. the Import Table)
let's say that struct's VirtualAddress is 0xc7d8 -- recall this is
an RVA.
then 0xc7d8 is where the first IMAGE_IMPORT_DESCRIPTOR
lives
since we are importing two modules, there will be 3
IMAGE_IMPORT_DESCRIPTOR structs in our array (which starts
at 0xc7d8, recall)


--> the 3rd IMAGE_IMPORT_DESCRIPTOR is all zeroes
then the Size field above (for this IMAGE_DATA_DIRECTORY)
will be 3 * sizeof( IMAGE_IMPORT_DESCRIPTOR )
120
IMAGE_DATA_DIRECTORY and
IMAGE_IMPORT_DESCRIPTOR
import table
IMAGE_IMPORT_DESCRIPTOR
:
IMAGE_IMPORT_DESCRIPTOR
121
IMAGE_SECTION_HEADER
122
IMAGE_SECTION_HEADER

Represents the image section header format.
typedef struct _IMAGE_SECTION_HEADER
{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union
{
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
The address of the first
DWORD VirtualAddress;
byte of the section when
DWORD SizeOfRawData;
loaded into memory,
DWORD PointerToRawData;
relative to the image base.
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER,
*PIMAGE_SECTION_HEADER;
123
Section Names
124
IMAGE_SECTION_HEADER Array of
Section Information
125
SECTION Array of Section
Information
126
Import Address Table


Within a PE file, there's an array of data structures, one
per imported DLL.
Each of these structures gives




the name of the imported DLL
points to an array of function pointers
The array of function pointers is known as the import
address table (IAT).
Each imported API has its own reserved spot in the IAT
where the address of the imported function is written by
the Windows loader.

Once a module is loaded, the IAT contains the address that is
invoked when calling imported APIs.
127
Imported API Calls and the IAT



The beauty of the IAT is that there's just one place in
a PE file where an imported API's address is stored.
No matter how many source files you scatter calls to
a given API through, all the calls go through the
same function pointer in the IAT.
Let's examine what the call to an imported API looks
like.
CALL 0x0040100C
•••
CALL 0x0040100C
•••
0x0040100C:
JMP DWORD PTR [0x00405030]

stub code
Here, 0x405030 is an entry within the IAT.
128
Stub Code
The CALL in previous slide transfers
control to a small stub.
 The stub is a JMP to the address whose
value is at 0x405030.

129
The Imports Section [Matt Pietrek][Iczelion]
130
Section .idata
Section .idata contains information
about Import Address Table.
 This part of the PE structure is particularly
very crucial for building a spy program
based on altering IAT.

131
Location of Section .idata in a
PE File
132
IMAGE_IMPORT_DESCRIPTOR
Structure
The anchor of the imports data is the
IMAGE_IMPORT_DESCRIPTOR structure.
 There's one
IMAGE_IMPORT_DESCRIPTOR for each
imported executable (e.g. DLL file).
 The end of the
IMAGE_IMPORT_DESCRIPTOR array is
indicated by an entry with fields all set to 0.

133
Structure
IMAGE_IMPORT_DESCRIPTOR
typedef struct
_IMAGE_IMPORT_DESCRIPTOR
{
DWORD
OriginalFirstThunk;
DWORD
TimeDateStamp;
DWORD
ForwarderChain;
DWORD
Name;
DWORD
FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR,
*PIMAGE_IMPORT_DESCRIPTOR;
134
Members of Structure
IMAGE_IMPORT_DESCRIPTOR
135
An Executable Importing Some
APIs from USER32.DLL
IMAGE_THUNK_DATA


An IMAGE_IMPORT_DESCRIPTOR element has elements with a RVA value
to a type IMAGE_THUNK_DATA, which is a pointer-sized union.
Each IMAGE_THUNK_DATA element corresponds to one imported function
from the executable. The ends of IMAGE_THUNK_DATA arrays are
indicated by an IMAGE_THUNK_DATA element with a value of zero.
136
Structure IMAGE_THUNK_DATA
typedef struct _IMAGE_IMPORT_BY_NAME
{
WORD
Hint;
BYTE
Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
typedef struct _IMAGE_THUNK_DATA
{
union {
PDWORD
Function;
PIMAGE_IMPORT_BY_NAME AddressOfData;
} u1;
} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;
137
Interpretation of Fields of Structure
IMAGE_THUNK_DATA

The IMAGE_THUNK_DATA union is a
DWORD with these interpretations:
DWORD Function;
DWORD Ordinal;
// Memory address of the imported function
// Ordinal value of imported API
DWORD AddressOfData;
// RVA to an IMAGE_IMPORT_BY_NAME with
// the imported API name
DWORD ForwarderString; // RVA to a forwarder string
138
IMAGE_THUNK_DATA Structures of
the IAT

The IMAGE_THUNK_DATA structures within the
IAT lead a dual-purpose life.
 In


the executable file, they contain:
either the ordinal of the imported API
or an RVA to an IMAGE_IMPORT_BY_NAME structure.


The IMAGE_IMPORT_BY_NAME structure is just a WORD, followed
by a string naming the imported API.
The WORD value is a hint to the loader as to what the ordinal of
the imported API might be.
 When
the loader brings in the executable, it overwrites
each IAT entry with the actual address of the imported
function.
139
Binding



When an executable is bound (via the bind
program, for instance), the IMAGE_THUNK_DATA
structures in the IAT are overwritten with the actual
address of the imported function.
The executable file on disk has the actual inmemory addresses of APIs in other DLLs in its IAT.
When loading a bound executable, the Windows
loader can bypass the step of looking up each
imported API and writing it to the IAT. The correct
address is already there.
140
Spying by Altering of the Import
Address Table

Here are the logical steps of a replacing cycle:

Find the IMAGE_IMPORT_DESCRIPTOR chunk of the DLL that
exports that function.




Practically speaking, usually we search this entry by the name of
the DLL
Locate the IMAGE_THUNK_DATA which holds the original
address of the imported function
Replace the function address with the one supplied by users
By changing the address of the imported function inside
the IAT, we ensure that all calls to the hooked function
will be re-routed to the function interceptor.
141
Case Study 1
142
A Simple Rootkit

A simple script put in Perl’s string context, compiled and
named netstat.exe may be an example of a trivial rootkit.

A real system netstat could be named oldnetstat.exe. The
principle of operation of the new netstat is that





once the command line calls the real netstat (now oldnetstat.exe),
its results will be directed to a temporary text file.
Then the rootkit searches that file for any information about the listening
port to remove it (according to the procedure predefined in the rootkit
code).
After modification, the result is displayed on the screen and the old file is
removed.
This principle is both simple and efficient and provides an interesting
possibility – it may be used to spoof output data acting from any other tool
available through the command line – for example, tlist, or dir.
There are many programs of this type available on the Web.

Some of them did not display, for example, information on listening
ports such as 666, 27374, 12345, 31337 – i.e. well-known Trojan
horse ports.
143
Case Study 2
144
A Windows Rootkit Example -Rootki
The idea of a first enhanced rootkit,
Rootki, for the Windows environment
was born in due time.
 The originator was Greg Hoglund.

145
Rootki 0.40 – Existing Form and
Activating Methods



This rootkit has been designed as a kernel
mode driver that runs with system privileges
right at the core of the system kernel.
Given this fact, it has access to all resources of
the operating system, thus having a broad field
of action.
In order to install it one requires the
administrator’s permissions whilst simple net
start/net stop commands are sufficient to
activate/disactivate it respectively.
146
Rootki 0.40 – Hiding Approach

Once the rootkit has been loaded, the hacker can
hide directories and files on the victim’s disk.
 This
method is efficient provided that the object to be
hidden has a name prefixed with _root_ – for example,
_root_directory_name.
 How does this work?

The rootkit, by patching the kernel,



intercepts all system calls for the listing of the disk content
and
all objects beginning with the sequence _root_ – are hidden from
display.
The same applies to the searching process – all files and
directories with the above sequence of characters are hidden
from the search.
147
Rootki 0.40 – Hiding
Processes

This rootkit feature can also be used
 to
hide processes running
as well as
 to do the same with the system registry entries,
by prefixing all keys and entries with _root_ .

This enables the hacker to install, for example,
services which will become a backdoor, thus
being as invisible for the system administrator
as
 services
or
 registry entries or
 processes running in the system memory.
148
Rootki 0.40 – Key Logger


The rootkit can also intercept all key strokes typed at
the system console.
This may be carried out by hooking into the keyboard
driver and issuing the ‘sniffkeys’ command.
149
Case Study 3
150
A Famous Rootkit Case


The word "rootkit" came to public awareness in
the 2005 Sony CD copy protection scandal, in
which Sony BMG music CDs surreptitiously
placed a rootkit on Microsoft Windows PCs
when the CD was played on the computer.
Sony provided no mention of this in the CD or
its packaging, referring only to security rights
management measures.
151
Protect Systems against Rootkits
152
Guarding against the Rootkit –
Checking from Other Hosts


“vulnerability” of a rootkit: objects are only hidden from
the environment of the compromised machine and they
can easily be seen from another computer.
Mapping a Network Drive remotely from another
machine (or using net use command) is a means to
see everything, which has been hidden for a local user.

This is because the remote machine is using a clean kernel to
view the files and directories on the compromised machine,
avoiding the rootkits filtration process.
153
Guarding against the Rootkit –
Renaming Check Utilities


A rootkit, however, cannot affect processes that have _root_ in their names.
In other words, when a system administrator, is analyzing the system log
using regedit.exe, he cannot see hidden entries, but just by changing its
name to _root_regedit.exe, it will be enough for him to see all of them
as well as hidden keys and registry entries. This is true for all programs – for
example, Task Manager.
154
Appendix (could be omitted)
155
List the Names of ALL Import
Functions of a PE File (1) [Iczelion]






Verify that the file is a valid PE
From the DOS header, go to the PE header
Obtain the address of the data directory in
OptionalHeader
Go to the 2nd member of the data directory. Extract the
value of VirtualAddress
Use that value to go to the first
IMAGE_IMPORT_DESCRIPTOR structure
Check the value of OriginalFirstThunk. If it's not
zero, follow the RVA in OriginalFirstThunk to the
RVA array. If OriginalFirstThunk is zero, use the
value in FirstThunk instead. Some linkers generate
PE files with 0 in OriginalFirstThunk. This is
considered a bug. Just to be on the safe side, we
check the value in OriginalFirstThunk first. 156
List the Names of ALL Import
Functions of a PE File (2) [Iczelion]




For each member in the array, we check the value of the member
against IMAGE_ORDINAL_FLAG32. If the most significant bit of the
member is 1, then the function is exported by ordinal and we can
extract the ordinal number from the low word of the member.
If the most significant bit of the member is 0, use the value in the
member as the RVA into the IMAGE_IMPORT_BY_NAME, skip Hint,
and you're at the name of the function.
Skip to the next array member, and retrieve the names until the end
of the array is reached (it's null -terminated). Now we are done
extracting the names of the functions imported from a DLL. We go to
the next DLL.
Skip to the next IMAGE_IMPORT_DESCRIPTOR and process it. Do
that until the end of the array is reached
(IMAGE_IMPORT_DESCRIPTOR array is terminated by a member
with all zeroes in its fields).
157