欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]MFC 写的一个PEedit

[原创]MFC 写的一个PEedit

  前言   
       来论坛很长时间了,这是第一次发主题帖。最近学习了pe文件结构,所以就写了一个peedit,算是一个深入理解pe文件的过程吧,嘿嘿,写的一般,望大家多多指教。
     Pe文件结构相对来说比较复杂。但是学习它也是有规律可循的。由于网上学习pe的文章如过江之鲫,而且有很多都是很不错的,为了避免重复造轮子,所以在这里不再赘述,只在关键的地方说明下。下面这是pe文件格式和相关的资料查询链接。
    1.《黑客免杀攻防》第七章
    2.《Windows Pe权威指南》相关章节
    3.http://bbs.pediy.com/showthread.php?threadid=22892   
  4.PE文件格式,qduwg翻译http://bbs.pediy.com/showthread.php? threadid=19618
    5. http://bbs.pediy.com/showthread.php?t=98202
    这是pe文件结构图,相对于其他的pe文件结构图来说,本人觉得这图很不错。这样会对pe文件结构有一个感性的认识。

==========================================
       正如前面所说,pe文件结构的资料资料很多,所以写这个的目的主要是为了加深自己对pe文件结构的理解与认识和用MFC开发编写peedit的能力。需要说明的是,写pe文件相关的程序不难,那么其区别就在于能不能将程序写像一件艺术品,或者有自己独到的之处。比如用了巧妙的方法,而不是看前人怎么写,自己拿过来用用就了事,所以写程序并不是说只要有功能在就o了。这是我们程序员应该遵守的准则我觉得(呵呵,我知道我也有很多不足的地方,我会慢慢的改正的)。
不费话了,下面就介绍下我的项目吧;
主要功能类的安排
因为pe文件结构有许许多多的表,使用父类与子类配合来解析各个表;

这是结构体,通过成员函数返回给各个需要此结构体的子类

一些关键的函数
1.  rva转化为映射到内存的绝对地址
//rva就是内存相对偏移地址这里直接转化为加载进内存中的·绝对地址

DWORD RVA2Memaddr( DWORD dwVA,DWORD lpiamge,PIMAGE_NT_HEADERS32 pNT32 )

{

    PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT32);

    for ( DWORD i=0; i<=pNT32->FileHeader.NumberOfSections; i++ )

    {

        DWORD dwFileAddr=0;

        if ( dwVA < pSection[i].VirtualAddress )

        {

            DWORD dwAddr= dwVA - pSection[i-1].VirtualAddress-lpiamge;

            dwMemAddr=dwAddr+ pSection[i-1].PointerToRawData;

            return dwMemAddr;

        }

        else  if(dwVA>= pSection[pNT32->FileHeader.NumberOfSections-1].VirtualAddress)

        {

            DWORD dwAddr= dwVA - pSection[pNT32->FileHeader.NumberOfSections-1].VirtualAddress-lpiamge;

            dwMemAddr= dwAddr+ pSection[pNT32->FileHeader.NumberOfSections-1].PointerToRawData;

            return dwMemAddr;

        }

    } 

    return 0;

}

2.pe映像文件的载入
//载入pe文件

PeMisicInfo CPELoad::LoadPEFile(LPCTSTR lpszPath)

{

    DWORD PeFileSize=0;

    LPVOID DumpAddr=nullptr;

    BOOL CanBeRead;

    PIMAGE_NT_HEADERS32 Nt_headers;

    //创建文件映射

    HANDLE hFile=CreateFile(lpszPath,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,OPEN_EXISTING,SECURITY_IMPERSONATION,NULL);

    if(!hFile) goto EndProcess;

    PeFileSize=GetFileSize(hFile,NULL);

    if(PeFileSize==0)goto EndProcess;

    DumpAddr=VirtualAlloc(NULL,PeFileSize,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);

    if(!DumpAddr)goto EndProcess;

    DWORD dwRet;

    CanBeRead=ReadFile(hFile,DumpAddr,PeFileSize,&dwRet,NULL);

    int a=GetLastError();

    if(!CanBeRead)goto EndProcess;//判断是不是pe文件

    // 判断是不是pe文件

    BOOL isPeFile=IsPeFile(DumpAddr,PeFileSize,Nt_headers);

    if(!isPeFile) goto EndProcess;

    mypemisc.Dumpaddr=DumpAddr;

    mypemisc.nt_headeras=Nt_headers;

    mypemisc.hFile=hFile;

    mypemisc.lpPath=lpszPath;

    return mypemisc;

EndProcess:

    if(hFile)CloseHandle(hFile);

    ExitProcess(0);

}


具体的代码(展示一下关键的代码,工程源码见附件)
1.获取导出表信息
void CImportDir::ShowModuleInfo(vector<PIMAGE_SECTION_HEADER> Section)

{

    //删除掉模块栏的所有条目

    m_modulelist.DeleteAllItems();

    //删除所有vector中模块

    mymodulename.clear();

    PeMisicInfo miscinfo=ReturnMiscInfo();

    PIMAGE_NT_HEADERS32 LocalHeaders=miscinfo.nt_headeras;

    DWORD dumpaddr=(DWORD)miscinfo.Dumpaddr;

    m_dumpaddr=dumpaddr;

    WORD optional_header_size=LocalHeaders->FileHeader.SizeOfOptionalHeader;

    PIMAGE_OPTIONAL_HEADER32  Optional_header=&LocalHeaders->OptionalHeader;

    PIMAGE_DATA_DIRECTORY pDataDir = (PIMAGE_DATA_DIRECTORY)Optional_header->DataDirectory;

    //导入表的地址

    DWORD my_export_rva=pDataDir[1].VirtualAddress;

    DWORD Import_Table_Section_ShiftAddr;

    DWORD OA;

   //数据段的RVA

    for(int a=0;a<Section.size();a++)

    {

        if(Section[a]->VirtualAddress>my_export_rva)

        {

            m_OA=OA=Section[a-1]->VirtualAddress-Section[a-1]->PointerToRawData;

            Import_Table_Section_ShiftAddr=my_export_rva-OA;

            break;

        }

    }

    if(Import_Table_Section_ShiftAddr==0xcccccccc)

    {

        MessageBox(L"未初始化",L"错误",MB_OK);

        return;

    }

    //获取输入表信息

    IMAGE_IMPORT_DESCRIPTOR *my_Import_Data=(PIMAGE_IMPORT_DESCRIPTOR)(Import_Table_Section_ShiftAddr+(DWORD)dumpaddr);

    PIMAGE_THUNK_DATA32 pInt;

    //判断的条件是因为大多数情况IMAGE_THUNK_DATA 会指向一个IMPORT_BY_NAME 结束的时候会以一个

    //全零的IMAGE_THUNK_DATA结束

    if(pInt=(PIMAGE_THUNK_DATA32)my_Import_Data->OriginalFirstThunk)

    {

        while(my_Import_Data->Name)

        {

            MYIMAGE_IMPORT_DESCRIPTOR my_image_des={0};

            DWORD pszDllName_Addr=my_Import_Data->Name-OA+dumpaddr;

            my_image_des.dllname=pszDllName_Addr;

            my_image_des.my_image_descriptor.FirstThunk=my_Import_Data->FirstThunk;

            my_image_des.my_image_descriptor.OriginalFirstThunk=my_Import_Data->OriginalFirstThunk;

            my_image_des.my_image_descriptor.ForwarderChain=my_Import_Data->ForwarderChain;

            my_image_des.my_image_descriptor.Name=my_Import_Data->Name;

            mymodulename.push_back(my_image_des);

            my_Import_Data++;

        }

        for(int a=0;a<mymodulename.size();a++)

        {

            CString myid;

            myid.Format(L"%d",a);

            char* mychar;

            m_modulelist.InsertItem(LVIF_TEXT | LVIF_STATE,a, myid,(a % 2) == 0 ? LVIS_SELECTED : 0, LVIS_SELECTED,0,0);

            for(int i=1;i<6;i++)

            {

                LPCWCH OutputChar[4]={0};

                CString mymoduleinfo;

                switch (i)

                {

                case 1:

                    MyUtil.ConvertUtf8ToUnicode((char*)mymodulename[a].dllname,*OutputChar);

                    mymoduleinfo.Format(L"%s",*OutputChar);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 2:

mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.OriginalFirstThunk);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 3:

                    mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.ForwarderChain);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 4:

mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.Name);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 5:

mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.FirstThunk);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                default:

                    break;

                }

            }

        }

    }

}


2.导出表信息
void CExportDir::GetExportInfo()

