Table of Contents for
Practical Malware Analysis

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Practical Malware Analysis by Andrew Honig Published by No Starch Press, 2012
  1. Cover
  2. Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software
  3. Praise for Practical Malware Analysis
  4. Warning
  5. About the Authors
  6. About the Technical Reviewer
  7. About the Contributing Authors
  8. Foreword
  9. Acknowledgments
  10. Individual Thanks
  11. Introduction
  12. What Is Malware Analysis?
  13. Prerequisites
  14. Practical, Hands-On Learning
  15. What’s in the Book?
  16. 0. Malware Analysis Primer
  17. The Goals of Malware Analysis
  18. Malware Analysis Techniques
  19. Types of Malware
  20. General Rules for Malware Analysis
  21. I. Basic Analysis
  22. 1. Basic Static Techniques
  23. Antivirus Scanning: A Useful First Step
  24. Hashing: A Fingerprint for Malware
  25. Finding Strings
  26. Packed and Obfuscated Malware
  27. Portable Executable File Format
  28. Linked Libraries and Functions
  29. Static Analysis in Practice
  30. The PE File Headers and Sections
  31. Conclusion
  32. Labs
  33. 2. Malware Analysis in Virtual Machines
  34. The Structure of a Virtual Machine
  35. Creating Your Malware Analysis Machine
  36. Using Your Malware Analysis Machine
  37. The Risks of Using VMware for Malware Analysis
  38. Record/Replay: Running Your Computer in Reverse
  39. Conclusion
  40. 3. Basic Dynamic Analysis
  41. Sandboxes: The Quick-and-Dirty Approach
  42. Running Malware
  43. Monitoring with Process Monitor
  44. Viewing Processes with Process Explorer
  45. Comparing Registry Snapshots with Regshot
  46. Faking a Network
  47. Packet Sniffing with Wireshark
  48. Using INetSim
  49. Basic Dynamic Tools in Practice
  50. Conclusion
  51. Labs
  52. II. Advanced Static Analysis
  53. 4. A Crash Course in x86 Disassembly
  54. Levels of Abstraction
  55. Reverse-Engineering
  56. The x86 Architecture
  57. Conclusion
  58. 5. IDA Pro
  59. Loading an Executable
  60. The IDA Pro Interface
  61. Using Cross-References
  62. Analyzing Functions
  63. Using Graphing Options
  64. Enhancing Disassembly
  65. Extending IDA with Plug-ins
  66. Conclusion
  67. Labs
  68. 6. Recognizing C Code Constructs in Assembly
  69. Global vs. Local Variables
  70. Disassembling Arithmetic Operations
  71. Recognizing if Statements
  72. Recognizing Loops
  73. Understanding Function Call Conventions
  74. Analyzing switch Statements
  75. Disassembling Arrays
  76. Identifying Structs
  77. Analyzing Linked List Traversal
  78. Conclusion
  79. Labs
  80. 7. Analyzing Malicious Windows Programs
  81. The Windows API
  82. The Windows Registry
  83. Networking APIs
  84. Following Running Malware
  85. Kernel vs. User Mode
  86. The Native API
  87. Conclusion
  88. Labs
  89. III. Advanced Dynamic Analysis
  90. 8. Debugging
  91. Source-Level vs. Assembly-Level Debuggers
  92. Kernel vs. User-Mode Debugging
  93. Using a Debugger
  94. Exceptions
  95. Modifying Execution with a Debugger
  96. Modifying Program Execution in Practice
  97. Conclusion
  98. 9. OllyDbg
  99. Loading Malware
  100. The OllyDbg Interface
  101. Memory Map
  102. Viewing Threads and Stacks
  103. Executing Code
  104. Breakpoints
  105. Loading DLLs
  106. Tracing
  107. Exception Handling
  108. Patching
  109. Analyzing Shellcode
  110. Assistance Features
  111. Plug-ins
  112. Scriptable Debugging
  113. Conclusion
  114. Labs
  115. 10. Kernel Debugging with WinDbg
  116. Drivers and Kernel Code
  117. Setting Up Kernel Debugging
  118. Using WinDbg
  119. Microsoft Symbols
  120. Kernel Debugging in Practice
  121. Rootkits
  122. Loading Drivers
  123. Kernel Issues for Windows Vista, Windows 7, and x64 Versions
  124. Conclusion
  125. Labs
  126. IV. Malware Functionality
  127. 11. Malware Behavior
  128. Downloaders and Launchers
  129. Backdoors
  130. Credential Stealers
  131. Persistence Mechanisms
  132. Privilege Escalation
  133. Covering Its Tracks—User-Mode Rootkits
  134. Conclusion
  135. Labs
  136. 12. Covert Malware Launching
  137. Launchers
  138. Process Injection
  139. Process Replacement
  140. Hook Injection
  141. Detours
  142. APC Injection
  143. Conclusion
  144. Labs
  145. 13. Data Encoding
  146. The Goal of Analyzing Encoding Algorithms
  147. Simple Ciphers
  148. Common Cryptographic Algorithms
  149. Custom Encoding
  150. Decoding
  151. Conclusion
  152. Labs
  153. 14. Malware-Focused Network Signatures
  154. Network Countermeasures
  155. Safely Investigate an Attacker Online
  156. Content-Based Network Countermeasures
  157. Combining Dynamic and Static Analysis Techniques
  158. Understanding the Attacker’s Perspective
  159. Conclusion
  160. Labs
  161. V. Anti-Reverse-Engineering
  162. 15. Anti-Disassembly
  163. Understanding Anti-Disassembly
  164. Defeating Disassembly Algorithms
  165. Anti-Disassembly Techniques
  166. Obscuring Flow Control
  167. Thwarting Stack-Frame Analysis
  168. Conclusion
  169. Labs
  170. 16. Anti-Debugging
  171. Windows Debugger Detection
  172. Identifying Debugger Behavior
  173. Interfering with Debugger Functionality
  174. Debugger Vulnerabilities
  175. Conclusion
  176. Labs
  177. 17. Anti-Virtual Machine Techniques
  178. VMware Artifacts
  179. Vulnerable Instructions
  180. Tweaking Settings
  181. Escaping the Virtual Machine
  182. Conclusion
  183. Labs
  184. 18. Packers and Unpacking
  185. Packer Anatomy
  186. Identifying Packed Programs
  187. Unpacking Options
  188. Automated Unpacking
  189. Manual Unpacking
  190. Tips and Tricks for Common Packers
  191. Analyzing Without Fully Unpacking
  192. Packed DLLs
  193. Conclusion
  194. Labs
  195. VI. Special Topics
  196. 19. Shellcode Analysis
  197. Loading Shellcode for Analysis
  198. Position-Independent Code
  199. Identifying Execution Location
  200. Manual Symbol Resolution
  201. A Full Hello World Example
  202. Shellcode Encodings
  203. NOP Sleds
  204. Finding Shellcode
  205. Conclusion
  206. Labs
  207. 20. C++ Analysis
  208. Object-Oriented Programming
  209. Virtual vs. Nonvirtual Functions
  210. Creating and Destroying Objects
  211. Conclusion
  212. Labs
  213. 21. 64-Bit Malware
  214. Why 64-Bit Malware?
  215. Differences in x64 Architecture
  216. Windows 32-Bit on Windows 64-Bit
  217. 64-Bit Hints at Malware Functionality
  218. Conclusion
  219. Labs
  220. A. Important Windows Functions
  221. B. Tools for Malware Analysis
  222. C. Solutions to Labs
  223. Lab 1-1 Solutions
  224. Lab 1-2 Solutions
  225. Lab 1-3 Solutions
  226. Lab 1-4 Solutions
  227. Lab 3-1 Solutions
  228. Lab 3-2 Solutions
  229. Lab 3-3 Solutions
  230. Lab 3-4 Solutions
  231. Lab 5-1 Solutions
  232. Lab 6-1 Solutions
  233. Lab 6-2 Solutions
  234. Lab 6-3 Solutions
  235. Lab 6-4 Solutions
  236. Lab 7-1 Solutions
  237. Lab 7-2 Solutions
  238. Lab 7-3 Solutions
  239. Lab 9-1 Solutions
  240. Lab 9-2 Solutions
  241. Lab 9-3 Solutions
  242. Lab 10-1 Solutions
  243. Lab 10-2 Solutions
  244. Lab 10-3 Solutions
  245. Lab 11-1 Solutions
  246. Lab 11-2 Solutions
  247. Lab 11-3 Solutions
  248. Lab 12-1 Solutions
  249. Lab 12-2 Solutions
  250. Lab 12-3 Solutions
  251. Lab 12-4 Solutions
  252. Lab 13-1 Solutions
  253. Lab 13-2 Solutions
  254. Lab 13-3 Solutions
  255. Lab 14-1 Solutions
  256. Lab 14-2 Solutions
  257. Lab 14-3 Solutions
  258. Lab 15-1 Solutions
  259. Lab 15-2 Solutions
  260. Lab 15-3 Solutions
  261. Lab 16-1 Solutions
  262. Lab 16-2 Solutions
  263. Lab 16-3 Solutions
  264. Lab 17-1 Solutions
  265. Lab 17-2 Solutions
  266. Lab 17-3 Solutions
  267. Lab 18-1 Solutions
  268. Lab 18-2 Solutions
  269. Lab 18-3 Solutions
  270. Lab 18-4 Solutions
  271. Lab 18-5 Solutions
  272. Lab 19-1 Solutions
  273. Lab 19-2 Solutions
  274. Lab 19-3 Solutions
  275. Lab 20-1 Solutions
  276. Lab 20-2 Solutions
  277. Lab 20-3 Solutions
  278. Lab 21-1 Solutions
  279. Lab 21-2 Solutions
  280. Index
  281. Index
  282. Index
  283. Index
  284. Index
  285. Index
  286. Index
  287. Index
  288. Index
  289. Index
  290. Index
  291. Index
  292. Index
  293. Index
  294. Index
  295. Index
  296. Index
  297. Index
  298. Index
  299. Index
  300. Index
  301. Index
  302. Index
  303. Index
  304. Index
  305. Index
  306. Index
  307. Updates
  308. About the Authors
  309. Copyright

