PE各种操作

#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#pragma warning(disable:4996)

#define FILEPATH_IN "D:\IPMSG2007.exe"
#define FILEPATH_OUT "D:\Dll2.dll"
#define FILEPATH "D:\Dll3.dll"
#define SHELLCODELENGTH 12
#define MESSAGEBOXADDR 0x76A885D0
#define INFILEPATH "D:\IPMSG2007.exe"

BYTE shellCode[] = {
    0x6A, 00, 0x6A, 00, 0x6A, 00, 0x6A, 00,
    0xE8, 00, 00, 00, 00,
    0xE9, 00, 00, 00, 00
};
//函数声明                                
//**************************************************************************                                
//ReadPEFile:将文件读取到缓冲区                                
//参数说明:                                
//lpszFile 文件路径                                
//pFileBuffer 缓冲区指针                                
//返回值说明:                                
//读取失败返回0  否则返回实际读取的大小                                
//**************************************************************************                                
DWORD ReadPEFile(IN LPSTR lpszFile, OUT LPVOID* pFileBuffer);
//**************************************************************************                                
//CopyFileBufferToImageBuffer:将文件从FileBuffer复制到ImageBuffer                                
//参数说明:                                
//pFileBuffer  FileBuffer指针                                
//pImageBuffer ImageBuffer指针                                
//返回值说明:                                
//读取失败返回0  否则返回复制的大小                                
//**************************************************************************                                
DWORD CopyFileBufferToImageBuffer(IN LPVOID pFileBuffer, OUT LPVOID* pImageBuffer);
//**************************************************************************                                
//CopyImageBufferToNewBuffer:将ImageBuffer中的数据复制到新的缓冲区                                
//参数说明:                                
//pImageBuffer ImageBuffer指针                                
//pNewBuffer NewBuffer指针                                
//返回值说明:                                
//读取失败返回0  否则返回复制的大小                                
//**************************************************************************                                
DWORD CopyImageBufferToNewBuffer(IN LPVOID pImageBuffer,OUT LPVOID* pNewBuffer);
//**************************************************************************                                
//MemeryTOFile:将内存中的数据复制到文件                                
//参数说明:                                
//pMemBuffer 内存中数据的指针                                
//size 要复制的大小                                
//lpszFile 要存储的文件路径                                
//返回值说明:                                
//读取失败返回0  否则返回复制的大小                                
//**************************************************************************                                
BOOL MemeryTOFile(IN LPVOID pMemBuffer, IN size_t size, OUT LPSTR lpszFile);
//**************************************************************************                                
//RvaToFileOffset:将内存偏移转换为文件偏移                                
//参数说明:                                
//pFileBuffer FileBuffer指针                                
//dwRva RVA的值                                
//返回值说明:                                
//返回转换后的FOA的值  如果失败返回0                                
//**************************************************************************                                
DWORD RvaToFileOffset(IN LPVOID pFileBuffer, IN DWORD dwRva);


DWORD ReadPEFile(IN LPSTR lpszFile, OUT LPVOID* pFileBuffer)
{
    FILE* fp = fopen(lpszFile, "rb");
    DWORD fileSize = 0;
    if (!fp)
    {
        printf("无法打开exe文件!");
        return 0;
    }
    fseek(fp, 0, SEEK_END);
    fileSize = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    *pFileBuffer = malloc(fileSize);
    if (!(*pFileBuffer))
    {
        printf("分配空间失败!");
        fclose(fp);
        return 0;
    }

    size_t n = fread(*pFileBuffer, fileSize, 1, fp);
    if (!n)
    {
        printf("读取数据失败!");
        free(*pFileBuffer);
        fclose(fp);
        return 0;
    }
    fclose(fp);
    return n;
}

DWORD CopyFileBufferToImageBuffer(IN LPVOID pFileBuffer, OUT LPVOID* pImageBuffer)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;

    if ((*(PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
    {
        printf("不是有效的MZ标志!");
        free(pFileBuffer);
        return 0;
    }

    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
    {
        printf("不是有效的PE标志!");
        free(pFileBuffer);
        return 0;
    }
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);

    *pImageBuffer = malloc(pOptionalHeader->SizeOfImage);
    if (!(*pImageBuffer))
    {
        printf("分配内存失败!");
        return 0;
    }
    memset(*pImageBuffer, 0, pOptionalHeader->SizeOfImage);
    memcpy(*pImageBuffer, pFileBuffer, pOptionalHeader->SizeOfHeaders);
    //printf("%c%c", *((char *)*pImageBuffer), *((char*)*pImageBuffer + 1));
    for (int i = 0; i < pFileHeader->NumberOfSections;i++)
    {
        memcpy((char *) *pImageBuffer + pSectionHeader->VirtualAddress,(char *) pFileBuffer + pSectionHeader->PointerToRawData,
            pSectionHeader->SizeOfRawData);
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER);
    }
    return pOptionalHeader->SizeOfImage;
}

DWORD CopyImageBufferToNewBuffer(IN LPVOID pImageBuffer, OUT LPVOID* pNewBuffer)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL, flag = NULL;
    
    if ((*(PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
    {
        printf("不是有效的MZ标志!");
        free(pImageBuffer);
        return 0;
    }

    pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
    if (*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
    {
        printf("不是有效的PE标志!");
        free(pImageBuffer);
        return 0;
    }
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pImageBuffer + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
    pSectionHeader = flag = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);


    int num = 0;
    for (int i = 0; i < pFileHeader->NumberOfSections; i++)
    {
        num += pSectionHeader->SizeOfRawData;
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER);
    }
    pSectionHeader = flag;
    num += pOptionalHeader->SizeOfHeaders;
    *pNewBuffer = malloc(num);
    memset(*pNewBuffer, 0, num);
    memcpy(*pNewBuffer, pImageBuffer, pOptionalHeader->SizeOfHeaders);

    for (int j = 0; j < pFileHeader->NumberOfSections; j++)
    {
        memcpy((char*)*pNewBuffer + pSectionHeader->PointerToRawData, (char*)pImageBuffer + pSectionHeader->VirtualAddress,
            pSectionHeader->SizeOfRawData);
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER);
    }
    //printf("%c %c %d
", *((char*)*pNewBuffer), *((char*)*pNewBuffer + 1), __LINE__);
    return num;
}
BOOL MemeryTOFile(IN LPVOID pMemBuffer, IN size_t size, OUT LPSTR lpszFile)
{
    FILE* fp;
    fp = fopen(lpszFile, "wb");
    if (!fp)
    {
        printf("打开文件失败!");
        return FALSE;
    }

    fwrite(pMemBuffer, size, 1, fp);
    fclose(fp);
    return TRUE;
}

VOID TestAddCodeInCodeSec()
{
    LPVOID pFileBuffer = NULL;
    LPVOID pImageBuffer = NULL;
    LPVOID pNewBuffer = NULL;
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PBYTE codeBegin = NULL;
    BOOL isOk = FALSE;
    DWORD size = 0;

    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    if (!pFileBuffer)
    {
        printf("文件-->缓冲区失败!");
        return;
    }
    CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
    if (!pImageBuffer)
    {
        printf("FileBuffer-->ImageBuffer失败!");
        free(pFileBuffer);
        return;
    }
    pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(((DWORD)pDosHeader + pDosHeader->e_lfanew) + 4 + IMAGE_SIZEOF_FILE_HEADER);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + 0XE0);
    if (pSectionHeader->SizeOfRawData - pSectionHeader->Misc.VirtualSize < SHELLCODELENGTH)
    {
        printf("代码空闲区不够!");
        free(pFileBuffer);
        free(pImageBuffer);

    }
    codeBegin = (PBYTE)((DWORD)pImageBuffer + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize);
    memcpy(codeBegin, shellCode, SHELLCODELENGTH);
    //修改E8 X
    DWORD callAddr = MESSAGEBOXADDR - (pOptionalHeader->ImageBase + (((DWORD)codeBegin + 0xD) - (DWORD)pImageBuffer));
    *(PDWORD)(codeBegin + 9) = callAddr;
    //修改E9 X
    DWORD jmpAddr = (pOptionalHeader->ImageBase + pOptionalHeader->AddressOfEntryPoint)
        - (pOptionalHeader->ImageBase + ((DWORD)codeBegin + SHELLCODELENGTH - (DWORD)pImageBuffer));
    *(PWORD)(codeBegin + 0xE) = jmpAddr;

    pOptionalHeader->AddressOfEntryPoint = (DWORD)codeBegin - (DWORD)pImageBuffer;
    size = CopyImageBufferToNewBuffer(pImageBuffer, &pNewBuffer);
    if (size == 0 || !pNewBuffer)
    {
        printf("ImageBuffer-->NewBuffer失败!");
        free(pFileBuffer);
        free(pImageBuffer);
        return;
    }

    isOk = MemeryTOFile(pNewBuffer, size, FILEPATH_OUT);
    if (isOk)
    {
        printf("存盘成功!");

    }
}

//添加节和节表
DWORD AddSectionToFileBuffer()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    LPVOID pFileBuffer = NULL;
    DWORD addr = 0;

    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    pSectionHeader = (PIMAGE_SECTION_HEADER)(pOptionalHeader + 1);
    if (pOptionalHeader->SizeOfHeaders - (pDosHeader->e_lfanew + 4 + 20 + pFileHeader->SizeOfOptionalHeader
        + pFileHeader->NumberOfSections * 0x28) < 80)
    {
        printf("节表后空间不足!");
        free(pFileBuffer);
        return;
    }
    PIMAGE_SECTION_HEADER pNewSectionHeader = pSectionHeader + (pFileHeader->NumberOfSections - 1);
    int sum = pNewSectionHeader->PointerToRawData + pNewSectionHeader->SizeOfRawData + 0x1000;
    addr = pNewSectionHeader->PointerToRawData + pNewSectionHeader->SizeOfRawData;
    LPVOID pNewBuffer = malloc(sum);
    memset((char *)pNewBuffer + pNewSectionHeader->PointerToRawData + pNewSectionHeader->SizeOfRawData, 0x20, 0x1000);
    pFileHeader->NumberOfSections += 1;
    pOptionalHeader->SizeOfImage += 0x1000;
    PIMAGE_SECTION_HEADER pLastSectionHeader = pSectionHeader + 4;
    memcpy(pLastSectionHeader, pSectionHeader, 0x28);
    strcpy(pLastSectionHeader->Name, ".tttt");
    pLastSectionHeader->Misc.VirtualSize = 0x1000;
    int size = (pNewSectionHeader->Misc.VirtualSize > pNewSectionHeader->SizeOfRawData) ? pNewSectionHeader->Misc.VirtualSize : pNewSectionHeader->SizeOfRawData;
    pLastSectionHeader->VirtualAddress = pNewSectionHeader->VirtualAddress + size;
    pLastSectionHeader->SizeOfRawData = 0x1000;
    pLastSectionHeader->PointerToRawData = pNewSectionHeader->PointerToRawData + pNewSectionHeader->SizeOfRawData;
    //printf("%x
