首页
社区
课程
招聘
[旧帖] PE添加新节的问题 0.00雪花
发表于: 2016-1-14 17:52 4474

[旧帖] PE添加新节的问题 0.00雪花

2016-1-14 17:52
4474
最近正在学习PE文件结构,就想着自己试着实现添加一个新的节,因本人比较菜,所以无法添加成功。现在把代码贴出来,希望哪位大神帮忙看一下哪里出错了

#define FILEIN                                "C:\\Windows\\notepad.exe"
#define FILEOUT                                "C:\\notepad.exe"
#define SHELLCODELENGTH                0x12
#define MESSAGEBOXADDR                0x77D507EA

BYTE shellCode[] =
{
        0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
        0xE8, 0x00, 0x00, 0x00, 0x00,
        0xE9, 0x00, 0x00, 0x00, 0x00
};

//判断是否为PE文件
BOOL IsPEFile(LPVOID ImageBase)
{
        PIMAGE_DOS_HEADER pDosHeader = NULL;
        PIMAGE_NT_HEADERS pNtHeader = NULL;

        if (!ImageBase)
        {
                return FALSE;
        }

        pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
        if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        {
                return FALSE;
        }
        pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
        if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
        {
                return FALSE;
        }
        return TRUE;
}

//得到NTHeader
PIMAGE_NT_HEADERS GetNtHeader(LPVOID ImageBase)
{
        PIMAGE_DOS_HEADER pDosHeader = NULL;
        PIMAGE_NT_HEADERS pNtHeader = NULL;
        if (!IsPEFile(ImageBase))
        {
                return NULL;
        }
        pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
        pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
        return pNtHeader;
}

//得到FileHeader
PIMAGE_FILE_HEADER GetFileHeader(LPVOID ImageBase)
{
        PIMAGE_NT_HEADERS        pNtHeader = NULL;
        PIMAGE_FILE_HEADER        pFileHeader = NULL;
        pNtHeader = GetNtHeader(ImageBase);
        if (!pNtHeader)
        {
                return NULL;
        }
        pFileHeader = &pNtHeader->FileHeader;
        return pFileHeader;
}

//得到OptionalHeader
PIMAGE_OPTIONAL_HEADER GetOptionalHeader(LPVOID ImageBase)
{
        PIMAGE_NT_HEADERS pNtHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
        pNtHeader = GetNtHeader(ImageBase);
        if (!pNtHeader)
        {
                return NULL;
        }
        pOptionHeader = &pNtHeader->OptionalHeader;
        return pOptionHeader;
}

//得到第一个节表
PIMAGE_SECTION_HEADER GetFirstSectionHeader(LPVOID ImageBase)
{
        PIMAGE_NT_HEADERS pNtHeader = NULL;
        PIMAGE_SECTION_HEADER pSectionHeader = NULL;
        pNtHeader = GetNtHeader(ImageBase);
        if (!pNtHeader)
        {
                return NULL;
        }
        pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
        return pSectionHeader;
}

//FileBuffer到ImageBuffer
DWORD FileBufferToImageBuffer(LPVOID pFileBuffer, LPVOID* pImageBuffer)
{
        DWORD        numberSection = 0;
        LPVOID        pTempImageBuffer = NULL;
        PIMAGE_FILE_HEADER                pFileHeader = NULL;
        PIMAGE_OPTIONAL_HEADER        pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER        pSectionHeader = NULL;
        if (!IsPEFile(pFileBuffer))
        {
                printf("不是标准的PE文件!\n");
                return 0;
        }
        pFileHeader = GetFileHeader(pFileBuffer);
        pOptionHeader = GetOptionalHeader(pFileBuffer);
        pSectionHeader = GetFirstSectionHeader(pFileBuffer);
        if (!pFileHeader || !pOptionHeader || !pSectionHeader)
        {
                return 0;
        }
        //获取节数、分配ImageBuffer
        numberSection = pFileHeader->NumberOfSections;
        pTempImageBuffer = malloc(pOptionHeader->SizeOfImage);
        if (!pTempImageBuffer)
        {
                printf("分配内存失败!\n");
                return 0;
        }
        //初始化为0
        memset(pTempImageBuffer, 0, pOptionHeader->SizeOfImage);
        //拷贝PE头
        memcpy(pTempImageBuffer, pFileBuffer, pOptionHeader->SizeOfHeaders);
        //拷贝节
        for (DWORD i=0; i<numberSection; i++, pSectionHeader++)
        {
                memcpy((LPVOID)((DWORD)pTempImageBuffer+pSectionHeader->VirtualAddress),
                        (LPVOID)((DWORD)pFileBuffer+pSectionHeader->PointerToRawData),
                        pSectionHeader->SizeOfRawData);
        }
        //收尾处理
        *pImageBuffer = pTempImageBuffer;
        pTempImageBuffer = NULL;
        return pOptionHeader->SizeOfImage;
}