{

    LPCWCH outputchar={0};

    LPCWCH outputchar1={0};

    m_exportlistcrl.DeleteAllItems();

    m_vec_myexportinfo.clear();

    PeMisicInfo miscinfo=ReturnMiscInfo();//获取pe基本信息

    PIMAGE_NT_HEADERS32   pNT32    = miscinfo.nt_headeras;

    PIMAGE_DATA_DIRECTORY pDataDir = (PIMAGE_DATA_DIRECTORY)pNT32->OptionalHeader.DataDirectory;

    PIMAGE_DATA_DIRECTORY   pExportDir      = &pDataDir[IMAGE_DIRECTORY_ENTRY_EXPORT];

    if(pExportDir->Size!=0)

    {

    DWORD                   dwExportOfffset = Rva2FileA(pExportDir->VirtualAddress, pNT32);//输出表地文件偏移

    PIMAGE_EXPORT_DIRECTORY pExport         = (PIMAGE_EXPORT_DIRECTORY)((DWORD)miscinfo.Dumpaddr+dwExportOfffset);

    PDWORD pEAT = (PDWORD)((DWORD)miscinfo.Dumpaddr + Rva2FileA(pExport->AddressOfFunctions, pNT32));

    PDWORD pENT = (PDWORD)((DWORD)miscinfo.Dumpaddr + Rva2FileA(pExport->AddressOfNames, pNT32));

    PWORD  pEIT = (PWORD)((DWORD)miscinfo.Dumpaddr  + Rva2FileA(pExport->AddressOfNameOrdinals, pNT32));

    PCHAR exenameaddr=(PCHAR)((DWORD)miscinfo.Dumpaddr + Rva2FileA(pExport->Name, pNT32));  

    mysttring.ConvertUtf8ToUnicode((char*)exenameaddr,outputchar1);

    /////////////////////////////////////////////

    //格式化输出

    m_ExpDirFa.Format(L"0x%X",dwExportOfffset);

    m_funaddr.Format(L"0x%X",pExport->AddressOfFunctions);

    m_funnameaddr.Format(L"0x%X",pExport->AddressOfNames);

    m_funnamenums.Format(L"%d",pExport->NumberOfNames);

    m_char.Format(L"%d",pExport->Characteristics);

    m_exename.Format(L"%s",outputchar1);

    m_funordaddr.Format(L"0x%X",pExport->AddressOfNameOrdinals);

    m_funnums.Format(L"0x%X",pExport->NumberOfFunctions);

    m_baseaddr.Format(L"0x%X",pExport->Base);

    m_namerva.Format(L"0x%X",pExport->Name);

    for ( DWORD dwOrdinal=0; dwOrdinal<pExport->NumberOfFunctions; dwOrdinal++ )

    {

        if ( !pEAT[dwOrdinal] )

            continue;

        for ( DWORD dwIndex=0; dwIndex<pExport->NumberOfFunctions; dwIndex++ )

        {

         EXPORTINFO myexportinfo={0};

            if ( pEIT[dwIndex] == dwOrdinal )

            {

                PCHAR pszFunName = (PCHAR)((DWORD)miscinfo.Dumpaddr+Rva2FileA(pENT[dwIndex], pNT32));

                myexportinfo.Ordinal=pExport->Base+dwOrdinal;

                myexportinfo.FuncRva=pEAT[dwOrdinal];

                mysttring.ConvertUtf8ToUnicode(pszFunName,outputchar);

                myexportinfo.funcname=outputchar;

                m_vec_myexportinfo.push_back(myexportinfo);

                break;

            }

            else if ( dwIndex == pExport->NumberOfFunctions-1 )

            {

                myexportinfo.Ordinal=pExport->Base+dwOrdinal;

                myexportinfo.FuncRva=pEAT[dwOrdinal];

                myexportinfo.funcname=(LPCWCH) L"(Null)" ;

                m_vec_myexportinfo.push_back(myexportinfo);

                break;

            }

          /// free(myexportinfo); 

        }

    }

    ///////////////////////////////////./////

    //显示信息

    ////////////////////////////////////////

    UpdateData(FALSE);

    Showinfo();

    }

    else

    {

        MessageBox(L"没有导出表!",L"错误",MB_OK|MB_ICONSTOP);

    }

}

3.资源表信息
    这是插入时的一个细节问题大家结合图与代码看看就明白了
   
void CSrc::ShowInfo()