Lab 11-2 Solutions

Short Answers

  1. Lab11-02.dll contains one export, named installer.

  2. If you run the malware from the command line using rundll32.exe Lab11-02.dll,installer, the malware copies itself to the Windows system directory as spoolvxx32.dll and installs itself persistently under AppInit_DLLs. The malware also tries to open Lab11-02.ini from the Windows system directory, but it doesn’t find it there.

  3. Lab11-02.ini must reside in %SystemRoot%\System32\ in order for the malware to run properly.

  4. The malware installs itself in the AppInit_DLLs registry value, which causes the malware to be loaded into every process that also loads User32.dll.

  5. This malware installs an inline hook of the send function.

  6. The hook checks if the outgoing packet is an email message containing RCPT TO:, and if this string is found, it adds an additional RCPT TO line containing a malicious email account.

  7. The malware targets only MSIMN.exe, THEBAT.exe, and OUTLOOK.exe because all are email clients. The malware does not install the hook unless it is running inside one of these processes.

  8. The INI file contains an encrypted email address. After decrypting Lab11-02.ini, we see it contains .

  9. See Capturing the Network Traffic for our method of capturing data using Wireshark, a fake mail server, and Outlook Express.

Detailed Analysis

We begin with basic static analysis of Lab11-02.dll. The DLL has only one export, named installer. The malware contains imports for manipulating the registry (RegSetValueEx), changing the file system (CopyFile), and searching through a process or thread listing (CreateToolhelp32Snapshot). The interesting strings for Lab11-02.dll are shown in Example C-48.

