写ZwTerminateProcess hook的时候hook到ZwTerminateProcess的参数是HANDLE ProcessHandle和NTSTATUS ExitStatus。结构如下:
NTSTATUS
ZwTerminateProcess(
IN HANDLE ProcessHandle,
IN NTSTATUS ExitStatus
);
当ProcessHandle为null的时候,表明改进程结束自身进程。当该进程结束其他进程是,ProcessHandle指向这个被结束进程的process object。为了获取被结束进程的名称,要进行以下操作。
1. 通过ObReferenceObjectByHandle获得该进程的EPROCESS指针。
2. 通过未公开函数PsGetProcessImageFileName来获取进程名称。
PsGetProcessImageFileName结构如下:
UCHAR * PsGetProcessImageFileName(
__in PEPROCESS Process
);
具体代码如下:
void GetProcessNamebyHandle(HANDLE handle,PCHAR Name) { PEPROCESS Process; NTSTATUS status; char *nameptr=NULL; status = ObReferenceObjectByHandle(handle,0,NULL,KernelMode,&Process,NULL); if(!NT_SUCCESS(status)) { DbgPrint("GetProcessNamebyHandle failed\n"); strcpy(nameptr,"Unkown"); return; } //KdPrint(("Process:%x\n",Process)); nameptr =PsGetProcessImageFileName(Process); strncpy(Name,nameptr,PROCNAMELEN); Name[PROCNAMELEN]=0x00; return; }
FakedZwTerminateProcess代码如下:
NTSTATUS FakedZwTerminateProcess(IN HANDLE ProcessHandle,
IN NTSTATUS ExitStatus) { char aProcessName[PROCNAMELEN]; char killedProName[PROCNAMELEN]; NTSTATUS status; status = RealZwTerminateProcess(ProcessHandle, ExitStatus); if(NT_SUCCESS(status)&&NT_SUCCESS(ExitStatus)) { GetProcessName(aProcessName); if(ProcessHandle==NULL) { strncpy(killedProName,aProcessName,sizeof(aProcessName)); } else { GetProcessNamebyHandle(ProcessHandle,killedProName); } sprintf(output,"TerminateProcess: %s --> %s\n",aProcessName,killedProName); KdPrint(("%s\n",output)); } return status; }
其中GetProcessName(aProcessName)函数是获取调用ZwTerminateProcess的当前进程。
其代码的实现和原理可以参见内核驱动程序中获取当前用户进程的进程名的方法 一文。