[调试器的实现<控制台版>]第五章 函数名称解析
1.相关函数 相关结构,与主要成员
//导出表结构 struct ExportFunInfor { char szFunName[64]; //函数名称 int nExportNumber; //导出编号 DWORD dwFunAddress; //函数所在地址 }; struct ExportTableInfor //导出函数表 { char szDllTableName[32]; //表名<DLL> CList<ExportFunInfor,ExportFunInfor> *pEptTableFun; //数据 }; //保存解析DLL的所有函数 CList<ExportTableInfor,ExportTableInfor> m_ExportTableList;
2.设计思路
进入StartDebugDll时,传来一个参数,此参数保存了当前加载DLL的信息,可以通过此信息解析出导出表在文件中的位置,然后可以定位到导出函数的位置,把函数用类成员m_ExportTableList保存。
3.关键代码部分
ExportFunInfor pEptFunInfor; ZeroMemory(&pEptFunInfor,sizeof(ExportFunInfor)); for ( i = 0; i <= (int)m_DllExportTable.NumberOfFunctions; i++ ) { ReadProcessMemory(hProcess,(LPCVOID)nStartFunAddr, &nAllFunOffset,sizeof(int),&dwOldProto); if ( 0 == nAllFunOffset ) { //循环读取链表 nStartFunAddr += sizeof(DWORD); continue; } for( j = 0; j <= (int)m_DllExportTable.NumberOfNames; j++) { ReadProcessMemory(hProcess,(LPVOID)(nStartFunNameOrd + j*2), &nFunNameAddr,sizeof(WORD),&dwOldProto); if(i == (int)nFunNameAddr) { memset(szFunName,0,MAX_PATH); DWORD nAddress = j*sizeof(DWORD) + nStartFunName; ReadProcessMemory(hProcess,(LPVOID)(nAddress), CurAddress,sizeof(DWORD),&dwOldProto); nCurAddress += (DWORD)StartAddress; ReadProcessMemory(hProcess,(LPVOID)(nCurAddress), szFunName,MAX_PATH,&dwOldProto); break; } }
4.显示解析函数部分
主要对CALL, MOV, JMP, 6个寄存器<eax,ebx,ecx,edx,esi,edi>的函数名称显示进行解析。
处理函数:void CMyDebugInfor::ShowExportFun(char *szBuf)
注意:当CALL/JMP一个指令地址时,又JMP/CALL另一个地址或更深层次的嵌套解析情况下,采用递归来处理这种特殊情况。
附件: