hook PsCreateSystemThread
很多RootKit在ring0下利用PsCreateSystemThread来创建系统线程做某些WS的事情,我们平时不利用ARK工具的话,是很难发现这些线程,在某些情况下,需要anti一些特定的rootkit,这里给出一个简单的示例:
.h:
#pragma once
![]()
#include
<
ntddk.h
>
![]()
typedef
long
LONG;
typedef unsigned
char
BOOL,
*
PBOOL;
typedef unsigned
char
BYTE,
*
PBYTE;
typedef unsigned
long
DWORD,
*
PDWORD;
typedef unsigned
short
WORD,
*
PWORD;
![]()
typedef
void
*
HMODULE;
typedef
long
NTSTATUS,
*
PNTSTATUS;
typedef unsigned
long
DWORD;
typedef DWORD
*
PDWORD;
typedef unsigned
long
ULONG;
typedef unsigned
long
ULONG_PTR;
typedef ULONG
*
PULONG;
typedef unsigned
short
WORD;
typedef unsigned
char
BYTE;
typedef unsigned
char
UCHAR;
typedef unsigned
short
USHORT;
typedef
void
*
PVOID;
typedef BYTE BOOLEAN;
#define
SEC_IMAGE 0x01000000
![]()
NTSTATUS
PsLookupProcessByProcessId(
IN HANDLE ProcessId,
OUT PEPROCESS
*
Process
);
.c:
#include
"
HookPsThread.h
"
![]()
/**/
/******************************************************************************
![]()
Hook PsCreateSystemThread
out adress
![]()
******************************************************************************/
![]()
//
=============================================================================
//
Version Define
//
=============================================================================
#define
EPROCESS_SIZE 1
#define
PEB_OFFSET 2
#define
FILE_NAME_OFFSET 3
#define
PROCESS_LINK_OFFSET 4
#define
PROCESS_ID_OFFSET 5
#define
EXIT_TIME_OFFSET 6
//
=============================================================================
//
Logic Define
//
=============================================================================
ULONG PsCreateSystemThreadAddr
=
0
;
![]()
char
PsCreateSystemThreadData[
5
]
=
{0}
;
![]()
DWORD ProcessNameOffset;
![]()
//
-----------------------------------------------------------------------------
//
GetPlantformDependentInfo
//
-----------------------------------------------------------------------------
DWORD GetPlantformDependentInfo( DWORD dwFlag )
![]()
{
DWORD current_build;
DWORD ans = 0;
PsGetVersion(NULL, NULL, ¤t_build, NULL);
switch ( dwFlag )
![]()
{
case EPROCESS_SIZE:
if (current_build == 2195) ans = 0 ; // 2000,当前不支持2000,下同
if (current_build == 2600) ans = 0x25C; // xp
if (current_build == 3790) ans = 0x270; // 2003
break;
case PEB_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x1b0;
if (current_build == 3790) ans = 0x1a0;
break;
case FILE_NAME_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x174;
if (current_build == 3790) ans = 0x164;
break;
case PROCESS_LINK_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x088;
if (current_build == 3790) ans = 0x098;
break;
case PROCESS_ID_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x084;
if (current_build == 3790) ans = 0x094;
break;
case EXIT_TIME_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x078;
if (current_build == 3790) ans = 0x088;
break;
}
return ans;
}
![]()
![]()
//
-----------------------------------------------------------------------------
//
GetFunctionAddr
//
-----------------------------------------------------------------------------
ULONG GetFunctionAddr( IN PCWSTR FunctionName)
![]()
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
![]()
//
-----------------------------------------------------------------------------
//
_PsCreateSystemThread
//
-----------------------------------------------------------------------------
NTSTATUS _PsCreateSystemThread(IN PKSTART_ROUTINE StartRoutine)
![]()
{
ULONG RAddr = (ULONG)StartRoutine; //Routine Address
//Get Process Info
LPTSTR CurProc;
PEPROCESS EProcess;
PsLookupProcessByProcessId(PsGetCurrentProcessId(), &EProcess);
CurProc =(LPTSTR)EProcess;
CurProc =CurProc+ProcessNameOffset;
![]()
if (strncmp((char*)CurProc,"System",6) != 0)
![]()
{
DbgPrint("Current Process : %s, StartRoutine : %X\n", (char *)CurProc, StartRoutine);
}
return 0;
}
![]()
//
-----------------------------------------------------------------------------
//
MyPsCreateSystemThread
//
-----------------------------------------------------------------------------
__declspec (naked)
void
MyPsCreateSystemThread()
![]()
{
_asm
![]()
{
pushad
push [esp+20h+18h]
call _PsCreateSystemThread
popad
mov edi,edi
push ebp
mov ebp,esp
jmp PsCreateSystemThreadAddr
}
}
![]()
//
-----------------------------------------------------------------------------
//
Install Hook
//
-----------------------------------------------------------------------------
VOID InHook()
![]()
{
PsCreateSystemThreadAddr = GetFunctionAddr(L"PsCreateSystemThread");
![]()
__asm
![]()
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
}
![]()
//Save asmCode
memcpy(PsCreateSystemThreadData, (PVOID)PsCreateSystemThreadAddr, 5);
(ULONG)PsCreateSystemThreadAddr += 5;
![]()
//Inline PsCreateSystemThread
__asm
![]()
{
mov esi, PsCreateSystemThreadAddr
sub esi, 5
mov byte ptr[esi], 0xE9
lea eax, [MyPsCreateSystemThread]
sub eax, esi
sub eax, 5
mov dword ptr [esi+1],eax
}
![]()
__asm
![]()
{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
}
![]()
DbgPrint("Hooked OK
.\n");
return;
}
![]()
//
-----------------------------------------------------------------------------
//
Uninstall Hook
//
-----------------------------------------------------------------------------
VOID UnHook()
![]()
{
__asm
![]()
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
}
(ULONG)PsCreateSystemThreadAddr -= 5;
memcpy((PVOID)PsCreateSystemThreadAddr, PsCreateSystemThreadData, 5);
__asm
![]()
{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
}
DbgPrint("UnHook OK
.\n");
return;
}
![]()
//
-----------------------------------------------------------------------------
//
Driver UnLoad
//
-----------------------------------------------------------------------------
void
OnUnload(PDRIVER_OBJECT pDriverObj)
![]()
{
UnHook();
DbgPrint("UnLoading Driver");
}
![]()
//
-----------------------------------------------------------------------------
//
Driver LoadEntry
//
-----------------------------------------------------------------------------
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
![]()
{
pDriverObj->DriverUnload = OnUnload;
![]()
DbgPrint("Loading Driver");
ProcessNameOffset = GetPlantformDependentInfo(FILE_NAME_OFFSET);
InHook();
return STATUS_SUCCESS;
}
.h:
.c:
很多RootKit在ring0下利用PsCreateSystemThread来创建系统线程做某些WS的事情,我们平时不利用ARK工具的话,是很难发现这些线程,在某些情况下,需要anti一些特定的rootkit,这里给出一个简单的示例:
.h:
#pragma once
![]()
#include
<
ntddk.h
>
![]()
typedef
long
LONG;
typedef unsigned
char
BOOL,
*
PBOOL;
typedef unsigned
char
BYTE,
*
PBYTE;
typedef unsigned
long
DWORD,
*
PDWORD;
typedef unsigned
short
WORD,
*
PWORD;
![]()
typedef
void
*
HMODULE;
typedef
long
NTSTATUS,
*
PNTSTATUS;
typedef unsigned
long
DWORD;
typedef DWORD
*
PDWORD;
typedef unsigned
long
ULONG;
typedef unsigned
long
ULONG_PTR;
typedef ULONG
*
PULONG;
typedef unsigned
short
WORD;
typedef unsigned
char
BYTE;
typedef unsigned
char
UCHAR;
typedef unsigned
short
USHORT;
typedef
void
*
PVOID;
typedef BYTE BOOLEAN;
#define
SEC_IMAGE 0x01000000
![]()
NTSTATUS
PsLookupProcessByProcessId(
IN HANDLE ProcessId,
OUT PEPROCESS
*
Process
);
.c:
#include
"
HookPsThread.h
"
![]()
/**/
/******************************************************************************
![]()
Hook PsCreateSystemThread
out adress
![]()
******************************************************************************/
![]()
//
=============================================================================
//
Version Define
//
=============================================================================
#define
EPROCESS_SIZE 1
#define
PEB_OFFSET 2
#define
FILE_NAME_OFFSET 3
#define
PROCESS_LINK_OFFSET 4
#define
PROCESS_ID_OFFSET 5
#define
EXIT_TIME_OFFSET 6
//
=============================================================================
//
Logic Define
//
=============================================================================
ULONG PsCreateSystemThreadAddr
=
0
;
![]()
char
PsCreateSystemThreadData[
5
]
=
{0}
;
![]()
DWORD ProcessNameOffset;
![]()
//
-----------------------------------------------------------------------------
//
GetPlantformDependentInfo
//
-----------------------------------------------------------------------------
DWORD GetPlantformDependentInfo( DWORD dwFlag )
![]()
{
DWORD current_build;
DWORD ans = 0;
PsGetVersion(NULL, NULL, ¤t_build, NULL);
switch ( dwFlag )
![]()
{
case EPROCESS_SIZE:
if (current_build == 2195) ans = 0 ; // 2000,当前不支持2000,下同
if (current_build == 2600) ans = 0x25C; // xp
if (current_build == 3790) ans = 0x270; // 2003
break;
case PEB_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x1b0;
if (current_build == 3790) ans = 0x1a0;
break;
case FILE_NAME_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x174;
if (current_build == 3790) ans = 0x164;
break;
case PROCESS_LINK_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x088;
if (current_build == 3790) ans = 0x098;
break;
case PROCESS_ID_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x084;
if (current_build == 3790) ans = 0x094;
break;
case EXIT_TIME_OFFSET:
if (current_build == 2195) ans = 0;
if (current_build == 2600) ans = 0x078;
if (current_build == 3790) ans = 0x088;
break;
}
return ans;
}
![]()
![]()
//
-----------------------------------------------------------------------------
//
GetFunctionAddr
//
-----------------------------------------------------------------------------
ULONG GetFunctionAddr( IN PCWSTR FunctionName)
![]()
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
![]()
//
-----------------------------------------------------------------------------
//
_PsCreateSystemThread
//
-----------------------------------------------------------------------------
NTSTATUS _PsCreateSystemThread(IN PKSTART_ROUTINE StartRoutine)
![]()
{
ULONG RAddr = (ULONG)StartRoutine; //Routine Address
//Get Process Info
LPTSTR CurProc;
PEPROCESS EProcess;
PsLookupProcessByProcessId(PsGetCurrentProcessId(), &EProcess);
CurProc =(LPTSTR)EProcess;
CurProc =CurProc+ProcessNameOffset;
![]()
if (strncmp((char*)CurProc,"System",6) != 0)
![]()
{
DbgPrint("Current Process : %s, StartRoutine : %X\n", (char *)CurProc, StartRoutine);
}
return 0;
}
![]()
//
-----------------------------------------------------------------------------
//
MyPsCreateSystemThread
//
-----------------------------------------------------------------------------
__declspec (naked)
void
MyPsCreateSystemThread()
![]()
{
_asm
![]()
{
pushad
push [esp+20h+18h]
call _PsCreateSystemThread
popad
mov edi,edi
push ebp
mov ebp,esp
jmp PsCreateSystemThreadAddr
}
}
![]()
//
-----------------------------------------------------------------------------
//
Install Hook
//
-----------------------------------------------------------------------------
VOID InHook()
![]()
{
PsCreateSystemThreadAddr = GetFunctionAddr(L"PsCreateSystemThread");
![]()
__asm
![]()
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
}
![]()
//Save asmCode
memcpy(PsCreateSystemThreadData, (PVOID)PsCreateSystemThreadAddr, 5);
(ULONG)PsCreateSystemThreadAddr += 5;
![]()
//Inline PsCreateSystemThread
__asm
![]()
{
mov esi, PsCreateSystemThreadAddr
sub esi, 5
mov byte ptr[esi], 0xE9
lea eax, [MyPsCreateSystemThread]
sub eax, esi
sub eax, 5
mov dword ptr [esi+1],eax
}
![]()
__asm
![]()
{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
}
![]()
DbgPrint("Hooked OK
.\n");
return;
}
![]()
//
-----------------------------------------------------------------------------
//
Uninstall Hook
//
-----------------------------------------------------------------------------
VOID UnHook()
![]()
{
__asm
![]()
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
}
(ULONG)PsCreateSystemThreadAddr -= 5;
memcpy((PVOID)PsCreateSystemThreadAddr, PsCreateSystemThreadData, 5);
__asm
![]()
{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
}
DbgPrint("UnHook OK
.\n");
return;
}
![]()
//
-----------------------------------------------------------------------------
//
Driver UnLoad
//
-----------------------------------------------------------------------------
void
OnUnload(PDRIVER_OBJECT pDriverObj)
![]()
{
UnHook();
DbgPrint("UnLoading Driver");
}
![]()
//
-----------------------------------------------------------------------------
//
Driver LoadEntry
//
-----------------------------------------------------------------------------
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
![]()
{
pDriverObj->DriverUnload = OnUnload;
![]()
DbgPrint("Loading Driver");
ProcessNameOffset = GetPlantformDependentInfo(FILE_NAME_OFFSET);
InHook();
return STATUS_SUCCESS;
}
.h:
.c: