(未完待续)Windows PE 文件加壳学习笔记

来源:互联网 发布:和讯网数据爬虫 编辑:程序博客网 时间:2024/05/14 19:56
要想给PE文件加壳,搞清楚PE文件的格式是前提。
以可执行程序EXE文件为例, 由描述程序信息的文件头和记录代码数据的节组成。
文件头包括DOS文件头, PE文件头, PE可选信息头组成
下面给出个结构的C定义(在windos开发包 winnt.h 文件中可以找到)

typedef struct _PE_IMAGE_DOS_HEADER {   // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
} PE_IMAGE_DOS_HEADER;

typedef struct _PE_IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} PE_IMAGE_FILE_HEADER;

typedef struct _PE_IMAGE_OPTIONAL_HEADER32 {
    //
    // Standard fields.
    //

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    PE_IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} PE_IMAGE_OPTIONAL_HEADER32;

typedef struct _PE_IMAGE_NT_HEADERS32 {
    DWORD Signature;
    PE_IMAGE_FILE_HEADER FileHeader;
    PE_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} PE_IMAGE_NT_HEADERS32;



结构好像很复杂,其实很多部分的定义已经弃用了。 这是因为这个结构兼容 DOS, Win16, Win32以及Win64系统。 而前二者已经成为历史了,所以不少和它们相关的定义已经失效了。

文件信息头之后就是节(SECTION)信息了。 先是节头,让后才是节的数据。
给出节头的定义:
typedef struct _PE_IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} PE_IMAGE_SECTION_HEADER;

这个节头把文件空间与程序运行的虚拟空间联系起来, Windos PE 加载器正是根据这个节头还有上面提到的文件头中的数据把文件映像加载到内存中。

当加载器把数据读到内存后,还要做一些初始化工作。 这有牵涉到上面提到的PE可选信息头PE_IMAGE_OPTIONAL_HEADER32里面的最后一个数据项DataDirectory了。
DataDirectory这个数组有16个元素,各含义如下:
#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory
//      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7   // (X86 usage)
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor
#define IMAGE_DIRECTORY_ENTRY_RESERVED         15

其中比较重要的是
导出符号表 IMAGE_DIRECTORY_ENTRY_EXPORT;
导入符号表 IMAGE_DIRECTORY_ENTRY_IMPORT;
资源 IMAGE_DIRECTORY_ENTRY_RESOURCE;
导入地址表 IMAGE_DIRECTORY_ENTRY_IAT;

导出符号表作用是记录该程序导出的符号,通常是DLL文件的符号,可由其他进程调用。
导入符号表示记录该程序需要调用的外部程序。
资源的作用是记录程序资源的结构信息。
导入地址表是改程序用到的外部程序的地址。

这些数据存在于文件中的某一个节。

