首页 > 其他 > 详细

遍历资源表

时间:2021-04-11 22:07:44      阅读:40      评论:0      收藏:0      [点我收藏+]
#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include<stdlib.h>
#include<stdio.h>

#define FILE_PATH_IN    "C:/Windows/System32/notepad.exe"

static const char* szResName[0x11]
{
    0,
    "Corsor",
    "Bitmap",
    "Icon",
    "Menu",
    "Dialog",
    "StringTable",
    "FontDir",
    "Font",
    "Accelerator",
    "RCDATA",
    "MessageTable",
    "GroupCursor",
    "zz",
    "GroupIcon",
    "xx",
    "Version"
};

DWORD RVA2FOA(IN DWORD stRVA, IN LPVOID pFileBuffer)
{
    //重置头指针
    PIMAGE_DOS_HEADER pDosHeader = nullptr;
    PIMAGE_NT_HEADERS pNTHeader = nullptr;
    PIMAGE_FILE_HEADER pFileHeader = nullptr;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader = nullptr;
    PIMAGE_SECTION_HEADER pSectionHeader = nullptr;

    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + sizeof(pNTHeader->Signature));
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);

    //内存对齐
    DWORD dwMemAlignCount = pOptionalHeader->FileAlignment;

    //节区头个数
    DWORD dwSectionCount = pFileHeader->NumberOfSections;

    //距节区的偏移
    DWORD dwDiffer = 0;

    for (DWORD i = 0; i < dwSectionCount; i++,pSectionHeader++)
    {
        //在内存中对齐后的大小
        DWORD dwBlockCount = 0;
        dwBlockCount = pSectionHeader->SizeOfRawData / dwMemAlignCount;
        dwBlockCount += (pSectionHeader->SizeOfRawData % dwMemAlignCount ? 1 : 0);

        DWORD dwBeginRVA = pSectionHeader->VirtualAddress;
        DWORD dwEndRVA = pSectionHeader->VirtualAddress + dwBlockCount * dwMemAlignCount;

        if (stRVA >= dwBeginRVA && stRVA < dwEndRVA)
        {
            dwDiffer = stRVA - dwBeginRVA;
            return dwDiffer + pSectionHeader->PointerToRawData;
        }

        else if (stRVA < dwBeginRVA)
        {
            return stRVA;
        }
    }

    return 0;
}

DWORD ReadFile(OUT LPVOID* pFileBuffer,IN const char* lpszFile)
{
    LPVOID pTempFileBuffer = nullptr;
    FILE* pFile = nullptr;

    DWORD FileSize = 0;
    size_t n = 0;

    //打开文件
    pFile = fopen(lpszFile, "rb");
    if (pFile == nullptr)
    {
        printf("文件打开失败");
        return 0;
    }

    //计算文件长度
    fseek(pFile, 0, SEEK_END);
    FileSize = ftell(pFile);
    fseek(pFile, 0, SEEK_SET);

    //分配缓冲区
    pTempFileBuffer = calloc(FileSize, sizeof(char));
    if (pTempFileBuffer == nullptr)
    {
        printf("缓冲区分配失败");
        fclose(pFile);
        return 0;
    }

    //初始化缓冲区
    memset(pTempFileBuffer, 0, FileSize);

    //读取文件
    n = fread(pTempFileBuffer, FileSize, 1, pFile);
    if (n == 0)
    {
        printf("读取文件失败");
        fclose(pFile);
        free(pTempFileBuffer);
        pTempFileBuffer = nullptr;
        return 0;
    }

    //关闭文件
    fclose(pFile);

    *pFileBuffer = pTempFileBuffer;
    pTempFileBuffer = nullptr;

    return n;
}

