本文共 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/