吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4677|回复: 7
收起左侧

[会员申请] 申请会员ID:IDK【未报道,账号删除】

  [复制链接]
吾爱游客  发表于 2017-3-17 18:01
1、申 请 I D :IDK
2、个人邮箱:278580509@qq.com



VS 2013 MFC    64位环境下  解析64位PE文件



       //导出表
        CString m_ExputTable;
        //导入表
        CString m_ImportTable;
        //资源表
        CString m_ResourceTable;
        //重定位表
        CString m_RelocationeTable;
        //TLS表
        CString m_TLSTable;
        //延迟输入表
        CString m_DelayImportTable;
        //区段表
        CString m_SectionsTable;
        //数据目录表
        CString m_DataTable;







[C++] 纯文本查看 复制代码
CFile file;
        BOOL bResult = file.Open(m_PEShowOpenPath, CFile::modeRead | CFile::shareDenyNone, NULL);
        CFileStatus status;
        file.GetStatus(status);

        TmpCstr = status.m_ctime.Format(_T("创建时间:%Y-%m-%d %H:%M:%S \r\n"));
        m_VaPEShowEdit += TmpCstr;

        TmpCstr = status.m_mtime.Format(_T("修改时间:%Y-%m-%d %H:%M-%S\r\n"));
        m_VaPEShowEdit += TmpCstr;

        TmpCstr = status.m_atime.Format(_T("访问时间:%Y-%m-%d %H:%M-%S\r\n"));
        m_VaPEShowEdit += TmpCstr;

        TCHAR A[64] = { 0 };
        _stprintf_s(A, L"%u KB", status.m_size);
        TmpCstr = (_T("大小:"));
        TmpCstr += A;
        TmpCstr += (_T("\r\n"));
        m_VaPEShowEdit += TmpCstr;

        file.Close();


        HANDLE hFile = INVALID_HANDLE_VALUE;
        CString Error = _T("");
        hFile = CreateFile(m_PEShowOpenPath,
                GENERIC_READ,
                FILE_SHARE_READ,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL
                );
        if (hFile == INVALID_HANDLE_VALUE)
        {
                Error.Format(_T("错误码:%d"), GetLastError());
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                MessageBox(Error);
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                return 0;
        }

        DWORD dwFileSize = GetFileSize(hFile, NULL);

        pFileData  = new BYTE[dwFileSize];

        DWORD  dwReadSize = 0;
        if (!ReadFile(hFile, pFileData, dwFileSize, &dwReadSize, NULL))
        {
                Error.Format(_T("错误码:%d"), GetLastError());
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                MessageBox(Error);
                return 0;
        }

        // 使用DOS头结构指向缓冲区
        IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER*)pFileData;

        if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        {
                MessageBox(_T("没有MZ标记"));
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                return FALSE;
        }

        
        // 判断是否是有效的NT头
        // 获取Nt头
        IMAGE_NT_HEADERS* pNTHeader = (IMAGE_NT_HEADERS*)(pDosHeader->e_lfanew + (ULONG64)pDosHeader);
        
        if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
                MessageBox(_T("没有PE标记"));
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                return FALSE;
        }


        m_VaPEShowEdit += _T("\r\n");
        m_VaPEShowEdit += _T("********PE头解析***********");
        m_VaPEShowEdit += _T("\r\n");


        //获取PE头
        IMAGE_FILE_HEADER * pFileHeader = (IMAGE_FILE_HEADER *)(pDosHeader->e_lfanew + (ULONG64)pDosHeader + 4);
        //CUP
        if (pFileHeader->Machine == IMAGE_FILE_MACHINE_I386)
        {
                m_VaPEShowEdit += _T("运行平台:Intel 386");
                m_VaPEShowEdit += _T("\r\n");
        }
        else if (pFileHeader->Machine == IMAGE_FILE_MACHINE_IA64)
        {
                m_VaPEShowEdit += _T("运行平台:Intel 64");
                m_VaPEShowEdit += _T("\r\n");
        }
        else if (pFileHeader->Machine == IMAGE_FILE_MACHINE_AMD64)
        {
                m_VaPEShowEdit += _T("运行平台:AMD64 (K8)");
                m_VaPEShowEdit += _T("\r\n");
        }
        else{
                m_VaPEShowEdit += _T("运行平台:其他");
                m_VaPEShowEdit += _T("\r\n");
        }

        TmpCstr.Format(_T("文件的区块数目:%d"), pFileHeader->NumberOfSections);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        tm createTime = { 0 };
        errno_t nRet = _gmtime64_s(&createTime, (__time64_t *)&pFileHeader->TimeDateStamp);
        if (nRet==0)
        {
                TCHAR tmp[50] = { 0 };
                _wasctime_s(tmp, &createTime);
                m_VaPEShowEdit += tmp;
                m_VaPEShowEdit += _T("\r\n");
        }
        else
        {
                TmpCstr.Format(_T("获取时间出错错误代码:%d\r\n"), nRet);
                m_VaPEShowEdit += TmpCstr;
        }
        

        TmpCstr.Format(_T("指向符号表:%d"), pFileHeader->PointerToSymbolTable);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("符号表中符号个数:%d"), pFileHeader->NumberOfSymbols);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("IMAGE_OPTIONAL_HEADER32大小:%d"), pFileHeader->SizeOfOptionalHeader);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");


        TmpCstr.Format(_T("文件属性:%d"), pFileHeader->Characteristics);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        //区块表

        // 得到第一个区段
        IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);

        for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++) {

                TCHAR tmpWchar[9] = { 0 };

                CHAR_TO_WCHAR((CHAR*)&(pSectionHeader.Name), tmpWchar);
                TmpCstr.Format(_T("区段名: %s"), tmpWchar);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");

                TmpCstr.Format(_T("区段数据的文件偏移:%x H"), pSectionHeader.PointerToRawData);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");

                TmpCstr.Format(_T("区段数据的RVA:%x H"), pSectionHeader.VirtualAddress);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");

                TmpCstr.Format(_T("区段数据的大小:%x H"), pSectionHeader.SizeOfRawData);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");
                m_SectionsTable += _T("\r\n");
                m_SectionsTable += _T("\r\n");
        }




        CString File32Or64;


        if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
                File32Or64=_T("文件类型:32位\r\n");
                m_VaPEShowEdit += File32Or64;
                AnalysisOF32BitPE();
        }
        else if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC){

                File32Or64 = _T("文件类型:64位\r\n");
                m_VaPEShowEdit += File32Or64;
                AnalysisOF64BitPE();

        }
