驱动开发:内核监视LoadImage映像回调
在笔者上一篇文章《驱动开发:内核注册并监控对象回调》介绍了如何运用ObRegisterCallbacks注册进程与线程回调,并通过该回调实现了拦截指定进行运行的效果,本章LyShark将带大家继续探索一个新的回调注册函数,PsSetLoadImageNotifyRoutine常用于注册LoadImage映像监视,当有模块被系统加载时则可以第一时间获取到加载模块信息,需要注意的是该回调函数内无法进行拦截,如需要拦截则需写入返回指令这部分内容将在下一章进行讲解,本章将主要实现对模块的监视功能。
监视模块加载与卸载需要费别使用两个函数,这两个函数的参数传递都是自己的回调地址。
- PsSetLoadImageNotifyRoutine 设置回调
- PsRemoveLoadImageNotifyRoutine 移除回调
此处MyLySharkLoadImageNotifyRoutine回调地址必须有三个参数传递组成,其中FullImageName代表完整路径,ModuleStyle代表模块类型,一般来说ModuleStyle=0表示加载SYS驱动,如果ModuleStyle=1则表示加载的是DLL,最后一个参数ImageInfo则是映像的详细参数结构体。
VOID MyLySharkLoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ModuleStyle, PIMAGE_INFO ImageInfo)
那么如何实现监视映像加载呢,来看如下完整代码片段,首先PsSetLoadImageNotifyRoutine注册回调,当有模块被加载则自动执行MyLySharkLoadImageNotifyRoutine回调函数,其内部首先判断ModuleStyle得出是什么类型的模块,然后再通过GetDriverEntryByImageBase拿到当前进程详细参数并打印输出。
// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include <ntddk.h>
#include <ntimage.h>
// 未导出函数声明
PUCHAR PsGetProcessImageFileName(PEPROCESS pEProcess);
// 获取到镜像装载基地址
PVOID GetDriverEntryByImageBase(PVOID ImageBase)
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS64 pNTHeader;
PVOID pEntryPoint;
pDOSHeader = (PIMAGE_DOS_HEADER)ImageBase;
pNTHeader = (PIMAGE_NT_HEADERS64)((ULONG64)ImageBase + pDOSHeader->e_lfanew);
pEntryPoint = (PVOID)((ULONG64)ImageBase + pNTHeader->OptionalHeader.AddressOfEntryPoint);
return pEntryPoint;
}
// 获取当前进程名
UCHAR* GetCurrentProcessName()
{
PEPROCESS pEProcess = PsGetCurrentProcess();
if (NULL != pEProcess)
{
UCHAR *lpszProcessName = PsGetProcessImageFileName(pEProcess);
if (NULL != lpszProcessName)
{
return lpszProcessName;
}
}
return NULL;
}
// 设置自己的回调函数
VOID MyLySharkLoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ModuleStyle, PIMAGE_INFO ImageInfo)
{
PVOID pDrvEntry;
// MmIsAddress 验证地址可用性
if (FullImageName != NULL && MmIsAddressValid(FullImageName))
{
// ModuleStyle为零表示加载sys
if (ModuleStyle == 0)
{
// 得到装载主进程名
UCHAR *load_name = GetCurrentProcessName();
pDrvEntry = GetDriverEntryByImageBase(ImageInfo->ImageBase);
DbgPrint("[LyShark SYS加载] 模块名称:%wZ --> 装载基址:%p --> 镜像长度: %d --> 装载主进程: %s \n", FullImageName, pDrvEntry, ImageInfo->ImageSize, load_name);
}
// ModuleStyle非零表示加载DLL
else
{
// 得到装载主进程名
UCHAR *load_name = GetCurrentProcessName();
pDrvEntry = GetDriverEntryByImageBase(ImageInfo->ImageBase);
DbgPrint("[LyShark DLL加载] 模块名称:%wZ --> 装载基址:%p --> 镜像长度: %d --> 装载主进程: %s \n", FullImageName, pDrvEntry, ImageInfo->ImageSize, load_name);
}
}
}
VOID UnDriver(PDRIVER_OBJECT driver)
{
PsRemoveLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)MyLySharkLoadImageNotifyRoutine);
DbgPrint("[LyShark.com] 驱动卸载完成...");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark.com \n");
PsSetLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)MyLySharkLoadImageNotifyRoutine);
DbgPrint("[LyShark.com] 驱动加载完成...");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
运行这个驱动程序,则会输出被加载的驱动详细参数。

