首页
论坛
课程
招聘
[原创]3rd:告别硬编码,使用符号文件自动解析符号
2011-9-15 16:46 10005

[原创]3rd:告别硬编码,使用符号文件自动解析符号

2011-9-15 16:46
10005
好吧……我承认这个东西很是有骗子的嫌疑
但是我本身就是说放的初级的文章。好东西留着以后再放,还望大家海涵~

符号文件大家应该很熟咯,我就不说什么废话了
具体看DbgHelp库的用法。要想解析符号,只需要做以下几步即可;

1:首先创建一个目录 symsrv.yes文件,据说symsrv.dll会检查,如果存在才允许下载,道听途说的,没有去逆一下,见谅见谅
2:调用SymInitialize初始化,其中必须要传入有效进程句柄,可选传入符号文件搜索路径……如果没有指定这个路径,稍后可以调用SymSetSearchPath来指定
3:欲解析符号前,使用SymGetSymbolFile来取得符号文件,如果搜索路径没有这个文件,那么将从微软服务器下载,然后调用SymLoadModule64加载它咯
4:解析咯

注:很重要的一点,要想从微软符号文件服务器下载东西,第二步符号文件搜索路径时须得指定:
srv* xxxx *http://msdl.microsoft.com/download/symbols
大家都眼熟,就不多说了

PS:我代码里用了一个硬编码,大家见谅,嘿嘿

代码很短,我直接贴上来了
#include <stdio.h>
#include <Windows.h>
#include <DbgHelp.h>

#pragma comment(lib , "DbgHelp.lib")
#pragma comment(lib , "ImageHlp.lib")


PLOADED_IMAGE IMAGEAPI ImageLoad(
	__in  PSTR DllName,
	__in  PSTR DllPath
	);


HANDLE hProcess;
char* url = "http://msdl.microsoft.com/download/symbols";

HANDLE hIn;
HANDLE hOut;

void ChangeOutputTextColor(
	DWORD rgbColor)
{
	SetConsoleTextAttribute ( hOut , FOREGROUND_RED);
}

BOOLEAN InitSymHandler()
{
	HANDLE hfile;
	char Path[MAX_PATH]={0};
	char FileName[MAX_PATH]={0};
	char SymPath[MAX_PATH*2]={0};

	if (!GetCurrentDirectoryA( MAX_PATH ,Path))
	{
		printf ("cannot get current directory \n");
		return FALSE;
	}
	strcpy( FileName , Path);
	strcat(FileName ,"\\symsrv.yes");
	printf ("%s \n",FileName);
	hfile = CreateFileA ( FileName,
						  FILE_ALL_ACCESS,
						  FILE_SHARE_READ,
						  NULL,
						  OPEN_ALWAYS,
						  FILE_ATTRIBUTE_NORMAL,
						  NULL);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		printf ("create or open file error: 0x%X \n",GetLastError());
		return FALSE;
	}
	CloseHandle (hfile);

	hProcess = OpenProcess( PROCESS_ALL_ACCESS,
							 FALSE,
							 4);
	if (hProcess == INVALID_HANDLE_VALUE)
	{
		printf ("Cannot open system process \n");
		return FALSE;
	}
	SymSetOptions ( SYMOPT_CASE_INSENSITIVE | SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);
	strcat(Path,"\\symbols*");
	strcpy(SymPath,"SRV*");
	strcat(SymPath,Path);
	strcat(SymPath,url);

	printf ("%s \n",SymPath);
	SymInitialize( hProcess,
					SymPath,
					FALSE);
	return TRUE;
}

BOOLEAN LoadSymModule(
	char* ImageName,
	DWORD ModuleBase)
{
	DWORD64 tmp;
	char    SymFileName[MAX_PATH]={0};
	PLOADED_IMAGE pli = ImageLoad ( ImageName , NULL);

	if (pli == NULL)
	{
		printf ("cannot get loaded module of %s \n",ImageName);
		return FALSE;
	}


	if (!SymGetSymbolFile( hProcess,
		NULL,
		pli->ModuleName,
		sfPdb,
		SymFileName,
		MAX_PATH,
		SymFileName,
		MAX_PATH))
	{
		printf ("cannot get symbol file of %s ,error: 0x%x \n",ImageName,GetLastError());
		return FALSE;
	}

	tmp =  SymLoadModule64( hProcess,
							pli->hFile,
							pli->ModuleName,
							NULL,
							(DWORD64)ModuleBase,
							pli->SizeOfImage);


	if (!tmp)
	{
		printf ("cannot load module , error : %X \n",GetLastError());
		return FALSE;
	}

	return TRUE;
}


