I tried working on unpacking the file found in the .rsrc section of the Pepex variant that I analyzed, and had mixed results. I first tried a couple of things like simply looking for a far jump in a disassembly (like with UPX), which didn’t work. I can’t say I’m too surprised, but I figured I would give it a try. I tried running the original malware and then patching the code to force the branch where the file is loaded and executed, but the file that drops is just the packed file from .rsrc (in this case, dropped as %system%\system32\LSASvc.exe).
Next I tried putting breakpoints on Kernel32.LoadLibraryA and Kernel32.LoadLibraryW which showed that a couple of libraries were loaded (GDI32 and imm32). However, the binary keeps failing shortly after the calls to GetProcAddress for various functions from imm32 and GDI32 complete. I notice a string on the stack that says:
So, it clearly knows it’s being messed with. Not sure if this had something to do with what I was trying to do in the debugger, or if it just didn’t like being taken out of the .rsrc section of the overall malware.
Some online tutorials suggest doing something like this:
1) find the PUSH EAX instruction following the PUSHFW and PUSHAD instructions
2) follow what’s in ESP
3) find the string 46 02 C4 FF:
4) set a hardware breakpoint (on access, word) for that string
5) Run program, when BP is hit you should be close to OEP
Trying to follow this keeps resulting in exceptions/errors and crashes. However, a few lines below the original PUSH EAX instruction, I saw this:
I figured that I would just check out what is at 400000, and:
I see the 4D 5A magic numbers and then dumped from there. I ended up dumping the file three ways – used each of Olly’s methods of reconstructing the PE header, and then also without reconstructing it.
What I ended up with was a somewhat unpacked file from the .rsrc section and then the file from the .rsrc section that was created after patching the code to follow that branch (which is what I had originally gotten from the .rsrc section running Resource Hacker).
The unpacked file actually reveals many strings. I’ll go through some of what I find the most interesting, with the full set of strings at the end. First we see what appear to be pretty typical imports – Kernel32, User32, ADVAPI32, WS2_32 and some error message strings. Following this is the first block of function names. Some of the more interesting ones are:
VirtualAlloc, CreateThread, VirtualFree: These are some functions associated with process replacement. I’m not seeing others (such as ResumeThread, WriteProcessMemory, etc.) but perhaps I’m just not seeing them in this file because of the way it was unpacked. This is something to keep in mind as I take a look at what this executable does when run by the parent malware.
WriteFile, DeleteFileA, ReadFile, CopyFileA: I’m always happy to see these functions because it tells me there might be some obvious file system artifacts to look for, but it also makes me wonder if this file copies an existing, legitimate file somewhere else (such as a temp directory) and then does some sort of MiTM thing.
GetSystemDirectoryA, GetTempFileNameA, GetTempPathA: Related to the thoughts above regarding replacement of a legitimate file. I wonder if something happens like: 1) copy legitimate file to a temp path 2) replacement legitimate file with malicious file 3) malicious file receives input from system first before passing on to the legitimate file now residing in the temp directory so that nothing seems amiss.
FindFirstFileA, FindNextFileA: Looks like this thing will look for a specific file.
GetComputerNameA, GetVersionExA, GetDriveTypeA: Makes me think of some sort of system inventory.
CreateProcessA: Will be interesting to see what, if anything, this file creates with a call to this function.
CreateServiceA, StartServiceA: Another interesting clue that some of the other strings here might relate to a service name that this file uses when it creates a service with itself.
The smaller block of libraries and functions at the end just appears to be a repeat of what we’ve seen earlier. Below the large block of functions, we see an interesting set of strings:
Unable to load function: %s (%s)
Unable to load ordinal: %d (%s)
LSAService
Microsoft LSA Logon Authorization Service
\LSASvc.exe
( Win32s )
( Windows 98 )
( Windows 95 )
ver %d.%d %s (Build %d)
Server
SERVERNT
Workstation
WINNT
ProductType
SYSTEM\CurrentControlSet\Control\ProductOptions
( Windows2000
( WindowsNT
( Unknown )
%s <%uk>
*%s
C:\
Looks like the first two are some error messages specific to this sample. After that I’m going to guess that when this calls CreateServiceA and StartServiceA it calls itself LSAService/Microsoft LSA Logon Authorization Service. Next we see what appears to be some sort of system inventory creation text. I’m going to try to get this to run and see what happens dynamically.
Looking at the malware in the debugger, after the file is written from the .rsrc section, there is a call to CreateProcess with these parameters:
Stepping through the parameters with the help of MSDN:
pProcessInfo: Pointer to a PROCESS_INFORMATION struct that receives info about the new process. In this run this value happens to be 18FB44.
PstartupInfo: Pointer to a STARTUPINFO or STARTUPINFOEX struct. In this run this value is 18FB00. We also see this string:
CurrentDir: The path to the current directory for the process. In this run, it’s set to NULL, so the new process will have the same path as the calling process (which in our case would be c:\ma\lab\)
pEnvironment: NULL in our run, which means that the new process will use the environment of the calling process
CreationFlags: In our case this has been set to CREATE_NO_WINDOW (0x08000000). I’m going to change this to 0x00000010 (CREATE_NEW_CONSOLE) so we can see what it does:
InheritHandles: In our run, this is set to FALSE, so no handles are inherited from the main malware process.
pThreadSecurity: Set to NULL, so handles to the new thread cannot be inherited by child processes.
pProcessSecurity: Also NULL, so handles to the new process cannot be inherited by child processes.
CommandLine: The command line to be executed, which in our case is the string from above – C:\Windows\system32\lsasvc.exe -i (though on our system that’s the SysWOW64 directory since I’m running this on a Win7 VM). The -i argument is interesting. Maybe this means “-install”? I wonder if there is a corresponding -u or -r argument.
ModuleFileName: NULL, so “…the module name must be the first white space-delimited token in the lpCommandLine string…”, therefore lsasvc.exe.
After this, we see some MOVs that zero out some areas in ESP and then we see the parameters set up for the call to CreateProcessA – looks like how I want it:
Running this, however, didn’t produce a console. I was hoping that since the author went out of their way to set this as CREATE_NO_WINDOW, that perhaps I could change the CreationFlags to get something to appear. In discussing this with someone online (thanks Defunct), my current thought process is that since the parent isn’t run in its own console and since this child process should be getting the parent’s STARTUPINFO struct, that could be one reason why we aren’t “seeing” anything. The malware could also have been compiled to be a GUI app and not as a console app. Anyway…
Despite this, we do see some interesting things happen when the process is run. First, Regshot reveals the following changes in the registry:
———————————-
Keys added: 2
———————————-
HKLM\SYSTEM\ControlSet001\services\LSAService
HKLM\SYSTEM\CurrentControlSet\services\LSAService
———————————-
Values added: 14
———————————-
HKLM\SYSTEM\ControlSet001\services\LSAService\Type: 0x00000010
HKLM\SYSTEM\ControlSet001\services\LSAService\Start: 0x00000002
HKLM\SYSTEM\ControlSet001\services\LSAService\ErrorControl: 0x00000001
HKLM\SYSTEM\ControlSet001\services\LSAService\ImagePath: “C:\Windows\system32\LSASvc.exe”
HKLM\SYSTEM\ControlSet001\services\LSAService\DisplayName: “Microsoft LSA Logon Authorization
Service”
HKLM\SYSTEM\ControlSet001\services\LSAService\WOW64: 0x00000001
HKLM\SYSTEM\ControlSet001\services\LSAService\ObjectName: “LocalSystem”
HKLM\SYSTEM\CurrentControlSet\services\LSAService\Type: 0x00000010
HKLM\SYSTEM\CurrentControlSet\services\LSAService\Start: 0x00000002
HKLM\SYSTEM\CurrentControlSet\services\LSAService\ErrorControl: 0x00000001
HKLM\SYSTEM\CurrentControlSet\services\LSAService\ImagePath: “C:\Windows\system32\LSASvc.exe”
HKLM\SYSTEM\CurrentControlSet\services\LSAService\DisplayName: “Microsoft LSA Logon Authorization
Service”
HKLM\SYSTEM\CurrentControlSet\services\LSAService\WOW64: 0x00000001
HKLM\SYSTEM\CurrentControlSet\services\LSAService\ObjectName: “LocalSystem”
Per MSDN, the service Type (0x00000010) is a Win32 program that can be started by the service controller. The Start type (0x00000002) indicates that it should automatically load at startup. This looks to be how this other file achieves some persistence and also stealth as it tries to masquerade as a legitimate-sounding service.
Process Explorer and Process Monitor let us observe that the call to CreateProcessA spawns an LSASvc.exe process (PID 1160) and then that process terminates with another LSASvc.exe process being created (PID 2816). This new process (2816) starts listening on port 186. This is pretty interesting, because the parent malware didn’t appear to have any C2 functionality, and this might indicate how the malware can be worked with remotely.
I tried to fix the dumped file with LordPE and ImpRec, but still had issues with the file so I’m probably going to leave it be, at least for now. There were some interesting things going on in this file, though, so I’ve updated the report from the last post and am including that here. Please let me know if you have any thoughts on any of this, particularly on unpacking Petite!
Updated Report (with additions in bold): MalEXE003-updated
Full Strings:
!This program cannot be run in DOS mode.
Rich
.petite
KERNEL32.dll
USER32.dll
ADVAPI32.dll
WS2_32.dll
runtime error
TLOSS error
SING error
DOMAIN error
R6028
– unable to initialize heap
R6027
– not enough space for lowio initialization
R6026
– not enough space for stdio initialization
R6025
– pure virtual function call
R6024
– not enough space for _onexit/atexit table
R6019
– unable to open console device
R6018
– unexpected heap error
R6017
– unexpected multithread lock error
R6016
– not enough space for thread data
abnormal program termination
R6009
– not enough space for environment
R6008
– not enough space for arguments
R6002
– floating point not loaded
Microsoft Visual C++ Runtime Library
Runtime Error!
Program:
…
<program name unknown>
GetLastActivePopup
GetActiveWindow
MessageBoxA
user32.dll
CloseHandle
WaitForSingleObject
CreateEventA
GetLastError
lstrcatA
GetSystemDirectoryA
CopyFileA
GetModuleFileNameA
GetModuleHandleA
CreateThread
lstrcmpiA
GetVersionExA
Sleep
GetTickCount
lstrlenA
GetComputerNameA
FindClose
FindNextFileA
WriteFile
FindFirstFileA
GetTempFileNameA
lstrcpyA
GetTempPathA
CreateProcessA
DeleteFileA
ReadFile
SetFilePointer
GetFileSize
CreateFileA
GetDriveTypeA
wsprintfA
StartServiceCtrlDispatcherA
SetServiceStatus
RegisterServiceCtrlHandlerA
CloseServiceHandle
StartServiceA
CreateServiceA
OpenSCManagerA
RegCloseKey
RegQueryValueExA
RegOpenKeyExA
ExitProcess
TerminateProcess
GetCurrentProcess
GetStartupInfoA
GetCommandLineA
GetVersion
UnhandledExceptionFilter
FreeEnvironmentStringsA
FreeEnvironmentStringsW
WideCharToMultiByte
GetEnvironmentStrings
GetEnvironmentStringsW
SetHandleCount
GetStdHandle
GetFileType
HeapDestroy
HeapCreate
VirtualFree
HeapFree
RtlUnwind
GetCPInfo
GetACP
GetOEMCP
HeapAlloc
VirtualAlloc
HeapReAlloc
GetProcAddress
LoadLibraryA
MultiByteToWideChar
LCMapStringA
LCMapStringW
GetStringTypeA
GetStringTypeW
This file has been tampered with and
MAY BE INFECTED BY A VIRUS!
Unable to load function: %s (%s)
Unable to load ordinal: %d (%s)
LSAService
Microsoft LSA Logon Authorization Service
\LSASvc.exe
( Win32s )
( Windows 98 )
( Windows 95 )
ver %d.%d %s (Build %d)
Server
SERVERNT
Workstation
WINNT
ProductType
SYSTEM\CurrentControlSet\Control\ProductOptions
( Windows2000
( WindowsNT
( Unknown )
%s <%uk>
*%s
C:\
ERROR!
Corrupt Data!
ExitProcess
LoadLibraryA
GetProcAddress
VirtualProtect
GlobalAlloc
GlobalFree
GetModuleHandleA
MessageBoxA
wsprintfA
RegCloseKey
KERNEL32.dll
USER32.dll
ADVAPI32.dll
WS2_32.dll