/************************************************************************/
/* 获取信息,并根据用户的选择结束进程或者允许运行 */
/* arg[0] 和 arg[1] 分别为PspUserThreadStartup 的两个参数 */
/* arg[0] = StartRoutine, arg[1] = StartContext */
/************************************************************************/
void DoSomethingIWant(PULONG arg)
{
ULONG dwEProcess = (ULONG)PsGetCurrentProcess();
ANSI_STRING ansiCurrentProcessName,ansiPerentProcessName;
ULONG uRet = 0;
ULONG Pid, PerentPid;
KSPIN_LOCK SpinLock;
KIRQL kirql;
PLIST_ENTRY
head
,curr;
ULONG n;
if
(g_uStartSign == 0)
//
没准备好?
{
return
;
}
Pid = (ULONG)PsGetCurrentProcessId();
PerentPid = *(PULONG)(dwEProcess + OFFSET_PERENT_PID_EPROCESS);
//
通过偏移从EPROCESS中获取父进程ID,偏移为硬编码
KeInitializeSpinLock(&SpinLock);
if
(g_uStartSign != arg[1])
//
是否为进程的第一个线程
{
//
添加PID到PidTable中
KeAcquireSpinLock(&SpinLock,&kirql);
SetPidTable(Pid, 1);
KeReleaseSpinLock(&SpinLock,kirql);
//
取当前进程名
GetProcessPathName(dwEProcess,&ansiCurrentProcessName);
//
取父进程名
GetProcessPathNameByPID(PerentPid, &ansiPerentProcessName);
//
打印信息~~
DbgPrint(
"[ProcessMon]Process Creating, Process Name = %s ,PID = %d ,PerentName = %s PID = %d\r\n"
,
ansiCurrentProcessName.Buffer,Pid, ansiPerentProcessName.Buffer,PerentPid);
//
让用户选择
uRet = GetUserChoose(&ansiPerentProcessName,&ansiCurrentProcessName, PerentPid, Pid);
//
从PidTable中删除PID
KeAcquireSpinLock(&SpinLock,&kirql);
SetPidTable(Pid, 0);
KeReleaseSpinLock(&SpinLock,kirql);
//
释放内存了.
if
(ansiCurrentProcessName.Length) RtlFreeAnsiString(&ansiCurrentProcessName);
if
(ansiPerentProcessName.Length) RtlFreeAnsiString(&ansiPerentProcessName);
//
根据用户的选择允许运行或者结束进程
if
(uRet)
ZwTerminateProcess(NtCurrentProcess(), 0);
KeSetEvent(&g_eventNotify, 0, 0);
//
通知那些等待的线程---------------------
KeClearEvent(&g_eventNotify);
//
置为非信号----------------------------|
}
//
|
else
//
|
{
//
|
//
不是第一个线程 |
while
(IsPidInTable(Pid))
//
如果线程所属进程在等待用户判断,则让其等待 |
{
//
|
KeWaitForSingleObject(&g_eventNotify,Executive,KernelMode,0,0);
//
<-----
}
//
通过EPROCESS->ThreadListHead遍历线程,ThreadListHead的偏移量为硬编码
for
(n = 0, curr =
head
= (PLIST_ENTRY)(dwEProcess + OFFSET_THREAD_LIST_HEAD_EPROCESS);
curr->Blink !=
head
;
curr = curr->Blink, n++){}
//
计算当前进程的线程数目
DbgPrint(
"[ProcessMon]Pid: %.4d ,Thread count = %d\r\n"
,Pid, n);
}
return
;
}
/************************************************************************/
/* 自己假冒的函数 保存现场后CALL DoSomethingIWant */
/************************************************************************/
__declspec(naked) void FakePspUserThreadStartup()
{
__asm{
pushfd
pushad
mov ebx,esp
add ebx,44
push ebx
call DoSomethingIWant
popad
popfd
jmp g_Orig
}
}
/************************************************************************/
/* 挂钩PspUserThreadStartup */
/* 挂钩的地址是PspUserThreadStartup+2 */
/************************************************************************/
void HookPspUserThreadStartup()
{
PUCHAR pHookAddr = (PUCHAR)FindPspUserThreadStartupAddress();
UCHAR JMPCode[5] = {0xe9,0,0,0,0};
UCHAR JMPBackCode[5] = {0xe9,0,0,0,0};
g_Orig = ExAllocatePool(NonPagedPool,10);
if
(!g_Orig)
{
DbgPrint(
"[ProcessMon]Failed with Allocate Pool\r\n"
);
return
;
}
if
(!pHookAddr)
return
;
pHookAddr += 2;
//
挂钩的地址是PspUserThreadStartup+2
*((PULONG)(JMPCode+1)) = (ULONG) FakePspUserThreadStartup - ((ULONG)pHookAddr + 5);
*((PULONG)(JMPBackCode+1)) = (ULONG)pHookAddr + 5 - ((ULONG)g_Orig + 10);
memcpy(
g_Orig,
(PVOID)pHookAddr,
5);
memcpy(
(PVOID)((ULONG)g_Orig+5),
(PVOID)JMPBackCode,
5);
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
memcpy((PVOID)pHookAddr,JMPCode,5);
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}