Example C-48. Interesting strings in Lab11-02.dll

RCPT TO: <
THEBAT.EXE
OUTLOOK.EXE
MSIMN.EXE
send
wsock32.dll
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
spoolvxx32.dll
AppInit_DLLs
\Lab11-02.ini

The strings AppInit_DLLs and SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows indicate that the malware might use AppInit_DLLs to install itself for persistence. The string \Lab11-02.ini indicates that the malware uses the INI file provided in this lab.

Examining the contents of Lab11-02.ini, we see that it appears to contain encoded or encrypted data. The send and wsock32.dll strings may indicate that the malware uses networking functionality, but that is unclear until we dig deeper. The process names (OUTLOOK.EXE, MSIMN.EXE, and THEBAT.EXE) are email clients, and combining those strings with RCPT TO: leads us to suspect that this malware does something with email.

Note

RCPT is an SMTP command to establish a recipient for an email message.

Next, we use basic dynamic tools like procmon to monitor the malware. We begin by trying to install the malware using the installer export with the following command:

rundll32.exe Lab11-02.dll,installer

In procmon, we set a filter for the process rundll32.exe, and see the malware create a file named spoolvxx32.dll in the Windows system directory. Upon further inspection, we see that this file is identical to Lab11-02.dll. Further in the procmon listing, we see the malware add spoolvxx32.dll to the list of AppInit_DLLs (causing the malware to be loaded into every process that loads User32.dll). Finally, we see that the malware attempts to open Lab11-02.ini from the Windows system directory. Therefore, we should copy the INI file to the Windows system directory in order for the malware to access it.