", pLastSectionHeader->PointerToRawData);
    memcpy(pNewBuffer, pFileBuffer, sum);
    

    free(pFileBuffer);
    if (MemeryTOFile(pNewBuffer, sum, FILEPATH_OUT))
    {
        printf("存盘成功!");
    }
    free(pNewBuffer);
    return addr;
}


//扩大最后一个节
VOID ExpandLastSection()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    LPVOID pFileBuffer = NULL;
    LPVOID pNewBuffer = NULL;

    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    pSectionHeader = (PIMAGE_SECTION_HEADER)(pOptionalHeader + 1);
    PIMAGE_SECTION_HEADER pLastSectionHeader = pSectionHeader + pFileHeader->NumberOfSections - 1;

    pNewBuffer = malloc(pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData + 0x1000);
    memset((char*)pNewBuffer + pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData, 0x20, 0x1000);
    pOptionalHeader->SizeOfImage += 0x1000;
    pLastSectionHeader->Misc.VirtualSize = pLastSectionHeader->SizeOfRawData = pLastSectionHeader->SizeOfRawData + 0x1000;
    memcpy(pNewBuffer, pFileBuffer, pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData);

    if (MemeryTOFile(pNewBuffer, pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData + 0x1000
        , FILEPATH_OUT))
    {
        printf("存盘成功!");
    }
    free(pFileBuffer);
    free(pNewBuffer);
}

//合并所有节
VOID MergeAllSection()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL, pNextSectionHeader = NULL;
    LPVOID pFileBuffer = NULL, pImageBuffer = NULL, pNewBuffer = NULL;
    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);

    free(pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    pNextSectionHeader = pSectionHeader = (PIMAGE_SECTION_HEADER)(pOptionalHeader + 1);

    pSectionHeader->Misc.VirtualSize = pSectionHeader->SizeOfRawData = pOptionalHeader->SizeOfImage -
        pSectionHeader->VirtualAddress;
    for (int i = 0; i < pFileHeader->NumberOfSections; i++)
    {
        pSectionHeader->Characteristics = pSectionHeader->Characteristics | pNextSectionHeader->Characteristics;
        pNextSectionHeader += 1;
    }
    pFileHeader->NumberOfSections = 1;
    CopyImageBufferToNewBuffer(pImageBuffer, &pNewBuffer);
    if (MemeryTOFile(pNewBuffer, pOptionalHeader->SizeOfImage, FILEPATH_OUT))
    {
        printf("存盘成功!");
    }
    free(pImageBuffer);
    free(pNewBuffer);
}

DWORD RvaToFileOffset(IN LPVOID FileBuffer, IN DWORD Rva)
{
    PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER)FileBuffer;
    PIMAGE_NT_HEADERS pNT = (PIMAGE_NT_HEADERS)((DWORD)FileBuffer + pDOS->e_lfanew);
    PIMAGE_SECTION_HEADER pSECTION = (PIMAGE_SECTION_HEADER)(pNT + 1);
    int i;
    for (i = 0; i < pNT->FileHeader.NumberOfSections; i++, pSECTION++) {
        if (Rva >= pSECTION->VirtualAddress && Rva < pSECTION->VirtualAddress + pSECTION->SizeOfRawData) {
            return (Rva - pSECTION->VirtualAddress + pSECTION->PointerToRawData);
            break;
        }
    }

    return 0;
}

