typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;
//
由于KeServiceDescriptorTable只有一项,这里就简单点了
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
//KeServiceDescriptorTable
为导出函数
/////////////////////////////////////
ULONG GetFunctionAddr( IN PCWSTR FunctionName);
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
VOID GetAddress();
ULONG OutCall;
VOID CLI();
VOID STI();
char *Name=
"[DbgPrint:] %8x %8x %8x %8x %8x %8x %8x %8x"
;
ULONG JmpAddress;
//
跳转到NtOpenProcess里的地址
ULONG OldServiceAddress;
//
原来NtOpenProcess的服务地址
ULONG DbgPrintFunAddr;
UCHAR KiByte[5]={0xe9,0x00,0x00,0x00,0x00};
ULONG OutHook_1,OutJmp_1;
//////////////////////////////////////
__declspec(naked) NTSTATUS __stdcall MyNtTerminateProcess()
{
//
__asm
//
{
//
pushad
//
pushf
//
}
__asm
{
push dword ptr [ebp+28h]
push dword ptr [ebp+24h]
push dword ptr [ebp+20h]
push dword ptr [ebp+1ch]
push dword ptr [ebp+18h]
push dword ptr [ebp+14h]
push dword ptr [ebp+10h]
push dword ptr [ebp+0xC]
//
push ecx
//Hwnd
push dword ptr [ebp+0x8]
push Name
//Ascii
call DbgPrintFunAddr
add esp,0x28
}
//
__asm
//
{
//
popad
//
popf
//
}
__asm
{
call OutCall
//NtCreateProcessEx
jmp OutJmp_1
//
ret
//
jmp JmpAddress
}
}
///////////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = OnUnload;
DbgPrintFunAddr = (ULONG)GetFunctionAddr(L
"DbgPrint"
);
//ObReferenceObjectByHandle
有导出。。
GetAddress();
//
DbgPrint(
"[DbgPrint: ] %8x"
,DbgPrintFunAddr);
KdPrint((
"[MyNtCreateProcessEx:] %8x"
,MyNtCreateProcessEx));
Hook();
return
STATUS_SUCCESS;
}
/////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
Unhook();
}
/////////////////////////////////////////////////////
VOID Hook()
{
ULONG JmpOffKiAt;
//
UCHAR JmpCodeKiAt[5]={0xE8,0x00,0x00,0x00,0x00};
//
这里是CALL方式 我用CALL怎么都处理不好。
UCHAR JmpCodeKiAt[5]={0xE9,0x00,0x00,0x00,0x00};
//Jmp
方式
UCHAR MaxByte[4]={0xFF,0xFF,0xFF,0xFF};
RtlCopyMemory (KiByte, (PVOID)OutHook_1, 5);
//
保存HOOK原位置数据
JmpOffKiAt=(PCHAR)MyMyNtTerminateProcess-(PCHAR)OutHook_1-0x5;
RtlCopyMemory(JmpCodeKiAt+1,&JmpOffKiAt,4);
CLI();
RtlCopyMemory((PVOID)OutHook_1,(PVOID)JmpCodeKiAt,5);
STI();
}
VOID Unhook()
{
CLI();
RtlCopyMemory((PVOID)OutHook_1,KiByte,5);
STI();
KdPrint((
"Unhook"
));
}
ULONG GetFunctionAddr( IN PCWSTR FunctionName)
//Get
Funcion Address
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
return
(ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
VOID GetAddress()
{
ULONG AddCall_1,AddCallEnd_1,i,KiFunAddr;
UCHAR CallByte_1[4]={0x00,0x00,0x00,0x00};
UCHAR MaxByte[4]={0xFF,0xFF,0xFF,0xFF};
PBYTE CurByte;
ULONG CurAddr_1;
ULONG Address,Adds_1;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x30 * 4;
Address = *(ULONG*)Address;
CurByte = (PBYTE)Address;
for
(i=0;i<=200;i++)
{
if
(CurByte[i] == 0xC3)
//
先搜索返回
{
KiFunAddr = *(PULONG)&CurByte[i+1];
break
;
}
}
CurByte=CurByte+i+0x4;
//
跳过第一个E8
CurByte= (PBYTE)CurByte;
//
DbgPrint(
"[CurByte] %x\n"
,(ULONG)CurByte);
for
(i=0;i<=200;i++)
{
if
(CurByte[i] == 0xe8)
//
{
//Adds_1
= *(PULONG)&CurByte[i+1];
//
取地址后接着取内容
Adds_1 = *(ULONG*)&CurByte[i+1];
//DbgPrint
(
"[Adds_1] %x\n"
,(ULONG)Adds_1);
break
;
}
}
AddCall_1= (ULONG)&CurByte[i+1];
//Call
代码地址
//DbgPrint
(
"[AddCall_1地址] %x\n"
,(ULONG)AddCall_1);
OutHook_1 = (ULONG)AddCall_1-0x1;
OutJmp_1 = (ULONG)AddCall_1+0x4;
AddCallEnd_1 = AddCall_1+0x4;
//CALL
地址后面
JmpAddress = AddCallEnd_1;
AddCall_1 = (ULONG)*((PULONG)MaxByte)-(ULONG)Adds_1;
//
比下面的更加智能化
AddCall_1 = AddCallEnd_1-AddCall_1-0x1;
//DbgPrint
(
"[NtCreateProcessEx_Call] %x\n"
,(ULONG)AddCall_1);
//
到这里已经定位出 NtCreateProcessEx_Call 的函数地址了
OutCall = (ULONG)AddCall_1;
}
VOID CLI()
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
}
VOID STI()
{
__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}