We move our analysis to IDA Pro to look more deeply into the malware. We begin by analyzing the installer export. A graph of the cross-references from installer is shown in Figure C-36.

Cross-reference graph of the installer export

Figure C-36. Cross-reference graph of the installer export

As you can see, installer sets a value in the registry and copies a file to the Windows system directory. This matches what we saw during dynamic analysis and is confirmed in the disassembly. The installer function’s only purpose is to copy the malware to spoolvxx32.dll and set it as an AppInit_DLLs value.

In Example C-49, we focus on DllMain, which starts by checking for DLL_PROCESS_ATTACH, as with the previous lab. It appears that this malware runs only during DLL_PROCESS_ATTACH; otherwise, DllMain returns without doing anything else.

Example C-49. Code in DllMain that attempts to open Lab11-02.ini from the system directory

1000161E         cmp     [ebp+fdwReason], DLL_PROCESS_ATTACH
...
10001651         call    _GetWindowsSystemDirectory 
10001656         mov     [ebp+lpFileName], eax
10001659         push    104h                    ; Count
1000165E         push    offset aLab1102_ini     ; \\Lab11-02.ini 
10001663         mov     edx, [ebp+lpFileName]
10001666         push    edx                     ; Dest
10001667         call    strncat 
1000166C         add     esp, 0Ch
1000166F         push    0                       ; hTemplateFile
10001671         push    FILE_ATTRIBUTE_NORMAL   ; dwFlagsAndAttributes
10001676         push    OPEN_EXISTING           ; dwCreationDisposition
10001678         push    0                       ; lpSecurityAttributes
1000167A         push    FILE_SHARE_READ         ; dwShareMode
1000167C         push    GENERIC_READ            ; dwDesiredAccess
10001681         mov     eax, [ebp+lpFileName]
10001684         push    eax                     ; lpFileName
10001685         call    ds:CreateFileA 

In Example C-49 at , we see the Windows system directory retrieved, as well as the string for Lab11-02.ini at . Together, these form a path with the strncat at . The malware attempts to open the INI file for reading at . If the file cannot be opened, DllMain returns.

If the malware successfully opens the INI file, it reads the file into a global buffer, as shown in Example C-50 at .

Example C-50. Reading and decrypting the INI file

100016A6         push    offset byte_100034A0  ; lpBuffer
100016AB         mov     edx, [ebp+hObject]
100016AE         push    edx                     ; hFile
100016AF         call    ds:ReadFile
100016B5         cmp     [ebp+NumberOfBytesRead], 0 
100016B9         jbe     short loc_100016D2
100016BB         mov     eax, [ebp+NumberOfBytesRead]
100016BE         mov     byte_100034A0[eax], 0
100016C5         push    offset byte_100034A0 
100016CA         call    sub_100010B3

After the call to ReadFile, the malware checks to make sure the file size is greater than 0 at . Next, the buffer containing the file contents is passed to sub_100010B3 at . sub_100010B3 looks like it might be a decoding routine because it is the first function called after opening a handle to a suspected encoded file, so we’ll call it maybeDecoder. To test our theory, we load the malware into OllyDbg and set a breakpoint at 0x100016CA. (Make sure you copy the INI file and the malware into the Windows system directory and rename the DLL spoolvxx32.dll.) After the breakpoint is hit, we step over the call maybeDecoder. Figure C-37 shows the result.

OllyDbg showing the decoded contents of Lab11-02.ini

Figure C-37. OllyDbg showing the decoded contents of Lab11-02.ini

At in Figure C-37, the decrypted content—the email address —is pointed to by EAX. This email address is stored in the global variable byte_100034A0, which we rename email_address in IDA Pro to aid future analysis.

We have one last function to analyze inside DllMain: sub_100014B6. Because this function will install an inline hook, we’ll rename it hook_installer. The hook_installer function is complicated, so before diving into it, we provide a high-level overview of what this inline hook looks like after installation in Figure C-38.

The send function before and after a hook is installed

