首页 > 其他分享 >驱动开发:内核监视LoadImage映像回调

驱动开发:内核监视LoadImage映像回调

时间:2022-10-30 11:00:41浏览次数:84  
标签:FullImageName ImageInfo 映像 ModuleStyle 内核 模块 LoadImage 回调 加载

在笔者上一篇文章`《驱动开发:内核注册并监控对象回调》`介绍了如何运用`ObRegisterCallbacks`注册`进程与线程`回调,并通过该回调实现了`拦截`指定进行运行的效果,本章`LyShark`将带大家继续探索一个新的回调注册函数,`PsSetLoadImageNotifyRoutine`常用于注册`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映像回调_Windows 内核驱动开发

文章作者:​lyshark​​ (王瑞)
版权声明:本博客文章与代码均为学习时整理的笔记,文章 [均为原创] 作品,转载请 [添加出处] ,您添加出处是我创作的动力!

转载文章请遵守​​《中华人民共和国著作权法》​​相关法律规定或遵守​《署名CC BY-ND 4.0国际》​规范,合理合规携带原创出处转载,如果不携带文章出处,并恶意转载多篇原创文章被本人发现,本人保留起诉权!


标签:FullImageName,ImageInfo,映像,ModuleStyle,内核,模块,LoadImage,回调,加载
From: https://blog.51cto.com/lyshark/5807436

相关文章

  • 驱动开发:内核监控进程与线程回调
    在前面的文章中`LyShark`一直在重复的实现对系统底层模块的枚举,今天我们将展开一个新的话题,内核监控,我们以`监控进程线程`创建为例,在`Win10`系统中监控进......
  • 驱动开发:内核测试模式过DSE签名
    微软在`x64`系统中推出了`DSE`保护机制,DSE全称`(DriverSignatureEnforcement)`,该保护机制的核心就是任何驱动程序或者是第三方驱动如果想要在正常模式......
  • HarmonyOS系统中内核实现温湿度采集方法
      大家好,今天主要来聊一聊,如何使用鸿蒙系统中的温湿度传感器方法。   第一:温湿度传感器基本原理  大部分的传感器是在环境温度变化后会产生一个相应的延伸,因此传......
  • 驱动开发:内核强制结束进程运行
    通常使用Windows系统自带的任务管理器可以正常地结束掉一般进程,而某些特殊的进程在应用层很难被结束掉,例如某些系统核心进程其权限是在0环内核态,但有时我们不得不想办法结......
  • 驱动开发:内核强制结束进程运行
    通常使用Windows系统自带的任务管理器可以正常地结束掉一般进程,而某些特殊的进程在应用层很难被结束掉,例如某些系统核心进程其权限是在0环内核态,但有时我们不得不想办法结束......
  • Linux内核设计与实现 第三版 电子书 pdf
    作者:[美]RobertLove出版社:机械工业出版社原作名:LinuxKernelDevelopment译者:陈莉君/康华 链接:Linux内核设计与实现第三版  本书详细描述了Linux内......
  • 奔跑吧Linux内核 电子书 pdf
    作者:张天飞出版社:人民邮电出版社链接:奔跑吧Linux内核  本书内容基于Linux4.x内核,主要选取了Linux内核中比较基本和常用的内存管理、进程管理、并发与同步,以及......
  • Linux内核完全注释 修正版 电子书 pdf
    作者:赵炯出版社:机械工业出版社 链接:Linux内核完全注释  Linux内核完全注释,ISBN:9787111149682,作者:赵炯编著......
  • 驱动开发:内核监控FileObject文件回调
    本篇文章与上一篇文章《驱动开发:内核注册并监控对象回调》所使用的方式是一样的都是使用ObRegisterCallbacks注册回调事件,只不过上一篇博文中LyShark将回调结构体OB_OPERATI......
  • 用户态和内核态
    那用户态和内核态又是啥呢?Linux系统的体系结构大家大学应该都接触过了,分为用户空间(应用程序的活动空间)和内核。我们所有的程序都在用户空间运行,进入用户运行状态也就是(用户......