博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PE解析导入表--实例
阅读量:2065 次
发布时间:2019-04-29

本文共 11154 字,大约阅读时间需要 37 分钟。

//得到导入表的信息:导入库名,导入函数ID,导入函数地址void CPe32 ::GetImportTableInfo(){                 if (m_bSuccess)                {                                 //空结尾的导入表结构成员                                 IMAGE_IMPORT_DESCRIPTOR zero = {0};                                 //得到导入目录结构                                 IMAGE_DATA_DIRECTORY ImportDataDirectory  = m_pPeHeader->OptionalHeader.DataDirectory[1];                                 if (ImportDataDirectory .VirtualAddress == 0)                                {   //不含有导入表直接返回                                                 return ;                                }                                 //获得导入表在PE文件中的位置                                 DWORD dwImportInFilePos = GetFileOffsetFromRva(ImportDataDirectory .VirtualAddress);                                 if (dwImportInFilePos > m_iFileSize) //判断导入表的位置是否合法                                {                                                 return ;                                }                                 //得到文件中导入表结构指针,有多少个DLL,则导入表中有多少个成员                                 IMAGE_IMPORT_DESCRIPTOR *pImportDescriptor =                                                ( IMAGE_IMPORT_DESCRIPTOR *)((BYTE *)m_pFileBuffer + dwImportInFilePos);                                 int iDllNum = 0;                                 //pImportDescriptor是导入表中IMAGE_IMPORT_DESCRIPTOR结构体数组的首地址。                                 while (1)                                {                                                 //取得导入库名称字符串所在文件中的位置                                                 DWORD dwDllNameInFilePos = GetFileOffsetFromRva(pImportDescriptor->Name);                                                 if (dwDllNameInFilePos == -1 ||                                                                dwDllNameInFilePos > m_iFileSize) //检测得到的文件偏移是否合法                                                {               //第一个导入库名称位置不合法,停止导入表的解析                                                                 if (iDllNum == 0)                                                                {                                                                                 return ;                                                                }                                                                 break; //遇到不合法的(非法或解析到结尾) 跳出循环。                                                }                                                 //DLL库名,文件基地址加文件偏移,通过加载此DLL的方式验证是否是合法的DLL                                                 //注意:使用此方法验证需要将本代码所在程序与被解析的程序放到相同目录下以保证非系统DLL验证成功//                                             if (!LoadLibraryA((const char *)((BYTE *)m_pFileBuffer + dwDllNameInFilePos)))//                                             {   //第一个导入库不合法,停止导入表的解析//                                                             if (iDllNum == 0)//                                                             {//                                                                             int iError = GetLastError();//                                                                             return ;//                                                             }//                                                             break; //遇到不合法的导入库跳出循环。//                                             }                                                iDllNum++;                                                pImportDescriptor++; //跳到下一个。                                }                                pImportDescriptor -= iDllNum; //恢复导入表到起始位置                                 //导入表成员个数:即导入的DLL个数                                m_ImportInfo.lDllNum = iDllNum;                                 //导入表中DLL信息指针                                m_ImportInfo.pDll_info = new DLL_INFO [iDllNum];                                 for (int i = 0; i < m_ImportInfo.lDllNum; i++)                                {                                                 //获得导入函数序号/名称表RVA的RVA值                                                 long lThunkData = pImportDescriptor[i].OriginalFirstThunk;                                                 if(lThunkData == 0)  //如果OriginalFirstThunk指向的是0则FirstThunk指向是导入函数序号/名称表的RVA值                                                {                                                                lThunkData = pImportDescriptor[i].FirstThunk;                                                }                                                 int iFuncNum = 0;                                                 //由导入函数序号/名称表的RVA值获得其在文件中的偏移                                                 DWORD dwFunctionNameInFilePos = GetFileOffsetFromRva(lThunkData);                                                 if (dwFunctionNameInFilePos == -1 ||                                                                dwFunctionNameInFilePos > m_iFileSize) //检测得到的文件偏移是否合法                                                {                                                                               break; //遇到不合法的(非法或解析到结尾) 跳出循环。                                                }                                                 //文件基址+文件偏移=导入函数序号/名称表实际地址                                                 IMAGE_THUNK_DATA *pThunk = (IMAGE_THUNK_DATA *)((BYTE *)m_pFileBuffer + dwFunctionNameInFilePos);                                                 //pThunk是指向DWORD的数组,数组遇到全零DWORD结束                                                 //得到从某DLL中导入的函数个数                                                 while (pThunk->u1.Function)                                                {                                                                iFuncNum++;                                                                pThunk++;                                                }                                                pThunk -= iFuncNum; //恢复到起始位置                                                 //取得导入库名称字符串所在文件中的位置                                                 DWORD dwDllNameInFilePos = GetFileOffsetFromRva(pImportDescriptor->Name);                                                 if (dwDllNameInFilePos == -1 ||                                                                dwDllNameInFilePos > m_iFileSize) //检测得到的文件偏移是否合法                                                {                                                                 continue; //遇到不合法的(非法或解析到结尾) 停止当前这个,继续解析下一个。                                                }                                                 //DLL库名,文件基地址加文件偏移                                                 int iLen = strlen((const char *)m_pFileBuffer + dwDllNameInFilePos);                                                 if (iLen > 256)                                                {                                                                               continue;//导入DLL库文件名过长,不合法则 停止当前这个,继续解析下一个。                                                }                                                 //保存导入DLL库名                                                strcpy(m_ImportInfo.pDll_info[i].cDllName, (const char *)((BYTE *)m_pFileBuffer + dwDllNameInFilePos));                                                 //保存从该DLL库中导入的函数个数                                                m_ImportInfo.pDll_info[i].lFuncNum = iFuncNum;                                                 //某DLL中导入的函数信息的指针                                                m_ImportInfo.pDll_info[i].pFunctionInfo = new FUNC_INFO [iFuncNum];                                                 for (int j = 0; j < iFuncNum; j++)                                                {                                                                 //仅以序号导入                                                                 if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32 )                                                                {                                                                                m_ImportInfo.pDll_info[i].pFunctionInfo[j].lOrdinal = pThunk->u1.Ordinal; //保存导入序号                                                                                 //保存导入函数填充地址                                                                                m_ImportInfo.pDll_info[i].pFunctionInfo[j].pdwRva = (DWORD *)pImportDescriptor[i].FirstThunk + j;                                                                }                                                                 else //以函数名导入的                                                                {                                                                                               //由导入函数序号/名称表的RVA值获得其在文件中的偏移                                                                                 DWORD dwFunctionNameInFilePos = GetFileOffsetFromRva(pThunk->u1.Ordinal);                                                                                 if (dwFunctionNameInFilePos == -1 ||                                                                                                dwFunctionNameInFilePos > m_iFileSize) //检测得到的文件偏移是否合法                                                                                {                                                                                                               continue; //遇到不合法的(非法或解析到结尾) 停止当前这个,继续解析下一个。                                                                                }                                                                                 IMAGE_IMPORT_BY_NAME *pImportHintName = (IMAGE_IMPORT_BY_NAME *)((BYTE *)m_pFileBuffer + dwFunctionNameInFilePos);                                                                                 int iLen = strlen((const char *)pImportHintName->Name);                                                                                 if (iLen > 256)                                                                                {                                                                                                                               continue;//导入函数名过长,不合法则 停止当前这个,继续解析下一个。                                                                                }                                                                                 //保存导入函数名                                                                                strcpy(m_ImportInfo.pDll_info[i].pFunctionInfo[j].cFunctionName, (const char *)pImportHintName->Name);                                                                                 //保存导入函数序号                                                                                m_ImportInfo.pDll_info[i].pFunctionInfo[j].lOrdinal = pImportHintName->Hint;                                                                                 //保存导入函数填充地址                                                                                m_ImportInfo.pDll_info[i].pFunctionInfo[j].pdwRva = (DWORD *)pImportDescriptor[i].FirstThunk + j;                                                                }                                                                pThunk++;  //跳到下一个导入函数                                                }                                }                }                 return ;}

 