Figure C-38. The send function before and after a hook is installed

The left side of Figure C-38 shows what a normal call to the send function in ws2_32.dll looks like. The right side of the figure shows how hook_installer installs an inline hook of the send function. The start of the send function is replaced with a jump to malicious code, which calls a trampoline (shown in the figure’s lower-right box). The trampoline simply executes the start of the send function (which was overwritten with the first jump) and then jumps back to the original send function, so that the send function can operate as it did before the hook was installed.

Before hook_installer installs the hook, it checks to see which process the malware is running in. To do so, it calls three functions to get the current process name. Example C-51 contains code from the first of these functions, sub_10001075.

Example C-51. Calling GetModuleFileNameA to get the current process name

1000107D         push    offset Filename         ; lpFilename
10001082         mov     eax, [ebp+hModule]
10001085         push    eax                     ; hModule
10001086         call    ds:GetModuleFileNameA 
1000108C         mov     ecx, [ebp+arg_4]
1000108F         mov     dword ptr [ecx], offset Filename

As you can see, GetModuleFileNameA is called at , and it returns the full path to the process in which the DLL is loaded because the argument hModule is set to 0 before the call to this function. Next, the malware returns the name in arg_4 (the string pointer passed to the function). This string is passed to two more functions, which parse the filename and change all of its characters to uppercase.

Note

Malware that uses AppInit_DLLs as a persistence mechanism commonly uses GetModuleFileNameA. This malicious DLL is loaded into just about every process that starts on the system. Because malware authors may want to target only certain processes, they must determine the name of the process in which their malicious code is running.

Next, the current process name in uppercase letters is compared to the process names THEBAT.EXE, OUTLOOK.EXE, and MSIMN.EXE. If the string does not equal one of these filenames, the malware will exit. However, if the malware has been loaded into one of these three processes, the malicious code seen in Example C-52 will execute.

Example C-52. Malicious code that sets an inline hook

10001561         call    sub_100013BD 
10001566         push    offset dword_10003484   ; int
1000156B         push    offset sub_1000113D     ; int
10001570         push    offset aSend            ; "send"
10001575         push    offset aWsock32_dll     ; "wsock32.dll"
1000157A         call    sub_100012A3 
1000157F         add     esp, 10h
10001582         call    sub_10001499 

Example C-52 has several functions for us to analyze. Inside , we see calls to GetCurrentProcessId and then sub_100012FE, which we rename to suspend_threads. The suspend_threads function calls GetCurrentThreadId, which returns a thread identifier (TID) of the current thread of execution. Next, suspend_threads calls CreateToolhelp32Snapshot and uses the result to loop through all of the TIDs for the current process. If a TID is not the current thread, then SuspendThread is called using the TID. We can conclude that the function called at suspends all executing threads in the current process.

Conversely, the function called at does the exact opposite: It resumes all of the threads using calls to ResumeThread. We conclude that the code in Example C-52 is surrounded by two functions that suspend and then resume execution. This behavior is common when malware is making a change that could impact current execution, such as changing memory or installing an inline hook.

Next, we examine the code in the call at . The function sub_100012A3 takes four arguments, as shown by the series of pushes in Example C-52. Since this function is called only from this location, we can rename all of the arguments to match what is passed to the function, as shown in Example C-53 beginning at .

Example C-53. sub_100012A3 resolving the send function

100012A3 sub_100012A3 proc near
100012A3
100012A3 lpAddress= dword ptr -8
100012A3 hModule = dword ptr -4
100012A3 wsock32_DLL= dword ptr  8 
100012A3 send_function= dword ptr  0Ch
100012A3 p_sub_1000113D= dword ptr  10h
100012A3 p_dword_10003484= dword ptr  14h
100012A3
100012A3         push    ebp
100012A4         mov     ebp, esp
100012A6         sub     esp, 8
100012A9         mov     eax, [ebp+wsock32_DLL]
100012AC         push    eax                     ; lpModuleName
100012AD         call    ds:GetModuleHandleA 
...
100012CF         mov     edx, [ebp+send_function]
100012D2         push    edx                     ; lpProcName
100012D3         mov     eax, [ebp+hModule]
100012D6         push    eax                     ; hModule
100012D7         call    ds:GetProcAddress 
100012DD         mov     [ebp+lpAddress], eax