VOID PrintfExportImform()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PIMAGE_EXPORT_DIRECTORY pExport = NULL;
    LPVOID pFileBuffer = NULL;
    DWORD pExportFileOffset = NULL;

    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    
    pExportFileOffset = pOptionalHeader->DataDirectory[0].VirtualAddress;
    pExportFileOffset = RvaToFileOffset(pFileBuffer, pExportFileOffset);
    pExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + pExportFileOffset);
    //printf("%d", pExport->NumberOfFunctions);
    //函数地址
    DWORD FileOffOfFunctions = RvaToFileOffset(pFileBuffer, pExport->AddressOfFunctions);
    LPVOID pFunctionInFile = (LPVOID)((DWORD)pFileBuffer + FileOffOfFunctions);
    for (int i = 0; i < pExport->NumberOfFunctions; i++)
    {
        printf("%x
", *((PDWORD)pFunctionInFile));
        pFunctionInFile = (LPVOID)((DWORD)pFunctionInFile + 4);
    }

    //函数名称
    //AddressOfNames在文件中的偏移
    DWORD FileOffOfNames = RvaToFileOffset(pFileBuffer, pExport->AddressOfNames);
    //printf("%x", FileOffOfNames);
    //AddressOfNames在文件中的地址
    LPVOID pNamesInFile = (LPVOID)((DWORD)pFileBuffer + FileOffOfNames);
    //printf("%x", pNamesInFile);
    //AddressOfNames数组项在文件中的偏移
    DWORD OffsetOfNames;      
    LPVOID pNameInFile = NULL;
    //OffsetOfNames = RvaToFileOffset(pFileBuffer, (DWORD)(*((PDWORD)pNamesInFile)));
    for (int j = 0; j < pExport->NumberOfNames; j++)
    {
        OffsetOfNames = RvaToFileOffset(pFileBuffer, (DWORD)(*((PDWORD)pNamesInFile)));
        pNameInFile = (LPVOID)((DWORD)pFileBuffer + OffsetOfNames);
        printf("%s
", pNameInFile);
        pNamesInFile = (LPVOID)((DWORD)pNamesInFile + 4);
    }
    //函数序号
    DWORD OrdOffsetInFile = RvaToFileOffset(pFileBuffer, pExport->AddressOfNameOrdinals);
    LPVOID pOrdinalsInFile = (LPVOID)((DWORD)pFileBuffer + OrdOffsetInFile);
    for (int k = 0; k < pExport->NumberOfNames; k++)
    {
        printf("%d
", *((PWORD)pOrdinalsInFile));
        pOrdinalsInFile = (LPVOID)((DWORD)pOrdinalsInFile + 2);
    }
} 

VOID GetFunctionAddrByName(LPVOID pFileBuffer, char* funcName)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PIMAGE_EXPORT_DIRECTORY pExport = NULL;
    DWORD pExportFileOffset = NULL;

    //ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);

    pExportFileOffset = pOptionalHeader->DataDirectory[0].VirtualAddress;
    pExportFileOffset = RvaToFileOffset(pFileBuffer, pExportFileOffset);
    pExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + pExportFileOffset);
    //printf("%d", pExport->NumberOfFunctions);
    
    //函数名称
    //AddressOfNames在文件中的偏移
    DWORD FileOffOfNames = RvaToFileOffset(pFileBuffer, pExport->AddressOfNames);
    //printf("%x", FileOffOfNames);
    //AddressOfNames在文件中的地址
    LPVOID pNamesInFile = (LPVOID)((DWORD)pFileBuffer + FileOffOfNames);
    //printf("%x", pNamesInFile);
    //AddressOfNames数组项在文件中的偏移
    DWORD OffsetOfNames;
    LPVOID pNameInFile = NULL;
    //OffsetOfNames = RvaToFileOffset(pFileBuffer, (DWORD)(*((PDWORD)pNamesInFile)));
    int j;
    for (j = 0; j < pExport->NumberOfNames; j++)
    {
        OffsetOfNames = RvaToFileOffset(pFileBuffer, (DWORD)(*((PDWORD)pNamesInFile)));
        pNameInFile = (LPVOID)((DWORD)pFileBuffer + OffsetOfNames);
        if( !strcmp(funcName, (char *)pNameInFile))
            break;
        pNamesInFile = (LPVOID)((DWORD)pNamesInFile + 4);
    }
    //函数序号
    DWORD OrdOffsetInFile = RvaToFileOffset(pFileBuffer, pExport->AddressOfNameOrdinals);
    LPVOID pOrdinalsInFile = (LPVOID)((DWORD)pFileBuffer + OrdOffsetInFile);
    pOrdinalsInFile = (LPVOID)((DWORD)pOrdinalsInFile + 2 * j);
    int flag = *((PWORD)pOrdinalsInFile);
    


    //函数地址
    DWORD FileOffOfFunctions = RvaToFileOffset(pFileBuffer, pExport->AddressOfFunctions);
    LPVOID pFunctionInFile = (LPVOID)((DWORD)pFileBuffer + FileOffOfFunctions);
    pFunctionInFile = (LPVOID)((DWORD)pFunctionInFile + 4 * flag);
        printf("%x
", *((PDWORD)pFunctionInFile));
    

}

VOID GetFunctionAddrByOrdinals(LPVOID pFileBuffer, int num)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PIMAGE_EXPORT_DIRECTORY pExport = NULL;
    DWORD pExportFileOffset = NULL;

    //ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);

    pExportFileOffset = pOptionalHeader->DataDirectory[0].VirtualAddress;
    pExportFileOffset = RvaToFileOffset(pFileBuffer, pExportFileOffset);
    pExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + pExportFileOffset);
    //printf("%d", pExport->NumberOfFunctions);

    DWORD FileOffOfFunctions = RvaToFileOffset(pFileBuffer, pExport->AddressOfFunctions);
    LPVOID pFunctionInFile = (LPVOID)((DWORD)pFileBuffer + FileOffOfFunctions);
    pFunctionInFile = (LPVOID)((DWORD)pFunctionInFile + 4 * (num - pExport->Base));
    printf("%x
", *((PDWORD)pFunctionInFile));
}

