利用Debug Help Library定位Windows NT内核未导出的函数和结构体 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

利用Debug Help Library定位Windows NT内核未导出的函数和结构体

fanyeee 系统安全 2018-03-08 10:19:39
272477
收藏

导语:我们该如何获得没有被Windows NT内核所导出的函数和结构体的虚拟地址呢?

获得没有被Windows NT内核所导出的函数和结构体的虚拟地址

众所周知,许多函数和结构体都没有被Windows NT内核所导出,例如PsGetNextProcess函数、KeServiceDescriptorTable等等。那么,我们该如何获得这些函数和结构体的虚拟地址呢?

为此,我们可以通过模式匹配来查找函数内部的特定函数或结构体,但是这种查找方式并不可靠,因为微软一旦对这些函数或结构体进行了修改,原来的模式匹配算法就失效了。

那么,使用Microsoft的Debug Help Library怎么样呢?

我们可以利用它来访问可执行文件(如%systemroot%/system32/ntoskrnl.exe)的符号调试信息,提取所需函数/结构体的RVA并添加到nt的地址。

比如,可以使用Psapi的EnumDeviceDrivers获取ntoskrnl.exe的地址,使用SymFromName获取函数/结构体的符号信息。

如果目标系统没有任何含有调试信息的可执行文件,如symchk.exe,SymSrv.dll等。那么,要获取包含ntoskrnl.exe调试信息的.pdb文件,则需要使用symchk.exe手动下载:

01.png

我们可以在Windows 10的C:\Program Files (x86)\Windows Kits\10\Debuggers\x64目录下找到symchk.exe,它会用到SymbolCheck.dll、SymSrv.dll和DbgHelp.dll。

将所有必要的文件嵌入到一个可执行文件,并在运行时将其提取出来是一个不错的选择。我们需要用到下列可执行文件:DbgHelp.dll、SymbolCheck.dll、symchk.exe和SymSrv.dll

示例源代码如下所示:

// Get ntoskrn.exe address at run-time
VOID* krnlAddr; // First element of the array is base address of ntoskrnl.exe/nt
DWORD retLen;
if (!EnumDeviceDrivers(&krnlAddr, sizeof(krnlAddr), &retLen))
         return GetLastError();
HANDLE procHandle = GetCurrentProcess();
if (!SymInitialize(procHandle, nullptr, FALSE)) {
         auto er = GetLastError();
         printf_s("SymInitialize error: %d\n", er);
         return er;
}
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
         MAX_SYM_NAME * sizeof(TCHAR) +
         sizeof(ULONG64) - 1) /
         sizeof(ULONG64)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
STARTUPINFO sa{ sizeof(STARTUPINFO)};
PROCESS_INFORMATION pi{};
TCHAR execSrv[] = L"./symchk.exe /v c:\\Windows\\System32\\ntoskrnl.exe /oc .";
if (!CreateProcess(nullptr, execSrv, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &sa, &pi)) {
         return GetLastError();
}
WaitForSingleObject(pi.hProcess, INFINITE);
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
CHAR symName[MAX_SYM_NAME] = "KeServiceDescriptorTable"; // change it
auto baseAddr = SymLoadModuleEx(procHandle, nullptr, "%systemroot%\\system32\\ntoskrnl.exe", nullptr, 0, 0, nullptr, 0);
if (!SymFromName(procHandle, symName, pSymbol)) {
         auto er = GetLastError();
         if (er == ERROR_MOD_NOT_FOUND)
                   puts("The specified module could not be found\n");
         printf_s("SymFromName error: %d\n", er);
         return er;
}
auto symAddr = (pSymbol->Address - baseAddr) + (DWORD64)krnlAddr;
printf_s("Virtual address of %s: 0x%llx\n", symName, symAddr);
SymCleanup(procHandle);

本方法的优点:

· 在正确的环境下,我们能得到准确的信息

· 跨平台

本方法的缺点:

· 我们需要用到用户模式进程

· 我们需要互联网连接

· 由于包含多个可执行文件,用户模式应用程序占用空间比较大

感谢您阅读本文…

  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务