void PrintResourceTable()
{
    PIMAGE_DOS_HEADER pDosHeader = nullptr;
    PIMAGE_NT_HEADERS pNTHeader = nullptr;
    PIMAGE_FILE_HEADER pFileHeader = nullptr;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader = nullptr;

    PIMAGE_DATA_DIRECTORY pDataDirectory = nullptr;
    PIMAGE_RESOURCE_DIRECTORY pResourceTable = nullptr;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY pResourceEntry = nullptr;

    LPVOID pFileBuffer = nullptr;
    DWORD dwSize = 0;
    
    dwSize = ReadFile(&pFileBuffer, FILE_PATH_IN);
    if (dwSize == 0 || pFileBuffer == nullptr)
    {
        printf("读取文件失败");
    }

    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + sizeof(pNTHeader->Signature));
    pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);

    //定位资源表
    pDataDirectory = (PIMAGE_DATA_DIRECTORY)(&pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
    pResourceTable = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pFileBuffer + RVA2FOA(pDataDirectory->VirtualAddress, pFileBuffer));
    pResourceEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceTable + 1);

    //解析第一层
    DWORD dwTypeCount = pResourceTable->NumberOfIdEntries + pResourceTable->NumberOfNamedEntries;
    for (DWORD i = 0; i < dwTypeCount; i++)
    {
        //最高位为0
        if (pResourceEntry[i].NameIsString == 0)
        {
            if (pResourceEntry[i].Id < 0x11)
            {
                printf("资源类型ID:%d %s\n", pResourceEntry[i].Id, szResName[pResourceEntry[i].Id]);
            }
            else
            {
                printf("资源类型ID:%d\n", pResourceEntry[i].Id);
            }
        }
        //最高位为1
        else if (pResourceEntry[i].NameIsString == 1)
        {
            PIMAGE_RESOURCE_DIR_STRING_U pStr = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResourceTable + pResourceEntry[i].NameOffset);
            WCHAR szStr[MAX_PATH] = { 0 };
            memcpy(szStr, pStr->NameString, pStr->Length * sizeof(WCHAR));
            printf("资源类型名称:%ls\n", szStr);
        }

        //解析第二层
        if (pResourceEntry[i].DataIsDirectory == 1)
        {
            printf("第二层目录偏移:%x\n", pResourceEntry[i].OffsetToDirectory);
            PIMAGE_RESOURCE_DIRECTORY pRes2 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResourceTable + pResourceEntry[i].OffsetToDirectory);
            PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry2 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes2 + 1);
            DWORD dwCount = pRes2->NumberOfIdEntries + pRes2->NumberOfNamedEntries;

            for (DWORD i = 0; i < dwCount; i++)
            {
                //最高位为0
                if (pResEntry2[i].NameIsString == 0)
                {
                    printf("  ->资源标识ID:%d\n", pResEntry2[i].Id);
                }
                else
                {
                    PIMAGE_RESOURCE_DIR_STRING_U pStr = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResourceTable + pResEntry2[i].NameOffset);
                    WCHAR szStr[MAX_PATH] = { 0 };
                    memcpy(szStr, pStr->NameString, pStr->Length * sizeof(WCHAR));
                    printf("  ->资源名称:%ls\n", szStr);
                }

                //解析第三层
                if (pResEntry2[i].DataIsDirectory == 1)
                {

                    PIMAGE_RESOURCE_DIRECTORY pRes3 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResourceTable + pResEntry2[i].OffsetToDirectory);
                    PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry3 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes3 + 1);
                    printf("    -->代码页标号为:%x\n", pResEntry3->Id);
                    if (pResEntry3->DataIsDirectory == 0)
                    {
                        PIMAGE_RESOURCE_DATA_ENTRY pResDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pResourceTable+pResEntry3->OffsetToData);
                        printf("    --数据RVA:%x\n", pResDataEntry->OffsetToData);
                        printf("    --数据大小:%x\n", pResDataEntry->Size);
                    }
                }
            }
            
        }
    }

}

int main()
{
    PrintResourceTable();

    return 0;
}

 

遍历资源表

原文:https://www.cnblogs.com/yanmo/p/14645019.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!