//打印重定位表
VOID PrintRelocation()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    LPVOID pFileBuffer = NULL;
    PIMAGE_BASE_RELOCATION pRelocation = NULL;
    DWORD offset = 0;
    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);

    offset = RvaToFileOffset(pFileBuffer, pOptionalHeader->DataDirectory[5].VirtualAddress);
    pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + offset);
    int num = 0;
    int i = 0;
    LPVOID pDetails = NULL;
    while (1)
    {
        if (pRelocation->VirtualAddress == 0 && pRelocation->SizeOfBlock == 0)
            break;
        num = (pRelocation->SizeOfBlock - 8) / 2;
        printf("VirtualAddress:%x
", pRelocation->VirtualAddress);
        printf("SizeOfBlock:%d
", pRelocation->SizeOfBlock);
        printf("修改项:
");
        pDetails = (LPVOID)((DWORD)pRelocation + 8);
        for (i = 0; i < num; i++)
        {
            printf("%x
", *((PWORD)pDetails));
            pDetails = (LPVOID)((DWORD)pDetails + 2);
        
        }
        pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocation + pRelocation->SizeOfBlock);
    }


}

DWORD FileFoaToRva(LPVOID pFileBuffer, DWORD foa)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(pNTHeader + 1);
    for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, pSectionHeader++)
    {
        if (foa > pSectionHeader->PointerToRawData && foa <= pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData)
            return (foa - pSectionHeader->PointerToRawData + pSectionHeader->VirtualAddress);
    }

    return 0;

}
VOID MoveExport()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_EXPORT_DIRECTORY pExport = NULL;
    LPVOID pFileBuffer = NULL;
    LPVOID pAddrOfFunc = NULL;
    LPVOID pAddrOfNames = NULL;
    LPVOID pAddrOfOri = NULL;
    LPVOID pCurrent = NULL;
    LPVOID pFunc = NULL;
    LPVOID pNames = NULL;
    LPVOID pOrdinals = NULL;
    LPVOID pNamesInFile = NULL;
    LPVOID pAddrName = NULL;
    int sum = 0;
    DWORD addr = AddSectionToFileBuffer();
    sum = addr + 0x1000;
    ReadPEFile(FILEPATH_OUT, &pFileBuffer);

    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    
    DWORD Foa = RvaToFileOffset(pFileBuffer, pOptionalHeader->DataDirectory[0].VirtualAddress);
    pExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + Foa);

    pAddrOfFunc = (LPVOID)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pExport->AddressOfFunctions));
    pAddrOfNames = (LPVOID)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pExport->AddressOfNames));
    pAddrOfOri = (LPVOID)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pExport->AddressOfNameOrdinals));
    
    pFunc = pCurrent = (LPVOID)((DWORD)pFileBuffer + addr);
    memcpy(pCurrent, pAddrOfFunc, 4 * pExport->NumberOfFunctions);

    pOrdinals = pCurrent = (LPVOID)((DWORD)pCurrent + 4 * pExport->NumberOfFunctions);
    memcpy(pCurrent, pAddrOfOri, 2 * pExport->NumberOfNames);

    pNames = pAddrName = pCurrent = (LPVOID)((DWORD)pCurrent + 2 * pExport->NumberOfNames);
    memcpy(pCurrent, pAddrOfNames, 4 * pExport->NumberOfNames);
    
    pCurrent = (LPVOID)((DWORD)pCurrent + 4 * pExport->NumberOfNames);
    for (int i = 0; i < pExport->NumberOfNames; i++)
    {
        Foa = RvaToFileOffset(pFileBuffer,(DWORD) (*((PDWORD)pAddrOfNames)));
        pNamesInFile = (LPVOID)((DWORD)pFileBuffer + Foa);
        strcpy((char*)pCurrent, (char*)pNamesInFile);
        *((PDWORD)pAddrName) = FileFoaToRva(pFileBuffer,(DWORD)pCurrent - (DWORD)pFileBuffer);
        pCurrent = (LPVOID)((DWORD)pCurrent + strlen((char*)pNamesInFile) + 1);
        pAddrName = (LPVOID)((DWORD)pAddrName + 4);
        pAddrOfNames = (LPVOID)((DWORD)pAddrOfNames + 4);
    }
    memcpy(pCurrent, pExport, 0x28);
    pExport = (PIMAGE_EXPORT_DIRECTORY)pCurrent;
    pExport->AddressOfFunctions = FileFoaToRva(pFileBuffer, (DWORD)pFunc - (DWORD)pFileBuffer);
    pExport->AddressOfNames = FileFoaToRva(pFileBuffer, (DWORD)pNames - (DWORD)pFileBuffer);
    pExport->AddressOfNameOrdinals = FileFoaToRva(pFileBuffer, (DWORD)pOrdinals - (DWORD)pFileBuffer);
    pOptionalHeader->DataDirectory[0].VirtualAddress = FileFoaToRva(pFileBuffer,(DWORD)pCurrent - (DWORD)pFileBuffer);
    MemeryTOFile(pFileBuffer, sum, FILEPATH);
}

