- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
依据10年的进程保护修改的,也是一个经典的SSDT HOOK. 模仿商业保护阻止其他软件修改内存。
在内核中HOOK NtWriteVirtualMemory函数,这样用户层的那些内存修改器就无法修改内存了。
以下以保护进程 Form1.exe为例 在 win7 32 位系统下测试通过。
注意 我这里获取函数地址用的是函数序号来获取的,函数序号 在win7和xp 系统里面是不同的。
NtWriteVirtualMemory函数 在win7 32 位系统里面的序号为399,用xuetr点击驱动层钩子 SSDT 即可发现。
在xp 系统里面不是 399.所以大家如果要使用以下源码,必须注意修改小这个 函数序号。
#include <ntddk.h>
typedef struct _SystemServiceDescriptorTable
{
PVOID ServiceTableBase; //SSDT表的基地址
PULONG ServiceCounterTableBase; //指向另一个索引表,该表包含了每个服务表项被调用的次数
ULONG NumberOfService; //当前系统所支持的服务个数
ULONG ParamTableBase; //包含了每个服务所需的参数字节数
}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;
extern PSystemServiceDescriptorTable KeServiceDescriptorTable; //导出函数,DDK的头文件中并未声明
//内核函数声明
typedef NTSTATUS (*NtWRITEVIRTUALMEMORY)(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG ReturnLength OPTIONAL);
//定义一个内核函数的数据类型
NtWRITEVIRTUALMEMORY pRealAddr;//用 NtWRITEVIRTUALMEMORY 定义 一个 真的 函数类型
ULONG RealServiceAddress; //接受被hook的函数地址
CHAR *TerminateName = "Form1.exe"; //这里就是我们的进程名。
UCHAR* PsGetProcessImageFileName( IN PEPROCESS Process );
BOOLEAN IsProtect(CHAR *temp) //判断正在结束的进程是否是我们要保护的魔兽进程
{
ULONG len = strcmp(TerminateName, temp);
if(!len)
return TRUE;
return FALSE;
}
NTSTATUS MyNtWriteVirtualMemory(IN HANDLE ProcessHandle,IN PVOID BaseAddress,IN PVOID Buffer,IN ULONG BufferLength,OUT PULONG ReturnLength OPTIONAL)
{
PEPROCESS process; //接受通过ProcessHandle返回的进程
NTSTATUS status;
CHAR *pName; //接受进程的进程名
status = ObReferenceObjectByHandle(ProcessHandle, FILE_READ_DATA,0, KernelMode,&process,NULL); //获取进程
if(!NT_SUCCESS(status))
return (NTSTATUS)(NtWRITEVIRTUALMEMORY)pRealAddr(ProcessHandle, BaseAddress,Buffer,BufferLength,ReturnLength);
pName = (CHAR*)PsGetProcessImageFileName(process); //获取进程名
if(IsProtect(pName)) //判断是否是我们要保护的进程,是则返回权限不足,不能修改内存,否则调用原函数
return STATUS_ACCESS_DENIED;
return (NTSTATUS)(NtWRITEVIRTUALMEMORY)pRealAddr(ProcessHandle, BaseAddress,Buffer,BufferLength,ReturnLength);
}
NTSTATUS Hook()
{
ULONG Address;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 399 * 4;//399是函数序号,可用xuetr查看。这个399是win7 32 系统里面的。XP系统不是399,自己查
RealServiceAddress = *(ULONG*)Address;
pRealAddr = (NtWRITEVIRTUALMEMORY)RealServiceAddress;
//开启SSDT 表为可写
_asm
{
cli;
mov eax, cr0;
and eax, not 10000h;
mov cr0, eax;
}
*((ULONG*)Address) = (ULONG)MyNtWriteVirtualMemory; //替换为我们自己的MyNtWriteVirtualMemory 函数
DbgPrint("完成HOOK内核函数");
//设置SSDT表位只读
_asm
{
mov eax, cr0;
or eax, 10000h;
mov cr0, eax;
sti;
}
}
VOID UnHook()//把SSDT中的NtTerminateprocess函数还原
{
ULONG Address;
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 399 * 4;//399是函数序号,可用xuetr查看。这个399是win7 32 系统里面的。XP系统不是399,自己查
__asm
{
cli
mov eax, cr0;
and eax, not 10000h ;
mov cr0, eax ;
}
*((ULONG*)Address) = (ULONG)RealServiceAddress;
__asm
{
mov eax, cr0 ;
or eax, 10000h ;
mov cr0, eax ;
sti ;
}
}
VOID Unload(PDRIVER_OBJECT driver)
{
UNREFERENCED_PARAMETER(driver);
UnHook();
DbgPrint("卸载驱动完成...");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING str)
{
NTSTATUS status;
UNREFERENCED_PARAMETER(str);
driver->DriverUnload = Unload;
DbgPrint("驱动加载完成");
status = Hook();
return STATUS_SUCCESS;
} |
|