//ImageBuffer到NewBuffer
DWORD ImageBufferToNewBuffer(LPVOID pImageBuffer, LPVOID* pNewBuffer)
{
        DWORD        numberSection = 0;
        LPVOID        pTempNewBuffer = NULL;
        DWORD        dwFileSize = 0;
        PIMAGE_FILE_HEADER                pFileHeader = NULL;
        PIMAGE_OPTIONAL_HEADER        pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER        pSectionHeader = NULL;
        if (!IsPEFile(pImageBuffer))
        {
                printf("不是标准的PE文件!\n");
                return 0;
        }
        pFileHeader = GetFileHeader(pImageBuffer);
        pOptionHeader = GetOptionalHeader(pImageBuffer);
        pSectionHeader = GetFirstSectionHeader(pImageBuffer);
        if (!pFileHeader || !pOptionHeader || !pSectionHeader)
        {
                return 0;
        }
        //获取节数、分配ImageBuffer
        numberSection = pFileHeader->NumberOfSections;
        dwFileSize = pSectionHeader[numberSection-1].PointerToRawData+pSectionHeader[numberSection-1].SizeOfRawData;
        pTempNewBuffer = malloc(dwFileSize);
        //初始化
        memset(pTempNewBuffer, 0, dwFileSize);
        //拷贝头
        memcpy(pTempNewBuffer, pImageBuffer, pOptionHeader->SizeOfHeaders);
        for (DWORD i=0; i<numberSection; i++, pSectionHeader++)
        {
                memcpy((LPVOID)((DWORD)pTempNewBuffer+pSectionHeader->PointerToRawData),
                        (LPVOID)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress),
                        pSectionHeader->SizeOfRawData);
        }
        *pNewBuffer = pTempNewBuffer;
        pTempNewBuffer = NULL;
        return dwFileSize;
}

//写入文件
BOOLEAN Write(LPVOID pMemBuffer, DWORD size, LPSTR lpszFile)
{
        FILE*        pFile = NULL;
        pFile = fopen(lpszFile, "wb+");
        if (!pFile)
        {
                return FALSE;
        }
       
        fwrite(pMemBuffer, 1, size, pFile);
        fclose(pFile);
        return TRUE;
}