BOOLEAN EnumSyms(
	char* ImageName,
	DWORD ModuleBase,
	PSYM_ENUMERATESYMBOLS_CALLBACK EnumRoutine,
	PVOID Context)
{
	BOOLEAN bEnum;

	if ( !LoadSymModule( ImageName , ModuleBase) )
	{
		return FALSE;
	}

	bEnum = SymEnumSymbols( hProcess,
							ModuleBase,
							NULL,
							EnumRoutine,
							Context);
	if (!bEnum)
	{
		printf ("cannot enum symbols ,error: %x \n",GetLastError());
	}

	return bEnum;
}

BOOLEAN CALLBACK EnumSymRoutine(
	PSYMBOL_INFO psi,
	ULONG		 SymSize,
	PVOID		 Context)
{
	printf ("%s : 0x%X \n",psi->Name,psi->Address);

	return TRUE;
}

int main(void)
{

	hIn = GetStdHandle ( STD_INPUT_HANDLE);
	hOut = GetStdHandle (STD_OUTPUT_HANDLE);

	if (!InitSymHandler ())
	{
		goto __exit;
	}
	;
	//ChangeOutputTextColor (4);

	EnumSyms("ntkrnlpa.exe", 0x804d8000,(PSYM_ENUMERATESYMBOLS_CALLBACK)EnumSymRoutine,NULL);
__exit:
	getchar();
}

[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

收藏
点赞0
打赏
分享
最新回复 (6)
雪    币: 37
活跃值: 活跃值 (185)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
skypismire 活跃值 1 2011-9-15 17:20
2
0
瞅瞅......好像不错哦
雪    币: 2933
活跃值: 活跃值 (2217)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2012-6-27 16:32
3
0
强力支持
雪    币: 705
活跃值: 活跃值 (51)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
半道出家 活跃值 2012-6-30 10:59
4
0
hProcess = OpenProcess( PROCESS_ALL_ACCESS,
FALSE,
4);
if (hProcess == INVALID_HANDLE_VALUE)
{
printf ("Cannot open system process \n");
return FALSE;
}

猛了点,hProcess的判断也不对。
雪    币: 4493
活跃值: 活跃值 (1099)
能力值: ( LV8,RANK:129 )
在线值:
发帖
回帖
粉丝
yimingqpa 活跃值 1 2012-6-30 12:22
5
0
  这货只能判断没导出的函数吧?
俺研究了很久了不知道是俺写的有问题还是本来只能解析没导出的函数.
#pragma once
#ifndef PDBDATA_H
#define PDBDATA_H
#include "KillProtectDll.h"
#include "..\\KillProtect\\struct.h"
#include <fstream>
;using namespace std;

class PDBData
{
private:
        wchar_t ch_path[MAX_PATH];
protected:
public:
        PDBData();
        ~PDBData();
        wchar_t* GetPDBPath();
        BOOL Symbol_View(char* ch_Module,DWORD64 BaseAddr,DWORD FileSize);
        BOOL WcharToAchar(wchar_t* ch_temp,char* ch_temp1);
        ULONG EnumModule(wchar_t* ch_ModuleName,BOOL b_open);
};

#endif
//------------------------------------------
#include "PDBData.h"

PDBData::PDBData()
{
        ZeroMemory(ch_path,MAX_PATH);
}

PDBData::~PDBData()
{

}

wchar_t* PDBData::GetPDBPath()
{
        ::GetModuleFileName(::GetModuleHandle(DLL_Name),ch_path,MAX_PATH);
        ::PathRemoveFileSpec(ch_path);
        ::PathAppend(ch_path,PDB_Path);
        return ch_path;
}

char* ch_Name[]={"PsTerminateProcess","PsGetNextProcess","PsGetNextProcessThread"};
_FuncCou FunCont[100];
int in_Count=0;
BOOL CALLBACK EnumSymCallBack( PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext )
{
        for(unsigned int i=0;i<3;i++)
        {
                if(strcmp(pSymInfo->Name,ch_Name[i])==0)
                {
                        ZeroMemory(&FunCont[in_Count],sizeof(FunCont[in_Count]));
                        ::memcpy(FunCont[in_Count].ch_FunName,pSymInfo->Name,strlen(pSymInfo->Name)+1);
                        FunCont[in_Count].dw_Addr=pSymInfo->Address;
                        in_Count++;
                }
        }       
        return TRUE;
}

BOOL PDBData::Symbol_View(char* ch_Module,DWORD64 BaseAddr,DWORD FileSize)
{
        PIMAGEHLP_SYMBOL pSymbol=NULL;
        DWORD Options=::SymGetOptions();
        Options=Options|SYMOPT_DEBUG;
        ::SymSetOptions(Options);
        HANDLE hProcess=::GetCurrentProcess();
        BOOL bRet=::SymInitialize(hProcess,0,FALSE);
        if(!bRet)
        {
                return FALSE;
        }
        char SymbolPath[MAX_PATH];
        ::GetCurrentDirectoryA(MAX_PATH,SymbolPath);
        ::PathAppendA(SymbolPath,PDB_PathA);
        ::SymSetSearchPath(hProcess,SymbolPath);
        char FileName[MAX_PATH] ;
        ::GetSystemDirectoryA(FileName,MAX_PATH);
        ::PathAppendA(FileName,ch_Module);
        DWORD64 BaseOfDll=::SymLoadModule64(hProcess,NULL,FileName,NULL,BaseAddr,FileSize);
        if(BaseOfDll == 0)
        {
                return FALSE;
        }
        ::SymEnumSymbols(hProcess,BaseOfDll,0,EnumSymCallBack,0);
        ::SymUnloadModule64(hProcess,BaseOfDll);
        ::SymCleanup(hProcess);
        return TRUE;
}

BOOL PDBData::WcharToAchar( wchar_t* ch_temp,char* ch_temp1 )
{
        int in_len=::WideCharToMultiByte(CP_ACP,0,ch_temp,wcslen(ch_temp)*2+1,NULL,NULL,NULL,NULL);
        ::WideCharToMultiByte(CP_ACP,0,ch_temp,wcslen(ch_temp)*2+1,ch_temp1,in_len,NULL,NULL);
        return TRUE;
}

ULONG PDBData::EnumModule( wchar_t* ch_ModuleName,BOOL b_open=FALSE)
{
        int status;
        LPVOID lpBuffer;
        int len=0;
        PSYSTEM_MODULE_INFORMATION ModuleTion;
        NtQuerySystemInformation* _NtQuerySystemInformation;
        _NtQuerySystemInformation=(NtQuerySystemInformation*)::GetProcAddress(::GetModuleHandle(L"ntdll.dll"),"NtQuerySystemInformation");
        status=_NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)11,NULL,0,(PULONG)&len);
        lpBuffer=new BYTE[len];
        if(lpBuffer==NULL)
        {
                return 0;
        }
        _NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)11,lpBuffer,len,NULL);
        ModuleTion=(PSYSTEM_MODULE_INFORMATION)lpBuffer;
        ULONG data=0;
        char ch_modulenames[MAX_PATH];
        ZeroMemory(ch_modulenames,MAX_PATH);
        WcharToAchar(ch_ModuleName,ch_modulenames);
        for(unsigned int i=0;i<ModuleTion->Count;i++)
        {
                if(strstr(ModuleTion->Module[i].ImageName,ch_modulenames))
                {
                        if(b_open==FALSE)
                        {
                                data=(ULONG)ModuleTion->Module[0].Base;
                        }
                        else
                        {
                                data=(ULONG)ModuleTion->Module[0].Size;
                        }
                        break;
                }
        }
        delete [] lpBuffer;
        return data;
}
雪    币: 80
活跃值: 活跃值 (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
iforgiven 活跃值 2012-11-12 10:35
6
0
有几个问题想请教一下。

第一、我运行的时候“SymGetSymbolFile”函数返回错误(复制lz的代码)。

第二、多核PAE的情况下内核的源文件为ntkrpamp.exe。SymGetSymbolFile中的参数仍然为“ntkrnlpa.exe”?如果参数应该为“ntkrpamp.exe”那内核文件的版本问题该怎么解决呢?在更新系统补丁的情况下,更新后的“ntkrnlpa.exe”(源文件为:ntkrpamp.exe)跟系统中原始的”ntkrpamp.exe“版本并不一样。
雪    币: 80
活跃值: 活跃值 (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
iforgiven 活跃值 2012-11-12 13:05
7
0
已解决,第一个问题是因为system32目录下没有”symsrv.dll“文件的结果,第二个SymGetSymbolFile会获取真实的pdb文件。
游客
登录 | 注册 方可回帖
返回