{

    //这里用ID关联资源之间的关系,来显示层与层之间的关系

    int ID1=0;

    m_srcTreecrl.ModifyStyle(NULL,TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT);

    PeMisicInfo miscinfo=ReturnMiscInfo();

    PIMAGE_NT_HEADERS32 pNT32 = (PIMAGE_NT_HEADERS32)miscinfo.nt_headeras;

    // 1.2 获取数据目录表

    PIMAGE_DATA_DIRECTORY pDir = (PIMAGE_DATA_DIRECTORY)pNT32->OptionalHeader.DataDirectory;

    // 1.3 获取资源表的数据目录

    PIMAGE_DATA_DIRECTORY pDataDir = pDir+IMAGE_DIRECTORY_ENTRY_RESOURCE;

    // 1.4 获取资源表

    PIMAGE_RESOURCE_DIRECTORY pResource1 = (PIMAGE_RESOURCE_DIRECTORY)RVA2Memaddr(pDataDir->VirtualAddress, miscinfo.Dumpaddr, pNT32);

    // 2. 循环遍历资源表

    // 2.1 第一层目录遍历

    DWORD dwCount1 = pResource1->NumberOfIdEntries+pResource1->NumberOfNamedEntries;

    for ( DWORD i=0; i<dwCount1; i++ )

    {

        SRCSTRUCT mystc={0};

        ID1++;

        mystc.ID=ID1;

        LPCWCH* outputchar=new LPCWCH;

        PIMAGE_RESOURCE_DIRECTORY_ENTRY pDirEntry1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResource1+sizeof(IMAGE_RESOURCE_DIRECTORY));

        if ( pDirEntry1[i].NameIsString )

        {

            PIMAGE_RESOURCE_DIR_STRING_U pString = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResource1+pDirEntry1[i].NameOffset);

            mystc.str.Format(L"Type:%ls",pString->NameString);

            Level1.push_back(mystc);

        } 

        else

        {

            if ( pDirEntry1[i].Name>0x10 )

            {

                mystc.str.Format(L"%04X",pDirEntry1[i].Name);

                Level1.push_back(mystc);

            }

            else

            {

                mystc.str.Format(L"%ls",szResourceType[pDirEntry1[i].Name] );

                Level1.push_back(mystc);

            }

        }

        if ( pDirEntry1[i].DataIsDirectory )

        {

            int secid=0;

            // 2.2 第二层目录的遍历

            PIMAGE_RESOURCE_DIRECTORY pResource2 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResource1+pDirEntry1[i].OffsetToDirectory);

            DWORD dwCount2 = pResource2->NumberOfIdEntries+pResource2->NumberOfNamedEntries;

            for ( DWORD j=0; j<dwCount2; j++ )

            {

                SRCSTRUCT mystc2={0};

                mystc2.ID=ID1;

                //第二级的id

                secid++;

                mystc2.secid=secid;

                PIMAGE_RESOURCE_DIRECTORY_ENTRY pDirEntry2 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResource2+sizeof(IMAGE_RESOURCE_DIRECTORY));

                if ( pDirEntry2[j].NameIsString )

                {

                    LPWSTR szBuffer[30];

                    PIMAGE_RESOURCE_DIR_STRING_U pString = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResource2+pDirEntry2[j].NameOffset);

                    mystc2.str.Format(L"ID:%ls",pString->NameString);

                    Level2.push_back(mystc2);

                } 

                else

                {

                    mystc2.str.Format(L"ID:%X",pDirEntry2[j].Name);

                    Level2.push_back(mystc2);

                }

                if ( pDirEntry2[j].DataIsDirectory )

                {

                   DWORD subId=0;

                    // 2.3 第三层目录的遍历

                    PIMAGE_RESOURCE_DIRECTORY pResource3 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResource1+pDirEntry2[j].OffsetToDirectory);

                    DWORD dwCount3 = pResource3->NumberOfIdEntries+pResource3->NumberOfNamedEntries;

                    for ( DWORD k=0; k< dwCount3; k++ )

                    {

                        SRCSTRUCT mystc3={0};

                        mystc3.secid=secid;

                        mystc3.ID=ID1;

                        subId++;

                        mystc3.subID=subId;

                        PIMAGE_RESOURCE_DIRECTORY_ENTRY pDirEntry3 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResource3+sizeof(IMAGE_RESOURCE_DIRECTORY));

                        PIMAGE_RESOURCE_DATA_ENTRY pData = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pResource1+pDirEntry3[k].OffsetToData);

                        mystc3.str.Format(L"Lng:%04X,RVA:0x%p Size:%04X Page:0x%p",pDirEntry3[k].Name,pData->OffsetToData, pData->Size, pData->CodePage);

                        Level3.push_back(mystc3); 

                    }

                } 

                else

                {

                    // ....

                }

            }

        } 

        else

        {

            // ......

        }

    }

