指尖博客

记录个人成长

滴水三期PE文件结构之新增节

这节的练习,我断断续续研究了好久,因为我本人编程能力还有待提高所以有些痛苦,不过还好搞定了
要点:
0x1修改NumberOfSections,增加了几个节就加几,这修改不对会导致程序报错。
0x2新节内存中偏移,你需要先找到最后一个节,比较VirtualSize和SizeOfRawData,谁大取谁作为最后一个节的大小。
0x3新节文件中偏移,无需再比较,直接取SizeOfRawData;

//SizeOfFile为文件中的大小
DWORD AddSection(PVOID PFileBuffer, PVOID* PNewFileBuffer,DWORD SizeOfFile)
{
    PIMAGE_DOS_HEADER PDos_Header = NULL;
    PIMAGE_NT_HEADERS PNT_Header = NULL;
    PIMAGE_FILE_HEADER PFile_Header = NULL;
    PIMAGE_OPTIONAL_HEADER POptional_Header = NULL;
    PIMAGE_SECTION_HEADER PSection_Header = NULL;
    PIMAGE_SECTION_HEADER PLastSection = NULL;
    PVOID PTemFile = NULL;
    DWORD PSizeOfNewFile =SizeOfFile+0x1000;//增加0x1000的内存空间
    if (!PFileBuffer)
    {
        printf("AddSection:文件无效\n");
    return 0;
    }
    if (*((PWORD)PFileBuffer) != IMAGE_DOS_SIGNATURE)
    {
        printf("AddSection:文件不含MZ标识\n");
    return 0;
    }
    PDos_Header = (PIMAGE_DOS_HEADER)PFileBuffer;
    if (*((PDWORD)((DWORD)PFileBuffer + PDos_Header->e_lfanew)) != IMAGE_NT_SIGNATURE)
    {
    printf("AddSection:不含PE标识,不是exe程序\n");
    return 0;
    }
    PTemFile = (PVOID)malloc(PSizeOfNewFile);//分配临时储存空间
    if (!PTemFile)
    {
    printf("AddSection:分配空间失败\n");
    free(PTemFile);
    return 0;
    }
    memset(PTemFile, 0, PSizeOfNewFile);//初始化为0
    memcpy(PTemFile, PFileBuffer, PSizeOfNewFile);//将FileBuffer复制到临时空间
    //初始化头部结构体
    PNT_Header = (PIMAGE_NT_HEADERS)((DWORD)PTemFile + PDos_Header->e_lfanew);
    PFile_Header = (PIMAGE_FILE_HEADER)((DWORD)PTemFile + PDos_Header->e_lfanew + 4);
    POptional_Header = (PIMAGE_OPTIONAL_HEADER)((DWORD)PTemFile + PDos_Header->e_lfanew + 0x18);
    PSection_Header = (PIMAGE_SECTION_HEADER)((DWORD)POptional_Header + PFile_Header->SizeOfOptionalHeader);
    //计算所有头部结构的大小
    DWORD lfanew = PDos_Header->e_lfanew;
    DWORD SizeOfHeader = POptional_Header->SizeOfHeaders;
    DWORD NumberOfSection = PFile_Header->NumberOfSections;
    DWORD SizeOfNFO = 0x4 + 0x18 + PFile_Header->SizeOfOptionalHeader;
    //计算剩余空间
    DWORD Remain = SizeOfHeader - lfanew - SizeOfNFO - NumberOfSection * sizeof(*PSection_Header);
    //将节表指向最后一个
    PLastSection = &PSection_Header[PFile_Header->NumberOfSections - 1];
    //判断剩余空间是否满足条件
    if (Remain < 2 * sizeof(*PSection_Header))
    {
    printf("剩余空间大小不足,将移动头部\n");
    //移动头部
    memcpy((PDWORD)PTemFile + 0x40, (PDWORD)PTemFile + PDos_Header->e_lfanew, Remain);
    PDos_Header->e_lfanew = 0x40;//指向新的NT头开始位置
    //重新初始化PE头结构体
    PDos_Header = (PIMAGE_DOS_HEADER)PTemFile;
    PNT_Header = (PIMAGE_NT_HEADERS)((DWORD)PTemFile + PDos_Header->e_lfanew);
    PFile_Header = (PIMAGE_FILE_HEADER)((DWORD)PTemFile + PDos_Header->e_lfanew + 4);
    POptional_Header = (PIMAGE_OPTIONAL_HEADER)((DWORD)PTemFile + PDos_Header->e_lfanew + 0x18);
        PSection_Header = (PIMAGE_SECTION_HEADER)((DWORD)POptional_Header + PFile_Header-        >SizeOfOptionalHeader);
    }
    //初始化新节表信息
    PWORD PNumberOfSection = &PFile_Header->NumberOfSections;
    PDWORD PSizeOfImage = &POptional_Header->SizeOfImage;
    PVOID PSectionName = &PSection_Header[PFile_Header->NumberOfSections].Name;
    PDWORD PSectionMisc = &PSection_Header[PFile_Header->NumberOfSections].Misc.VirtualSize;
    PDWORD PSectionVirtualAddress = &PSection_Header[PFile_Header->NumberOfSections].VirtualAddress;
    PDWORD PSectionPointerToRawData = &PSection_Header[PFile_Header->NumberOfSections].PointerToRawData;
    PDWORD PSectionSizeOfRawData = &PSection_Header[PFile_Header->NumberOfSections].SizeOfRawData;
    PDWORD PSectionCharacteristic = &PSection_Header[PFile_Header->NumberOfSections].Characteristics;
    //节表数量+1
    * PNumberOfSection = PFile_Header->NumberOfSections + 1;
    printf("NumberOfSection:%x\n", PFile_Header->NumberOfSections);
    //新节表赋值
    *PSizeOfImage = POptional_Header->SizeOfImage + 0x1000;
    memcpy(PSectionName, ".zhijian", 8);
    *PSectionMisc = 0x1000;
    //计算上一个节表大小,VirtualSize和SizeOfRawData
    DWORD PSize = PLastSection->Misc.VirtualSize > PLastSection->SizeOfRawData ?
    PLastSection->Misc.VirtualSize : PLastSection->SizeOfRawData;
    *PSectionVirtualAddress = PLastSection->VirtualAddress + PSize;//新内存中节表开始地址
    *PSectionSizeOfRawData = 0x1000;
    //新节表文件中开始地址
    *PSectionPointerToRawData = PLastSection->PointerToRawData + PLastSection->SizeOfRawData;
    *PSectionCharacteristic = 0xFFFFFFFF;
    *PNewFileBuffer = PTemFile;
    PTemFile = NULL;
    return PSizeOfNewFile;
}

正常运行
软件可以正常使用
新增节成功
新增节数据

暂无评论

发表评论