首页
社区
课程
招聘
[分享]PE结构是那一类!获取导入表和导出表的类!方便使用!
发表于: 2007-10-19 17:02 13514

[分享]PE结构是那一类!获取导入表和导出表的类!方便使用!

2007-10-19 17:02
13514

我想高手们都别笑话!我发出来希望有研究PE结构的朋友们喜欢,为了不占空间,我把关键的几个发出来,其它的大同小异,我想自己组也能组成一个类,然后,自己使用的,目前网络上没有一个是完整的点的例子,这里是我自己整理添加的,供大家参考!!!:

//--------------------------------------PNExeInfo.h----------------------------------------------------

//加载调试辅助:
#include "IMAGEHLP.H"
#pragma comment(lib,"ImageHlp.lib")

#include "tlhelp32.h"
#pragma comment(lib,"th32.lib")

class CPNExeInfo  
{
public:
        CPNExeInfo();
        virtual ~CPNExeInfo();
public:
        BOOL Release();
        int     LoadPE(DWORD pId);              //进程装载
        int            LoadPE(DWORD pId,DWORD mId);    //模块装载
        int            LoadPE(LPCTSTR path);           //文件装载
        DWORD        GetSize(){return dwFileSize;}

        //文件头函数:
        PIMAGE_DOS_HEADER             GetDosHeader(){return _dosHeader;}
        PIMAGE_NT_HEADERS             GetNTHeaders(){return _ntHeader;}
        PIMAGE_SECTION_HEADER    GetSection(DWORD dwRVA=NULL);
        //输入表函数:
        PIMAGE_IMPORT_DESCRIPTOR GetImportModule(DWORD *dwSize=NULL,LPCTSTR *name=NULL);
        PIMAGE_THUNK_DATA                 GetProcOfModule(LPCTSTR name,DWORD *dwSize=NULL,
                                                                                         LPCTSTR *ProcName=NULL,DWORD *Hint=NULL,
                                                                                         DWORD *Offset=NULL,DWORD *Value=NULL,DWORD *Rva=NULL);
        PIMAGE_THUNK_DATA                 GetProcOfModule(int count,DWORD *dwSize=NULL,
                                                                                         LPCTSTR *ProcName=NULL,DWORD *Hint=NULL,
                                                                                         DWORD *Offset=NULL,DWORD *Value=NULL,DWORD *Rva=NULL);
        //输出表函数:
        PIMAGE_EXPORT_DIRECTORY GetExportInfo(DWORD *dwSize=NULL,LPCTSTR *strFun=NULL,DWORD *dwAddr=NULL,
                                                                                         DWORD *dwOrdin=NULL,DWORD *dwOffset=NULL,LPTSTR DllName=NULL);
protected:
        LPCTSTR                m_path;  //路径

        HANDLE                hFile;      //打开文件句柄
        DWORD                dwFileSize; //文件大小
private:
        HANDLE                hMapping; //映射句柄
        LPVOID                m_pData;
       
        PIMAGE_DOS_HEADER        _dosHeader;
        PIMAGE_NT_HEADERS        _ntHeader;
};

//-----------------------------------------PNExeInfo.cpp

//装载文件:
int CPNExeInfo::LoadPE(LPCTSTR path)
{
        DWORD dwRead=NULL;
        //保存路径:
        m_path=path;

        //以只读方式,其他进程对文件有读写权,打开文件:
        hFile=CreateFile(m_path,GENERIC_READ,FILE_SHARE_WRITE|FILE_SHARE_READ,
                         NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        if(hFile==INVALID_HANDLE_VALUE){return        -10;}  //-10代表打开文件失败;

        //获取文件大小:
        dwFileSize=GetFileSize(hFile,NULL);
        if(dwFileSize <= 0){CloseHandle(hFile);return -11;} //-11代表获取文件大小失败;

        /*
        //创建镜像:
        hMapping=::CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
        if(hMapping==NULL){
                CloseHandle(hFile);return -20;}        //-20创建镜像出错;

        //映射地址:
        m_pData=::MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
        if(m_pData==NULL){CloseHandle(hFile);return -21;} //-21代表影射地址出错;
        */

        //方便以后销毁,采用分配内存方式:
        m_pData=(DWORD*)::VirtualAlloc(NULL,dwFileSize,MEM_COMMIT,PAGE_READWRITE);

        ReadFile(hFile,m_pData,dwFileSize,&dwRead,NULL);
        //方便其他函数调用,初始化函数头:
    _dosHeader =(PIMAGE_DOS_HEADER)m_pData;
    _ntHeader  =(PIMAGE_NT_HEADERS)((LONG)_dosHeader+(LONG)_dosHeader->e_lfanew);
       
        //关闭文件:
        CloseHandle(hFile);
        return 0;
}

//装载其它进程,方便获得导出,和导入表:
int CPNExeInfo::LoadPE(DWORD pId)
{
        DWORD  dwRead=NULL;
        HANDLE hModule=NULL;
    MODULEENTRY32* minfo=new MODULEENTRY32;

        if((int)pId<=0){return -10;}
       
        hModule=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pId);
        if((DWORD)hModule<=0){return -11;}
        Module32First(hModule, minfo);

        HANDLE hOpenProcess=::OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE,FALSE,pId);
       
        //创建地址:
        m_pData=(DWORD*)::VirtualAlloc(NULL,minfo->modBaseSize,MEM_COMMIT,PAGE_READWRITE);
        //读取进程:
        ::ReadProcessMemory(hOpenProcess,minfo->modBaseAddr,m_pData,minfo->modBaseSize,&dwRead);

        _dosHeader =(PIMAGE_DOS_HEADER)m_pData;
    _ntHeader  =(PIMAGE_NT_HEADERS)((LONG)_dosHeader+(LONG)_dosHeader->e_lfanew);
       
        //释放:
        if(hModule!=NULL){CloseHandle(hModule);}
        if(hOpenProcess!=NULL){CloseHandle(hOpenProcess);}
        return 0;
}