RealShowInfo();

 }

导入表信息
获取模块信息
void CImportDir::ShowModuleInfo(vector<PIMAGE_SECTION_HEADER> Section)

{

    //删除掉模块栏的所有条目

    m_modulelist.DeleteAllItems();

    //删除所有vector中模块

    mymodulename.clear();

    PeMisicInfo miscinfo=ReturnMiscInfo();

    PIMAGE_NT_HEADERS32 LocalHeaders=miscinfo.nt_headeras;

    DWORD dumpaddr=(DWORD)miscinfo.Dumpaddr;

    m_dumpaddr=dumpaddr;

    WORD optional_header_size=LocalHeaders->FileHeader.SizeOfOptionalHeader;

    PIMAGE_OPTIONAL_HEADER32  Optional_header=&LocalHeaders->OptionalHeader;

    PIMAGE_DATA_DIRECTORY pDataDir = (PIMAGE_DATA_DIRECTORY)Optional_header->DataDirectory;

    //导入表的地址

    DWORD my_export_rva=pDataDir[1].VirtualAddress;

    DWORD Import_Table_Section_ShiftAddr;

    DWORD OA;

   //数据段的RVA

    for(int a=0;a<Section.size();a++)

    {

        if(Section[a]->VirtualAddress>my_export_rva)

        {

            m_OA=OA=Section[a-1]->VirtualAddress-Section[a-1]->PointerToRawData;

            Import_Table_Section_ShiftAddr=my_export_rva-OA;

            break;

        }

    }

    if(Import_Table_Section_ShiftAddr==0xcccccccc)

    {

        MessageBox(L"未初始化",L"错误",MB_OK);

        return;

    }

    //获取输入表信息

    IMAGE_IMPORT_DESCRIPTOR *my_Import_Data=(PIMAGE_IMPORT_DESCRIPTOR)(Import_Table_Section_ShiftAddr+(DWORD)dumpaddr);

    PIMAGE_THUNK_DATA32 pInt;

    //判断的条件是因为大多数情况IMAGE_THUNK_DATA 会指向一个IMPORT_BY_NAME 结束的时候会以一个

    //全零的IMAGE_THUNK_DATA结束

    if(pInt=(PIMAGE_THUNK_DATA32)my_Import_Data->OriginalFirstThunk)

    {

        while(my_Import_Data->Name)

        {

            MYIMAGE_IMPORT_DESCRIPTOR my_image_des={0};

            DWORD pszDllName_Addr=my_Import_Data->Name-OA+dumpaddr;

            my_image_des.dllname=pszDllName_Addr;

            my_image_des.my_image_descriptor.FirstThunk=my_Import_Data->FirstThunk;

            my_image_des.my_image_descriptor.OriginalFirstThunk=my_Import_Data->OriginalFirstThunk;

            my_image_des.my_image_descriptor.ForwarderChain=my_Import_Data->ForwarderChain;

            my_image_des.my_image_descriptor.Name=my_Import_Data->Name;

            mymodulename.push_back(my_image_des);

            my_Import_Data++;

        }

        for(int a=0;a<mymodulename.size();a++)

        {

            CString myid;

            myid.Format(L"%d",a);

            char* mychar;

            m_modulelist.InsertItem(LVIF_TEXT | LVIF_STATE,a, myid,(a % 2) == 0 ? LVIS_SELECTED : 0, LVIS_SELECTED,0,0);

            for(int i=1;i<6;i++)

            {

                LPCWCH OutputChar[4]={0};

                CString mymoduleinfo;

                switch (i)

                {

                case 1:

                    MyUtil.ConvertUtf8ToUnicode((char*)mymodulename[a].dllname,*OutputChar);

                    mymoduleinfo.Format(L"%s",*OutputChar);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 2:

                    mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.OriginalFirstThunk);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 3:

                    mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.ForwarderChain);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 4:

                    mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.Name);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 5:

                    mymoduleinfo.Format(L"0x%X",mymodulename[a].my_image_descriptor.FirstThunk);

                    m_modulelist.SetItemText(a,i,mymoduleinfo);

                    break;

                default:

                    break;

                }

            }

        }

    }

}