//任意节添加代码
VOID AddCodeInAnySection(DWORD index)
{
        DWORD        dwFileSize = 0;
        PBYTE        codeBegin = NULL;
        BOOL        isOk = FALSE;
        DWORD        numberSection = 0;
        LPVOID        pFileBuffer = NULL;
        LPVOID        pImageBuffer = NULL;
        LPVOID        pNewBuffer = NULL;
        PIMAGE_FILE_HEADER                pFileHeader = NULL;
        PIMAGE_OPTIONAL_HEADER        pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER        pSectionHeader = NULL;
        Read(FILEIN, &pFileBuffer);
        if (!pFileBuffer)
        {
                printf("读取文件到FileBuffer失败!\n");
                return;
        }
        FileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
        if (!pImageBuffer)
        {
                printf("从FileBuffer到ImageBuffer失败!\n");
                free(pFileBuffer);
                return;
        }
        pFileHeader = GetFileHeader(pImageBuffer);
        pOptionHeader = GetOptionalHeader(pImageBuffer);
        pSectionHeader = GetFirstSectionHeader(pImageBuffer);
        numberSection = pFileHeader->NumberOfSections;
        if (index >= numberSection)
        {
                printf("代码区空闲空间不够!\n");
                free(pFileBuffer);
                free(pImageBuffer);
                return;
        }
        pSectionHeader = pSectionHeader + index;
        //写入数据
        codeBegin = (PBYTE)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress+pSectionHeader->Misc.VirtualSize);
        memcpy(codeBegin, shellCode, SHELLCODELENGTH);
        //修正E8
        DWORD callAddr = MESSAGEBOXADDR - (pOptionHeader->ImageBase+((DWORD)(codeBegin+0xD)-(DWORD)pImageBuffer));
        *(PDWORD)(codeBegin+9) = callAddr;
        //修复E9
        DWORD jmpAddr = (pOptionHeader->ImageBase+pOptionHeader->AddressOfEntryPoint)- (pOptionHeader->ImageBase+ ((DWORD)(codeBegin+0x12)-(DWORD)pImageBuffer));
        *(PDWORD)(codeBegin+0xE) = jmpAddr;
        //修复OEP
        pOptionHeader->AddressOfEntryPoint = (DWORD)codeBegin - (DWORD)pImageBuffer;

        //拷贝属性
        DWORD x = (pSectionHeader-index)->Characteristics;
        DWORD y = (pSectionHeader)->Characteristics;
        pSectionHeader->Characteristics = x | y;

        //ImageBuffer到NewBuffer
        dwFileSize = ImageBufferToNewBuffer(pImageBuffer, &pNewBuffer);
        if (dwFileSize==0 || !pNewBuffer)
        {
                printf("从ImageBuffer到NewBuffer失败!\n");
                free(pFileBuffer);
                free(pImageBuffer);
                return;
        }
       
        //存盘
        isOk = Write(pNewBuffer, dwFileSize, FILEOUT);
        if (isOk)
        {
                printf("存盘成功!\n");
                return;
        }
       
        //释放内存
        free(pFileBuffer);
        free(pImageBuffer);
        free(pNewBuffer);
}

