本程序使用了hde32反汇编引擎,所以性能更加稳定!
#pragma once
#include <ntddk.h>
NTSYSAPI
NTSTATUS
NTAPI
NtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle);
NTSTATUS
DetourNtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle);
VOID
TrueCellUnload(IN PDRIVER_OBJECT DriverObject);
BOOLEAN
HookFunc(BOOLEAN IsHook);
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath);
NTSTATUS
IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
OUT POBJECT_NAME_INFORMATION *ObjectNameInformation );
#include "Ncs.h"
#include "hde32.h"
#pragma comment(lib, "hde32.lib")
UCHAR OriFuncHead[12]={0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};//假设目标函数头部有12个字节
UCHAR NewFuncHead[5]={0xE9,0x00,0x00,0x00,0x00};//jmp [相对偏移] 的字节码——奇妙的地方
ULONG ulHeadLen=0;
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath){
KdPrint(("[TrueCell] Driver Entry!\r\n"));
DriverObject->DriverUnload=TrueCellUnload;
return HookFunc(TRUE)?STATUS_SUCCESS:STATUS_UNSUCCESSFUL;
}
VOID TrueCellUnload(IN PDRIVER_OBJECT DriverObject){
HookFunc(FALSE);
KdPrint(("[TrueCell] Driver Unload!\r\n"));
}
_declspec(naked) NTSTATUS
GoNtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle){//跳板
_asm{
nop;// \
nop;// |
nop;// |
nop;// |
nop;// |
nop;// |
nop;// >开辟足够大的空间来容纳NtCreateSection开头的ulHeadlen个字节的机器码
nop;// |
nop;// |
nop;// |
nop;// |
nop;// /
mov eax,NtCreateSection;
add eax,ulHeadLen;
jmp eax
}
}
NTSTATUS
DetourNtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle){//代理函数
PFILE_OBJECT FileObject;
POBJECT_NAME_INFORMATION wcFilePath;
//由Protect判断当前Section是否可执行:一般将要执行的DLL和EXE的都是Section可执行的
if (Protect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY) ){
//获取FileHandle对应的FILE_OBJEC——其有我们感兴趣的成员和作用
if (NT_SUCCESS(ObReferenceObjectByHandle(FileHandle,0,NULL,KernelMode,&FileObject,NULL))){//获取文件对象
//获取FileObject对应的文件全路径
if (IoQueryFileDosDeviceName(FileObject,&wcFilePath)==STATUS_SUCCESS){//获取文件对象所对应的文件Dos设备名称,即是全路径
DbgPrint("[TrueCell] %ws\r\n",wcFilePath->Name.Buffer);
ExFreePool(wcFilePath);//IoQueryFileDosDeviceName获取的OBJECT_NAME_INFORMATION 需要手动释放
}
ObDereferenceObject(FileObject);//放弃对FileObject的引用
}
}
//“返回”到真正的“跳板”处,完成Hook过程
return GoNtCreateSection(SectionHandle,DesiredAccess,ObjectAttributes,SectionSize,Protect,Attributes,FileHandle);
}
BOOLEAN HookFunc(BOOLEAN IsHook){
ULONG Offset;
KIRQL Irql;
ULONG CR0Value;
hde32s hs;
PUCHAR code_pos;
if (IsHook==FALSE && ulHeadLen==0){
return FALSE;
}
KdPrint(("[TrueCell] %s\r\n",IsHook?"Hook":"UnHook"));
Irql=KeRaiseIrqlToDpcLevel();
if (IsHook){
Offset=(ULONG)DetourNtCreateSection-(ULONG)NtCreateSection-5;
RtlCopyMemory(NewFuncHead+1,(PUCHAR)&Offset,4);
code_pos=(PUCHAR )NtCreateSection;
while (ulHeadLen<5){//利用反汇编引擎HDE,解析目标函数位置头部能容纳Hook跳转指令所需空间的大小
RtlZeroMemory(&hs,sizeof(hs));
ulHeadLen+=hde32_disasm(code_pos,&hs);
code_pos+=ulHeadLen;
}
RtlCopyMemory(OriFuncHead,(PUCHAR)NtCreateSection,ulHeadLen);
RtlCopyMemory(GoNtCreateSection,(PUCHAR)NtCreateSection,ulHeadLen);//将目标函数位置头部的指令复制到踏板函数体内
}
_asm{//关闭写保护
cli;
push eax;
mov eax,cr0;
mov CR0Value,eax;
and eax,0xfffeffff;
mov cr0,eax;
pop eax;
}
if (IsHook){
RtlMoveMemory((PUCHAR)NtCreateSection,NewFuncHead,5);
}else{
RtlMoveMemory((PUCHAR)NtCreateSection,OriFuncHead,ulHeadLen);
}
_asm{//重启写保护
push eax;
mov eax,CR0Value;
mov cr0,eax;
pop eax;
sti;
}
KeLowerIrql(Irql);
return TRUE;
}
#pragma once
#include <ntddk.h>
NTSYSAPI
NTSTATUS
NTAPI
NtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle);
NTSTATUS
DetourNtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle);
VOID
TrueCellUnload(IN PDRIVER_OBJECT DriverObject);
BOOLEAN
HookFunc(BOOLEAN IsHook);
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath);
NTSTATUS
IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
OUT POBJECT_NAME_INFORMATION *ObjectNameInformation );
#include "Ncs.h"
#include "hde32.h"
#pragma comment(lib, "hde32.lib")
UCHAR OriFuncHead[12]={0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};//假设目标函数头部有12个字节
UCHAR NewFuncHead[5]={0xE9,0x00,0x00,0x00,0x00};//jmp [相对偏移] 的字节码——奇妙的地方
ULONG ulHeadLen=0;
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath){
KdPrint(("[TrueCell] Driver Entry!\r\n"));
DriverObject->DriverUnload=TrueCellUnload;
return HookFunc(TRUE)?STATUS_SUCCESS:STATUS_UNSUCCESSFUL;
}
VOID TrueCellUnload(IN PDRIVER_OBJECT DriverObject){
HookFunc(FALSE);
KdPrint(("[TrueCell] Driver Unload!\r\n"));
}
_declspec(naked) NTSTATUS
GoNtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle){//跳板
_asm{
nop;// \
nop;// |
nop;// |
nop;// |
nop;// |
nop;// |
nop;// >开辟足够大的空间来容纳NtCreateSection开头的ulHeadlen个字节的机器码
nop;// |
nop;// |
nop;// |
nop;// |
nop;// /
mov eax,NtCreateSection;
add eax,ulHeadLen;
jmp eax
}
}
NTSTATUS
DetourNtCreateSection(OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PLARGE_INTEGER SectionSize OPTIONAL,
IN ULONG Protect,
IN ULONG Attributes,
IN HANDLE FileHandle){//代理函数
PFILE_OBJECT FileObject;
POBJECT_NAME_INFORMATION wcFilePath;
//由Protect判断当前Section是否可执行:一般将要执行的DLL和EXE的都是Section可执行的
if (Protect & (PAGE_EXECUTE|PAGE_EXECUTE_READ|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY) ){
//获取FileHandle对应的FILE_OBJEC——其有我们感兴趣的成员和作用
if (NT_SUCCESS(ObReferenceObjectByHandle(FileHandle,0,NULL,KernelMode,&FileObject,NULL))){//获取文件对象
//获取FileObject对应的文件全路径
if (IoQueryFileDosDeviceName(FileObject,&wcFilePath)==STATUS_SUCCESS){//获取文件对象所对应的文件Dos设备名称,即是全路径
DbgPrint("[TrueCell] %ws\r\n",wcFilePath->Name.Buffer);
ExFreePool(wcFilePath);//IoQueryFileDosDeviceName获取的OBJECT_NAME_INFORMATION 需要手动释放
}
ObDereferenceObject(FileObject);//放弃对FileObject的引用
}
}
//“返回”到真正的“跳板”处,完成Hook过程
return GoNtCreateSection(SectionHandle,DesiredAccess,ObjectAttributes,SectionSize,Protect,Attributes,FileHandle);
}
BOOLEAN HookFunc(BOOLEAN IsHook){
ULONG Offset;
KIRQL Irql;
ULONG CR0Value;
hde32s hs;
PUCHAR code_pos;
if (IsHook==FALSE && ulHeadLen==0){
return FALSE;
}
KdPrint(("[TrueCell] %s\r\n",IsHook?"Hook":"UnHook"));
Irql=KeRaiseIrqlToDpcLevel();
if (IsHook){
Offset=(ULONG)DetourNtCreateSection-(ULONG)NtCreateSection-5;
RtlCopyMemory(NewFuncHead+1,(PUCHAR)&Offset,4);
code_pos=(PUCHAR )NtCreateSection;
while (ulHeadLen<5){//利用反汇编引擎HDE,解析目标函数位置头部能容纳Hook跳转指令所需空间的大小
RtlZeroMemory(&hs,sizeof(hs));
ulHeadLen+=hde32_disasm(code_pos,&hs);
code_pos+=ulHeadLen;
}
RtlCopyMemory(OriFuncHead,(PUCHAR)NtCreateSection,ulHeadLen);
RtlCopyMemory(GoNtCreateSection,(PUCHAR)NtCreateSection,ulHeadLen);//将目标函数位置头部的指令复制到踏板函数体内
}
_asm{//关闭写保护
cli;
push eax;
mov eax,cr0;
mov CR0Value,eax;
and eax,0xfffeffff;
mov cr0,eax;
pop eax;
}
if (IsHook){
RtlMoveMemory((PUCHAR)NtCreateSection,NewFuncHead,5);
}else{
RtlMoveMemory((PUCHAR)NtCreateSection,OriFuncHead,ulHeadLen);
}
_asm{//重启写保护
push eax;
mov eax,CR0Value;
mov cr0,eax;
pop eax;
sti;
}
KeLowerIrql(Irql);
return TRUE;
}