好友
阅读权限30
听众
最后登录1970-1-1
|
几个关键的方法 我拷贝到这里
//读取文件信息
void CListImportFunDlg::ReadPeInfo(char *fileName)
{
int len = 0;
if(fileName == NULL) //如果文件名错误
return;
if(m_buf != NULL) //如果buf不为空 则先行释放
{
delete [] m_buf;
m_buf = NULL;
}
CStdioFile file;
if(file.Open(fileName, CFile::modeRead|CFile::typeBinary))
{ //如果读取文件成功
len = file.GetLength();
m_filesize = len;
m_buf = new BYTE[len];
file.Read(m_buf, len); //读取文件信息
file.Close();
}
else
{
DWORD error = GetLastError();
LPVOID lpMsgBuf;
//得到当前错误的 字符串
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Display the string.
MessageBox((LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
}
}
IMAGE_IMPORT_DESCRIPTOR importDes;
//显示import表中的数据 指向的引入表项的首地址
void CListImportFunDlg::ShowImportTable()
{
char dllname[40] = {0};
BYTE *temp = m_pImportTable;
int offset = 0;
char outputBuf[0x100] = {0};
for(int cnt=0; cnt<m_dllNum; cnt++)
{
importDes = *(IMAGE_IMPORT_DESCRIPTOR*)(m_pImportTable+cnt*0x14);
if(0 == importDes.Name)
return; //完成了
temp = m_buf+importDes.Name-m_v_import_Off; //转换成本地文件偏移
sprintf(dllname, "%s", (char*)temp); //得到所在dll的名字
sprintf(outputBuf, "-------------- %s Import Table --------------\n", dllname);
AddMsg(outputBuf, 1);
if(importDes.FirstThunk&0x80000000)
{//表示为函数的序列号
if(0 == importDes.OriginalFirstThunk)
continue;
temp = (BYTE*)importDes.OriginalFirstThunk;
temp += (DWORD)m_buf;
temp -= m_v_import_Off;
}
else
{
temp = (BYTE*)importDes.FirstThunk;
temp += (DWORD)m_buf;
temp -= m_v_import_Off;
}
int cnt1 = 0;
BYTE *addr = NULL;
while(1)
{
addr = (BYTE*)*(DWORD*)(temp+cnt1*4);
if(NULL == addr)
break;
memset(outputBuf, 0, sizeof(outputBuf));
if((DWORD)addr&0x80000000)
{
sprintf(outputBuf, "(%03d) [%04X]\n", cnt1+1, (DWORD)addr&0xFFFF);
}
else
{
addr -= m_v_import_Off;
if((DWORD)addr > (DWORD)m_filesize)
{
sprintf(outputBuf, "import (%03d) [%04X] -- Address (%Xh)\n", cnt1+1, (addr));
}
else
{
addr += (DWORD)m_buf;
sprintf(outputBuf, "import (%03d) [%04X] -- %s\n", cnt1+1, *(WORD*)(addr), addr+2);
}
}
AddMsg(outputBuf);
cnt1++;
}
}
}
IMAGE_EXPORT_DIRECTORY exportDes;
//显示export表中的数据 指向的输出表项的首地址
void CListImportFunDlg::ShowExportTable()
{
if(NULL == m_pExportTable) //如果输出表的地址为0则说明没有
{
AddMsg("-------------- No Export Table Found!!!--------------\n");
AddMsg("______________________________________________\n");
return;
}
char dllname[40] = {0};
BYTE *temp = m_pExportTable;
int offset = 0;
char outputBuf[0x100] = {0};
offset = *(DWORD*)(temp+0xc);
offset -= m_v_export_Off;
offset += (DWORD)m_buf;
sprintf(dllname, "%s", offset);
sprintf(outputBuf, "-------------- %s Export Table --------------\n", dllname);
AddMsg(outputBuf, 1);
offset = *(DWORD*)(temp+0x20); //得到输出函数名字数组的头
offset -= m_v_export_Off;
offset += (DWORD)m_buf;
int funNum = *(DWORD*)(temp+0x18); //通过名字输出的函数的个数
temp = (BYTE*)offset; //
BYTE *addr = NULL;
for(int cnt=0; cnt<funNum; cnt++)
{
addr = (BYTE*)*(DWORD*)(temp+cnt*4);
addr -= m_v_export_Off;
addr += (DWORD)m_buf;
sprintf(outputBuf, "export (%03d) -- %s\n", cnt+1, addr);
AddMsg(outputBuf);
}
}
//通过一个虚拟偏移地址 RVA 的到它所在节的偏移值
int CListImportFunDlg::GetSectionOffset(int addr, char* secName)
{
BYTE *temp = m_pPEHead;
if(m_buf == NULL)
return 0;
IMAGE_SECTION_HEADER sectionH; //用于保存节的结构
int sectionCount = *(WORD*)(m_pPEHead+0x6); //得到节的个数
temp = m_pPEHead+0xf8; //得到块的首地址
//同所有的节比较 找到所在的节信息
int maxAddr = 0;
for(int cnt=0; cnt<sectionCount; cnt++)
{
sectionH = *(IMAGE_SECTION_HEADER*)(temp+cnt*0x28);
//本块的映射地址+本块的大小 得到本块的最大
maxAddr = sectionH.VirtualAddress + sectionH.Misc.VirtualSize;
//计算偏移值
if(addr > maxAddr)
continue;
if(secName != NULL)
sprintf(secName, "%s", sectionH.Name);
return sectionH.VirtualAddress - sectionH.PointerToRawData;
}
return 0;
}
//进一步处理pe文件 返回如果为false 说明当前的文件不是pe文件
BOOL CListImportFunDlg::ParsePEStruct()
{
BYTE *temp = m_buf;
if(m_buf == NULL)
return FALSE;
if(memcmp(temp, "MZ", 2) != 0)
return FALSE;
int len = *(DWORD*)(temp+0x3c); //pe文件的首地址
temp += len;
if(memcmp(temp, "PE\0\0", 4) != 0)
{
delete [] m_buf;
m_buf = NULL;
return FALSE;
}
m_pPEHead = temp; //得到首地址
temp += 0x80; //指向数据目录表中的第2项 “import项”
int offset = *(DWORD*)temp; //得到 输入表项数组的首地址的 RVA 需要转换成文件地址
len = *(DWORD*)(temp+4); //得到 输入表数组的总大小
m_dllNum = len/0x14; //得到共有多少个dll引入表
m_v_import_Off = GetSectionOffset(offset, m_secName); //得到rva和真正物理地址的差 和 所在的节的名字
char msg[0x100] = {0};
sprintf(msg, "SectionName: %s offset: %d\n\n", m_secName, m_v_import_Off);
AddMsg(msg);
//指到import table 表结构的数组的头部 每一个import结构占用14h个字节
m_pImportTable = m_buf+(offset-m_v_import_Off); //经过运算后的引入表的物理地址
//指到export table 表结构的首地址
temp = m_pPEHead;
temp += 0x78;
offset = *(DWORD*)temp;
m_v_export_Off = GetSectionOffset(offset, m_secName); //得到rva和真正物理地址的差 和 所在的节的名字
if(NULL != offset)
{
m_pExportTable = m_buf+(offset-m_v_export_Off); //经过计算后的输出表的物理地址
sprintf(msg, "SectionName: %s offset: %d\n\n", m_secName, m_v_export_Off);
AddMsg(msg);
}
else
m_pExportTable = NULL; //没有输出表
return TRUE;
} |
|