實現關閉程式函式,殺掉pchunter
現在問題擺在面前,如何解決這個問題,想了想最好的方法就是直接看作業系統怎麼實現 TerminateProcess 的自己實現個就好了,在一定程度上就可以阻止別人通過hook技術來攔截.
NtTerminateProcess的函式實現,其中最關鍵的 如圖:
這個函式主要乾的事情就是遍歷程式的執行緒,然後對每個執行緒執行PspTerminateThreadByPointer
再分析下 PspTerminateThreadByPointer 函式的實現
這個函式是分兩種情況的:
情況一,是執行緒自己關閉自己:直接執行PspExitThread
PspExitThread這個函式太龐雜簡單說下它的作用:
1. 執行了一大堆清理程式碼,主要清理當前執行緒Ethread的資源
2. 從排程連結串列和等待連結串列中去掉它
3. 如果是程式的最後一個執行緒,直接清理程式空間
4. 執行KiSwapThread切換到一個新執行緒去
情況二,關閉掉別的執行緒:在對方線執行緒中插入一個核心apc,這個核心apc最後會呼叫PspExitThread函式
PspTerminateThreadByPointer 和NtTerminateProcess分析總結:
1. 所謂殺死程式,其實只要把每個執行緒殺死就好了,最後一個執行緒會負責收屍的
2. 執行緒不能被殺死,只能自殺.所以如果想殺掉執行緒最好讓它自己執行自殺程式碼,核心apc(後面會簡單講下核心apc,沒法深入再講就錯題了)是個不錯的選擇
核心Apc執行的時機(講的不對請指正哈):
1. 中斷和異常返回,下面是ReatOs的程式碼(貼程式碼為證,避免別人說我瞎嗶嗶O(∩_∩)O哈哈~)
2. 高irql轉到第irql,這塊直接看win732逆向的程式碼:KfLowerIrql
主要關注: HalpCheckForSoftwareInterrrupt
執行apc的地方就是KiDeliverApc
3. 執行緒切換的時候,還是直接貼win2000的程式碼
原理講完了,現在直接貼效果圖了:
殺掉之前,寫好程式id:
執行完殺掉的程式碼:
另外直接附上程式碼:
Entry.c
#include <KrTypeDef.h>
#include <ntddk.h>
//需要殺死的程式id
#define PCHUNTER_ID 3232
VOID DriverUnload(PDRIVER_OBJECT pDriver);
PEPROCESS LookupProcess(HANDLE hPid);
PETHREAD LookupThread(HANDLE hTid);
VOID KillProcess(PEPROCESS pEProcess);
ULONG GetPspTerminateThreadByPointer();
ULONG GetPspExitThread(ULONG PspTerminateThreadByPointer);
VOID SelfTerminateThread(
KAPC *Apc,
PKNORMAL_ROUTINE *NormalRoutine,
PVOID *NormalContext,
PVOID *SystemArgument1,
PVOID *SystemArgument2);
fpTypePspExitThread g_fpPspExitThreadAddr = NULL;
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pPath)
{
DbgBreakPoint();
pDriver->DriverUnload = DriverUnload;
//提前把函式查詢出來
ULONG uPspTerminateThreadByPointerAddr = GetPspTerminateThreadByPointer();
if (0 == uPspTerminateThreadByPointerAddr)
{
KdPrint(("查詢PspTerminateThreadByPointerAddr地址出錯\n"));
return STATUS_SUCCESS;
}
g_fpPspExitThreadAddr = (fpTypePspExitThread)GetPspExitThread(uPspTerminateThreadByPointerAddr);
if (NULL == g_fpPspExitThreadAddr)
{
KdPrint(("查詢PspExitThread地址出錯\n"));
return STATUS_SUCCESS;
}
//
PEPROCESS pProcess = LookupProcess((HANDLE)PCHUNTER_ID);
if (NULL == pProcess)
{
KdPrint((("沒有在PsCidTable中找到程式,尼瑪不會隱藏了吧\n")));
}
else
{
KillProcess(pProcess);
}
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
KdPrint(("驅動退出\n"));
}
PEPROCESS LookupProcess(HANDLE hPid)
{
PEPROCESS pEProcess = NULL;
if (NT_SUCCESS(PsLookupProcessByProcessId(hPid, &pEProcess)))
return pEProcess;
return NULL;
}
VOID KillProcess(PEPROCESS pEProcess)
{
PEPROCESS pEProc = NULL;
PETHREAD pEThrd = NULL;
ULONG i = 0;
for (i = 4; i < 0x25600; i += 4)
{
pEThrd = LookupThread((HANDLE)i);
if (!pEThrd) continue;
pEProc = IoThreadToProcess(pEThrd);
if (pEProc == pEProcess)
{
PKAPC pApc = NULL;
pApc = (PKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (NULL == pApc) return;
//插入核心apc
KeInitializeApc(pApc, (PKTHREAD)pEThrd, OriginalApcEnvironment, (PKKERNEL_ROUTINE)&SelfTerminateThread, NULL, NULL, 0, NULL);
KeInsertQueueApc(pApc, NULL, 0, 2);
}
ObDereferenceObject(pEThrd);
}
}
PETHREAD LookupThread(HANDLE hTid)
{
PETHREAD pEThread = NULL;
if (NT_SUCCESS(PsLookupThreadByThreadId(hTid, &pEThread)))
return pEThread;
return NULL;
}
VOID SelfTerminateThread(
KAPC *Apc,
PKNORMAL_ROUTINE *NormalRoutine,
PVOID *NormalContext,
PVOID *SystemArgument1,
PVOID *SystemArgument2)
{
ExFreePool(Apc);
g_fpPspExitThreadAddr(STATUS_SUCCESS);
}
ULONG GetPspTerminateThreadByPointer()
{
UNICODE_STRING funcName;
RtlInitUnicodeString(&funcName, L"PsTerminateSystemThread");
ULONG step = 0;
ULONG targetFunAddr = 0;
ULONG baseFunAddr = (ULONG)MmGetSystemRoutineAddress(&funcName);
for (step = baseFunAddr; step < (baseFunAddr + 1024); step++)
{
//searching for 0x50,0xe8
if (((*(PUCHAR)(UCHAR*)(step - 1)) == 0x50) && ((*(PUCHAR)(UCHAR*)(step)) == 0xe8))
{
ULONG offset = *(PULONG)(step + 1);
targetFunAddr = step + 5 + offset;
break;
}
}
return targetFunAddr;
} //PspExitThread stamp code:0x0c 0xe8
ULONG GetPspExitThread(ULONG PspTerminateThreadByPointer)
{
ULONG step = 0;
ULONG targetFunAddr = 0;
ULONG baseFunc = PspTerminateThreadByPointer;
for (step = baseFunc; step < (baseFunc + 1024); step++)
{
//searching for 0x0c,0xe8
if (((*(PUCHAR)(UCHAR*)(step - 1)) == 0x0c) && ((*(PUCHAR)(UCHAR*)(step)) == 0xe8))
{
ULONG m_offset = *(PULONG)(step + 1);
targetFunAddr = step + 5 + m_offset;
break;
}
}
return targetFunAddr;
}
KrTypeDef.h
#pragma once
#include <ntifs.h>
#include <ntddk.h>
#pragma warning(disable:4189 4100)
typedef enum _KAPC_ENVIRONMENT
{
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment,
InsertApcEnvironment
} KAPC_ENVIRONMENT;
typedef VOID (*PKNORMAL_ROUTINE) (
IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
typedef VOID(*PKKERNEL_ROUTINE) (
IN struct _KAPC *Apc,
IN OUT PKNORMAL_ROUTINE *NormalRoutine,
IN OUT PVOID *NormalContext,
IN OUT PVOID *SystemArgument1,
IN OUT PVOID *SystemArgument2
);
typedef VOID(*PKRUNDOWN_ROUTINE) (
IN struct _KAPC *Apc
);
VOID NTAPI KeInitializeApc(__in PKAPC Apc,
__in PKTHREAD Thread,
__in KAPC_ENVIRONMENT TargetEnvironment,
__in PKKERNEL_ROUTINE KernelRoutine,
__in_opt PKRUNDOWN_ROUTINE RundownRoutine,
__in PKNORMAL_ROUTINE NormalRoutine,
__in KPROCESSOR_MODE Mode,
__in PVOID Context
);
BOOLEAN NTAPI KeInsertQueueApc(IN PKAPC Apc,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2,
IN KPRIORITY PriorityBoost);
typedef VOID(NTAPI *fpTypePspExitThread)(
IN NTSTATUS ExitStatus
);
#define OFFSET(type, f) ((SIZE_T) \
((char *)&((type *)0)->f - (char *)(type *)0))
ps:程式碼有處bug,就是假設在殺執行緒的同時建立執行緒怎麼辦?
最後謝謝大家!
相關文章
- DELPHI實現關閉指定程式,自身防殺2013-10-18
- linux批量殺掉程式linux批量殺掉程式2010-07-23Linux
- 強行關閉“殺”不了的程式(轉)2007-08-11
- Oracle徹底殺掉程式2017-09-01Oracle
- 殺掉鎖死的程式2013-03-19
- go windows鎖屏 && 關閉桌面(殺掉檔案資源管理器)2020-10-15GoWindows
- 字串相關函式的實現2018-08-03字串函式
- 關閉工作管理員殺不了的程式(轉)2007-08-11
- ORACLE中殺掉一個程式2010-11-16Oracle
- 殺掉aspnet_wp程式2006-05-09
- 【sqlserver】殺掉所有死鎖程式2012-08-31SQLServer
- 關閉 linux下的umask( )函式、setsid( )函式2016-07-12Linux函式
- Linux下批次殺掉 包含某個關鍵字的 程式程式2016-09-14Linux
- (函式)實現strstr函式2017-02-04函式
- Linux如何殺掉殭屍程式2017-06-05Linux
- 殺掉長期inactive的程式2011-04-07
- App被殺掉2016-02-23APP
- python 關於 函式物件與閉包2020-05-07Python函式物件
- windows上殺掉指定名稱的程式2021-04-24Windows
- 函式閉包2018-07-04函式
- 閉包函式2016-04-14函式
- 美麗的閉包,在js中實現函式過載2018-06-16JS函式
- 【C語言】常用的字串函式及相關函式的自我實現2020-10-12C語言字串函式
- 回撥函式 與 函式閉包2019-05-29函式
- 閉包函式(匿名函式)的理解2021-06-07函式
- 25行程式碼實現Promise函式2017-11-22行程Promise函式
- wdaproxy 啟動,即被系統殺掉程式,求解。2020-07-13
- oracle生成批量殺掉active程式的sql2012-12-07OracleSQL
- 在UNIX環境下批次殺掉ORACLE程式2011-01-18Oracle
- .NET併發程式設計-函式閉包2021-02-08程式設計函式
- JS函式表示式——函式遞迴、閉包2018-05-19JS函式遞迴
- go 閉包函式2019-03-25Go函式
- js函式閉包2019-03-15JS函式
- Linux下IPC機制實現相關函式2017-05-28Linux函式
- JS閉包函式和回撥函式2017-10-30JS函式
- 函式物件、裝飾器、閉包函式2024-05-20函式物件
- js函式 函式自呼叫 返回函式的函式 (閉包)2017-10-25JS函式
- Java程式猿筆記——基於redis分散式鎖實現“秒殺”2019-01-03Java筆記Redis分散式