通过PspTerminateThreadByPointer结束进程
2008-07-16 20:27
337 查看
早前写的代码了,免得腐烂了,贴出来
这个思想是在读了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
// XP: nt!PsTerminateSystemThread -> GetPspTerminateThreadByPointer
// 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保护起来就对了..
这个思想是在读了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
// XP: nt!PsTerminateSystemThread -> GetPspTerminateThreadByPointer
// 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保护起来就对了..
相关文章推荐
- 模拟PspTerminateProcess结束进程-学习笔记
- PspTerminateProcess 结束冰刃进程
- 模拟PspTerminateProcess结束进程-学习笔记
- C++通过TerminateProess结束进程实例
- Window下通过命令行查看\结束进程
- 通过枚举获得控制台进程号,结束进程
- Atitit 通过调用gui接口杀掉360杀毒 360卫士 qq保镖等难以结束的进程(javac# php )
- 通过shell脚本开始和结束守护进程
- Atitit 通过调用gui接口杀掉360杀毒 360卫士 qq保镖等难以结束的进程(javac# php )
- The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
- 通过结束进程来关闭程序
- CMD 查看进程与结束进程 By Shawl.qiu
- 获取指定窗口句柄结束进程 OpenProcess FindWindow GetExitCodeprocess TerminateProcess
- The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact
- cmd下获取指定进程名的pid号,并通过taskkill结束该进程
- TerminateProess结束进程
- 通过Vista系统自带命令提示符结束恶意进程
- 通过回调函数阻止进程创建(验证结束,方案完全可行)
- PspTerminateProcess 结束冰刃进程
- 进程防结束之PS_CROSS_THREAD_FLAGS_SYSTEM