关于这些表的结构不是三言两语可以解释的了的,分析EXE文件的数据或者看代码吧 ,嘿嘿
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "./bst/bst_stdafx.h"
  5. #include "./bst/bst_blob.h"
  6. #include "./bst/bst_pack.h"
  7. #define XPAKER_FILE_ALIGNMENT   0x1000
  8. #define XPAKER_SECTION_ALIGNMENT 0X200
  9. int main(int argc, char** argv)
  10. {
  11.     //必须先做节的内存映射,否则PE文件中的虚地址不能用
  12.     char szInputFile[0x100];
  13.     char szOutputFile[0x100];
  14.     if(argc<2) return 0;
  15.     strcpy(szInputFile, argv[1]);
  16.     sprintf(szOutputFile, "_%s",szInputFile);
  17.     memptr_t pRead, pWrite;
  18.     PE_IMAGE_DOS_HEADER* pDosHeader;
  19.     PE_IMAGE_NT_HEADERS32* pPEHeaders;
  20.     PE_IMAGE_SECTION_HEADER* pSecHeader;
  21.     uint_t nSecNum;
  22.     PE_IMAGE_IMPORT_DESCRIPTOR* pImportDesc;
  23.     uint_t nImportDescNum;
  24.     PE_IMAGE_IMPORT_BY_NAME* pImportName;
  25.     uint_t i,j;
  26.     
  27.     blob_c PERawImage;
  28.     PERawImage.bload(szInputFile);
  29.     
  30.     pRead=PERawImage.begin();
  31.     pDosHeader=(PE_IMAGE_DOS_HEADER*)pRead; //得到原始镜像dos头的地址
  32.     
  33.     pRead+=pDosHeader->e_lfanew;
  34.     pPEHeaders = (PE_IMAGE_NT_HEADERS32*)pRead; //得到原始镜像PE头的地址
  35.     
  36.     pRead+=sizeof(PE_IMAGE_NT_HEADERS32);
  37.     pSecHeader=(PE_IMAGE_SECTION_HEADER*)pRead; //得到原始镜像节表的地址
  38.     nSecNum = pPEHeaders->FileHeader.NumberOfSections;
  39.     
  40.     //------------------------------------------------------------------------------------
  41.     //------------------------------------------------------------------------------------
  42.     blob_c PEImage(pPEHeaders->OptionalHeader.SizeOfImage);
  43.     
  44.     //映射后的内存映像
  45.     memcpy(PEImage.begin(), PERawImage.begin(), pPEHeaders->OptionalHeader.SizeOfHeaders);
  46.     for(i=0;i<=nSecNum-1;i++)
  47.     {
  48.         memset(PEImage.begin()+pSecHeader[i].VirtualAddress, 0, pSecHeader[i].Misc.VirtualSize);
  49.         memcpy(PEImage.begin()+pSecHeader[i].VirtualAddress, PERawImage.begin()+pSecHeader[i].PointerToRawData, pSecHeader[i].SizeOfRawData);
  50.     }
  51.     pRead=PEImage.begin();
  52.     pDosHeader=(PE_IMAGE_DOS_HEADER*)pRead; //得到虚拟镜像dos头的地址
  53.     
  54.     pRead+=pDosHeader->e_lfanew;
  55.     pPEHeaders = (PE_IMAGE_NT_HEADERS32*)pRead; //得到虚拟镜像PE头的地址
  56.     
  57.     pRead+=sizeof(PE_IMAGE_NT_HEADERS32);
  58.     pSecHeader=(PE_IMAGE_SECTION_HEADER*)pRead; //得到虚拟镜像节表的地址
  59.     nSecNum = pPEHeaders->FileHeader.NumberOfSections;
  60.     
  61.     
  62.     pRead = PEImage.begin() + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  63.     pImportDesc = (PE_IMAGE_IMPORT_DESCRIPTOR*)pRead; //得到虚拟镜像导入表的地址
  64.     
  65.     
  66.     //得到导入表的模块数目
  67.     for(i=0;TRUE;i++)
  68.     {
  69.         if(pImportDesc[i].Characteristics==0 && pImportDesc[i].FirstThunk==0)
  70.             break;
  71.     }
  72.     nImportDescNum = i;
  73.     
  74.     
  75.     //"winnt.h"
  76. /*  
  77.     //打印输入表
  78.     if(nImportDescNum!=0)
  79.     {
  80.         FILE* f_out;
  81.         f_out=fopen("debug.txt","wt");
  82.         
  83.         for(i=0;i<=nImportDescNum-1;i++)
  84.         {
  85.             fprintf(f_out, "%s/n", PEImage.begin()+pImportDesc[i].Name);//打印模块名
  86.             
  87.             if(pImportDesc[i].OriginalFirstThunk!=0)
  88.                 pRead = PEImage.begin() + pImportDesc[i].OriginalFirstThunk;
  89.             else
  90.                 pRead = PEImage.begin() + pImportDesc[i].FirstThunk;
  91.             
  92.             for(j=0;TRUE;j++)
  93.             {           
  94.                 if(((DWORD*)pRead)[j]==0)
  95.                     break;
  96.                 if(((DWORD*)pRead)[j]&IMAGE_ORDINAL_FLAG32)
  97.                 {
  98.                     fprintf(f_out, "  *%08X/n", ((DWORD*)pRead)[j]&0x7FFFFFFF);//打印无符号函数
  99.                 }
  100.                 else
  101.                 {
  102.                     pImportName = (PE_IMAGE_IMPORT_BY_NAME*)(PEImage.begin() + ((DWORD*)pRead)[j]);
  103.                     fprintf(f_out, "  %04X %s/n", pImportName->Hint, pImportName->Name);//打印函数
  104.                 }
  105.                 
  106.                 
  107.             }
  108.             fprintf(f_out, "/n");
  109.         }       
  110.         fclose(f_out);
  111.     }
  112. //*/
  113. /*
  114.     //重定位导入表内函数
  115.     HMODULE hModule;
  116.     FARPROC pProc;
  117.     //hModule = LoadLibrary();
  118.     //pProc = GetProcAddress(hModule, MAKEINTRESOURCE());
  119.     if(nImportDescNum!=0)
  120.     {
  121.         for(i=0;i<=nImportDescNum-1;i++)
  122.         {
  123.             hModule = LoadLibrary((LPCSTR)(PEImage.begin()+pImportDesc[i].Name));//fprintf(f_out, "%s/n", PEImage.begin()+pImportDesc[i].Name);//打印模块名
  124.             
  125.             if(pImportDesc[i].OriginalFirstThunk!=0)
  126.                 pRead = PEImage.begin() + pImportDesc[i].OriginalFirstThunk;
  127.             else
  128.                 pRead = PEImage.begin() + pImportDesc[i].FirstThunk;
  129.             
  130.             for(j=0;TRUE;j++)
  131.             {           
  132.                 if(((DWORD*)pRead)[j]==0)
  133.                     break;
  134.                 if(((DWORD*)pRead)[j]&IMAGE_ORDINAL_FLAG32)
  135.                 {
  136.                     pProc = GetProcAddress(hModule, MAKEINTRESOURCE(((DWORD*)pRead)[j]&0x7FFFFFFF));//fprintf(f_out, "  *%08X/n", ((DWORD*)pRead)[j]&0x7FFFFFFF);//打印无符号函数
  137.                 }
  138.                 else
  139.                 {
  140.                     pImportName = (PE_IMAGE_IMPORT_BY_NAME*)(PEImage.begin() + ((DWORD*)pRead)[j]);
  141.                     pProc = GetProcAddress(hModule, (LPCSTR)(pImportName->Name));//fprintf(f_out, "  %04X %s/n", pImportName->Hint, pImportName->Name);//打印函数
  142.                 }
  143.                 pRead = PEImage.begin() + pImportDesc[i].FirstThunk;
  144.                 ((DWORD*)pRead)[j] = (DWORD)pProc;
  145.             }
  146.         }
  147.     }//if
  148.     //输出IAT 重定位外部符号的地址
  149.     if(pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress!=0)
  150.     {
  151.         FILE* f_out;
  152.         f_out=fopen("debug1.txt","wt");
  153.         j = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size / 4;
  154.         pRead = PEImage.begin() + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
  155.         for(i=0;i<=j-1;i++)
  156.         {
  157.             fprintf(f_out, "%08X/n", ((DWORD*)pRead)[i]);
  158.         }
  159.         fclose(f_out);
  160.     }
  161. //*/
  162. //------------------------------------------------------------
  163.     //加壳,组装PE
  164.     uint_t PackerCodeRelocateOffset[0x10]={0x000B, 0x0013, 0x001B, 0x0023, 0x002B, 0x0033, 0x003B, };
  165.     blob_c PEReleaseBuf(pPEHeaders->OptionalHeader.SizeOfImage*3);
  166.     memset(PEReleaseBuf.begin(),0,PEReleaseBuf.size());
  167.     blob_c PELoaderData;
  168.     PELoaderData.bload(".//PackLoader//loader.dat");
  169.     ///*写映像
  170.     blob_c tmpSectionBuf_text(pPEHeaders->OptionalHeader.SizeOfImage*4);
  171.     memset(tmpSectionBuf_text.begin(),0,tmpSectionBuf_text.size());
  172.     //编码
  173.     BYTE nPeek;
  174.     BYTE byCurByte, nRptCnt;
  175.     uint_t nOldImageSize = pPEHeaders->OptionalHeader.SizeOfImage;
  176.     uint_t nOldHeaderSize = pPEHeaders->OptionalHeader.SizeOfHeaders;
  177.     pRead = PEImage.begin()+pPEHeaders->OptionalHeader.SizeOfHeaders;
  178.     pWrite = tmpSectionBuf_text.begin();
  179.     nPeek = 0;
  180.     nRptCnt = 0;
  181.     byCurByte = *((BYTE*)pRead);
  182.     for(i=0;i<=nOldImageSize-nOldHeaderSize-1;i++)
  183.     {
  184.         if(byCurByte == *((BYTE*)pRead) && nRptCnt<=(0x3F-1))   //最长的重复记录 63 个
  185.         {
  186.             nRptCnt++;
  187.         }
  188.         else
  189.         {
  190.             if(nRptCnt==1)
  191.             {
  192.                 if(byCurByte>=0xC0)
  193.                 {
  194.                     *((BYTE*)pWrite++) = 0xC1;  //没有重复,但是值大于C0
  195.                     *((BYTE*)pWrite++) = byCurByte;
  196.                 }
  197.                 else
  198.                 {
  199.                     *((BYTE*)pWrite++) = byCurByte;
  200.                 }
  201.             }
  202.             else
  203.             {
  204.                 *((BYTE*)pWrite++) = 0xC0+nRptCnt;  //重复,输出重复的代码
  205.                 *((BYTE*)pWrite++) = byCurByte;
  206.                 nRptCnt = 1;    //重新开始计数
  207.             }
  208.             byCurByte = *((BYTE*)pRead); //重复判定的字符更新
  209.         }
  210.         pRead++;
  211.     }
  212.     *((BYTE*)pWrite++) = 0xC0;  //结束符
  213.     //写壳代码
  214.     uint_t nPackerCodeEntryOffset;
  215.     nPackerCodeEntryOffset = pWrite-tmpSectionBuf_text.begin(); 
  216.     pRead = PELoaderData.begin();
  217.     memcpy(pWrite, pRead, PELoaderData.size());
  218.     //重建导入表
  219.     uint_t nOriginalFirstThunkOfImportDataOffset, nFirstThunkOfImportDataOffset, nImportTableOfImportDataOffset, nStrOfImportDataOffset;
  220.     uint_t nOriginalFirstThunkOfImportDataPtr, nFirstThunkOfImportDataPtr, nImportTableOfImportDataPtr, nStrOfImportDataPtr;
  221.     nFirstThunkOfImportDataOffset = 0;
  222.     nOriginalFirstThunkOfImportDataOffset = nFirstThunkOfImportDataOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
  223.     nImportTableOfImportDataOffset = nOriginalFirstThunkOfImportDataOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
  224.     nStrOfImportDataOffset = nImportTableOfImportDataOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
  225.     nOriginalFirstThunkOfImportDataPtr = nOriginalFirstThunkOfImportDataOffset;
  226.     nFirstThunkOfImportDataPtr = nFirstThunkOfImportDataOffset;
  227.     nImportTableOfImportDataPtr = nImportTableOfImportDataOffset;
  228.     nStrOfImportDataPtr = nStrOfImportDataOffset;
  229.     uint_t nPackerImportDataOffset = nPackerCodeEntryOffset + PELoaderData.size();
  230.     uint_t nPackerIATOffset = nPackerCodeEntryOffset + PELoaderData.size();
  231.     uint_t nImortDataVirtualOffset = 0x1000 + (pPEHeaders->OptionalHeader.SizeOfImage - pPEHeaders->OptionalHeader.SizeOfHeaders) +nPackerIATOffset;
  232.     uint_t nPackerImportOffset = nPackerIATOffset + pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
  233.     blob_c tmpImportTableBuf(pPEHeaders->OptionalHeader.SizeOfImage*2);
  234.     memcpy(tmpImportTableBuf.begin()+nImportTableOfImportDataOffset, pImportDesc, pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size);
  235.     memcpy(tmpImportTableBuf.begin()+nFirstThunkOfImportDataOffset, PEImage.begin()+pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress, pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size);
  236.     PE_IMAGE_IMPORT_DESCRIPTOR* ptmpImportDesc = (PE_IMAGE_IMPORT_DESCRIPTOR*)(tmpImportTableBuf.begin()+nImportTableOfImportDataOffset);
  237.     if(nImportDescNum!=0)
  238.     {
  239.         for(i=0;i<=nImportDescNum-1;i++)
  240.         {
  241.             //fprintf(f_out, "%s/n", PEImage.begin()+pImportDesc[i].Name);//打印模块名
  242.             strcpy((char*)tmpImportTableBuf.begin()+nStrOfImportDataPtr, (char*)PEImage.begin()+pImportDesc[i].Name);
  243.             ptmpImportDesc[i].Name = nStrOfImportDataPtr + nImortDataVirtualOffset;
  244.             nStrOfImportDataPtr += strlen((char*)PEImage.begin()+pImportDesc[i].Name)+1;
  245.             
  246.             ptmpImportDesc[i].OriginalFirstThunk = 0;
  247.             pRead = PEImage.begin() + pImportDesc[i].FirstThunk;
  248.             ptmpImportDesc[i].FirstThunk = ptmpImportDesc[i].FirstThunk - pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + nImortDataVirtualOffset;
  249.             nFirstThunkOfImportDataPtr = pImportDesc[i].FirstThunk - pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
  250.             for(j=0;TRUE;j++)
  251.             {           
  252.                 if(((DWORD*)pRead)[j]==0)
  253.                     break;
  254.                 if(!(((DWORD*)pRead)[j]&IMAGE_ORDINAL_FLAG32))
  255.                 {
  256.                     pImportName = (PE_IMAGE_IMPORT_BY_NAME*)(PEImage.begin() + ((DWORD*)pRead)[j]);
  257.                     //fprintf(f_out, "  %04X %s/n", pImportName->Hint, pImportName->Name);//打印函数
  258.                     *(BYTE*)(tmpImportTableBuf.begin()+nStrOfImportDataPtr+0) = 0;
  259.                     *(BYTE*)(tmpImportTableBuf.begin()+nStrOfImportDataPtr+1) = 0;  //Hint
  260.                     strcpy((char*)tmpImportTableBuf.begin()+nStrOfImportDataPtr+2, (char*)pImportName->Name);
  261.                     *((DWORD*)(tmpImportTableBuf.begin() + nFirstThunkOfImportDataPtr)) = nStrOfImportDataPtr + nImortDataVirtualOffset;nFirstThunkOfImportDataPtr+=4;
  262.                     nStrOfImportDataPtr += strlen((char*)pImportName->Name)+2+1; //2位Hint的长度,1为字符串结束符
  263.                 }
  264.                 else
  265.                 {
  266.                     nFirstThunkOfImportDataPtr+=4;
  267.                 }
  268.             
  269.             }
  270.             nFirstThunkOfImportDataPtr+=4;  //跳过0
  271.         }
  272.     }//if
  273.     uint_t ntmpImportTableBufSize;
  274.     ntmpImportTableBufSize = nStrOfImportDataPtr;
  275.     //写导入数据
  276.     pRead = tmpImportTableBuf.begin();
  277.     pWrite = tmpSectionBuf_text.begin() + nPackerImportDataOffset;
  278.     memcpy(pWrite, pRead, ntmpImportTableBufSize);
  279.     uint_t nSecTextImageSize;
  280.     nSecTextImageSize = nPackerImportDataOffset + ntmpImportTableBufSize;
  281.     nSecTextImageSize = (nSecTextImageSize+0x0FFF)&0xFFFFF000;
  282.     //重定位壳代码的地址
  283.     *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[0])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfImage;
  284.     *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[1])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfHeaders;
  285.     *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[2])) = nPackerCodeEntryOffset;
  286.     *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[3])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.AddressOfEntryPoint;
  287.     *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[4])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.SizeOfImage+nPackerIATOffset;
  288.     *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[5])) = pPEHeaders->OptionalHeader.ImageBase+pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
  289.     *((DWORD*)(tmpSectionBuf_text.begin()+nPackerCodeEntryOffset+PackerCodeRelocateOffset[6])) = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
  290.     
  291.     //*/
  292.     //填表头
  293.     PE_IMAGE_SECTION_HEADER tmpSecHeader_data, tmpSecHeader_text;
  294.     
  295.     memcpy(tmpSecHeader_data.Name, ".data", IMAGE_SIZEOF_SHORT_NAME);
  296.     tmpSecHeader_data.Misc.VirtualSize = pPEHeaders->OptionalHeader.SizeOfImage - pPEHeaders->OptionalHeader.SizeOfHeaders;
  297.     tmpSecHeader_data.VirtualAddress = pPEHeaders->OptionalHeader.SizeOfHeaders;
  298.     tmpSecHeader_data.SizeOfRawData = 0;//暂时
  299.     tmpSecHeader_data.PointerToRawData = pPEHeaders->OptionalHeader.SizeOfHeaders;//暂时
  300.     tmpSecHeader_data.PointerToRelocations = 0x00000000;
  301.     tmpSecHeader_data.PointerToLinenumbers = 0x00000000;
  302.     tmpSecHeader_data.NumberOfRelocations = 0x0000;
  303.     tmpSecHeader_data.NumberOfLinenumbers = 0x0000;
  304.     tmpSecHeader_data.Characteristics = 0xE0000080;
  305.     
  306.     memcpy(tmpSecHeader_text.Name, ".text", IMAGE_SIZEOF_SHORT_NAME);
  307.     tmpSecHeader_text.Misc.VirtualSize = nSecTextImageSize;//暂时
  308.     tmpSecHeader_text.VirtualAddress = pPEHeaders->OptionalHeader.SizeOfImage;
  309.     tmpSecHeader_text.SizeOfRawData = tmpSecHeader_text.Misc.VirtualSize;//暂时
  310.     tmpSecHeader_text.PointerToRawData = pPEHeaders->OptionalHeader.SizeOfHeaders;//暂时
  311.     tmpSecHeader_text.PointerToRelocations = 0x00000000;
  312.     tmpSecHeader_text.PointerToLinenumbers = 0x00000000;
  313.     tmpSecHeader_text.NumberOfRelocations = 0x0000;
  314.     tmpSecHeader_text.NumberOfLinenumbers = 0x0000;
  315.     tmpSecHeader_text.Characteristics = 0xE0000040;
  316.     PE_IMAGE_DOS_HEADER tmpDosHeader;
  317.     tmpDosHeader.e_magic = IMAGE_DOS_SIGNATURE;        // Magic number
  318.     tmpDosHeader.e_cblp = 0x0090;                      // Bytes on last page of file
  319.     tmpDosHeader.e_cp = 0x0003;                        // Pages in file
  320.     tmpDosHeader.e_crlc = 0x0000;                      // Relocations
  321.     tmpDosHeader.e_cparhdr = 0x0004;                   // Size of header in paragraphs
  322.     tmpDosHeader.e_minalloc = 0x0000;                  // Minimum extra paragraphs needed
  323.     tmpDosHeader.e_maxalloc = 0xFFFF;                  // Maximum extra paragraphs needed
  324.     tmpDosHeader.e_ss = 0x0000;                        // Initial (relative) SS value
  325.     tmpDosHeader.e_sp = 0x00B8;                        // Initial SP value
  326.     tmpDosHeader.e_csum = 0x0000;                      // Checksum
  327.     tmpDosHeader.e_ip = 0x0000;                        // Initial IP value
  328.     tmpDosHeader.e_cs = 0x0000;                        // Initial (relative) CS value
  329.     tmpDosHeader.e_lfarlc = 0x0040;                    // File address of relocation table
  330.     tmpDosHeader.e_ovno = 0x0000;                      // Overlay number
  331.     memset(tmpDosHeader.e_res, 0, sizeof(WORD)*4);                    // Reserved words
  332.     tmpDosHeader.e_oemid = 0x0000;                     // OEM identifier (for e_oeminfo)
  333.     tmpDosHeader.e_oeminfo = 0x0000;                   // OEM information; e_oemid specific
  334.     memset(tmpDosHeader.e_res2, 0, sizeof(WORD)*10);        // Reserved words
  335.     tmpDosHeader.e_lfanew = 0x00C0;                    // File address of new exe header
  336.     PE_IMAGE_NT_HEADERS32 tmpPEHeaders;
  337.     tmpPEHeaders.Signature = IMAGE_NT_SIGNATURE;
  338.     tmpPEHeaders.FileHeader.Machine = 0x014C;
  339.     tmpPEHeaders.FileHeader.NumberOfSections = 0x0002;  //就两个节
  340.     tmpPEHeaders.FileHeader.TimeDateStamp = 0x00000000;
  341.     tmpPEHeaders.FileHeader.PointerToSymbolTable = 0;
  342.     tmpPEHeaders.FileHeader.NumberOfSymbols = 0;
  343.     tmpPEHeaders.FileHeader.SizeOfOptionalHeader = 0x00E0;
  344.     tmpPEHeaders.FileHeader.Characteristics = 0x010F;
  345.     tmpPEHeaders.OptionalHeader.Magic = 0x010B;
  346.     tmpPEHeaders.OptionalHeader.MajorLinkerVersion = 0x06;
  347.     tmpPEHeaders.OptionalHeader.MinorLinkerVersion = 0x00;
  348.     tmpPEHeaders.OptionalHeader.SizeOfCode = 0x00000000;
  349.     tmpPEHeaders.OptionalHeader.SizeOfInitializedData = 0x00000000;
  350.     tmpPEHeaders.OptionalHeader.SizeOfUninitializedData = 0x00000000;
  351.     tmpPEHeaders.OptionalHeader.AddressOfEntryPoint = pPEHeaders->OptionalHeader.SizeOfImage+nPackerCodeEntryOffset;
  352.     tmpPEHeaders.OptionalHeader.BaseOfCode = 0; //没用
  353.     tmpPEHeaders.OptionalHeader.BaseOfData = 0; //没用
  354.     
  355.     tmpPEHeaders.OptionalHeader.ImageBase = pPEHeaders->OptionalHeader.ImageBase;
  356.     tmpPEHeaders.OptionalHeader.SectionAlignment = 0x00001000;
  357.     tmpPEHeaders.OptionalHeader.FileAlignment = 0x000001000;
  358.     tmpPEHeaders.OptionalHeader.MajorOperatingSystemVersion = 0x0004;
  359.     tmpPEHeaders.OptionalHeader.MinorOperatingSystemVersion = 0x0000;
  360.     tmpPEHeaders.OptionalHeader.MajorImageVersion = 0x0000;
  361.     tmpPEHeaders.OptionalHeader.MinorImageVersion = 0x0000;
  362.     tmpPEHeaders.OptionalHeader.MajorSubsystemVersion = 0x0004;
  363.     tmpPEHeaders.OptionalHeader.MinorSubsystemVersion = 0x0000;
  364.     tmpPEHeaders.OptionalHeader.Win32VersionValue = 0;
  365.     tmpPEHeaders.OptionalHeader.SizeOfImage = pPEHeaders->OptionalHeader.SizeOfHeaders + tmpSecHeader_data.Misc.VirtualSize + tmpSecHeader_text.Misc.VirtualSize;
  366.     tmpPEHeaders.OptionalHeader.SizeOfHeaders = 0x00001000;
  367.     tmpPEHeaders.OptionalHeader.CheckSum = 0x00000000;
  368.     tmpPEHeaders.OptionalHeader.Subsystem = pPEHeaders->OptionalHeader.Subsystem;
  369.     tmpPEHeaders.OptionalHeader.DllCharacteristics = 0;
  370.     tmpPEHeaders.OptionalHeader.SizeOfStackReserve = 0x00100000;
  371.     tmpPEHeaders.OptionalHeader.SizeOfStackCommit = 0x00001000;
  372.     tmpPEHeaders.OptionalHeader.SizeOfHeapReserve = 0x00100000;
  373.     tmpPEHeaders.OptionalHeader.SizeOfHeapCommit = 0x00001000;
  374.     tmpPEHeaders.OptionalHeader.LoaderFlags = 0;
  375.     tmpPEHeaders.OptionalHeader.NumberOfRvaAndSizes = 0x00000010;
  376.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = 0x00000000;
  377.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = 0x00000000;
  378.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = pPEHeaders->OptionalHeader.SizeOfImage+nPackerImportDataOffset+nImportTableOfImportDataOffset;
  379.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
  380.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = 0x00000000;
  381.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = 0x00000000;
  382.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0x00000000;
  383.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0x00000000;
  384.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress = 0x00000000;
  385.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size = 0x00000000;
  386.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0x00000000;
  387.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0x00000000;
  388.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0x00000000;
  389.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0x00000000;
  390.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].VirtualAddress = 0x00000000;
  391.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_ARCHITECTURE].Size = 0x00000000;
  392.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress = 0x00000000;
  393.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].Size = 0x00000000;
  394.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = 0x00000000;
  395.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = 0x00000000;
  396.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0x00000000;
  397.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0x00000000;
  398.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0x00000000;
  399.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0x00000000;
  400.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = pPEHeaders->OptionalHeader.SizeOfImage+nPackerImportDataOffset+nFirstThunkOfImportDataOffset;
  401.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = pPEHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
  402.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0x00000000;
  403.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0x00000000;
  404.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = 0x00000000;
  405.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = 0x00000000;
  406.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESERVED].VirtualAddress = 0;
  407.     tmpPEHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESERVED].Size = 0;
  408.     //写文件头
  409.     pWrite = PEReleaseBuf.begin();
  410.     memcpy(pWrite, &tmpDosHeader, sizeof(PE_IMAGE_DOS_HEADER)); 
  411.     pWrite = PEReleaseBuf.begin() + tmpDosHeader.e_lfarlc;
  412.     memcpy(pWrite, PERawImage.begin()+pDosHeader->e_lfarlc, 0x40); //0x40 dos stub 代码长度     
  413.     pWrite = PEReleaseBuf.begin() + tmpDosHeader.e_lfanew;
  414.     memcpy(pWrite, &tmpPEHeaders, sizeof(PE_IMAGE_NT_HEADERS32));
  415.     
  416.     //写2个节头
  417.     pWrite+=sizeof(PE_IMAGE_NT_HEADERS32);
  418.     memcpy(pWrite, &tmpSecHeader_data, sizeof(PE_IMAGE_SECTION_HEADER));
  419.     pWrite+=sizeof(PE_IMAGE_SECTION_HEADER);
  420.     memcpy(pWrite, &tmpSecHeader_text, sizeof(PE_IMAGE_SECTION_HEADER));
  421.     //写节数据
  422.     pWrite = PEReleaseBuf.begin() + tmpSecHeader_text.PointerToRawData;
  423.     memcpy(pWrite, tmpSectionBuf_text.begin(), tmpSecHeader_text.SizeOfRawData);
  424.     //dump成文件
  425.     FILE* f_rl;
  426.     f_rl = fopen(szOutputFile,"wb");
  427.     fwrite(PEReleaseBuf.begin(), tmpPEHeaders.OptionalHeader.SizeOfImage, 1, f_rl);
  428.     fclose(f_rl);
  429.     //...
  430.     return 0;   
  431. }
有点多,抱歉了。
功能不全,只能给不含资源的EXE加壳,比如win32 控制台程序。

搞清楚文件的结构之后,我们就可以开始操刀搞加壳了。

。。。待续



原创粉丝点击