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

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

时间:2022-10-25 08:11:18浏览次数:58  
标签:模块 ImageInfo 映像 ModuleStyle 内核 FullImageName 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: [email protected]
#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;
}

运行这个驱动程序,则会输出被加载的驱动详细参数。

标签:模块,ImageInfo,映像,ModuleStyle,内核,FullImageName,LoadImage,回调,加载
From: https://www.cnblogs.com/LyShark/p/16818943.html

相关文章

  • 驱动开发:内核无痕隐藏自身分析
    在笔者前面有一篇文章《驱动开发:断链隐藏驱动程序自身》通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了一个作者介绍的一种......
  • openGemini内核源码正式对外开源
    摘要:openGemini是一个开源的分布式时序数据库系统,可广泛应用于物联网、车联网、运维监控、工业互联网等业务场景,具备卓越的读写性能和高效的数据分析能力。本文分享自华为......
  • CentOS 7 升级内核及修改默认启动内核
    CentOS7的内核升级及修改默认启动的内核,操作备档http://elrepo.org/tiki/HomePage导入公钥:rpm--import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org Toinst......
  • ubuntu系统查看内核,升级内核,删除内核,切换内核
    1.查看内核列表sudodpkg--get-selections|greplinux-image2.查看当前使用的内核uname-r3.删除内核tips:删除当前版本重启会使用低一级的已安装内核,如......
  • 驱动开发:内核注册并监控对象回调
    在笔者上一篇文章《驱动开发:内核枚举进程与线程ObCall回调》简单介绍了如何枚举系统中已经存在的进程与线程回调,本章LyShark将通过对象回调实现对进程线程的句柄监控,在内核......
  • 驱动开发:内核监控进程与线程回调
    在前面的文章中LyShark一直在重复的实现对系统底层模块的枚举,今天我们将展开一个新的话题,内核监控,我们以监控进程线程创建为例,在Win10系统中监控进程与线程可以使用微软提供......
  • 驱动开发:内核监控进程与线程回调
    在前面的文章中LyShark一直在重复的实现对系统底层模块的枚举,今天我们将展开一个新的话题,内核监控,我们以监控进程线程创建为例,在Win10系统中监控进程与线程可以使用微软提......
  • 驱动开发:内核测试模式过DSE签名
    微软在x64系统中推出了DSE保护机制,DSE全称(DriverSignatureEnforcement),该保护机制的核心就是任何驱动程序或者是第三方驱动如果想要在正常模式下被加载则必须要经过微软......
  • 内核定时器以及应用
    1.内核定时器的作用当中断触发时,修改定时器时间间隔,进入定时器回调函数,待完成回调则恢复。 2.定时器嵌入其他数据结构   structtimer_listtimer,这个结构......
  • 驱动开发:内核枚举进程与线程ObCall回调
    在笔者上一篇文章《驱动开发:内核枚举Registry注册表回调》中我们通过特征码定位实现了对注册表回调的枚举,本篇文章LyShark将教大家如何枚举系统中的ProcessObCall进程回调......