In Example C-53, we see a handle to wsock32.dll obtained using GetModuleHandleA at . That handle is passed to GetProcAddress to resolve the send function at . The malware ends up passing the address of the send function and the two other parameters (sub_1000113D and dword_10003484) to sub_10001203, which we renamed place_hook.

Now, we examine place_hook and rename the arguments accordingly in order to aid our analysis. Example C-54 shows the start of place_hook.

Example C-54. Address calculation for the jump instruction

10001209         mov     eax, [ebp+_sub_1000113D]
1000120C         sub     eax, [ebp+send_address]
1000120F         sub     eax, 5
10001212         mov     [ebp+var_4], eax 

The code in Example C-54 calculates the difference between the memory address of the send function and the start of sub_1000113D. This difference has an additional 5 bytes subtracted from it before being moved into var_4 at . var_4 is used later in the code and prepended with 0xE9 (the opcode for jmp), making this a 5-byte instruction to jump to sub_1000113D.

Let’s see how the malware installs this code as a hook later in place_hook. The start of the send function is modified by the instructions shown in Example C-55.

Example C-55. The inline hook installation

10001271         mov     edx, [ebp+send_address]
10001274         mov     byte ptr [edx], 0E9h 
10001277         mov     eax, [ebp+send_address]
1000127A         mov     ecx, [ebp+var_4]
1000127D         mov     [eax+1], ecx 

At , the code copies the 0xE9 opcode into the start of the send function. Following that, it copies var_4 into memory just after the 0xE9 at . Recall from Example C-54 that var_4 contains the destination of the jump, sub_1000113D. The code in Example C-55 places a jmp instruction at the beginning of the send function that jumps to the function in our DLL at sub_1000113D, which we’ll now rename hook_function.

Before we examine hook_function, let’s wrap up our analysis of the inline hook installation. Example C-56 shows place_hook manipulating memory.

Example C-56. place_hook (sub_10001203) manipulating memory

10001218         push    ecx                     ; lpflOldProtect
10001219         push    PAGE_EXECUTE_READWRITE  ; flNewProtect
1000121B         push    5                       ; dwSize
1000121D         mov     edx, [ebp+send_address]
10001220         push    edx                     ; lpAddress
10001221         call    ds:VirtualProtect 
10001227         push    0FFh                    ; Size
1000122C         call    malloc
10001231         add     esp, 4
10001234         mov     [ebp+var_8], eax 

In Example C-56, place_hook calls VirtualProtect at on the start of the send function code. This action changes the memory protection to execute, read, and write access, thereby allowing the malware to modify the instructions of the send function. Another call to VirtualProtect at the end of the function restores the original memory-protection settings. Then, immediately after calling VirtualProtect, the malware allocates 0xFF bytes of memory using malloc and stores the result in var_8 at . Because this dynamically allocated memory will play an important role in the installation of our hook as a trampoline, we’ll rename var_8 to trampoline.

Note

In order for this to execute properly, the memory returned by the call to malloc must be executable memory, which might not always be the case if, for example, Data Execution Prevention (DEP) is enabled via /Noexecute=alwayson or similar.

Example C-57 shows the creation of the trampoline’s code.

Example C-57. Trampoline creation for the inline hook

10001246         push    5                       ; Size
10001248         mov     eax, [ebp+send_address]
1000124B         push    eax                     ; Src
1000124C         mov     ecx, [ebp+trampoline]
1000124F         add     ecx, 5
10001252         push    ecx                     ; Dst
10001253         call    memcpy 
10001258         add     esp, 0Ch
1000125B         mov     edx, [ebp+trampoline]
1000125E         mov     byte ptr [edx+0Ah], 0E9h 
10001262         mov     eax, [ebp+send_address]
10001265         sub     eax, [ebp+trampoline]
10001268         sub     eax, 0Ah
1000126B         mov     ecx, [ebp+trampoline]
1000126E         mov     [ecx+0Bh], eax 

In Example C-57, the memcpy at copies the first 5 bytes of the send function into the trampoline. Since the malware overwrites the first 5 bytes of the send instruction (Example C-55), it needs to make sure that the original instructions are saved. The malware assumes that the send function’s first several instructions align exactly on 5 bytes, which might not always be the case.

Next, the malware adds a jmp instruction to the trampoline code at and . At , the 0xE9 opcode is added. At , the location to jump is added. The jump location is calculated by subtracting the location of the trampoline from the location of the send function (meaning it will jump back to the send function).

