首页
社区
课程
招聘
[原创枚举内核符号,定位未导出函数地址
发表于: 2018-10-24 12:37 8611

[原创枚举内核符号,定位未导出函数地址

2018-10-24 12:37
8611

这几天在学习内核开发,当定位一些未导出函数时比较麻烦,特地写了一个内核符号文件搜索符号的代码,现在开放出来给大家用,技术太菜,欢迎大佬指导。

编译选择64位
其中编译时要用到了dbghelp.lib

另外要用到 DIA SDK(在visual studio 文件目录下可以找到)

下面是源码:
const char*sympath = "SRV*C:\\Symbols*http://msdl.microsoft.com/download/symbols";
HANDLE hSym= (HANDLE)0xDEADC0DE;
DWORD64 dllBase = NULL;
char* SymbolFile = NULL;
const wchar_t *g_szFilename;
IDiaDataSource *g_pDiaDataSource;
IDiaSession *g_pDiaSession;
IDiaSymbol *g_pGlobalSymbol;
DWORD g_dwMachineType = CV_CFL_80386;
typedef BOOL
(CALLBACK *EnumSymbolsCallBack)(
_In_ wchar_t* Name,
PVOID address);

_EXTERN_C
bool LoadDataFromPdb(
const wchar_t    *szFilename,
IDiaDataSource  **ppSource,
IDiaSession     **ppSession,
IDiaSymbol      **ppGlobal);
BOOL CALLBACK SymRegisterCallbackProc64(
HANDLE hProcess,
ULONG ActionCode,
ULONG64 CallbackData,
ULONG64 UserContext
)
{
switch (ActionCode)
{
case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
return FALSE;
case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
{
char buffer[MAX_PATH];
if (SearchTreeForFile("C:\\Symbols", "ntkrnlmp.pdb", buffer))
{
SymbolFile = buffer;
}
else if (SearchTreeForFile("C:\\Symbols", "ntoskrnl.pdb", buffer))
{
SymbolFile = buffer;
}
if (SymbolFile != NULL)
{
const size_t cSize = strlen(SymbolFile) + 1;
wchar_t* wc = new wchar_t[cSize];
mbstowcs(wc, SymbolFile, cSize);
if (SymbolFile != NULL)
{
LoadDataFromPdb(wc, &g_pDiaDataSource, &g_pDiaSession, &g_pGlobalSymbol);
}
}
break;
}
default:
break;
}

return TRUE;
}
////////////////////////////////////////////////////////////
// Create an IDiaData source and open a PDB file
//
bool LoadDataFromPdb(
const wchar_t    *szFilename,
IDiaDataSource  **ppSource,
IDiaSession     **ppSession,
IDiaSymbol      **ppGlobal)
{
wchar_t wszExt[MAX_PATH];
const wchar_t *wszSearchPath = L"SRV**\\\\symbols\\symbols"; // Alternate path to search for debug data
DWORD dwMachType = 0;

HRESULT hr = CoInitialize(NULL);

// Obtain access to the provider

hr = CoCreateInstance(__uuidof(DiaSource),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiaDataSource),
(void **)ppSource);

if (FAILED(hr)) {
wprintf(L"CoCreateInstance failed - HRESULT = %08X\n", hr);

return false;
}

_wsplitpath_s(szFilename, NULL, 0, NULL, 0, NULL, 0, wszExt, MAX_PATH);

if (!_wcsicmp(wszExt, L".pdb")) {
// Open and prepare a program database (.pdb) file as a debug data source

hr = (*ppSource)->loadDataFromPdb(szFilename);

if (FAILED(hr)) {
wprintf(L"loadDataFromPdb failed - HRESULT = %08X\n", hr);

return false;
}
}

else {

// Open and prepare the debug data associated with the executable

//hr = (*ppSource)->loadDataForExe(szFilename, wszSearchPath, &callback);

if (FAILED(hr)) {
wprintf(L"loadDataForExe failed - HRESULT = %08X\n", hr);

return false;
}
}

// Open a session for querying symbols

hr = (*ppSource)->openSession(ppSession);

if (FAILED(hr)) {
wprintf(L"openSession failed - HRESULT = %08X\n", hr);

return false;
}

// Retrieve a reference to the global scope

hr = (*ppSession)->get_globalScope(ppGlobal);

if (hr != S_OK) {
wprintf(L"get_globalScope failed\n");

return false;
}

// Set Machine type for getting correct register names

if ((*ppGlobal)->get_machineType(&dwMachType) == S_OK) {
switch (dwMachType) {
case IMAGE_FILE_MACHINE_I386: g_dwMachineType = CV_CFL_80386; break;
case IMAGE_FILE_MACHINE_IA64: g_dwMachineType = CV_CFL_IA64; break;
case IMAGE_FILE_MACHINE_AMD64: g_dwMachineType = CV_CFL_AMD64; break;
}
}

return true;
}


bool __declspec(dllexport) init()
{
BOOL b;
::SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_FAVOR_COMPRESSED);
//::SymSetOptions(SYMOPT_UNDNAME);
b = ::SymInitialize(hSym, sympath, FALSE);
if (!b)
{
return false;
}
SymRegisterCallback64(hSym, SymRegisterCallbackProc64, NULL);
return true;
}
bool __declspec(dllexport) Ubloadsymbol()
{
::SymUnloadModule64(hSym, dllBase);
SymbolFile=NULL;
dllBase = NULL;
::SymCleanup(hSym);
if (g_pGlobalSymbol) {
g_pGlobalSymbol->Release();
g_pGlobalSymbol = NULL;
}

if (g_pDiaSession) {
g_pDiaSession->Release();
g_pDiaSession = NULL;
}
CoUninitialize();
return true;
}