驱动开发:内核监视LoadImage映像回调的更多相关文章
- 驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章<驱动开发:内核特征码搜索函数封装>中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核LoadImage映像回调,在Win64环境下我们可以设置一个 ...
- Windows驱动开发-内核常用内存函数
搞内存常用函数 C语言 内核 malloc ExAllocatePool memset RtlFillMemory memcpy RtlMoveMemory free ExFreePool
- 驱动开发:内核运用LoadImage屏蔽驱动
在笔者上一篇文章<驱动开发:内核监视LoadImage映像回调>中LyShark简单介绍了如何通过PsSetLoadImageNotifyRoutine函数注册回调来监视驱动模块的加载,注 ...
- 驱动开发:内核枚举Registry注册表回调
在笔者上一篇文章<驱动开发:内核枚举LoadImage映像回调>中LyShark教大家实现了枚举系统回调中的LoadImage通知消息,本章将实现对Registry注册表通知消息的枚举,与 ...
- 用Visual studio2012在Windows8上开发内核驱动监视线程创建
在Windows NT中,80386保护模式的“保护”比Windows 95中更坚固,这个“镀金的笼子”更加结实,更加难以打破.在Windows 95中,至少应用程序I/O操作是不受限制的,而在Win ...
- 用Visual studio2012在Windows8上开发内核驱动监视进程创建
在Windows NT中,80386保护模式的“保护”比Windows 95中更坚固,这个“镀金的笼子”更加结实,更加难以打破.在Windows 95中,至少应用程序I/O操作是不受限制的,而在Win ...
- 驱动开发:内核监控Register注册表回调
在笔者前一篇文章<驱动开发:内核枚举Registry注册表回调>中实现了对注册表的枚举,本章将实现对注册表的监控,不同于32位系统在64位系统中,微软为我们提供了两个针对注册表的专用内核监 ...
- Win64 驱动内核编程-31.枚举与删除映像回调
枚举与删除映像回调 映像回调可以拦截 RING3 和 RING0 的映像加载.某些游戏保护会用此来拦截黑名单中的驱动加载,比如 XUETR.WIN64AST 的驱动.同理,在反游戏保护的过程中,也可以 ...
- 驱动开发:内核枚举进程与线程ObCall回调
在笔者上一篇文章<驱动开发:内核枚举Registry注册表回调>中我们通过特征码定位实现了对注册表回调的枚举,本篇文章LyShark将教大家如何枚举系统中的ProcessObCall进程回 ...
随机推荐
- Luogu3904 三只小猪 (组合数学,第二类斯特林数,高精)
即使\(n<=50\),斯特林数也会爆long long. #include <iostream> #include <cstdio> #include <cstr ...
- Luogu3092 [USACO13NOV]没有找零No Change (状压DP)
将金币状压,然后就没多说的了. #include <iostream> #include <cstdio> #include <cstring> #include ...
- java-servlet-转发AND路径
转发: a) 什么是转发?一个web组件将未完成的任务交给另一个web组件继续做.通常是一个servlet将数据获取之后转交给jsp进行展现.注:web组件值得是servlet或者jsp b) 如何转 ...
- 什么?WPF 不支持 SVG ?
什么?WPF 不支持 SVG ? 控件名:SharpVectors 作者:Elinam LLC (Japan) 项目地址: https://github.com/ElinamLLC/SharpVect ...
- Flink介绍
1,简介 Flink是Apache基金会旗下的一个开源大数据处理框架.Flink很牛逼,好多牛逼的公司都在用. 2,特征 *高吞吐和低延迟.每秒处理百万个时间,毫秒级延迟.有点既要老婆好,又要彩礼少的 ...
- [CF1515F] Phoenix and Earthquake(图论推导,构造)
题面 在紧张又忙碌地准备联合省选时,发生了大地震,把原本要参赛的 n n n 个城市之间的全部 m m m 条道路震垮了,使得原本互相都能到达的这 n n n 个城市无法交通了.现在,需要紧急恢复 n ...
- 【Manim】关于add_updater的基本使用方法
add_updater(update_function,index=None,call_update=False) 后面两个参数可以不写. update_function更新函数一般填入一个lambd ...
- js实现多条件排序
1.sort排序允许接受一个参数(函数),这个函数接受2个形参a,b,并且通过冒泡的方式比较.例子:Arr.sort((a,b) => a-b); 升序排列Arr.sort((a,b) =& ...
- K8S_总结
K8S 核心组件 配置存储中心 --> etcd服务 主控(master)节点 [1] kube-apiserver 服务 apiserver:(K8S 大脑) 1. 提供了集群管理的 RE ...
- 记一次 .NET 某打印服务 非托管内存泄漏分析
一:背景 1. 讲故事 前段时间有位朋友在微信上找到我,说他的程序出现了内存泄漏,能不能帮他看一下,这个问题还是比较经典的,加上好久没上非托管方面的东西了,这篇就和大家分享一下,话不多说,上 WinD ...