Finally, place_hook ends by setting the global variable dword_10003484 to the trampoline location. We rename dword_10003484 to trampoline_function to aid analysis.

Next, we analyze hook_function (sub_1000113D), which will have the same arguments as the send function since it is installed as a hook. We begin our analysis by right-clicking the function name, selecting Set Function Type, and entering the following:

int __stdcall hook_function(SOCKET s, char * buf, int len, int flags)

The hook function looks for the string RCPT TO: in buf. If the string isn’t found, the malware just calls trampoline_function, which causes send to operate as it did before the hook was installed. Otherwise, the code in Example C-58 will execute.

Example C-58. Creating the string to add a recipient

1000116D         push    offset aRcptTo_1        ; "RCPT TO: <" 
10001172         lea     ecx, [ebp+Dst]
10001178         push    ecx                     ; Dst
10001179         call    memcpy
...
10001186         push    offset email_address    ; Src 
...
10001198         lea     edx, [ebp+eax+Dst]
1000119F         push    edx                     ; Dst
100011A0         call    memcpy
100011A8         push    offset Source           ; ">\r\n" 
100011AD         lea     eax, [ebp+Dst]
100011B3         push    eax                     ; Dest
100011B4         call    strcat

The code in Example C-58 builds a string that is added to the outgoing buffer. This string starts with RCPT TO: < at , followed by email_address at , and ends with >\r\n at . The email_address value in this case is (extracted from Lab11-02.ini, as explained earlier when we looked at the contents of that file). This code adds a recipient to all outgoing email messages.

Low-Level Hook Operation Summary

Here’s a summary of the hook’s operation (also illustrated at a high-level in Figure C-38, shown earlier):

  • The program calls the send function.

  • The first instruction of the send function transfers execution to sub_1000113D.

  • sub_1000113D manipulates the outgoing buffer only if it contains a RCPT TO string.

  • sub_1000113D calls the trampoline code located on the heap and pointed to by dword_10003484.

  • The trampoline code executes the first three original instructions of the send function (which it overwrote to install the hook).

  • The trampoline code jumps back to the send function 5 bytes in, so that send can function normally.

Examining the Hook in OllyDbg

We can examine the inline hook using OllyDbg by installing the malware and then launching Outlook Express. (Outlook Express is bundled with Microsoft Windows XP and runs as msimn.exe.) We attach to the process using File ▸ Attach and selecting msimn.exe from the process listing. Attaching to a process immediately pauses all of the threads. If we examine the memory map, we see that spoolvxx32.dll is loaded in the process because it is an AppInit_DLLs value.

Next, we examine send by pressing CTRL-G and entering send in the text box. Figure C-39 shows the start of the send function with the jmp hook to sub_1000113D. (If you like, you can set a breakpoint at this jump and analyze the code during runtime.)

Examining the inline hook for the send function in msimn.exe

Figure C-39. Examining the inline hook for the send function in msimn.exe

Capturing the Network Traffic

To capture this malware in action and see how it manipulates network traffic, set up a safe environment as follows:

  1. Turn on host-only networking in your virtual machine.

  2. Install the malware on your virtual machine with the command rundll32.exe Lab11-02.exe,installer.

  3. Copy Lab11-02.ini into C:\Windows\System32\.

  4. Launch Wireshark and start capturing packets on the virtual machine network interface.

  5. Set up Outlook Express to send email to the host system.

  6. Run a fake mail server on your host machine with the command python -m smtpd -n -c DebuggingServer IP:25, where IP is the IP address of the host machine.

  7. Send an email from Outlook Express.

  8. Review the packet capture in Wireshark and select Follow TCP Stream on the email message.

Summary

Lab 11-2 Solutions is a malicious DLL that exports installer, which installs the malware persistently using AppInit_DLLs, causing the malware to be loaded into most processes. The malware checks to see if it is loaded into a mail client by using a preset list of process names to target. If the malware determines that it is running inside one of these processes, it will act as a user-mode rootkit by installing an inline hook for the send function. The hook takes the form of a jmp instruction placed at the beginning of the send function. The hook executes a function that scans every data buffer passed to the send function and searches for RCPT TO. If the malware finds the RCPT TO string, it inserts an additional RCPT TO containing an email address retrieved by decoding Lab11-02.ini, essentially copying the malware author on every email sent from the targeted email programs.