//添加新节
VOID AddNewSection()
{
        BOOL        isOk = FALSE;
        DWORD        dwFileSize = 0;
        DWORD        numberSection = 0;
        LPVOID        pFileBuffer = NULL;
        LPVOID        pImageBuffer = NULL;
        LPVOID        pNewImageBuffer = NULL;
        LPVOID        pNewBuffer = NULL;
        PIMAGE_DOS_HEADER                pDosHeader = NULL;
        PIMAGE_FILE_HEADER                pFileHeader = NULL;
        PIMAGE_OPTIONAL_HEADER        pOptionHeader = NULL;
        PIMAGE_SECTION_HEADER        pSectionHeader = NULL;
        Read(FILEIN, &pFileBuffer);
        if (!pFileBuffer)
        {
                printf("读取文件到FileBuffer失败!\n");
                return;
        }
        FileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
        if (!pImageBuffer)
        {
                printf("从FileBuffer到ImageBuffer失败!\n");
                free(pFileBuffer);
                return;
        }
        pFileHeader = GetFileHeader(pImageBuffer);
        pOptionHeader = GetOptionalHeader(pImageBuffer);
        pSectionHeader = GetFirstSectionHeader(pImageBuffer);
        numberSection = pFileHeader->NumberOfSections;
        pNewImageBuffer = malloc(pOptionHeader->SizeOfImage+0x1000);
        if (!pNewImageBuffer)
        {
                printf("新增空间失败!\n");
                free(pFileBuffer);
                free(pImageBuffer);
                return;
        }
        if ((pOptionHeader->SizeOfHeaders-((DWORD)pSectionHeader+IMAGE_SIZEOF_SECTION_HEADER*numberSection)) < IMAGE_SIZEOF_SECTION_HEADER*2)
        {
                printf("空闲空间不够!\n");
                free(pFileBuffer);
                free(pImageBuffer);
                return;
        }

        memcpy(pNewImageBuffer, pImageBuffer, pOptionHeader->SizeOfImage);
        pDosHeader = (PIMAGE_DOS_HEADER)pNewImageBuffer;
        pOptionHeader = GetOptionalHeader(pNewImageBuffer);
        pSectionHeader = GetFirstSectionHeader(pNewImageBuffer);
       
        memcpy((PVOID)((DWORD)pNewImageBuffer+sizeof(IMAGE_DOS_HEADER)),
                (PVOID)((DWORD)pNewImageBuffer+pDosHeader->e_lfanew),
                IMAGE_SIZEOF_FILE_HEADER+pFileHeader->SizeOfOptionalHeader+IMAGE_SIZEOF_SECTION_HEADER*numberSection+4);
        pDosHeader->e_lfanew = (DWORD)pImageBuffer+sizeof(IMAGE_DOS_HEADER);
       
        memcpy(pSectionHeader+numberSection, pSectionHeader, IMAGE_SIZEOF_SECTION_HEADER);
        memset(pSectionHeader+numberSection+1, 0, IMAGE_SIZEOF_SECTION_HEADER);
        //设置属性
        strcpy((char*)(pSectionHeader+numberSection), "NewSec");
        (pSectionHeader+numberSection)->Misc.VirtualSize = 0x1000;
        (pSectionHeader+numberSection)->SizeOfRawData = 0x1000;
        (pSectionHeader+numberSection)->VirtualAddress = (pSectionHeader+numberSection-1)->SizeOfRawData>(pSectionHeader+numberSection-1)->Misc.VirtualSize?(pSectionHeader+numberSection-1)->SizeOfRawData:(pSectionHeader+numberSection-1)->Misc.VirtualSize;
        (pSectionHeader+numberSection)->PointerToRawData = (pSectionHeader+numberSection-1)->PointerToRawData+(pSectionHeader+numberSection-1)->SizeOfRawData;
        pOptionHeader->SizeOfImage += 0x1000;
        pFileHeader->NumberOfSections += 1;

        //ImageBuffer到NewBuffer
        dwFileSize = ImageBufferToNewBuffer(pNewImageBuffer, &pNewBuffer);
        if (dwFileSize==0 || !pNewBuffer)
        {
                printf("从ImageBuffer到NewBuffer失败!\n");
                free(pFileBuffer);
                free(pImageBuffer);
                return;
        }
       
        //存盘
        isOk = Write(pNewBuffer, dwFileSize, FILEOUT);
        if (isOk)
        {
                printf("存盘成功!\n");
        }
       
        //释放内存
        free(pFileBuffer);
        free(pImageBuffer);
        free(pNewBuffer);
        free(pNewImageBuffer);
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 9
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
QQ452343623
2016-1-15 20:37
0
雪    币: 2663
活跃值: (2081)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
1.if ((pOptionHeader->SizeOfHeaders - ((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER*numberSection)) < IMAGE_SIZEOF_SECTION_HEADER * 2)
        {
                printf("空闲空间不够!\n");
                free(pFileBuffer);
                free(pImageBuffer);
                return;
        }
这个判断我是没有看明白,一个大小减去一个指针小于某个大小?

2.看代码貌似是你先将PE文件读入到内存,以0x1000的对齐的pImageBuffer。然后又开辟了一个pNewImageBuffer,将整个pImageBuffer拷贝到pNewImageBuffer中。然后又将pNewImageBuffer中除Dosheader的其它头又拷到pNewImageBuffer一遍,这个又没看懂,而且拷贝应该有问题(好像Dos头的大小不是固定的哦??)。添加的节的虚拟地址的问题。
2016-1-17 13:41
0
雪    币: 98
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
多谢你认真看代码,其实我之前没有认真调试过就发出来,所以出现了很多低级错误
2016-1-21 03:53
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
路过留个mark
2016-1-21 04:28
0
雪    币: 2663
活跃值: (2081)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
是的是的,调试下就出来了
2016-1-21 09:27
0
雪    币: 95
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
虽然看不懂,但还是要支持一下的
2016-4-8 14:09
0
游客
登录 | 注册 方可回帖
返回
//