然后是通过点击模块,获取具体模块的api信息
void CImportDir::ShowImportFuncInfo(PIMAGE_IMPORT_DESCRIPTOR my_Import_Data,DWORD OA,DWORD dumpaddr)

{

    m_funlist.DeleteAllItems();

    //先清空Func vector

    myfunlist.clear();

    //指向输入名称地址表(INT) 绝对地址

    DWORD pInt=my_Import_Data->OriginalFirstThunk-OA;

    DWORD pInt_addr=pInt+dumpaddr;

    PIMAGE_THUNK_DATA32 Pint=(PIMAGE_THUNK_DATA32)pInt_addr;

    //循环打印INT的内容

    if (Pint->u1.Ordinal)

    {

        while (Pint->u1.Ordinal)

        {

            DWORD i=0;

            if(!IMAGE_SNAP_BY_ORDINAL32(Pint->u1.Ordinal))

            {

                MYFUNCINFO myfun={0};

                DWORD  my_import_rva_data=(DWORD)Pint->u1.AddressOfData;

                DWORD  My_importFunciton_name_addr=my_import_rva_data-OA+dumpaddr;

                PIMAGE_IMPORT_BY_NAME My_importFunciton_name_struct=(PIMAGE_IMPORT_BY_NAME)(My_importFunciton_name_addr);

                myfun.FunName=(LPCTSTR)My_importFunciton_name_struct->Name;

                myfun.ThunkRVA=my_Import_Data->OriginalFirstThunk+i*4;

                myfun.Hint=My_importFunciton_name_struct->Hint;

                myfun.ThunkValue=my_import_rva_data;

                myfunlist.push_back(myfun);

                Pint++;

                i++;

                continue;

            }

            Pint++;

        }

        for(int a=0;a<myfunlist.size();a++)

        {

            CString myid;

            myid.Format(L"%d",a+1);

            m_funlist.InsertItem(LVIF_TEXT | LVIF_STATE,a, myid,(a % 2) == 0 ? LVIS_SELECTED : 0, LVIS_SELECTED,0,0);

            for(int i=1;i<6;i++)

            {

                LPCWCH outputfun[8]={0};

                CString mymoduleinfo;

                switch (i)

                {

                case 1:

                    MyUtil.ConvertUtf8ToUnicode((char*)myfunlist[a].FunName,*outputfun);

                    mymoduleinfo.Format(L"%s",*outputfun);

                    m_funlist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 2:

                    mymoduleinfo.Format(L"0x%X",myfunlist[a].ThunkRVA+4*a);

                    m_funlist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 3:

                    mymoduleinfo.Format(L"0x%X",myfunlist[a].ThunkRVA-OA+4*a);

                    m_funlist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 4:

                    mymoduleinfo.Format(L"0x%X",myfunlist[a].ThunkValue);

                    m_funlist.SetItemText(a,i,mymoduleinfo);

                    break;

                case 5:

                    mymoduleinfo.Format(L"0X%X",myfunlist[a].Hint);

                    m_funlist.SetItemText(a,i,mymoduleinfo);

                    break;

                default:

                    break;

                }

            }

        }

    }

}

===============
代码就贴这些了,
================
这写是软件界面的截图
主界面

导入表
]
导出表

资源表

16Edit
   这个是调用的16edit的库,本人表示再次被yoda大牛所折服。。。。

总结
     通过学习pe文件,给我的感觉就是微软那帮人真是厉害,那数据结构搞的如此复杂,当然复杂不是他们的目的,而是更好的更加稳定的让程序在windows上运行。另一个就是绝知此事要躬行,pe文件虽然不是很复杂,但是能掌握到何种程度是另一回事,而且学完之后,你能思考为什么会这样安排某一数据层次,就是另一个层次。思考问题外的问题往往我们会收获更多,这也许就是大牛与菜鸟的区别吧,呵呵。源码见附件,稍后会补上文档,大家先看看源码吧。这样会有更多的思考的机会,也希望大家能指出其中的错误,愿与大家共同成长。
附件密码是:kanxue123

上传的附件 srcstrutc.png
main2.png
import.png
export.png
16进制编辑.png
src2.png
图片1.jpg
class.png
basestruct.PNG
PEEdit.zip

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功