很早前写的代码了,免得腐烂了,贴出来
这个思想是在读了PJF牛人 "终止进程内幕" 后才晓得
基本思想就是用户态将欲结束的进程PID传递到内核驱动,驱动通过PsLookupProcessByProcessId得到进程的EPROCESS结构,再通过EPROCESS结构找到线程的链表头,遍历这个链表,逐一调用PspTerminateThreadByPointer,将其一个一个的KILL掉
这里有三个问题:
1. EPROCESS 结构里面的 线程链表头的 OFFSET 在2000, XP 2003中不一样,所以要硬编码
#define THREAD_LIST_HEAD_OFFSET_XP 0x190
#define THREAD_LIST_HEAD_OFFSET_2K 0x270
#define THREAD_LIST_HEAD_OFFSET_2K3 0x180
#define THREAD_LIST_ENTRY_OFFSET_XP 0x22c
#define THREAD_LIST_ENTRY_OFFSET_2K 0x240
#define THREAD_LIST_ENTRY_OFFSET_2K3 0x224
2.如何获得PspTerminateThreadByPointer
// 2k: NtTerminateThread -> PspTerminateThreadByPointer
BOOL GetPspTerminateThreadByPointer()
... {
char * PsTerminateSystemThreadAddr;
int iLen;
DWORD dwAddr;
//pAddr;
PNTPROC ServiceTable;
DWORD NtTerminateThreadAddr;
char * pAddr;
if (dwThreadListHeadOffset == THREAD_LIST_HEAD_OFFSET_2K)
...{
ServiceTable = KeServiceDescriptorTable->ntoskrnl.ServiceTable;
NtTerminateThreadAddr = *((PULONG)ServiceTable + NTTERMINATETHREAD_OFFSET_2K);
pAddr = (char *)NtTerminateThreadAddr;
for (iLen=0;iLen<0xff;iLen++)
...{
if (*pAddr == (char)0xff
&&*(pAddr+1) == (char)0x75
&&*(pAddr+2) == (char)0xfc
&&*(pAddr+8) == (char)0x8b
)
...{
pAddr += 4;
dwAddr = *(DWORD *)pAddr + (DWORD)pAddr +4;
//DbgPrint("PspTerminateThreadByPointer:: 0x%x ",dwAddr);
PspTerminateThreadByPointer = dwAddr;
return TRUE;
//break;
}
pAddr++;
}
}
else
...{
PsTerminateSystemThreadAddr= (char *)PsTerminateSystemThread;
__asm
...{
__emit 0x90;
__emit 0x90;
}
for (iLen=0;iLen<50;iLen++)
...{
if (*PsTerminateSystemThreadAddr == (char)0xff
&& *(PsTerminateSystemThreadAddr+1) == (char)0x75
&& *(PsTerminateSystemThreadAddr+2) == (char)0x08
)
...{
__asm
...{
__emit 0x90;
__emit 0x90;
}
PsTerminateSystemThreadAddr += 5;
dwAddr = *(DWORD *)PsTerminateSystemThreadAddr + (DWORD)PsTerminateSystemThreadAddr +4;
//DbgPrint("PspTerminateThreadByPointer:: 0x%x ",dwAddr);
PspTerminateThreadByPointer = dwAddr;
return TRUE;
//break;
}
PsTerminateSystemThreadAddr++;
}
}
return FALSE;
}
3. 在2k下面需要得到 PsLockProcess 和 PsUnlockProcess ,不然调用PspTerminateThreadByPointer就要挂
// 2K 下使用 ,NtTerminateThread -> PspTerminateThreadByPointer
BOOL GetLockProcessAddr()
... {
char * PsTerminateSystemThreadAddr;
int iLen;
DWORD dwAddr;
//pAddr;
PNTPROC ServiceTable;
DWORD NtTerminateThreadAddr;
char * pAddr;
ServiceTable = KeServiceDescriptorTable->ntoskrnl.ServiceTable;
/**//*
NtTerminateThreadAddr = *((PULONG)ServiceTable + NTTERMINATETHREAD_OFFSET_2K);
pAddr = (char *)NtTerminateThreadAddr;
for (iLen = 0;iLen<0xff;iLen++)
{
//想不到windows竟然用硬编码来寻址..
if (*pAddr == (char)0x2c
&&*(pAddr+1) == (char)0x02
&&*(pAddr+2) == (char)0x00
&&*(pAddr+3) == (char)0x00
)
{
pAddr += 5;
dwAddr = *(DWORD *)pAddr + (DWORD)pAddr +4;
DbgPrint("PsLockProcess :: 0x%x ",dwAddr);
PsLockProcess = dwAddr;
for (iLen = 0;iLen<0xff;iLen++)
{
if (*pAddr == (char)0x2c
&&*(pAddr+1) == (char)0x02
&&*(pAddr+2) == (char)0x00
&&*(pAddr+3) == (char)0x00
)
{
pAddr += 5;
dwAddr = *(DWORD *)pAddr + (DWORD)pAddr +4;
DbgPrint("PsUnLockProcess :: 0x%x ",dwAddr);
PsUnLockProcess = dwAddr;
return TRUE;
//return dwAddr;
//break;
}
pAddr++;
}
//return dwAddr;
//break;
}
pAddr++;
}
*/
//DbgPrint("NtAssignProcessToJobObject中寻找");
//在NtTerminateThread 中没有找到
//NtAssignProcessToJobObject中寻找
DWORD NtAssignProcessToJobObjectAddr = *((PULONG)ServiceTable + 0x12);
pAddr = (char *)NtAssignProcessToJobObjectAddr;
for (iLen = 0;iLen<0xff;iLen++)
...{
// 定位标志
if (*pAddr == (char)0xcc
&&*(pAddr+1) == (char)0x00
&&*(pAddr+2) == (char)0x00
&&*(pAddr+3) == (char)0x00
&&*(pAddr-6) == (char)0xe4
)
...{
// 找到定位标志
for (iLen = 0;iLen<0x30;iLen++)
...{
__asm
...{
__emit 0x90;
__emit 0x90;
}
//
if (*pAddr == (char)0xff
&&*(pAddr+1) == (char)0x75
&&*(pAddr+2) == (char)0xf4
//&&*(pAddr+3) == (char)0x00
)
...{
pAddr += 5;
dwAddr = *(DWORD *)pAddr + (DWORD)pAddr +4;
//DbgPrint("PsLockProcess :: 0x%x ",dwAddr);
PsLockProcess = dwAddr;
for (iLen = 0;iLen<0xff;iLen++)
...{
if (*pAddr == (char)0xff
&&*(pAddr+1) == (char)0x75
&&*(pAddr+2) == (char)0xfc
//&&*(pAddr+3) == (char)0x00
)
...{
pAddr += 4;
dwAddr = *(DWORD *)pAddr + (DWORD)pAddr +4;
//DbgPrint("PsUnLockProcess :: 0x%x ",dwAddr);
PsUnLockProcess = dwAddr;
return TRUE;
//return dwAddr;
//break;
}
pAddr++;
}
return FALSE;
break;
}
pAddr++;
}
return FALSE;
break;
}
pAddr++;
}
return FALSE;
}
4. 这些问题解决了就好办了
BOOL KillProcessByID(DWORD dwPid)
... {
PLIST_ENTRY ListThread;
PLIST_ENTRY ListThreadHead;
DWORD dwThreadAdd;
DWORD dwExitState = 0xC00002EB;
DWORD dwState;
//dwState = STATUS_SYSTEM_SHUTDOWN;
DWORD dwAddress = GetProcessByID(dwPid);
if (!dwAddress)
...{
return FALSE;
}
__asm
...{
CLI; //dissable interrupt
MOV EAX, CR0; //move CR0 register into EAX
AND EAX, NOT 10000H; //disable WP bit
MOV CR0, EAX; //write register back
}
ListThreadHead = ((PLIST_ENTRY)(dwAddress + dwThreadListHeadOffset));
if (dwThreadListHeadOffset == THREAD_LIST_HEAD_OFFSET_2K)
...{
//Lock Process
__asm
...{
//push PsLockPollOnTimeout - 0;
//push PsLockWaitForever - 2;
push 0;
push KernelMode;
push dwAddress;
call PsLockProcess;
mov dwState,eax;
}
if (dwState != STATUS_SUCCESS)
...{
//DbgPrint("failed!! ");
//__asm
//{
// push dwAddress;
// call PsUnLockProcess;
//}
return FALSE;
}
}
ListThread = ListThreadHead->Blink;
while (ListThread != ListThreadHead)
...{
if (!MmIsAddressValid((char*)ListThread-dwThreadListEntryOffset))
...{
if (dwThreadListHeadOffset == THREAD_LIST_HEAD_OFFSET_2K)
...{
__asm
...{
push dwAddress;
call PsUnLockProcess;
}
//return FALSE;
}
//DbgPrint("MmIsAddressValid !!!!! ---- failed!! ");
return FALSE;
}
dwThreadAdd = (DWORD)((char*)ListThread-dwThreadListEntryOffset);
//DbgPrint("Thread Address: 0x%x ",dwThreadAdd);
//XP上的定义
//NTSTATUS
//00880 NTAPI
//00881 PspTerminateThreadByPointer(IN PETHREAD Thread,
//00882 IN NTSTATUS ExitStatus,
//00883 IN BOOLEAN bSelf)
//2K 下的定义
//NTSTATUS
//PspTerminateThreadByPointer(
//IN PETHREAD Thread,
//IN NTSTATUS ExitStatus
//)
if (dwThreadListHeadOffset == THREAD_LIST_HEAD_OFFSET_2K)
...{
__asm
...{
//push 0;
push dwExitState;
push dwThreadAdd;
call PspTerminateThreadByPointer;
}
}
else
...{
__asm
...{
//push 0;
push dwExitState;
push dwThreadAdd;
call PspTerminateThreadByPointer;
}
}
ListThread = ListThread->Blink;
}
if (dwThreadListHeadOffset == THREAD_LIST_HEAD_OFFSET_2K)
...{
// unlock process
__asm
...{
push dwAddress;
call PsUnLockProcess;
}
}
__asm
...{
MOV EAX, CR0; //move CR0 register into EAX
OR EAX, 10000H; //enable WP bit
MOV CR0, EAX; //write register back
STI; //enable interrupt
}
return TRUE;
}
5. 最后把一个初始化函数贴出来
BOOL MyGetVersion()
... {
ULONG MajorVersion;
ULONG MinorVersion;
MinorVersion = 0;
MajorVersion = 0;
PsGetVersion(&MajorVersion,&MinorVersion,NULL,NULL);
if (MajorVersion == 5) ...{
if (MinorVersion == 0) ...{
//2K
//dwListOffset = LIST_ENTRY_OFFSET_2K;
//dwNameOffset = NAME_OFFSET_2K;
//dwStatusOffset = STATUS_OFFSET_2K;
dwThreadListHeadOffset = THREAD_LIST_HEAD_OFFSET_2K;
dwThreadListEntryOffset = THREAD_LIST_ENTRY_OFFSET_2K;
if (!GetLockProcessAddr())
...{
return FALSE;
}
}
else if (MinorVersion == 1) ...{
//XP
//dwListOffset = LIST_ENTRY_OFFSET_XP;
//dwNameOffset = NAME_OFFSET_XP;
//dwStatusOffset = STATUS_OFFSET_XP;
dwThreadListHeadOffset = THREAD_LIST_HEAD_OFFSET_XP;
dwThreadListEntryOffset = THREAD_LIST_ENTRY_OFFSET_XP;
}
else if (MinorVersion == 2)
...{
// 2K3
dwThreadListHeadOffset = THREAD_LIST_HEAD_OFFSET_2K3;
dwThreadListEntryOffset = THREAD_LIST_ENTRY_OFFSET_2K3;
}
else
...{
return FALSE;
}
}
else
...{
return FALSE;
}
return TRUE;
}
知道怎么杀的呢,就很好防止了,把PsLookupProcessByProcessId保护起来就对了..