DWORD MoveRelo()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_BASE_RELOCATION pRelocation = NULL;
    LPVOID pFileBuffer = NULL;
    LPVOID pNewBuffer = NULL;
    LPVOID pNewRe = NULL;
    int sum = 0;
    DWORD addr = AddSectionToFileBuffer();
    sum = addr + 0x1000;
    ReadPEFile(FILEPATH_OUT, &pFileBuffer);
             
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pOptionalHeader->DataDirectory[5].VirtualAddress));
    pNewRe = pNewBuffer = (LPVOID)((DWORD)pFileBuffer + addr);
    
    while (1)
    {
        if (pRelocation->SizeOfBlock == 0 && pRelocation->VirtualAddress == 0)
        {
            memcpy(pNewBuffer, pRelocation, 8);
            break;
        }
        memcpy(pNewBuffer, pRelocation, pRelocation->SizeOfBlock);
        pNewBuffer = (LPVOID)((DWORD)pNewBuffer + pRelocation->SizeOfBlock);
        pRelocation = (LPVOID)((DWORD)pRelocation + pRelocation->SizeOfBlock);
    }
    pOptionalHeader->DataDirectory[5].VirtualAddress = FileFoaToRva(pFileBuffer, (DWORD)pNewRe - (DWORD)pFileBuffer);

    MemeryTOFile(pFileBuffer, sum, FILEPATH);
    return addr;
}

VOID FixRelocation()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_BASE_RELOCATION pRelocation = NULL;
    LPVOID pFileBuffer = NULL;
    LPVOID pr = NULL;
    LPVOID offset = NULL;
    int addr = MoveRelo();
    int sum = 0, howMany = 0;
    sum = addr + 0x1000;
    //printf("%x
", addr);
    ReadPEFile(FILEPATH, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    //printf("%x
", RvaToFileOffset(pFileBuffer, pOptionalHeader->DataDirectory[5].VirtualAddress));
    pr = pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pOptionalHeader->DataDirectory[5].VirtualAddress));

    pOptionalHeader->ImageBase += 0x1000;
    int i = 0;
    while (1)
    {
        if (pRelocation->VirtualAddress == 0 && pRelocation->SizeOfBlock == 0)
            break;
        howMany = (pRelocation->SizeOfBlock - 8) / 2;
        for (i = 0; i < howMany; i++)
        {
            pr = (LPVOID)((DWORD)pRelocation + 8);
            if (*((PWORD)pr) >> 12 == 3)
            {
                offset = (LPVOID)(RvaToFileOffset(pFileBuffer, (pRelocation->VirtualAddress + 
                    (*((PWORD)pr) & 0xfff))) + (DWORD)pFileBuffer);
                *((PDWORD)offset) += 0x1000;
            }
            pr = (LPVOID)((DWORD)pr + 2);
        }
        pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocation + pRelocation->SizeOfBlock);
    }
    MemeryTOFile(pFileBuffer, sum, FILEPATH);

}

VOID PrintImportTable()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    LPVOID pFileBuffer = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
    PIMAGE_IMPORT_BY_NAME pName = NULL;
    DWORD addrOfOri = 0;
    int i = 0;

    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    pImport = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + 
        RvaToFileOffset(pFileBuffer, pOptionalHeader->DataDirectory[1].VirtualAddress));
    addrOfOri = (DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pImport->OriginalFirstThunk);
    while (1)
    {
        if (pImport->OriginalFirstThunk == 0)
            break;
        printf("****************%s****************
", (char *)((DWORD)pFileBuffer + 
            RvaToFileOffset(pFileBuffer, pImport->Name)));
        addrOfOri = (DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, pImport->OriginalFirstThunk);
        while (1)
        {
            if ((DWORD)(*(PDWORD)addrOfOri == 0))
            {
                break;
            }
            if ((DWORD)(*(PDWORD)addrOfOri) >> 31 == 1)
                printf("序号:%d
", (DWORD)(*(PDWORD)addrOfOri) & 0x7fffffff);
            else
            {
                pName = (PIMAGE_IMPORT_BY_NAME)((DWORD)pFileBuffer + 
                    RvaToFileOffset(pFileBuffer, (DWORD)(*(PDWORD)addrOfOri)));
                i = 0;
                while (pName->Name[i] != 0)
                {
                    
                    printf("%c", pName->Name[i]);
                    i++;
                }
                printf("
");
            }
            addrOfOri += 4;
        }
        pImport = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImport + 20);
    }
    free(pFileBuffer);
}