//好了,我们只要能加载了,什么都好说:

输出表:

PIMAGE_EXPORT_DIRECTORY CPNExeInfo::GetExportInfo(DWORD *dwSize,LPCTSTR *strFun,DWORD *dwAddr,
                                                                                         DWORD *dwOrdin,DWORD *dwOffset,LPTSTR DllName)
{
        PIMAGE_EXPORT_DIRECTORY _exportDir=NULL;
        _exportDir=(PIMAGE_EXPORT_DIRECTORY)_ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
       
        if(_exportDir==NULL){return NULL;}

        _exportDir=(PIMAGE_EXPORT_DIRECTORY)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)_exportDir,NULL);
       
        //数量初始化:
        DWORD dwNum=_exportDir->NumberOfNames;
        if(dwNum<_exportDir->NumberOfFunctions){dwNum=_exportDir->NumberOfFunctions;}
        if(dwSize!=NULL){*dwSize=dwNum;}

        //名称初始化:
        DWORD **ppdwNames = (DWORD **)_exportDir->AddressOfNames;
    ppdwNames = (PDWORD*)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)ppdwNames,NULL);
        if(!ppdwNames){return NULL;}

        //地址初始化:
        DWORD **ppdwAddr  = (DWORD **)_exportDir->AddressOfFunctions;
    ppdwAddr = (PDWORD*)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)ppdwAddr,NULL);
        if(!ppdwAddr){return NULL;}

        //序号初始化:
        DWORD *ppdwOrdin=(DWORD*)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)_exportDir->AddressOfNameOrdinals,NULL);
        if(!ppdwOrdin){return NULL;}
       
        //获取文件名:
        if(DllName!=NULL){
                char *szdllName=(PSTR)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)_exportDir->Name,NULL);
                //DllName=szdllName;
                strcpy(DllName,szdllName);
        }

        for(DWORD i=0;i<dwNum;i++)
        {
                char* szFun=(PSTR)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)*ppdwNames,NULL);
                if(strFun!=NULL){strFun[i]=szFun;}
                if(dwAddr!=NULL){dwAddr[i]=(DWORD)*ppdwAddr;}
                if(dwOffset!=NULL){
                        dwOffset[i]=(DWORD)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)*ppdwAddr,NULL);
                        dwOffset[i]=dwOffset[i]-(DWORD)_dosHeader;
                }
                if(dwOrdin!=NULL){dwOrdin[i]=(WORD)*ppdwOrdin;}

                ppdwOrdin=(DWORD*)((DWORD)ppdwOrdin+2);
                ppdwAddr++;
                ppdwNames++;
        }

        return _exportDir;
}

//输入模块:
PIMAGE_IMPORT_DESCRIPTOR CPNExeInfo::GetImportModule(DWORD *dwSize,LPCTSTR *name)
{
        PIMAGE_IMPORT_DESCRIPTOR        _importDesc=NULL;

        //获取输入表虚拟地址:
        _importDesc=(PIMAGE_IMPORT_DESCRIPTOR)_ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
        if(_importDesc==NULL){return NULL;}       
       
        //将虚拟地址进行转换:
        _importDesc=(PIMAGE_IMPORT_DESCRIPTOR)::ImageRvaToVa(_ntHeader,m_pData,(DWORD)_importDesc,NULL);
       
        DWORD  dwRe=(DWORD)_importDesc;
        int i=0;
        if(name!=NULL)
        {
                for(;_importDesc->Name!=NULL;i++)
                {
                        char *szName=(PSTR)ImageRvaToVa(_ntHeader, _dosHeader, (DWORD)_importDesc->Name, 0);
                        name[i]=szName;
                        _importDesc++;
                }
        }
        if(dwSize!=NULL)memcpy(dwSize,(DWORD*)&i,sizeof(DWORD));
        _importDesc=(PIMAGE_IMPORT_DESCRIPTOR)dwRe;

        return _importDesc;
}