bool __declspec(dllexport) LoadSymbolModule() 
{
HMODULE imagebase;
char *FullName, *rootName=NULL;
DWORD64 moduleBase;
PULONG_PTR driverBase;
DWORD dummy, numOfDrivers;
bool b;
driverBase = new ULONG_PTR[1024];

if (!::EnumDeviceDrivers((PVOID *)driverBase, sizeof(ULONG_PTR) * 1024, &dummy)) {
delete[] driverBase;
return false;
}
numOfDrivers = dummy / sizeof(ULONG_PTR);

FullName = new char[MAX_PATH];
b = false;
for (DWORD i = 0; i < numOfDrivers; i++) {
if (::GetDeviceDriverBaseNameA((PVOID)driverBase[i], FullName, MAX_PATH)) {
if (!::_strnicmp("ntoskrnl.exe", FullName, MAX_PATH)) {
::GetDeviceDriverFileNameA((PVOID)driverBase[i], FullName, MAX_PATH);
moduleBase = driverBase[i];
dllBase = driverBase[i];
rootName = new char[MAX_PATH];
if (!::_strnicmp(FullName, "\\SystemRoot\\", strlen("\\SystemRoot\\"))) {
::GetWindowsDirectoryA(rootName, MAX_PATH);
::strcat_s(rootName, MAX_PATH, &FullName[strlen("\\SystemRoot")]);

}
else {
::GetEnvironmentVariableA("SystemDrive", rootName, MAX_PATH);
::strcat_s(rootName, MAX_PATH, FullName);
}
b = true;
break;
}
}
}

if (!b) {
delete[] FullName;
delete[] driverBase;
return false;
}

if (!::SymLoadModule64(hSym, NULL, rootName, NULL, moduleBase, 0)) {
delete[] FullName;
delete[] driverBase;
delete[] rootName;
return false;
}
return true;
}

ULONG64 __declspec(dllexport) FindSymbolByName(const char* Name) 
{
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
MAX_SYM_NAME * sizeof(TCHAR) +
sizeof(ULONG64) - 1) /
sizeof(ULONG64)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;

if (SymFromName(hSym, Name, pSymbol))
{
return pSymbol->Address;
// SymFromName returned success
}