[C++] 纯文本查看 复制代码
DWORD PEShow::RvaToOffset(DWORD dwRva)
{
        // TODO:  在此添加控件通知处理程序代码
        IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER*)pFileData;

        IMAGE_NT_HEADERS *pNtHeader =   /*换行*/
                (IMAGE_NT_HEADERS*)((ULONGLONG)pDosHeader + pDosHeader->e_lfanew);

        // 得到区段个数
        DWORD   dwSectionNumber = pNtHeader->FileHeader.NumberOfSections;

        // 得到第一个区段
        IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);

        for (int i = 0; i < dwSectionNumber; ++i)
        {

                // 判断RVA是否在当前的区段中

                DWORD dwSectionEndRva =   /*换行*/
                        pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData;

                if (dwRva >= pSectionHeader[i].VirtualAddress
                        && dwRva <= dwSectionEndRva) {

                        // 计算出RVA对应的文件偏移
                        // 公式:
                        // 文件偏移  =  RVA - 区段的起始RVA + 区段的起始文件偏移
                        DWORD dwTemp = dwRva - pSectionHeader[i].VirtualAddress;
                        DWORD dwOffset = dwTemp + pSectionHeader[i].PointerToRawData;

                        return dwOffset;
                }
        }
        return -1;
}
[C++] 纯文本查看 复制代码
//64位PE
void PEShow::AnalysisOF64BitPE()
{
        CString TmpCstr;

        // 得到DOS头
        IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pFileData;

        // 得到Nt头(为了得到扩展头得先找到Nt头)
        IMAGE_NT_HEADERS64* pNtHeader =   /* 换行 */
                (IMAGE_NT_HEADERS64*)(pDosHeader->e_lfanew + (ULONG64)(pDosHeader));

        IMAGE_OPTIONAL_HEADER64* pOptionalHeader = &pNtHeader->OptionalHeader;




        m_VaPEShowEdit += _T("\r\n");
        m_VaPEShowEdit += _T("********扩展头解析***********");
        m_VaPEShowEdit += _T("\r\n");


        //获取 扩展头
        //IMAGE_OPTIONAL_HEADER* pOptionalHeader = &pNTHeader->OptionalHeader;

        TmpCstr.Format(_T("程序执行入口RVA:%x H"), pOptionalHeader->AddressOfEntryPoint);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("程序基址RVA:%x H"), pOptionalHeader->ImageBase);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("代码基址RVA:%x H"), pOptionalHeader->BaseOfCode);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        //TmpCstr.Format(_T("数据基址RVA:%x H"), pOptionalHeader->BaseOfData);
        //m_VaPEShowEdit += TmpCstr;
        //m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("内存中的区块的对齐大小:%x H"), pOptionalHeader->SectionAlignment);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("文件中的区块的对齐大小:%x H"), pOptionalHeader->FileAlignment);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("映像装入内存后的总尺寸:%x H"), pOptionalHeader->SizeOfImage);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        TmpCstr.Format(_T("所有头+区块表的尺寸大小:%x H"), pOptionalHeader->SizeOfHeaders);
        m_VaPEShowEdit += TmpCstr;
        m_VaPEShowEdit += _T("\r\n");

        m_ControlPEShow.SetWindowText(m_VaPEShowEdit);




        //数据目录表

        for (int i = 0; i < pOptionalHeader->NumberOfRvaAndSizes; i++)
        {
                m_DataTable += _T("\r\n");
                TmpCstr.Format(_T("数据的RVA:%x H      "), pOptionalHeader[i].DataDirectory->Size);
                m_DataTable += TmpCstr;
                TmpCstr.Format(_T("数据大小:%x H       "), pOptionalHeader[i].DataDirectory->VirtualAddress);
                m_DataTable += TmpCstr;
                m_DataTable += _T("\r\n");

        }




        //导出表

        // 获取到数据目录表
        IMAGE_DATA_DIRECTORY* pDataDirectory = pOptionalHeader->DataDirectory;


        //获得导出表
        DWORD dwExportTableRva = pDataDirectory[0].VirtualAddress;
        //将多出表的RVA转换成文件偏移

        if (dwExportTableRva == 0)
        {
                m_ExputTable = _T("没有数据");
        }
        else
        {
                ULONG64 dwExportTableOffset = RvaToOffset(dwExportTableRva);

                IMAGE_EXPORT_DIRECTORY *pExportTable = (IMAGE_EXPORT_DIRECTORY*)(dwExportTableOffset + (ULONG64)pFileData);

                ULONG64 dwNameOffset = RvaToOffset(pExportTable->Name);
                char* pDllName = (char*)(dwNameOffset + (ULONG64)pFileData);
                TCHAR ETname[50] = { 0 };
                CHAR_TO_WCHAR(pDllName, ETname);
                m_ExputTable = ETname;
                m_ExputTable += _T("\r\n\r\n");

                // 把所有的导出的函数地址打印出来。
                // 并且,如果是以名称导出,则输出该名称
                // 如果是以序号导出,则输出该序号。
                // 将地址表的RVA转换文件偏移
                DWORD dwAddressTableOffset = RvaToOffset(pExportTable->AddressOfFunctions);
                // 得到导出地址表
                ULONG64* pAddressTable = /*换行*/
                        (ULONG64*)(dwAddressTableOffset + (ULONG64)pFileData);

                // 得到序号表的地址                                                        
                WORD* pOrdinalTable = (WORD*)((ULONG64)pFileData + RvaToOffset(pExportTable->AddressOfNameOrdinals));

                DWORD* pNameTable = (DWORD*)((ULONG64)pFileData + RvaToOffset(pExportTable->AddressOfNames));

                BOOL bIndexIsExist = FALSE; // 


                for (int i = 0; i < pExportTable->NumberOfFunctions; ++i) {

                        // 打印地址
                        TmpCstr.Format(_T("虚序号[%d]     "), i);
                        m_ExputTable += TmpCstr;

                        //RVA
                        TmpCstr.Format(_T("地址(RVA):%08X H     "), pAddressTable[i]);
                        m_ExputTable += TmpCstr;

                        bIndexIsExist = FALSE;
                        int nNameIndex = 0;
                        for (; nNameIndex < pExportTable->NumberOfNames; ++nNameIndex) {

                                // 判断地址表的下标是否存在于序号表中
                                if (i == pOrdinalTable[nNameIndex]) {
                                        bIndexIsExist = TRUE;
                                        break;
                                }
                        }

                        if (bIndexIsExist == TRUE) {
                                // 得到名称表中的RVA
                                DWORD dwNameRva = pNameTable[nNameIndex];

                                // 将名称Rva转换成文件偏移
                                char* pFunName =
                                        (char*)((ULONG64)pFileData + RvaToOffset(dwNameRva));

                                TCHAR ETname1[50] = { 0 };
                                CHAR_TO_WCHAR(pFunName, ETname1);
                                TmpCstr.Format(_T("函数名:%s   "), ETname1);
                                m_ExputTable += TmpCstr;
                        }
                        else {

                                // 判断地址表当前索引到的袁术是否保存着地址
                                if (pAddressTable[i] != 0) {
                                        // i : 是地址表中的索引号,也就是一个虚序号
                                        // 真正的序号 = 虚序号 + 序号基数
                                        TmpCstr.Format(_T("序号:[%d]   "), pExportTable->Base);
                                        m_ExputTable += TmpCstr;
                                }
                        }

                        m_ExputTable += _T("\r\n\r\n");
                }
        }


        //导入表

        //1.1获得导入表的RVA
        DWORD   dwImportTableRva = pDataDirectory[1].VirtualAddress;
        // 1.2 将导入表的RVA转换成文件偏移
        DWORD   dwImportTableOffset = RvaToOffset(dwImportTableRva);
        // 1.3 将导入表结构体指针指向缓冲区中的导入表
        IMAGE_IMPORT_DESCRIPTOR* pImportTable =
                (IMAGE_IMPORT_DESCRIPTOR*)((ULONG64)pFileData + dwImportTableOffset);
        //2. 遍历导入表块


        //2.1判断是否遍历到了最后一个结构体。
        while (pImportTable->Name != 0) {

                //3. 解析出导入的Dll的模块名
                //  3.1 将Dll模块名的RVA转换成文件偏移
                DWORD dwNameOffset = RvaToOffset(pImportTable->Name);
                //  3.2 用一个char*指针指向dll名在内存中的位置
                char* pDllName = (char*)(dwNameOffset + (ULONG64)pFileData);

                TCHAR ITname[50] = { 0 };
                CHAR_TO_WCHAR(pDllName, ITname);
                m_ImportTable += ITname;
                m_ImportTable += _T("\r\n\r\n");

                // 4. 解析当前dll的导入函数名称
                // 4.1 得到导入名称表的地址
                pImportTable->OriginalFirstThunk; // 导入名称表
                pImportTable->FirstThunk; // 导入地址表
                // 上面说的两个表,在文件中保存的内容是完全相同的。

                DWORD dwIATOffset = RvaToOffset(pImportTable->FirstThunk);
                IMAGE_THUNK_DATA64 *pIAT = (IMAGE_THUNK_DATA64 *)((ULONG64)pFileData + dwIATOffset);

                // 4.2 遍历IAT
                //  IAT是一个IMAGE_THUNK_DATA结构体数组,
                //  数组是一个全0结尾。
                while (pIAT->u1.AddressOfData != 0) {



                        // 5.1 判断最高位是否是1

                        if (IMAGE_SNAP_BY_ORDINAL64(pIAT->u1.Ordinal)) {
                                // 函数是以序号导入的。
                                // 序号都是WORD类型,所以,只取它低16的值
                                TmpCstr.Format(_T("导入序号:[%d]   "), (pIAT->u1.Ordinal & 0xFFFF));
                                m_ImportTable += TmpCstr;
                        }
                        else {

                                // 函数是以名称方式导入的
                                // 字段保存着一个指向IMAGE_IMPORT_BY_NAME结构体的RVA
                                DWORD dwFunctionNameOffset = /*换行*/
                                        RvaToOffset(pIAT->u1.AddressOfData);

                                IMAGE_IMPORT_BY_NAME* pImportName = /*换行*/
                                        (IMAGE_IMPORT_BY_NAME*)((ULONG64)pFileData + dwFunctionNameOffset);


                                TCHAR FunName[50] = { 0 };
                                CHAR_TO_WCHAR(pImportName->Name, FunName);
                                TmpCstr.Format(_T("函数名称:[%s]   "), FunName);
                                m_ImportTable += TmpCstr;
                        }

                        // 递增到下一个结构体
                        ++pIAT;
                        m_ImportTable += _T("\r\n");
                }


                m_ImportTable += _T("\r\n\r\n");
                // 递增下一个结构体
                ++pImportTable;
        }



        // 资源表

        DWORD resourcesTableOffset = RvaToOffset(pDataDirectory[2].VirtualAddress);

        IMAGE_RESOURCE_DIRECTORY* pRoot =
                (IMAGE_RESOURCE_DIRECTORY*)(((ULONG64)pFileData) + resourcesTableOffset);


        IMAGE_RESOURCE_DIRECTORY*    pDir2;// 资源目录
        IMAGE_RESOURCE_DIRECTORY*    pDir3;// 资源目录

        IMAGE_RESOURCE_DIRECTORY_ENTRY* pEntry1;//目录入口
        IMAGE_RESOURCE_DIRECTORY_ENTRY* pEntry2;//目录入口
        IMAGE_RESOURCE_DIRECTORY_ENTRY* pEntry3;//目录入口

        IMAGE_RESOURCE_DATA_ENTRY*      pDataEntry;// 资源数据入口
        IMAGE_RESOURCE_DIR_STRING_U*    pIdString; // 保存Id的字符串

        /* 把第一层所有的目录入口都遍历出来 */
        // 得到第一个目录入口的地址
        pEntry1 = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pRoot + 1);
        for (int i = 0;
                i < pRoot->NumberOfIdEntries + pRoot->NumberOfNamedEntries;
                i++, pEntry1++) {

                //获取第一层目录入口的ID(ID就是资源的类型)
                if (pEntry1->NameIsString == 1) {
                        // NameOffset该字段的值是一个偏移
                        // 这个偏移是以资源表根目录的地址作为基址。
                        pIdString =
                                (IMAGE_RESOURCE_DIR_STRING_U*)(pEntry1->NameOffset + (ULONG64)pRoot);

                        m_ResourceTable += _T("资源类型:");
                        m_ResourceTable += pIdString->NameString;
                        m_ResourceTable += _T("\r\n\r\n");
                        //TmpCstr.Format(_T("资源类型:%s\r\n\r\n"), pIdString->NameString);
                        //m_RTEdit += TmpCstr;
                }
                else {
                        TCHAR* pType[] =
                        {
                                _T(""),          // 0
                                _T("鼠标指针"),   // 1
                                _T("位图"),   // 2
                                _T("图标"),       // 3
                                _T("菜单"),       // 4
                                _T("对话框"),      //5
                                _T("字符串列表"),  //6
                                _T("字体目录"),  //7
                                _T("字体"),      //8
                                _T("快捷键"),  //9
                                _T("非格式化资源"),  //A
                                _T("消息列表"),  //B
                                _T("鼠标指针组"),  //C
                                _T(""),             // D
                                _T("图标组"),  //E
                                _T(""),         // F
                                _T("版本信息")//10
                        };

                        if (pEntry1->Id > 16)
                        {
                                TmpCstr.Format(_T("资源类型:%d\r\n\r\n"), pEntry1->Id);
                                m_ResourceTable += TmpCstr;
                        }
                        else
                        {
                                TmpCstr.Format(_T("资源类型:%s\r\n\r\n"), pType[pEntry1->Id]);
                                m_ResourceTable += TmpCstr;
                        }

                }

                // 获取第二层目录
                if (pEntry1->DataIsDirectory == 1) {

                        pDir2 = /*得到第二层资源目录*/
                                (IMAGE_RESOURCE_DIRECTORY*)(pEntry1->OffsetToDirectory + (ULONG64)pRoot);

                        // 遍历第二层资源目录的所有目录入口
                        pEntry2 = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pDir2 + 1);
                        for (int j = 0;
                                j < pDir2->NumberOfIdEntries + pDir2->NumberOfNamedEntries;
                                ++j, ++pEntry2) {

                                // 得到资源的ID
                                if (pEntry2->NameIsString == 1) {
                                        // NameOffset该字段的值是一个偏移
                                        // 这个偏移是以资源表根目录的地址作为基址。
                                        pIdString =
                                                (IMAGE_RESOURCE_DIR_STRING_U*)(pEntry2->NameOffset + (ULONG64)pRoot);

                                        TmpCstr.Format(_T(" +资源ID:%s\r\n"), pIdString->NameString);
                                        m_ResourceTable += TmpCstr;
                                }
                                else {
                                        TmpCstr.Format(_T(" +资源ID:%d\r\n"), (DWORD)pEntry2->Id);
                                        m_ResourceTable += TmpCstr;
                                }
                                // 判断第三层是目录还是数据
                                if (pEntry2->DataIsDirectory == 1) {

                                        // 得到第三层目录的地址
                                        pDir3 =
                                                (IMAGE_RESOURCE_DIRECTORY*)(pEntry2->OffsetToDirectory + (ULONG64)pRoot);

                                        // 得到第三层的第一个目录入库
                                        pEntry3 =
                                                (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pDir3 + 1);

                                        TmpCstr.Format(_T("   +id:%d\r\n"), pEntry3->Id);
                                        m_ResourceTable += TmpCstr;
                                        // 得到数据入口
                                        pDataEntry =
                                                (IMAGE_RESOURCE_DATA_ENTRY*)(pEntry3->OffsetToData + (ULONG64)pRoot);

                                        TmpCstr.Format(_T("     +资源偏移(RVA):%x H\r\n"), pDataEntry->OffsetToData);
                                        m_ResourceTable += TmpCstr;
                                        TmpCstr.Format(_T("     +资源大小:%x H\r\n\r\n"), pDataEntry->Size);
                                        m_ResourceTable += TmpCstr;

                                }
                        }
                }
                m_ResourceTable += _T("\r\n\r\n");
        }






        //重定位表


        // 得到第一个重定位块的数组首地址(RVA)
        DWORD dwRelcationBlockOffset =
                RvaToOffset(pDataDirectory[5].VirtualAddress);

        // 得到第一个重定位块的地址
        IMAGE_BASE_RELOCATION* pRelcationBlock =
                (IMAGE_BASE_RELOCATION*)((ULONG64)pFileData + dwRelcationBlockOffset);

        while (TRUE)
        {
                // 判断是否是最后一个重定位块
                if (pRelcationBlock->VirtualAddress == 0 && pRelcationBlock->SizeOfBlock == 0) {
                        break;
                }
                TmpCstr.Format(_T("块开始的RVA[%x H],字节数[%x H] \r\n\r\n"), pRelcationBlock->VirtualAddress, pRelcationBlock->SizeOfBlock);
                m_RelocationeTable += TmpCstr;
                // 遍历重定位类型和偏移的数据块
                TypeOffset* pTypeOffset =
                        (TypeOffset*)((ULONG64)pRelcationBlock + sizeof(IMAGE_BASE_RELOCATION));

                DWORD   dwCount =
                        (pRelcationBlock->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(TypeOffset);

                for (int i = 0; i < dwCount; ++i) {

                        if (pTypeOffset[i].Type == 3)
                        {
                                TmpCstr.Format(_T("偏移[%x H]     "), pTypeOffset[i].Offset);
                                m_RelocationeTable += TmpCstr;
                        }
                        // 得到需要重定位的数据
                        DWORD dwRva = pRelcationBlock->VirtualAddress + pTypeOffset[i].Offset;
                        DWORD dwData = RvaToOffset(dwRva);
                        DWORD* pRelData = (DWORD*)(dwData + (ULONG64)pFileData);
                        printf("  +要修改的地址:[0x%08X]\n", *pRelData);

                        TmpCstr.Format(_T("要修改的地址:[%08x H]\r\n"), *pRelData);
                        m_RelocationeTable += TmpCstr;
                }
                m_RelocationeTable += _T("\r\n\r\n");

                // 递增到下一个重定位块
                pRelcationBlock =
                        (IMAGE_BASE_RELOCATION*)((ULONG64)(pRelcationBlock)+pRelcationBlock->SizeOfBlock);
        }


        //延迟加载表

        //获得导出表
        DWORD dwDelayTableRVA = pDataDirectory[13].VirtualAddress;
        if (dwDelayTableRVA == 0)
        {
                m_DelayImportTable += _T("没有数据");
        }
        else
        {
                //将多出表的RVA转换成文件偏移
                DWORD dwDelayTableOffset = RvaToOffset(dwDelayTableRVA);

                IMAGE_DELAYLOAD_DESCRIPTOR *pDelayTable = (IMAGE_DELAYLOAD_DESCRIPTOR*)(dwDelayTableOffset + (ULONG64)pFileData);
                if (pDelayTable->DllNameRVA == 0x00000300)
                {
                        m_DelayImportTable = _T("没有数据\r\n");
                }
                else
                {
                        while (pDelayTable->DllNameRVA)
                        {
                                //DllName
                                WCHAR DllName[20] = { 0 };
                                DWORD dwDelayTableNameOffset = RvaToOffset(pDelayTable->DllNameRVA);
                                ULONG64 dwName = (dwDelayTableNameOffset + (ULONG64)pFileData);
                                CHAR_TO_WCHAR((char *)dwName, DllName);


                                TmpCstr.Format(_T("DLLNameRVA:%x H   "), pDelayTable->DllNameRVA);
                                m_DelayImportTable += TmpCstr;

                                TmpCstr.Format(_T("DLLName:%s\r\n"), DllName);
                                m_DelayImportTable += TmpCstr;

                                //函数地址
                                TmpCstr.Format(_T("IAT(R)RVA:%x H   "), pDelayTable->ImportAddressTableRVA);
                                m_DelayImportTable += TmpCstr;


                                //函数名称
                                TmpCstr.Format(_T("INT(R)RVA:%x H\r\n"), pDelayTable->ImportNameTableRVA);
                                m_DelayImportTable += TmpCstr;

                                DWORD dwFunNameOffset = RvaToOffset(pDelayTable->ImportNameTableRVA);
                                DWORD dwFunName = dwFunNameOffset + (ULONG64)pFileData;

                                m_DelayImportTable += _T("-----------------------\r\n");

                                IMAGE_THUNK_DATA *pIAT = (IMAGE_THUNK_DATA *)((ULONG64)pFileData + dwFunNameOffset);

                                // 4.2 遍历IAT
                                //  n是一个IMAGE_THUNK_DATA结构体数组,
                                //  数组是一个全0结尾。
                                while (pIAT->u1.AddressOfData != 0) {

                                        // 5.1 判断最高位是否是1

                                        if (IMAGE_SNAP_BY_ORDINAL(pIAT->u1.Ordinal)) {
                                                // 函数是以序号导入的。
                                                // 序号都是WORD类型,所以,只取它低16的值
                                                TmpCstr.Format(_T("导入序号:%d\r\n"), (pIAT->u1.Ordinal & 0xFFFF));
                                                m_DelayImportTable += TmpCstr;
                                        }
                                        else {

                                                // 函数是以名称方式导入的
                                                // 字段保存着一个指向IMAGE_IMPORT_BY_NAME结构体的RVA
                                                DWORD dwFunctionNameOffset = /*换行*/
                                                        RvaToOffset(pIAT->u1.AddressOfData);

                                                IMAGE_IMPORT_BY_NAME* pImportName = /*换行*/
                                                        (IMAGE_IMPORT_BY_NAME*)((ULONG64)pFileData + dwFunctionNameOffset);


                                                TCHAR FunName[50] = { 0 };
                                                CHAR_TO_WCHAR(pImportName->Name, FunName);
                                                TmpCstr.Format(_T("函数名称:%s\r\n"), FunName);
                                                m_DelayImportTable += TmpCstr;
                                        }

                                        // 递增到下一个结构体
                                        ++pIAT;
                                        m_DelayImportTable += _T("\r\n");
                                }
                                ++pDelayTable;
                        }
                }
        }



        //TSL表

        DWORD dwTLSRVA = pDataDirectory[9].VirtualAddress;

        if (dwTLSRVA == 0)
        {
                m_TLSTable = _T("没有数据");
        }
        else{
                //将多出表的RVA转换成文件偏移
                DWORD dwTLSOffset = RvaToOffset(dwTLSRVA);

                PIMAGE_TLS_DIRECTORY64 pTLS = PIMAGE_TLS_DIRECTORY64(dwTLSOffset + (ULONG64)pFileData);


                TmpCstr.Format(_T("StartAddressOfRawData:%x H\r\n\r\n"), pTLS->StartAddressOfRawData);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("EndAddressOfRawData:%x H\r\n\r\n"), pTLS->EndAddressOfRawData);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("AddressOfIndex:%x H\r\n\r\n"), pTLS->AddressOfIndex);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("AddressOfCallBacks:%x H\r\n\r\n"), pTLS->AddressOfCallBacks);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("SizeOfZeroFill:%x H\r\n\r\n"), pTLS->SizeOfZeroFill);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("Characteristics:%x H\r\n\r\n"), pTLS->Characteristics);
                m_TLSTable += TmpCstr;
        }
        
}


发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2017-3-17 18:25
ID:IDK
邮箱:278580509@qq.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。

点评

一周已过  发表于 2017-4-8 10:17
yuedingwangji 发表于 2017-3-19 07:09
浪迹天涯的骑士 发表于 2017-3-19 15:18 来自手机
swjtu_ray 发表于 2017-3-19 15:38 来自手机
welcome你
滑稽小弟 发表于 2017-3-19 16:44 来自手机
欢迎新人
Hmily 发表于 2017-4-8 21:07
未报到,账号删除。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-24 18:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表