//获取模块的函数:
PIMAGE_THUNK_DATA CPNExeInfo::GetProcOfModule(LPCTSTR ModuleName,DWORD *dwSize,LPCTSTR *ProcName,
                                                                                          DWORD *Hint,DWORD *Offset,DWORD *Value,DWORD *Rva)
{
        DWORD                dwThunk=NULL;
        PIMAGE_THUNK_DATA        _pThunk=NULL;

        PIMAGE_IMPORT_DESCRIPTOR        _importDesc=NULL;

        //获取输入表虚拟地址:
        _importDesc=(PIMAGE_IMPORT_DESCRIPTOR)_ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
        if(_importDesc==NULL){return NULL;}       
       
        //将虚拟地址进行转换:
        _importDesc=(PIMAGE_IMPORT_DESCRIPTOR)::ImageRvaToVa(_ntHeader,m_pData,(DWORD)_importDesc,NULL);

        for(int i=0;_importDesc->Name!=NULL;i++)
        {
                char *szName=(PSTR)ImageRvaToVa(_ntHeader, _dosHeader, (DWORD)_importDesc->Name, 0);
                if(lstrcmp(ModuleName,szName)==0)
                {
                        if(_importDesc->OriginalFirstThunk!=0)
                        {
                                dwThunk=_importDesc->OriginalFirstThunk;
                                _pThunk=(PIMAGE_THUNK_DATA)ImageRvaToVa(_ntHeader,_dosHeader,
                                        (DWORD)_importDesc->OriginalFirstThunk,NULL);
                                break;
                        }
                        else
                        {
                                dwThunk=_importDesc->FirstThunk;
                                _pThunk=(PIMAGE_THUNK_DATA)ImageRvaToVa(_ntHeader,_dosHeader,
                                        (DWORD)_importDesc->FirstThunk,NULL);
                                break;
                        }
                }
                _importDesc++;
        }

        DWORD dwRe=(DWORD)_pThunk;

        if(ProcName==NULL){return _pThunk;}
        for(i=0;_pThunk->u1.AddressOfData!=NULL;i++)
        {
                char *szFun=(PSTR)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)_pThunk->u1.AddressOfData->Name, 0);
               
                ProcName[i]=szFun;
                if(Hint!=NULL){
                        if(szFun!=NULL){memcpy(&Hint[i],szFun-2,2);}
                        else{Hint[i]=-1;}
                }
                if(Offset!=NULL){
                        Offset[i]=(DWORD)ImageRvaToVa(_ntHeader,_dosHeader,(DWORD)dwThunk,NULL);
                        Offset[i]=Offset[i]-(DWORD)m_pData;
                }
                if(Value!=NULL){
                        Value[i]=(DWORD)_pThunk->u1.AddressOfData;
                        if((Value[i]&0x80000000)==0x80000000){Value[i]&=0x7FFFFFFF;}
                }
                if(Rva!=NULL){
                        Rva[i]=dwThunk;
                }
                dwThunk+=4;
                _pThunk++;
        }

        if(dwSize!=NULL)memcpy(dwSize,(DWORD*)&i,sizeof(DWORD));
        _pThunk=(PIMAGE_THUNK_DATA)dwRe;
        return _pThunk;
}

//---------------------------------------------------------------------------

用的着的就支持一下吧!

                                                            -By EasyStudy For PhantomNet


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (16)
雪    币: 2943
活跃值: (1788)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
2
用不着也支持你
2007-10-19 17:23
0
雪    币: 1946
活跃值: (248)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
3
sustain
2007-10-19 18:10
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
4
终于不用自己写了 ,辛苦了``我赚了,
2007-10-19 18:14
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
5
昨天留名,今天收货,
2007-10-20 09:18
0
雪    币: 690
活跃值: (1826)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
6
正在学刚好用的上,谢谢。
2007-10-20 11:24
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
很好,很强大
要是能再进行一些容错上的处理,就更完美了
2007-10-20 13:17
0
雪    币: 716
活跃值: (162)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
8
用起来方便了,谢谢。
2007-10-20 19:35
0
雪    币: 199
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
晕了,我自己也写了个,自私了一下,没机会得精华了
2007-10-20 21:56
0
雪    币: 451
活跃值: (78)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
10
很好,很强大
2007-11-4 12:24
0
雪    币: 224
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
不错  谢谢 学到东西了
2007-12-8 00:08
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
真是太好了,怎么我现在才发现.
2007-12-8 10:34
0
雪    币: 224
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
13
想问下楼主,对于大文件加载到内存,是不是会影响机器性能?
不用生成镜像读文件,直接读文件来实现那样有什么优缺点吗?
希望大家指点!!谢
2007-12-8 11:15
0
雪    币: 224
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
14
没人回答  up一下
2007-12-12 09:58
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
很好学习中,谢谢!!!
2007-12-12 14:03
0
雪    币: 1657
活跃值: (291)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
16
如果直接读文件,那么相对虚拟地址确定会很麻烦~~~~,要专门写代码转换!!
2007-12-12 15:42
0
雪    币: 224
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
哦  谢谢
现在这样写了  是感觉比较麻烦   但是都克服了  
学习就是要走弯路。
2007-12-12 17:29
0
游客
登录 | 注册 方可回帖
返回
//