- 注册时间
- 2021-3-9
- 最后登录
- 1970-1-1
该用户从未签到
|
发表于 2021-3-13 16:16:02
|
显示全部楼层
#include <ntddk.h>
#include <windef.h>
#define INITCODE code_seg("INIT") /*运行一次就释放内存*/
#define PAGECODE code_seg("PAGE") /*分页内存*/
VOID CloseMemoryProtect(); //关闭写保护
VOID OpenMemoryProtect(); //开启写保护
VOID MyDriver_Unload(PDRIVER_OBJECT pDriverObject); //卸载函数
#pragma pack(1) //一字节对齐
typedef struct JmpCode {
BYTE bytecode; //0xBA , mov edx,MyFunctionAddress,自定义HOOK类型
ULONG Address; //MyFunctionAddress
USHORT JmpEdx; //D2FF , jmp edx
} JmpCode, *PJmpCode;
#pragma pack()
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry;
extern PServiceDescriptorTableEntry KeServiceDescriptorTable; //SSDT表,声明指针用extern
ULONG Readdizhi,Writedizhi,OldRead,OldWrite; //读,写
JmpCode CopyCode,CopyCodeT; //保存进程,线程被HOOK的代码,以便卸载时恢复
PJmpCode OldAddress,OldAddressT; //要HOOK的进程和线程地址
PEPROCESS processEPROCESS = NULL,TprocessEPROCESS = NULL; //保存访问者的EPROCESS
ANSI_STRING p_str1,p_str2,p_str3; //保存进程名称
//用SSDT HOOK对抗TP保护的INLINE HOOK
//读内存
static __declspec(naked) NTSTATUS __stdcall MyNtReadVirtualMemory(HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
ULONG NumberOfBytesToRead,
PULONG NumberOfBytesReaded)
{
//跳过去
__asm
{
push 0x1C
push 0x804DAEE8
mov edx,0x805B5291
jmp edx
}
}
//写内存
static __declspec(naked) NTSTATUS __stdcall MyNtWriteVirtualMemory(HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
ULONG NumberOfBytesToWrite,
PULONG NumberOfBytesReaded)
{
//跳过去
__asm
{
push 0x1C
push 0x804DAF00
mov edx,0x805B539B
jmp edx
}
}
static __declspec(naked) VOID MyFunction() //NtOpenProcess调用ObOpenObjectByPointer的处理
{
__asm
{
push eax
push dword ptr [ebp-38h]
push dword ptr [ebp-24h]
}
//获得访问者的EPROCESS
processEPROCESS = IoGetCurrentProcess();
//将调用者的进程名保存到p_str2中
RtlInitAnsiString(&p_str2,(PCSZ)((ULONG)processEPROCESS+0x174));
if (RtlCompareString(&p_str1,&p_str2,TRUE) == 0)
{
//说明是DNF进程访问了这里,让其调用TP模块的函数跟Ring3通信,不被报非法模块
__asm
{
push 0x805CC625
mov edx,0x805CC621
mov edx,dword ptr [edx]
add edx,0x805CC625
jmp edx //TP模块的函数,DNF程序不从这里过,就报非法模块
}
}
else
{
//说明是其他进程访问了这里,直接调用ObOpenObjectByPointer,CE就可以附加了
__asm
{
push 0x805CC625
mov edx,0x805BCC6C //ObOpenObjectByPointer
jmp edx
}
}
}
static __declspec(naked) VOID MyFunctionT() //NtOpenThread调用ObOpenObjectByPointer的处理
{
__asm
{
push eax
push dword ptr [ebp-34h]
push dword ptr [ebp-20h]
}
//获得访问者的EPROCESS
TprocessEPROCESS = IoGetCurrentProcess();
//将调用者的进程名保存到p_str3中
RtlInitAnsiString(&p_str3,(PCSZ)((ULONG)TprocessEPROCESS+0x174));
if (RtlCompareString(&p_str1,&p_str3,TRUE) == 0)
{
//说明是DNF进程访问了这里,让其调用TP模块的函数跟Ring3通信,不被报非法模块
__asm
{
push 0x805CC8A7
mov edx,0x805CC8A3
mov edx,dword ptr [edx]
add edx,0x805CC8A7
jmp edx //TP模块的函数,DNF程序不从这里过,就报非法模块
}
}
else
{
//说明是其他进程访问了这里,直接调用ObOpenObjectByPointer,但是OD附加就蓝屏
__asm
{
push 0x805CC8A7
mov edx,0x805BCC6C //ObOpenObjectByPointer
jmp edx
}
}
}
#pragma PAGECODE
VOID CloseMemoryProtect() //去掉页面保护
{
__asm
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
}
#pragma PAGECODE
VOID OpenMemoryProtect() //恢复页面保护
{
__asm
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
#pragma INITCODE
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
ULONG jizhi;
//初始化驱动卸载函数
pDriverObject->DriverUnload = MyDriver_Unload;
jizhi = (ULONG)KeServiceDescriptorTable->ServiceTableBase; //获取SSDT表基址
Readdizhi = jizhi+186*4; //获取NtReadVirtualMemory
OldRead = *(PULONG)Readdizhi; //保存NtReadVirtualMemory原始地址
KdPrint(("Readdizhi地址为 %x",Readdizhi));
Writedizhi = jizhi+277*4; //获取NtWriteVirtualMemory
OldWrite = *(PULONG)Writedizhi; //保存NtWriteVirtualMemory原始地址
KdPrint(("Writedizhi地址为 %x",Writedizhi));
//保存原始代码,NtOpenProcess调用ObOpenObjectByPointer之前的7个字节
OldAddress = (PJmpCode)0x805CC619;
CopyCode.bytecode = OldAddress->bytecode;
CopyCode.Address = OldAddress->Address;
CopyCode.JmpEdx = OldAddress->JmpEdx;
//保存原始代码,NtOpenThread调用ObOpenObjectByPointer之前的7个字节
OldAddressT = (PJmpCode)0x805CC89B;
CopyCodeT.bytecode = OldAddressT->bytecode;
CopyCodeT.Address = OldAddressT->Address;
CopyCodeT.JmpEdx = OldAddressT->JmpEdx;
//将DNF.exe进程名放入p_str1中,以便判断
RtlInitAnsiString(&p_str1,"DNF.exe");
CloseMemoryProtect(); //去掉页面保护
//HOOK绕过TP保护读内存,写内存
*(PULONG)Readdizhi = (ULONG)MyNtReadVirtualMemory;
*(PULONG)Writedizhi = (ULONG)MyNtWriteVirtualMemory;
//HOOK绕过NtOpenProcess调用ObOpenObjectByPointer
OldAddress->bytecode = 0xBA;
OldAddress->Address = (ULONG)MyFunction;
OldAddress->JmpEdx = 0xE2FF;
//HOOK绕过NtOpenThread调用ObOpenObjectByPointer
OldAddressT->bytecode = 0xBA;
OldAddressT->Address = (ULONG)MyFunctionT;
OldAddressT->JmpEdx = 0xE2FF;
OpenMemoryProtect(); //恢复页面保护
KdPrint(("MyFunction地址为 %x",(ULONG)MyFunction));
KdPrint(("MyFunctionT地址为 %x",(ULONG)MyFunctionT));
KdPrint(("驱动加载成功..."));
return STATUS_SUCCESS;
}
#pragma PAGECODE
VOID MyDriver_Unload(PDRIVER_OBJECT pDriverObject)
{
CloseMemoryProtect(); //去掉页面保护
//代码恢复,读内存,写内存
*(PULONG)Readdizhi = OldRead;
*(PULONG)Writedizhi = OldWrite;
//代码恢复
OldAddress->bytecode = CopyCode.bytecode;
OldAddress->Address = CopyCode.Address;
OldAddress->JmpEdx = CopyCode.JmpEdx;
//代码恢复
OldAddressT->bytecode = CopyCodeT.bytecode;
OldAddressT->Address = CopyCodeT.Address;
OldAddressT->JmpEdx = CopyCodeT.JmpEdx;
OpenMemoryProtect(); //恢复页面保护
KdPrint(("驱动已被卸载..."));
} |
|