VOID printBoundImportTable()
{//RVATOFOA需要考虑rva在sizeofheaders里的情况
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_BOUND_IMPORT_DESCRIPTOR pBdImport = NULL, pImport = NULL;
    PIMAGE_BOUND_FORWARDER_REF pRef = NULL;
    LPVOID pFileBuffer = NULL;

    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    if (pOptionalHeader->DataDirectory[11].VirtualAddress == 0)
    {
        printf("没有绑定导入表
");
        return;
    }
    pBdImport = pImport =  (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + 
        RvaToFileOffset(pFileBuffer, pOptionalHeader->DataDirectory[11].VirtualAddress));
    int i = 0;
    while (1)
    {
        
        if (pBdImport->OffsetModuleName == 0 && pBdImport->NumberOfModuleForwarderRefs == 0 && pBdImport->TimeDateStamp == 0)
            break;
        printf("***************OffsetMoudleName:%s*****************
", (char*)((DWORD)pImport + pBdImport->OffsetModuleName));
        printf("TimeDateStamp:%d
", pBdImport->TimeDateStamp);
        printf("NumberOfModuleForWarderRefs:%d
", pBdImport->NumberOfModuleForwarderRefs);
        pRef = (PIMAGE_BOUND_FORWARDER_REF)((DWORD)pBdImport + 8);
        for (i = 0; i < pBdImport->NumberOfModuleForwarderRefs; i++)
        {
            printf("***************OffsetMoudleName:%s*****************
", (char*)((DWORD)pImport + pRef->OffsetModuleName));
            printf("TimeDateStamp:%d
", pRef->TimeDateStamp);
            pRef += 1;
        }
        pBdImport += pBdImport->NumberOfModuleForwarderRefs + 1;

    }
}

PrintResourceTable()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
    PIMAGE_RESOURCE_DIRECTORY pRes = NULL;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY pEntry = NULL;
    PIMAGE_DATA_DIRECTORY pDataDir = NULL;
    LPVOID pFileBuffer = NULL;

    ReadPEFile(FILEPATH_IN, &pFileBuffer);
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)(pFileHeader + 1);
    pRes = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer,pOptionalHeader->DataDirectory[2].VirtualAddress));
    size_t num1 = pRes->NumberOfNamedEntries + pRes->NumberOfIdEntries;
    pEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pRes + sizeof(IMAGE_RESOURCE_DIRECTORY));
    for (size_t i = 0; i < num1; i++)
    {
        if (!pEntry[i].NameIsString)
        {
            printf("资源类型ID: %d 
", pEntry[i].Id);
            if (pEntry[i].Id == 3)
            {
                PIMAGE_RESOURCE_DIRECTORY pRes2 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pRes + pEntry[i].OffsetToDirectory);
                PIMAGE_RESOURCE_DIRECTORY_ENTRY pEntry1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes2 + 1);
                size_t num2 = pRes2->NumberOfIdEntries + pRes2->NumberOfNamedEntries;
                for (size_t i = 0; i < num2; i++)
                {
                    if(!pEntry1[i].NameIsString)
                    {
                        printf("资源编号ID: %d", pEntry1[1].Id);
                    }
                    else
                    {
                        PIMAGE_RESOURCE_DIR_STRING_U pStr1 = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pRes + pEntry1[i].NameOffset);
                        WCHAR str1[MAX_PATH] = { 0 };
                        memcpy_s(str1, MAX_PATH, pStr1, pStr1->Length * sizeof(WCHAR));
                        printf("%资源名称: %ls", str1);
                    }
                    PIMAGE_RESOURCE_DIRECTORY pRes3 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pRes + pEntry1[i].OffsetToDirectory);
                    PIMAGE_RESOURCE_DIRECTORY_ENTRY pEntry2 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes3 + 1);
                    size_t num3 = pRes3->NumberOfIdEntries + pRes3->NumberOfNamedEntries;
                    for (size_t i = 0; i < num3; i++)
                    {
                        PIMAGE_RESOURCE_DATA_ENTRY pData = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pRes + pEntry2[i].OffsetToData);
                        printf("rva: %x  size: %x 
", pData->OffsetToData, pData->Size);
                    }
                    printf("

");
                }
            }
        }
        else {
            PIMAGE_RESOURCE_DIR_STRING_U pStr = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pRes + pEntry[i].NameOffset);
            WCHAR str[MAX_PATH] = { 0 };
            memcpy_s(str, MAX_PATH, pStr, pStr->Length * sizeof(WCHAR));
            printf("%资源名称: %ls", str);
        }
    }

}

