逆向 | PE新增节

逆向 | PE 新增节

还是给自己的书写代码,这里顺便存一份:
操作的样本是32位的。

#include <stdio.h>
#include <Windows.h>
#include <string.h>

VOID hex_print(UCHAR* p, DWORD size) {
    DWORD i;
    printf("\n--------%p--------\n", p);
    for (i = 0; i < size; i++) {
        printf("0x%02X ", p[i]);
        if ((i + 1) % 16 == 0) {
            printf("\n");
        }
    }
    printf("\n----------------\n");
}

VOID add_section(WCHAR* pefilename, DWORD section_size) {
    // 映射PE文件进内存
    printf("add section: [%ls] \n", pefilename);
    HANDLE fp = CreateFile(pefilename,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_SEQUENTIAL_SCAN,
        NULL);
    if (fp == NULL) {
        printf("err CreateFile \n");
        return;
    }

    DWORD dwBytesInBlock = GetFileSize(fp, NULL); //文件长度
    printf(" > file size: %x \n", dwBytesInBlock);

    HANDLE hFileMapping = CreateFileMapping(fp,
        NULL,
        PAGE_READWRITE,
        0,//(DWORD)(dwBytesInBlock >> 16),
        dwBytesInBlock,//(DWORD)(dwBytesInBlock & 0x0000FFFF),
        NULL);

    int dwError = GetLastError();

    // 偏移地址
    DWORD64 qwFileOffset = 0;

    // 将文件数据映射到进程的地址空间
    LPVOID pbFile = (LPVOID)MapViewOfFile(hFileMapping,
        FILE_MAP_ALL_ACCESS,
        (DWORD)(qwFileOffset >> 32),
        (DWORD)(qwFileOffset & 0xFFFFFFFF),
        dwBytesInBlock);

    printf(" > map: %p \n", pbFile);


    // 检索PE文件信息
    if (((PIMAGE_DOS_HEADER)pbFile)->e_magic != IMAGE_DOS_SIGNATURE) {
        printf(" > IMAGE_DOS_SIGNATURE check fail \n");
        hex_print((UCHAR*)pbFile, 16);
        return;
    }

    PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD64)pbFile + ((PIMAGE_DOS_HEADER)pbFile)->e_lfanew);
    if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
        printf(" > IMAGE_NT_SIGNATURE check fail \n");
        hex_print((UCHAR*)pNtHeader, 16);
        return;
    }

    // 判断是否有足够的空间增加一个节表项
    printf(" > NumberOfSections: %d \n", pNtHeader->FileHeader.NumberOfSections);
    printf(" > SizeOfHeaders: 0x%x \n", pNtHeader->OptionalHeader.SizeOfHeaders);
    if ((pNtHeader->FileHeader.NumberOfSections + 1) * sizeof(IMAGE_SECTION_HEADER) >
        (pNtHeader->OptionalHeader.SizeOfHeaders)) {
        printf("not enough space for a new section header! \n");
        return;
    }

    // 获取新增节标项的内存位置和文件偏移
    PIMAGE_SECTION_HEADER pNewSection = (PIMAGE_SECTION_HEADER)((DWORD64)pNtHeader + 24/*标准PE头size*/ +
        pNtHeader->FileHeader.SizeOfOptionalHeader + pNtHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
    printf("> new section position: 0x%x \n", (DWORD64)pNewSection - (DWORD64)pbFile);

    PIMAGE_SECTION_HEADER pLastSection = (PIMAGE_SECTION_HEADER)((DWORD64)pNewSection - 40/*节表项的大小*/);

    // 新增一个节表项
    memcpy(pNewSection->Name, ".mz", strlen(".mz"));
    pNewSection->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; // 设置节属性为可读可写
    pNewSection->PointerToRawData = pLastSection->PointerToRawData + pLastSection->SizeOfRawData;// 文件中的节偏移FOA(从最后一个节标项目获取到新增节的文件偏移)
    pNewSection->SizeOfRawData = section_size;    // 文件中的节大小
    pNewSection->Misc.VirtualSize = section_size;    // 在内存中的大小
    DWORD64 mem_size_last_section = 0;
    if (pLastSection->Misc.VirtualSize > pLastSection->SizeOfRawData) {
        if (pLastSection->Misc.VirtualSize % 0x1000 != 0) {
            mem_size_last_section = (pLastSection->Misc.VirtualSize / 0x1000/*内存对齐大小*/) * 0x1000 + 0x1000;
        }
        mem_size_last_section = pLastSection->Misc.VirtualSize;
    }
    else {
        mem_size_last_section = pLastSection->SizeOfRawData;
    }
    pNewSection->VirtualAddress = pLastSection->VirtualAddress + mem_size_last_section;
    printf("  > PointerToRawData: %p \n", pNewSection->PointerToRawData);
    printf("  > SizeOfRawData: %p \n", pNewSection->SizeOfRawData);
    printf("  > VirtualAddress: %p \n", pNewSection->VirtualAddress);
    printf("  > VirtualSize: %p \n", pNewSection->Misc.VirtualSize);

    // 输出新的节表项目
    hex_print((UCHAR*)pNewSection, 40);

    // 初始化节数据
    VOID* buf = malloc(section_size);
    DWORD wsize = 0;
    memset(buf, 0, section_size);
    SetFilePointer(fp, pNewSection->PointerToRawData, NULL, FILE_BEGIN);
    WriteFile(fp, buf, section_size, &wsize, NULL);

    // 更新PE头中接的数量和整个imagesize的大小
    pNtHeader->FileHeader.NumberOfSections += 1;
    pNtHeader->OptionalHeader.SizeOfImage = pNewSection->VirtualAddress + pNewSection->Misc.VirtualSize;

    // 释放资源
    free(buf);
    UnmapViewOfFile(pbFile);
    CloseHandle(hFileMapping);
    CloseHandle(fp);
}

posted @ 2024-07-16 20:44  Mz1  阅读(10)  评论(0编辑  收藏  举报