初学驱动,练习着写了一个demo,希望能申请到邀请码,
先看看效果图:
三个函数原型参考(WDK):
NTSYSCALLAPI
NTSTATUS
NTAPI
NtOpenProcess (
__out PHANDLE ProcessHandle, //返回被打开进程的句柄
__in ACCESS_MASK DesiredAccess, //访问权限
__in POBJECT_ATTRIBUTES ObjectAttributes, //对象属性结构
__in_opt PCLIENT_ID ClientId //进程ID
);
NTSYSCALLAPI
NTSYSAPI
NTSTATUS
NTAPI
NtReadVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT PULONG NumberOfBytesRead OPTIONAL
);
NTSYSCALLAPI
NTSYSAPI
NTSTATUS
NTAPI
NtWriteVirtualMemory(
IN HANDLE ProcessHandle,
OUT PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT PULONG NumberOfBytesWritten OPTIONAL
);
以下是main.cpp里面的代码,注释的很详细了:
//如果是C++编译器,就是用C的编译方式,不对代码做改动
#ifdef __cplusplus
extern "C"
{
#endif
#include "ntddk.h"
#ifdef __cplusplus
}
#endif
//定义SSDT结构
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}*PSERVICE_DESCRIPTOR_TABLE;
//运行时链接SSDT结构表,由ntoskrnl.exe导出,,在WINDBG里面可以用dd KeServiceDescriptorTable一步一步查看
extern "C" PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
VOID Hook(); //钩子函数声明
VOID UnHook();//钩子卸载函数
ULONG JmpAddressOpen;//SSDT_hook后,跳转到原来NtOpenProcess的地址后面,即是NtOpenProcess+10的地方 7A
ULONG JmpAddressRead;//SSDT_hook后,跳转到原来NtReadVirtualMemory的地址后面,即是NtReadVirtualMemory+10的地方 BA
ULONG JmpAddressWrite;//SSDT_hook后,跳转到原来NtWriteVirtualMemory的地址后面,即是NtRriteVirtualMemory+10的地方 115
ULONG OldServiceAddressOpen;//真正的NtOpenProcess地址
ULONG OldServiceAddressRead;//真正的NtReadVirtualMemory地址
ULONG OldServiceAddressWrite;//真正的NtWriteVirtualMemory地址
//卸载函数
VOID Unload(PDRIVER_OBJECT driver)
{
DbgPrint("卸载函数....");
UnHook();
}
//声明自己的NtOpenProcess函数,,替换原有函数
_declspec(naked) NTSTATUS _stdcall MyNtOpenProcess(
PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
DbgPrint("NtOpenProcess is called!");
//实现原NtOpenProcess函数的前十字节,并跳转到10字节后面继续执行
__asm{
push 0C4h
push 804F52D8h
jmp JmpAddressOpen
}
}
//声明自己的NtReadVirtualMemory函数,,替换原有函数
_declspec(naked) NTSTATUS _stdcall MyNtReadVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG BufferSize,
OUT PULONG NumberOfBytesRead OPTIONAL)
{
DbgPrint("NtReadVirtualMemory is called!");
//实现原NtReadVirtualMemory函数的前十字节,并跳转到10字节后面继续执行
__asm{
push 1Ch
push 804F6FA8h //共十个字节
jmp JmpAddressRead
}
}
//声明自己的NtWriteVirtualMemory函数,,替换原有函数
_declspec(naked) NTSTATUS _stdcall MyNtWriteVirtualMemory(
IN HANDLE ProcessHandle,
OUT PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT PULONG NumberOfBytesWritten OPTIONAL)
{
DbgPrint("NtWriteVirtualMemory is called!");
//实现原NtWriteVirtualMemory函数的前十字节,并跳转到10字节后面继续执行
__asm{
push 1Ch
push 804F6FC0h //共十个字节
jmp JmpAddressWrite
}
}
//入口函数
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
//#ifdef DEBUG
// __asm
// int 3 //如果是调试模式,就断下
//#endif
DriverObject->DriverUnload=Unload; //注册卸载函数
DbgPrint("Unhooker load.....");
Hook();
return STATUS_SUCCESS;
}
VOID Hook()
{
//三个地址分别保存真实函数的地址
ULONG AddressOpen,AddressRead,AddressWrite;
//HOOK前,获取被HOOK的函数的真实地址
AddressOpen=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x7A*4;
AddressRead=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0xBA*4;
AddressWrite=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x115*4;
//把真实地址保存,以便以后恢复
OldServiceAddressOpen=*(ULONG *)AddressOpen;
OldServiceAddressRead=*(ULONG *)AddressRead;
OldServiceAddressWrite=*(ULONG *)AddressWrite;
//打印真实函数地址
DbgPrint("OldServiceAddressOpen:0x%08X",OldServiceAddressOpen);
DbgPrint("OldServiceAddressRead:0x%08X",OldServiceAddressRead);
DbgPrint("OldServiceAddressWrite:0x%08X",OldServiceAddressWrite);
//打印自己的函数的地址
DbgPrint("MyNtOpenProcess:0x%08X",MyNtOpenProcess);
DbgPrint("MyNtReadVirtualMemory:0x%08X",MyNtReadVirtualMemory);
DbgPrint("MyNtWriteVirtualMemory:0x%08X",MyNtWriteVirtualMemory);
//计算出HOOK后腰跳转的地址
JmpAddressOpen =OldServiceAddressOpen + 10;
JmpAddressRead= OldServiceAddressRead + 10;
JmpAddressWrite =OldServiceAddressWrite + 10;
//打印跳转后的地址
DbgPrint("JmpAddressOpen:0x%08X",JmpAddressOpen);
DbgPrint("JmpAddressRead:0x%08X",JmpAddressRead);
DbgPrint("JmpAddressWrite:0x%08X",JmpAddressWrite);
//去掉内存保护
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//跳转!!
*((ULONG*)AddressOpen) = (ULONG)MyNtOpenProcess;//HOOK SSDT
*((ULONG*)AddressRead) = (ULONG)MyNtReadVirtualMemory;
*((ULONG*)AddressWrite) = (ULONG)MyNtWriteVirtualMemory;
//恢复内存保护
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
//恢复被HOOK的函数
VOID UnHook()
{
//三个地址分别保存真实函数的地址
ULONG AddressOpen,AddressRead,AddressWrite;
//HOOK前,获取HOOK的函数的地址
AddressOpen=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x7A*4;
AddressRead=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0xBA*4;
AddressWrite=(ULONG)(KeServiceDescriptorTable->ServiceTableBase)+0x115*4;
//去掉内存保护
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//跳!!!
*((ULONG*)AddressOpen) = (ULONG)OldServiceAddressOpen;//还原SSDT
*((ULONG*)AddressRead) = (ULONG)OldServiceAddressRead;
*((ULONG*)AddressWrite) = (ULONG)OldServiceAddressWrite;
//恢复内存保护
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
DbgPrint("Unhook....");
}
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
上传的附件: