[调试器的实现<控制台版>]第五章 函数名称解析

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另一个地址或更深层次的嵌套解析情况下,采用递归来处理这种特殊情况。

 

附件:

调试器源代码.rar

posted @ 2015-05-10 11:51  银河彼岸  阅读(301)  评论(0编辑  收藏  举报