return NULL;
}

bool __declspec(dllexport) EnumSymbol(EnumSymbolsCallBack callback)
{
DWORD dwSymTag;
DWORD dwRVA;
DWORD dwSeg;
DWORD dwOff;
BSTR bstrName;
ULONG64 address;
IDiaEnumSymbols *pEnumSymbols;
BSTR bstrUndname;
if (FAILED(g_pGlobalSymbol->findChildren(SymTagPublicSymbol, NULL, nsNone, &pEnumSymbols))) 
{
return false;
}
IDiaSymbol *pSymbol;
ULONG celt = 0;
while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) 
{
if (pSymbol->get_symTag(&dwSymTag) != S_OK) 
{
continue;
}
if (pSymbol->get_relativeVirtualAddress(&dwRVA) != S_OK) 
{
dwRVA = 0xFFFFFFFF;
}
address = dllBase + dwRVA;
if (pSymbol->get_name(&bstrName) == S_OK) 
{
if (pSymbol->get_undecoratedName(&bstrUndname) == S_OK)
{
//wprintf(L"%s(%s)\n", bstrName, bstrUndname);
SysFreeString(bstrUndname);
}
callback(bstrName, (PVOID)address);
//PrintPublicSymbol(pSymbol);
SysFreeString(bstrName);
pSymbol->Release();
}
}
pEnumSymbols->Release();
return true;
}


_END_EXTERN_C
const char*sympath = "SRV*C:\\Symbols*http://msdl.microsoft.com/download/symbols";
HANDLE hSym= (HANDLE)0xDEADC0DE;
DWORD64 dllBase = NULL;
char* SymbolFile = NULL;
const wchar_t *g_szFilename;
IDiaDataSource *g_pDiaDataSource;
IDiaSession *g_pDiaSession;
IDiaSymbol *g_pGlobalSymbol;
DWORD g_dwMachineType = CV_CFL_80386;
typedef BOOL
(CALLBACK *EnumSymbolsCallBack)(
_In_ wchar_t* Name,
PVOID address);

_EXTERN_C
bool LoadDataFromPdb(
const wchar_t    *szFilename,
IDiaDataSource  **ppSource,
IDiaSession     **ppSession,
IDiaSymbol      **ppGlobal);
BOOL CALLBACK SymRegisterCallbackProc64(
HANDLE hProcess,
ULONG ActionCode,
ULONG64 CallbackData,
ULONG64 UserContext
)
{
switch (ActionCode)
{
case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
return FALSE;
case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
{
char buffer[MAX_PATH];
if (SearchTreeForFile("C:\\Symbols", "ntkrnlmp.pdb", buffer))
{
SymbolFile = buffer;
}
else if (SearchTreeForFile("C:\\Symbols", "ntoskrnl.pdb", buffer))
{
SymbolFile = buffer;
}
if (SymbolFile != NULL)
{
const size_t cSize = strlen(SymbolFile) + 1;
wchar_t* wc = new wchar_t[cSize];
mbstowcs(wc, SymbolFile, cSize);
if (SymbolFile != NULL)
{
LoadDataFromPdb(wc, &g_pDiaDataSource, &g_pDiaSession, &g_pGlobalSymbol);
}
}
break;
}
default:
break;
}

return TRUE;
}
////////////////////////////////////////////////////////////
// Create an IDiaData source and open a PDB file
//
bool LoadDataFromPdb(
const wchar_t    *szFilename,
IDiaDataSource  **ppSource,
IDiaSession     **ppSession,
IDiaSymbol      **ppGlobal)
{
wchar_t wszExt[MAX_PATH];
const wchar_t *wszSearchPath = L"SRV**\\\\symbols\\symbols"; // Alternate path to search for debug data
DWORD dwMachType = 0;

HRESULT hr = CoInitialize(NULL);

// Obtain access to the provider

hr = CoCreateInstance(__uuidof(DiaSource),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IDiaDataSource),
(void **)ppSource);

if (FAILED(hr)) {
wprintf(L"CoCreateInstance failed - HRESULT = %08X\n", hr);

return false;
}

_wsplitpath_s(szFilename, NULL, 0, NULL, 0, NULL, 0, wszExt, MAX_PATH);

if (!_wcsicmp(wszExt, L".pdb")) {
// Open and prepare a program database (.pdb) file as a debug data source

hr = (*ppSource)->loadDataFromPdb(szFilename);

if (FAILED(hr)) {
wprintf(L"loadDataFromPdb failed - HRESULT = %08X\n", hr);

return false;
}
}

else {

// Open and prepare the debug data associated with the executable

//hr = (*ppSource)->loadDataForExe(szFilename, wszSearchPath, &callback);

if (FAILED(hr)) {
wprintf(L"loadDataForExe failed - HRESULT = %08X\n", hr);

return false;
}
}

// Open a session for querying symbols

hr = (*ppSource)->openSession(ppSession);

if (FAILED(hr)) {
wprintf(L"openSession failed - HRESULT = %08X\n", hr);

return false;
}

// Retrieve a reference to the global scope

hr = (*ppSession)->get_globalScope(ppGlobal);

if (hr != S_OK) {
wprintf(L"get_globalScope failed\n");

return false;
}

// Set Machine type for getting correct register names

if ((*ppGlobal)->get_machineType(&dwMachType) == S_OK) {
switch (dwMachType) {
case IMAGE_FILE_MACHINE_I386: g_dwMachineType = CV_CFL_80386; break;
case IMAGE_FILE_MACHINE_IA64: g_dwMachineType = CV_CFL_IA64; break;
case IMAGE_FILE_MACHINE_AMD64: g_dwMachineType = CV_CFL_AMD64; break;
}
}

return true;
}


bool __declspec(dllexport) init()
{
BOOL b;
::SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_FAVOR_COMPRESSED);
//::SymSetOptions(SYMOPT_UNDNAME);
b = ::SymInitialize(hSym, sympath, FALSE);
if (!b)
{
return false;
}
SymRegisterCallback64(hSym, SymRegisterCallbackProc64, NULL);
return true;
}
bool __declspec(dllexport) Ubloadsymbol()
{
::SymUnloadModule64(hSym, dllBase);
SymbolFile=NULL;
dllBase = NULL;
::SymCleanup(hSym);
if (g_pGlobalSymbol) {
g_pGlobalSymbol->Release();

[峰会]看雪.第八届安全开发者峰会10月23日上海龙之梦大酒店举办!

最后于 2018-10-26 09:07 被whathhh编辑 ,原因: 添加一些使用说明
上传的附件:
收藏
免费 1
支持
分享
最新回复 (7)
雪    币: 712
活跃值: (121)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
大家有什么问题,可以在下面问啊
2018-10-26 09:13
0
雪    币: 177
活跃值: (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
有什么参考书籍?
2018-12-7 12:47
0
雪    币: 712
活跃值: (121)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
vs安装目录下面有代码可以参考 叫 dia2sdk
2018-12-12 13:25
0
雪    币: 31
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
if (SymFromName(hSym, Name, pSymbol))
       {
               return pSymbol->Address;
               // SymFromName returned success
       }
       printf("SymFromName %d\n", GetLastError()); 这里总是报126错误
2019-6-2 09:14
0
雪    币: 712
活跃值: (121)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
freesec if (SymFromName(hSym, Name, pSymbol)) { return pSymbol->Address; // SymFromName returned ...
我代码比较烂,可以参考github 上blackBone里面的代码
2019-6-4 08:52
0
雪    币: 479
活跃值: (411)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
7
请问能简略描述下思路吗
2019-12-23 09:28
0
雪    币: 712
活跃值: (121)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
肆零柒柒 请问能简略描述下思路吗
Microsoft Visual Studio\2017\Professional\DIA SDK 这个文件夹下有头文件和实列
2019-12-26 10:50
0
游客
登录 | 注册 方可回帖
返回
//