Hunting Malware with Windows Sysinternals — Process Monitor
Welcome back to the final part of “Hunting Malware with Windows Sysinternals” series.
We’ve seen previously how we can leverage “Process Explorer” and “Autoruns” functionalities to hunt malware effectively. If you haven’t read the first two parts I highly suggest you do. Here is a link to both.
In this third part, we’ll be taking a look at the powerful “Process Monitor” or “procmon” for short. We’ll start with an introduction on what happens when a process request something form the OS and then we’ll dive into procmon and how we can use some of its features to understand and hunt malware.
Without further ado let’s get started.
Windows Internals and The Win32 API
Before we start our journey into procmon, I think we should make a little detour and understand what happens when a process tries to request something from the OS by taking a look at some Internals.
Windows segregates user operations and OS operations by what’s called “User Space / User Mode” and “Kernel Space / Kernel Mode”.
User space will contain everything ranging from applications, services, system processes like the service control manager, sessions manager and everything that the user will execute. Whereas the kernel space will handle everything related to memory, drivers, file system, I/O…etc.
So let’s say we have an application and we’ll call it “Application X”. In windows this application will be represented by a process in user mode when it runs, and we’ll possess at least one thread of execution.
Our process will want to do something at one point in its lifetime as a good process should. It could write / read a file, access the network, draw something on the screen and so on.
All of these actions requires the process to interact with the kernel, as it is the sole responsible for all, including system resources. To do that our process will need to use the Windows API.
For the purposes of this discussion we will not care in what language our application is written, instead we’ll only focus on how the system will handle the request.
So let’s say that our application wants to write a file, and calls the appropriate functions in its code. Windows will call eventually the API function that is responsible for writing files, namely “WriteFile” from the “kernel32.dll”. Which is a user mode DLL that contains the Win32 base API and our “WriteFile” function.
But as we’ve said “kernel32.dll” is still in user mode, that means we still need to go down. In truth the “WriteFile” function is just a wrapper that will check the parameters being sent and call another function in another DLL named “ntdll.dll”.
“ntdll.dll” is the lowest point we can reach in user mode and it’s the DLL that implements the undocumented windows API and the one responsible for the jump between user mode and kernel mode.
Continuing with our example, the function that will get called from the “ntdll.dll” is the “NtWriteFile” which will be the one responsible for the switch from user mode to the “executive” in kernel mode.
I will spare you what’ll happen in the rest of the journey of the thread. Safe to say we will get back from the kernel into our original calling function with our file created. Below is a diagram illustrating what we’ve just talked about in an abstract way.
This example can be generalized to illustrates what happens every time an application requests a resource from the kernel.
- An application wants to do something, by calling the appropriate function in its code (reading / writing a file, printing a document, communicating via the network…etc.).
- That function will at some point call the appropriate subsystem DLL (kernel32.dll, ws2_32.dll, advapi.dll…etc.).
- That subsystem DLL function will check the parameters and that everything is good to go, and will make a call to the native API corresponding function in “ntdll.dll”.
- The ntdll.dll will then pass on the rest of the work to the kernel and stuff will happen.
- If everything worked perfectly we should get back from the kernel with a return to the caller and continue the rest of the program.
Now that we’ve understood a little bit about how a process execute something, I think it’s time that we dive into process monitor.
Process Monitor
As we’ve seen above when a process wants to do something it has to access the kernel by using API’s. So if wanted to know what a process is accessing in terms of files and registry keys and so forth, we need a tool that can monitor those activities. Enter “Process Monitor”.
Process monitor is a tool that monitors and captures File system activity, registry activity, network activity, profiling events and processes and threads activity on a particular system by using a kernel driver.
It’s a powerful tool for troubleshooting and understanding what a process is doing behind the scene and at a lower level. So powerful, it even got its own meme.
In our case we’re interested in using procmon and its functionalities to hunt and understand what malware is actually doing, the files its creating, the registry keys its modifying, the network communications it could be having and so on.
Once we start procmon, it’ll start capturing events immediately and we’ll be greeted by an interface that contains the following information by default:
- Time of Day when the event occurred.
- Process Name: The name of the process that executed the action.
- PID: The process ID.
- Operation: The name of the operation that occurred.
- Path: The path used by the operation. It could be a registry path, a file path or a network communication.
- Result: The Result of the operation
- Details: about what happened during that operation.
Let’s discuss how we can use the information gathered by procmon in our hunting and analysis.
Process Monitor Filters
Because of the sheer amount of data that procmon captures, one of the key features to master is filtering. Filters become a necessity to anyone using this tool, and especially when analyzing malware.
Procmon offers a ton of filters, but for the sake of our sanity we’ll be focusing on those that are often used in malware analysis.
Operations
Every action captured by procmon is associated to an operation. There are more than 170 operations that we can filter on.
Generally, when doing dynamic analysis of malware we’re interested in knowing what files and registry keys are being created, deleted and modified, what network activity is happening and what DLL’s are being loaded and so forth by the malware.
The following operations are the most common operations performed by malware, and are the ones that we should filter on during analysis.
- CreateFile: When a process wants to create a file.
- WriteFile: When a process writes data to a file.
- SetRenameInformationFile: When a rename operation occurs on a file.
- SetDispositionInformationFile: When a file deletion occurs on a file.
- RegCreateKey: When registry key is created.
- RegSetValue: When the data for value is set in the registry
- RegDeleteKey: When a key gets deleted from the registry.
- RegDeleteValue: When a value gets deleted from the registry.
- TCP Connect, TCP Receive, UDP Send, UDP Receive: Process is Sending / Receiving a TCP or UDP connection.
- Load Image: When a process loads any DLL’s / Executables.
- Process Create: When a process creates a process.
- CreatePipe: When a process creates a Pipe.
You can access the filter functionality from the toolbar menu or by pressing “Ctrl+L”.
I’ve compiled all of these operations into one giant procmon filter that you can use during your malware analysis. Here is the link to download.
Highlighting
Next on our list of features is the highlighting feature. Same as filtering but this time instead of removing or including unnecessary events we can highlight those that we only care about.
This can be useful when we want to highlight a particular file, path that is of interest to us.
We can use this feature by selecting it from the toolbar menu or pressing “Ctrl+H”.
Process Tree View
On of the cool features of procmon is the process tree view. It’ll show every process captured in a trace in a tree like view representing the parent / child relationship between them. This can be extremely helpful when analyzing malware that spawn processes that dies quickly.
For example, we can launch a trace and then execute our malware and let it run for a while. The sample could launch “cmd.exe”, “powershell.exe” or even create other processes and we wouldn’t even notice. But procmon will.
When we feel like the malware ran for enough time. We can then stop the trace, navigate to the tree view and visualize every child of that malicious process. We can then include the process itself, all of its children or navigate to the first event it executed.
Conclusion
Procmon is a very powerful tool for malware analysis, it lets us see the unseen and uncover the many hidden layer of a process or an application.
I hope you enjoyed this three part series about the sysinternals tools and you found it useful.
If you want to gain a deeper understanding of the sysinternals suite as a whole I highly suggest you read “Troubleshooting with the Windows Sysinternals Tools, 2nd Edition”
If you have any feedback or suggestions, send them my way on twitter @nas_bench