转载地址:http://xpumf.baihongyu.com/

你可能感兴趣的文章
(模板 重要)Tarjan算法解决LCA问题(PAT 1151 LCA in a Binary Tree)
查看>>
(PAT 1154) Vertex Coloring (图的广度优先遍历)
查看>>
(PAT 1115) Counting Nodes in a BST (二叉查找树-统计指定层元素个数)
查看>>
(PAT 1143) Lowest Common Ancestor (二叉查找树的LCA)
查看>>
(PAT 1061) Dating (字符串处理)
查看>>
(PAT 1118) Birds in Forest (并查集)
查看>>
数据结构 拓扑排序
查看>>
(PAT 1040) Longest Symmetric String (DP-最长回文子串)
查看>>
(PAT 1145) Hashing - Average Search Time (哈希表冲突处理)
查看>>
(1129) Recommendation System 排序
查看>>
PAT1090 Highest Price in Supply Chain 树DFS
查看>>
(PAT 1096) Consecutive Factors (质因子分解)
查看>>
(PAT 1019) General Palindromic Number (进制转换)
查看>>
(PAT 1073) Scientific Notation (字符串模拟题)
查看>>
(PAT 1080) Graduate Admission (排序)
查看>>
Play on Words UVA - 10129 (欧拉路径)
查看>>
mininet+floodlight搭建sdn环境并创建简答topo
查看>>
【UML】《Theach yourself uml in 24hours》——hour2&hour3
查看>>
【linux】nohup和&的作用
查看>>
【UML】《Theach yourself uml in 24hours》——hour4
查看>>