HOOK SSDT NtOpenProcess 保护进程
2013-12-03 11:31
369 查看
感谢众大神分享的技术,因为几乎没直接用别人的源码,所以就标题原创
但是因为这个技术肯定是前辈们搞出来的,所以就特意说明下,此乃转载耶
模板用的张帆大牛的
记录一下,以后备用
有些许疑惑,不过都解决了:/article/10015553.html
dbgview
Enter DriverEntry
Hook之前调用MmGetSystemRoutineAddress: 0x805CC3FC
Hook之后直接用NtOpenProcess名 805CC3FC
Enter HookSSDTFunction
修改前: HOOK Func addr=0XF7CC2490
修改前: Need Hook addr=0X805CC3FC
修改后: Need Hook addr=0XF7CC2490
Leave HookSSDTFunction
Hook之后调用MmGetSystemRoutineAddress: 0x805CC3FC
Hook之后直接用NtOpenProcess名 805CC3FC
Leave DriverEntry
Enter DriverUnload
Enter DriverUnload
Leave DriverUnload
Enter HookSSDTFunction
修改前: HOOK Func addr=0X805CC3FC
修改前: Need Hook addr=0XF7CC2490
修改后: Need Hook addr=0X805CC3FC
Leave HookSSDTFunction
Leave DriverUnload
得出的结论就是貌似只有调用Zw*函数才会用SSDT表哎。。。。Nt*号函数都是直接用的地址来着
但是因为这个技术肯定是前辈们搞出来的,所以就特意说明下,此乃转载耶
模板用的张帆大牛的
记录一下,以后备用
有些许疑惑,不过都解决了:/article/10015553.html
//本来只是测试MmGetSystemRoutineAddresss函数的,然后发现直接用函数名就可以得到这个地址 //然后就像SSDT HOOK简单测试一下函数地址, //然后HOOK之后就想简单的实现进程保护 //就这样越多了
#ifdef _cplusplus extern "C" { #endif #include <ntddk.h> #ifdef _cplusplus } #endif //定义代码段分页标志 #define PAGEDCODE code_seg("PAGE") #define LOCKEDCODE code_seg() #define INITCODE code_seg("INIT") //定义数据段分页标志 #define PAGEDDATA code_seg("PAGE") #define LOCKEDDATA code_seg() #define INITDATA code_seg("INIT") //定义求数组个数的宏定义 #define arraysize(p) (sizeof(p) / sizeof((p)[0])) //定义设备扩展 typedef struct _DEVICE_EXTENSION{ PDEVICE_OBJECT pDevice; UNICODE_STRING ustrDeviceName; //设备名称 UNICODE_STRING ustrSymLinkName; //符号链接名 }DEVICE_EXTENSION, *PDEVICE_EXTENSION; //函数声明// //初始化时创建设备和符号 NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject); //驱动卸载例程 VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject); //驱动默认分派例程 NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp); typedef NTSTATUS ( *pfnNtOpenProcess)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID); pfnNtOpenProcess OldNtOpenProcess; NTSTATUS MyNtOpenProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesireAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientID); typedef struct _SERVICE_DESCRIPTOR_TABLE { PVOID ServiceTableBase;//System Service Dispatch Table 的基地址 PVOID ServiceCounterTableBase;//包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新 ULONG NumberOfServices;//由 ServiceTableBase 描述的服务的数目 PUCHAR ParamTableBase;//包含每个系统服务参数字节数表的基地址-系统服务参数表 }SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE; extern "C"{ __declspec(dllimport) SERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; }
//看了下调用MmGetSystemRoutineAddress查看函数地址 //顺便SSDT HOOK NtOpenProcess //注释全是测试用 //貌似标准做法是在DriverEntry中int 3 //然后再下断点双机调试 //以后不能用这个打印查看了。。。说不定一下就看见蓝精灵了 #include "Driver.h" NTSTATUS MyNtOpenProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesireAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientID) { //在这了实现进程保护的吧, 话说本来打算根据ObjectName来判断进程名的,但是貌似全是null值 //只能用pid了 //KdPrint(("SSDT HOOK NtOpenProcess Successful!")); NTSTATUS status = STATUS_SUCCESS; //要保护的进程PID LONG pid = 3780; //KdPrint(("ClientID->UniqueProcess = %ld\n", ClientID->UniqueProcess)); //PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)可获得EPROCESS结构 if((long)ClientID->UniqueProcess == pid) { //KdPrint(("Protected PID: %ld\n", pid)); return STATUS_ACCESS_DENIED; } //UNICODE_STRING szProtect; //RtlInitUnicodeString(&szProtect, L"1.exe"); //PUNICODE_STRING szProtect = (PUNICODE_STRING)ExAllocatePool(PagedPool,sizeof(UNICODE_STRING)); //RtlInitUnicodeString(szProtect, L"1.exe"); //_asm int 3; //__try //{ //ProbeForRead(ObjectAttributes->ObjectName, sizeof(UNICODE_STRING), 4); //KdPrint(("%wZ\n", ObjectAttributes->ObjectName)); //if(!RtlCompareUnicodeString(ObjectAttributes->ObjectName, &szProtect, FALSE)) //{ //ExFreePool(((PVOID)szProtect)); // return STATUS_UNSUCCESSFUL; //} //} //__except(EXCEPTION_EXECUTE_HANDLER) //{ status = OldNtOpenProcess(ProcessHandle, DesireAccess, ObjectAttributes, ClientID); //} return status; //ExFreePool((PVOID)szProtect); } //禁用写保护,wp=0 VOID PROTECT() { __asm { cli ; mov eax, cr0 and eax, ~0x10000 mov cr0, eax } } //启用写保护,wp=1 VOID UN_PROTECT() { __asm { mov eax, cr0 or eax, 0x10000 mov cr0, eax sti ; } } PVOID HookSSDTFunction(PVOID OldFunction, PVOID HookFunction) { KdPrint(("Enter HookSSDTFunction\n")); //KdPrint(("KeServiceDescriptorTable.ServiceTableBase=0x%X\n",KeServiceDescriptorTable.ServiceTableBase)); //KdPrint(("KeServiceDescriptorTable.NumberOfServices=0x%X\n",KeServiceDescriptorTable.NumberOfServices)); //PROTECT(); It is sure that if we use PROTECT function, we must change other code too; //我勒个去,我也用英语装逼一下,O(∩_∩)O哈哈~ PMDL pMdl = MmCreateMdl( NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4); if(!pMdl) { KdPrint(("Hook SSDT Failed!\n")); return 0; } MmBuildMdlForNonPagedPool(pMdl); pMdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; PLONG pMdlLocked = (PLONG)MmMapLockedPages(pMdl, KernelMode); //KdPrint(("ServiceTableBase Locked page 0X%X", pMdlLocked)); //网上HOOK 系列都是用的这个来获得和修改地址,原因见下 //OldZwOpenProcess = (ZWOPENPROCESS)(KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PBYTE)ZwOpenProcess+1)]) //lkd> u ZwOpenProcess //nt!ZwOpenProcess: //805016b4 b87a000000 mov eax,7Ah //805016b9 8d542404 lea edx,[esp+4] for(ULONG i = 0; i<KeServiceDescriptorTable.NumberOfServices; i++) { if((LONG)pMdlLocked[i] == (LONG)OldFunction) { //KdPrint(("修改前: HOOK Func addr=0X%X", (LONG)HookFunction)); //KdPrint(("修改前: Need Hook addr=0X%X", (LONG)pMdlLocked[i])); InterlockedExchange(&pMdlLocked[i], (LONG)HookFunction); //KdPrint(("修改后: Need Hook addr=0X%X", (LONG)pMdlLocked[i])); break; } } MmUnmapLockedPages(pMdlLocked, pMdl); IoFreeMdl(pMdl); //UN_PROTECT() KdPrint(("Leave HookSSDTFunction\n")); return OldFunction; } VOID Test(PCWSTR sz) { UNICODE_STRING strToFind; RtlInitUnicodeString(&strToFind, sz); PVOID AddrToFind = MmGetSystemRoutineAddress(&strToFind); if (!AddrToFind); //KdPrint(("MmGetSystemRoutineAddress: %S address is not fount\n", sz)); else; //KdPrint(("Hook之前调用MmGetSystemRoutineAddress: 0x%X\n", AddrToFind)); KdPrint(("Hook之后直接用NtOpenProcess名 %X\n", NtOpenProcess)); //直接用函数名获得的NtOpenProcess的地址和用MmGetSystemRoutineAddress获得的地址一样 //HookSSDTFunction(AddrToFind, MyNtOpenProcess); OldNtOpenProcess = (pfnNtOpenProcess)HookSSDTFunction(NtOpenProcess, MyNtOpenProcess); AddrToFind = MmGetSystemRoutineAddress(&strToFind); //KdPrint(("Hook之后调用MmGetSystemRoutineAddress: 0x%X\n", AddrToFind)); //KdPrint(("Hook之后直接用NtOpenProcess名 %X\n", NtOpenProcess)); } /************************************************************************ * 函数名称:DriverEntry * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象 * 参数列表: pDriverObject:从I/O管理器中传进来的驱动对象 pRegistryPath:驱动程序在注册表的中的路径 * 返回 值:返回初始化驱动状态 *************************************************************************/ #pragma INITCODE extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) { NTSTATUS status; KdPrint(("Enter DriverEntry\n")); //注册其他驱动调用函数 pDriverObject->DriverUnload = DriverUnload; status = CreateDevice(pDriverObject); Test(L"NtOpenProcess"); KdPrint(("Leave DriverEntry\n")); return status; } /************************************************************************ * 函数名称:CreateDevice * 功能描述:初始化设备对象 * 参数列表: pDriverObject:从I/O管理器中传进来的驱动对象 * 返回 值:返回初始化状态 *************************************************************************/ #pragma INITCODE NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject) { NTSTATUS status; PDEVICE_OBJECT pDevObj; PDEVICE_EXTENSION pDevExt; //创建设备名称 UNICODE_STRING devName; UNICODE_STRING symLinkName; RtlInitUnicodeString(&devName, L"\\Device\\MyDDKDevice"); //创建设备 status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj); if(!NT_SUCCESS(status)) return status; pDevObj->Flags |= DO_BUFFERED_IO; pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; pDevExt->pDevice = pDevObj; pDevExt->ustrDeviceName = devName; //创建符号链接 RtlInitUnicodeString(&symLinkName, L"\\??\\MyDDKDevice"); pDevExt->ustrSymLinkName = symLinkName; status = IoCreateSymbolicLink(&symLinkName, &devName); if(!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); return status; } return status; } /************************************************************************ * 函数名称:DriverUnload * 功能描述:负责驱动程序的卸载操作 * 参数列表: pDriverObject:驱动对象 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject) { KdPrint(("Enter DriverUnload")); PDEVICE_OBJECT pNextObj; KdPrint(("Enter DriverUnload")); pNextObj = pDriverObject->DeviceObject; while(pNextObj != NULL) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension; //删除符号链接 UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName; IoDeleteSymbolicLink(&pLinkName); pNextObj = pNextObj->NextDevice; IoDeleteDevice(pDevExt->pDevice); } KdPrint(("Leave DriverUnload")); HookSSDTFunction(MyNtOpenProcess, OldNtOpenProcess); KdPrint(("Leave DriverUnload")); } /************************************************************************ * 函数名称:DispatchRoutine * 功能描述:对读IRP进行处理 * 参数列表: pDevObj:功能设备对象 pIrp:从IO请求包 * 返回 值:返回状态 *************************************************************************/ #pragma PAGEDCODE NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { NTSTATUS status = STATUS_SUCCESS; KdPrint(("Enter DispatchRoutine")); pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); KdPrint(("Leave DispatchRoutine")); return status; }
dbgview
Enter DriverEntry
Hook之前调用MmGetSystemRoutineAddress: 0x805CC3FC
Hook之后直接用NtOpenProcess名 805CC3FC
Enter HookSSDTFunction
修改前: HOOK Func addr=0XF7CC2490
修改前: Need Hook addr=0X805CC3FC
修改后: Need Hook addr=0XF7CC2490
Leave HookSSDTFunction
Hook之后调用MmGetSystemRoutineAddress: 0x805CC3FC
Hook之后直接用NtOpenProcess名 805CC3FC
Leave DriverEntry
Enter DriverUnload
Enter DriverUnload
Leave DriverUnload
Enter HookSSDTFunction
修改前: HOOK Func addr=0X805CC3FC
修改前: Need Hook addr=0XF7CC2490
修改后: Need Hook addr=0X805CC3FC
Leave HookSSDTFunction
Leave DriverUnload
得出的结论就是貌似只有调用Zw*函数才会用SSDT表哎。。。。Nt*号函数都是直接用的地址来着
相关文章推荐
- SSDT HOOK,通过hook NtOpenProcess达到保护制定进程效果
- 内核编程之SSDTHook(2)Hook NtOpenProcess实现进程保护
- HOOK NtOpenProcess 保护指定进程
- 64位下Hook NtOpenProcess的实现进程保护 + 源码 (升级篇 )
- Hook SSDT NtOpenProcess的完整代码
- NtOpenProcess被HOOK,跳回原函数地址后仍然无法看到进程
- 实现hook OpenProcess实现ring3保护进程、代码
- 读取无保护的SSDT表中的NtOpenProcess函数的当前地址
- 新手学ssdt_hook_ntopenprocess
- NtOpenProcess被HOOK,跳回原函数地址后仍然无法看到进程
- NtOpenProcess被HOOK,跳回原函数地址后仍然无法看到进程
- Hook SSDT NtOpenProcess的完整代码
- Hook SSDT NtOpenProcess的完整代码
- 驱动笔记:SSDT HOOK实现进程保护
- 进程隐藏与进程保护(SSDT Hook 实现)(三)
- 进程隐藏与进程保护(SSDT Hook 实现)(三)
- NT内核级进程隐藏2-Hook SSDT及EPROCESS
- 进程隐藏与进程保护(SSDT Hook 实现)(一)
- 进程隐藏与进程保护(SSDT Hook 实现)(一)
- SSDT Hook实现内核级的进程保护