VOID PrintfResourceTable() {
    //定义一个名称数组
    static char* szResName[0x11] =

    { 0, "鼠标指针", "位图", "图标", "菜单", "对话框", "字符串列表",

    "字体目录", "字体", "快捷键", "非格式化资源", "消息列表",
    "鼠标指针组", "zz", "图标组", "xx", "版本信息"
    };


    //读取文件
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNtHeader = NULL;
    PIMAGE_FILE_HEADER pFileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
    PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL;

    printf("打印的文件是:%s!
", INFILEPATH);
    //定义文件缓冲区
    LPVOID pFileBuffer = NULL;
    ReadPEFile(INFILEPATH, &pFileBuffer);

    if (pFileBuffer != 0) {
        printf("文件打开成功!
");
    }
    else
    {
        printf("文件打开失败!
");
        free(pFileBuffer);
        return;
    }
    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNtHeader) + 4);
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
    pDataDirectory = (PIMAGE_DATA_DIRECTORY)(((DWORD)pOptionalHeader) + 96);

    pDataDirectory += 2;

    PIMAGE_RESOURCE_DIRECTORY  pResourceDirectory = NULL;

    DWORD RESRVA = pDataDirectory->VirtualAddress;
    DWORD RESFOA = 0;
    RESFOA = RvaToFileOffset(pFileBuffer, RESRVA);
    
    //定位资源目录
    pResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pFileBuffer + RESFOA);

    //printf("NumberOfNameEntries:%d,NumberOfIdEntries:%d
", pResourceDirectory->NumberOfNamedEntries, pResourceDirectory->NumberOfIdEntries);

    //获取RESOURCEENTRY 的个数

    size_t NumEntry = pResourceDirectory->NumberOfIdEntries + pResourceDirectory->NumberOfNamedEntries;

    //资源目录表的宽度

    size_t dwResourceData = sizeof(PIMAGE_RESOURCE_DIRECTORY);

    //定位资源目录节点

    PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResourceDirectory + 16);

    //获取第一层
    for (size_t i = 0; i < NumEntry; i++)
    {
        if (!pResEntry[i].NameIsString) {//0
            if (pResEntry[i].Id < 0x11)
                //如果id大于0x11就是自己写的ID资源
            {
                printf("资源类型ID:%p %s
", pResEntry[i].Id, szResName[pResEntry[i].Id]);
            }
            else {
                char  type[20];
                sprintf_s(type, "%d", pResEntry[i].Id);
                printf("资源类型ID:%p %s
", pResEntry[i].Id, type);
            }
        }
        else {//1那么这个第一个联合体的最高位为1,也就是说NameIsString为1,如果资源是未知的,这种资源属于字符串作为资源标识, Name就不会起作用了,NameOffset会指向IMAGE_RESOUCE_DIR_STRING_U的位置

            //先获取偏移
            PIMAGE_RESOURCE_DIR_STRING_U pStringRes = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResourceDirectory + pResEntry[i].NameOffset);
            //定义一个用来接收自定义字符串的宽数组然后直接复制
            WCHAR szStr[MAX_PATH] = { 0 };
            memcpy_s(szStr, MAX_PATH, pStringRes->NameString, pStringRes->Length * sizeof(WCHAR));

            printf("资源名称:%ls 
", szStr);
        }

        //第二层
        if (pResEntry[i].DataIsDirectory) {
            printf("第二层目录偏移是:%p
", pResEntry[i].OffsetToDirectory);
            //定义二层目录的目录头 以及entry
            PIMAGE_RESOURCE_DIRECTORY pResDirectory2 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResourceDirectory + pResEntry[i].OffsetToDirectory);

            PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry2 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResDirectory2 + 1);
            //获得ENtry个数
            size_t NumEntry2 = pResDirectory2->NumberOfIdEntries + pResDirectory2->NumberOfNamedEntries;

            for (DWORD i = 0; i < NumEntry2; i++)
            {
                if (!pResEntry2[i].NameIsString)
                {
                    printf("->资源标识ID:%d
", pResEntry2[i].Id);
                }
                else
                {
                    // 显示资源字符串
                    // NameOffset为相对资源的文件偏移
                    // 字符串偏移为 资源基地址+NameOffset
                    PIMAGE_RESOURCE_DIR_STRING_U pstcString = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResourceDirectory + pResEntry2[i].NameOffset);
                    WCHAR szStr[MAX_PATH] = { 0 };
                    memcpy(szStr,
                        pstcString->NameString,
                        pstcString->Length * sizeof(WCHAR)
                    );
                    printf("->资源字符串:%ls
", szStr);
                }
            }
            //第三层
            PIMAGE_RESOURCE_DIRECTORY pResourceDirectory3 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResourceDirectory + pResEntry2[i].OffsetToDirectory);
            printf("第三层目录:%d
", pResourceDirectory3->NumberOfIdEntries);
            PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry3 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceDirectory3 + 1);
            if (!pResEntry3[i].DataIsDirectory)
            {
                // 取数据偏移,显示数据
                PIMAGE_RESOURCE_DATA_ENTRY pResData = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pResourceDirectory + pResEntry3->OffsetToData);
                printf("->->->数据RVA:%x	数据大小:%x
", pResData->OffsetToData, pResData->Size);
                //printf("->->->数据大小:%x
", pResData->Size);
                //printf("->->->数据RVA:%x
", pResData->OffsetToData);
            }

        }
        printf("


");
    }
}
void main()
{
    PVOID p2 = NULL;    //pFileBuffer
    PVOID p3 = NULL;    //pImageBuffer
    PVOID p4 = NULL;    //pNewBuffer
    FILE* fp;
    int sum;
    ReadPEFile(FILEPATH_IN, &p2);
    //CopyFileBufferToImageBuffer(p2, &p3);
    //free(p2);
    /*sum = CopyImageBufferToNewBuffer(p3, &p4);
    free(p3);*/

    
    
    //TestAddCodeInCodeSec();
    //AddSectionToFileBuffer();
    //ExpandLastSection(); 
    //MergeAllSection();
    //PrintfExportImform();
    //GetFunctionAddrByName(p2, "sub1");
    //GetFunctionAddrByOrdinals(p2, 2);
    //PrintRelocation();
    //MoveExport();
    //MoveRelo();
    //FixRelocation();
    //PrintImportTable();
    //printBoundImportTable();
//    LPVOID pFileBuffer = NULL;
    //ReadPEFile(FILEPATH_IN, &pFileBuffer);
    //PrintBoundImport(pFileBuffer);
    PrintResourceTable();
}