您的位置:首页 > 其它

通过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保护起来就对了..
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: