#include <ntddk.h>
#include "stdio.h"
#include <Xed.h>
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
}
}
我看看了函数说明,第一个是句柄,可是我得到的数值怎么看都不对。
求教
我在调试输出中看到的一个参数和eprocess里面一个成员的数值相同
1ff***
参数应该没问题
我在使用PsTerminateProcess结束进程传入第一个参数发现不行。所以疑问。
大致过程:
push进参数
输出
恢复堆栈
调用原函数
--------------
q2:
cli
sti
这2个函数内部代码
我在一本书上看到
说的是用CR0来操作一个了寄存器的16BIT
置0或者1来实现对内存的访问控制
说的好像是R0可以访问R3的内存
但是我在驱动中都是操作的R0内存。
那么我不写可以吗?
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)