zoukankan      html  css  js  c++  java
  • Ps回调函数.拦截驱动模块原理+实现.

    一丶简介

    主要是讲解.内核中如何拦截模块加载的. 需要熟悉.内核回调的设置
    PE知识. ShellCode

    二丶原理

    1.原理

    原理是通过回调函数. 回调函数中有 ImageBase. 使用PE解析ImageBase 得到OEP. OEP位置写入 ret等ShellCode

    如何判断 是加载DLL 还是加载Sys. 可以看回调的第二个参数.(ProcessId) 如果ProcessId == 0. 则是加载Sys

    PS: 在内核中解析PE需要用到 ntImage.h头文件来进行解析.

    2.代码实现

    #include <ntimage.h>
    #include <ntddk.h>
    
    #include <wdm.h>
    
    ULONG_PTR g_LoadPtr = 0;
    
    
    void WPONx64(KIRQL irql)
    {
    	UINT64 cr0 = __readcr0();
    	cr0 |= 0x10000;
    	_enable();
    	__writecr0(cr0);
    	KeLowerIrql(irql);
    }
    
    
    
    KIRQL WPOFFx64()
    {
    	KIRQL irql = KeRaiseIrqlToDpcLevel();
    	UINT64 cr0 = __readcr0();
    	cr0 &= 0xfffffffffffeffff;
    	__writecr0(cr0);
    	_disable();
    	return irql;
    
    }
    
    
    BOOLEAN Fuck(PVOID pOep)
    {
    	KIRQL kirql;
    
    	if (NULL == pOep)
    		return FALSE;
    
    	//写入字节.
    	
    	UCHAR FuckCode[] = { "xB8x22x00x00xC0xC3" };
    	kirql = WPOFFx64();
    	KdBreakPoint();
    	memcpy(pOep, FuckCode, sizeof(FuckCode) / sizeof(FuckCode[0])); //开头写入拒绝访问错误码让其无法加载即可.
    	WPONx64(kirql);
    	return TRUE;
    }
    //根据ImageBase来获取加载模块的入口点
    PVOID GetImageOep(PVOID ImageBase)
    {
    
    	PVOID pAddressOfEntryPoint = NULL;
    	PIMAGE_DOS_HEADER pDosHead = NULL;
    	PIMAGE_NT_HEADERS pNtHead = NULL;
    	PIMAGE_FILE_HEADER pFileHead = NULL;
    	PIMAGE_OPTIONAL_HEADER pOptHead = NULL;
    
    	//开始解析
    	if (ImageBase == NULL)
    		return NULL;
    
    	pDosHead = (PIMAGE_DOS_HEADER)ImageBase;
    	pNtHead = (PIMAGE_NT_HEADERS)(pDosHead->e_lfanew + (char *)ImageBase);
    	pFileHead = (PIMAGE_FILE_HEADER)&pNtHead->FileHeader;
    	pOptHead = (PIMAGE_OPTIONAL_HEADER)&pNtHead->OptionalHeader;
    
    	//判断是否是PE头
    	if (pDosHead->e_magic != 0x5A4D && pNtHead->Signature != 0x5045)
    		return NULL;
    	pAddressOfEntryPoint = pOptHead->AddressOfEntryPoint + (char *)ImageBase;
    
    	return pAddressOfEntryPoint;
    }
    
    char * MyWideUnicodeStringToMutilString(PUNICODE_STRING uString)
    {
    	ANSI_STRING asStr;
    	char *Buffer = NULL; ;
    	RtlUnicodeStringToAnsiString(&asStr, uString, TRUE);
    	Buffer = ExAllocatePoolWithTag(NonPagedPool, uString->MaximumLength * sizeof(wchar_t), 0);
    	if (Buffer == NULL)
    		return NULL;
    	RtlCopyMemory(Buffer, asStr.Buffer, asStr.Length);
    	return Buffer;
    }
    VOID pSfFilterModule(
    	_In_opt_ PUNICODE_STRING FullImageName,
    	_In_ HANDLE ProcessId,                // pid into which image is being mapped
    	_In_ PIMAGE_INFO ImageInfo
    )
    {
    	/*
    	模块拦截思路:
    	1.通过 PIMAGE_INFO->ImageBase 得到模块的ImageBase
    	2.解析PE头.
    	3.可选头的OEP + ImageBase = 程序运行位置
    	4.在程序开头写入 ret.
    	5.通过参数一,判断是不是我们想要拦截的模块.然后进行1 2 3 4步
    	6.如何判断加载驱动模块还是DLL 根据参数2.ProcessId高低位判断即可. == 0加载驱动模块.否则加载DLL
    	*/
    
    	
    	
    	PVOID pDriverOep = NULL;
    	char *ComPareString = NULL;
    	if (MmIsAddressValid(FullImageName))
    	{
    		
    		if (ProcessId == 0)
    		{
    			//代表拦截驱动模块
    
    			
    
    			//判断名字是否是你想要拦截的.
    			KdBreakPoint();
    			
    			ComPareString = MyWideUnicodeStringToMutilString(FullImageName);
    			if (ComPareString == NULL)
    				return;
    
    			if (strstr(ComPareString,"1.sys"))
    			{
    				KdBreakPoint();
    				KdPrint(("你要拦截的驱动模块名字为: %wZ 
    ", FullImageName));
    				pDriverOep = GetImageOep(ImageInfo->ImageBase);
    
    				//判断拦截的名字是否是你想要拦截的
    				if (pDriverOep != NULL)
    				{
    					Fuck(pDriverOep);
    				}
    			}
    			
    		}
    		//输出调试
    		
    	}
    	
    }
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
    {
    	ULONG iCount = 0;
    	NTSTATUS ntStatus;
    	pDriverObj->DriverUnload = DriverUnLoad;
    	ntStatus = InitDeviceAnSybolicLinkName(pDriverObj);
    	if (!NT_SUCCESS(ntStatus))
    	{
    		return ntStatus;
    	}
    
    	ntStatus = InitDisPatchFunction(pDriverObj);
    	if (!NT_SUCCESS(ntStatus))
    	{
    		return ntStatus;
    	}
    
    
    	PsSetLoadImageNotifyRoutine(pSfFilterModule);
    	return STATUS_SUCCESS;
    }
    
    
    
    
    

    3.效果

    win7 64 sp1 下测试.

  • 相关阅读:
    高盛、沃尔玛 题做出来还挂了的吐槽
    amazon师兄debrief
    到所有人家距离之和最短的中点 296. Best Meeting Point
    问问题没人回答的情况怎么办终于有解了
    找名人 277. Find the Celebrity
    数组生存游戏 289. Game of Life
    547. Number of Provinces 省份数量
    428. Serialize and Deserialize Nary Tree 序列化、反序列化n叉树
    alias别名简介和使用
    面试官:线程池执行过程中遇到异常会发生什么,怎样处理? Vincent
  • 原文地址:https://www.cnblogs.com/iBinary/p/11483446.html
Copyright © 2011-2022 走看看