刚学驱动,有兴趣从网上找了份过d_N_f的驱动代码,按照自己机器上的地址把代码改了改,编译成功,但驱动一启动就蓝屏,蓝屏代码为7E,搞了半天也不知道哪里出错了,请各位大大们帮俺看看吧,(另:纯属个人兴趣,没有别的意思)
贴出源代码:
#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 MyGetFunAddress( IN PCWSTR FunctionName)
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
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 0x804DA4E0
mov edx,0x80538F40
jmp edx
}
}
//写内存
static __declspec(naked) NTSTATUS __stdcall MyNtWriteVirtualMemory(HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
ULONG NumberOfBytesToWrite,
PULONG NumberOfBytesReaded)
{
//跳过去
__asm
{
push 0x1C
push 0x804DA4F8
mov edx,0x80538F40
jmp edx
}
}
BYTE *ObOpenObjectByPointerAddress = NULL;
static __declspec(naked) VOID MyFunction() //NtOpenProcess调用ObOpenObjectByPointer的处理
{
__asm
{
push eax
push dword ptr [ebp-38h]
push dword ptr [ebp-24h]
}
//获得访问者的EPROCESS
processEPROCESS = IoGetCurrentProcess();
ObOpenObjectByPointerAddress = (BYTE*)MyGetFunAddress(L"ObOpenObjectByPointer");
//将调用者的进程名保存到p_str2中
RtlInitAnsiString(&p_str2,(PCSZ)((ULONG)processEPROCESS+0x174));
if (RtlCompareString(&p_str1,&p_str2,TRUE) == 0)
{
//说明是DNF进程访问了这里,让其调用TP模块的函数跟Ring3通信,不被报非法模块
__asm
{
push 0x805C253F
mov edx,0x805C253B
mov edx,dword ptr [edx]
add edx,0x805C253F
jmp edx //TP模块的函数,DNF程序不从这里过,就报非法模块
}
}
else
{
//说明是其他进程访问了这里,直接调用ObOpenObjectByPointer,CE就可以附加了
__asm
{
push 0x805C253F
mov edx,ObOpenObjectByPointerAddress //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();
ObOpenObjectByPointerAddress = (BYTE*)MyGetFunAddress(L"ObOpenObjectByPointer");
//将调用者的进程名保存到p_str3中
RtlInitAnsiString(&p_str3,(PCSZ)((ULONG)TprocessEPROCESS+0x174));
if (RtlCompareString(&p_str1,&p_str3,TRUE) == 0)
{
//说明是DNF进程访问了这里,让其调用TP模块的函数跟Ring3通信,不被报非法模块
__asm
{
push 0x805C27C1
mov edx,0x805C27BD
mov edx,dword ptr [edx]
add edx,0x805C27C1
jmp edx //TP模块的函数,DNF程序不从这里过,就报非法模块
}
}
else
{
//说明是其他进程访问了这里,直接调用ObOpenObjectByPointer,但是OD附加就蓝屏
__asm
{
push 0x805C27C1
mov edx,ObOpenObjectByPointerAddress //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)0x805C2533;
CopyCode.bytecode = OldAddress->bytecode;
CopyCode.Address = OldAddress->Address;
CopyCode.JmpEdx = OldAddress->JmpEdx;
//保存原始代码,NtOpenThread调用ObOpenObjectByPointer之前的7个字节
OldAddressT = (PJmpCode)0x805C27B5;
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(("驱动已被卸载..."));
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)