PE--资源表

本来该用递归来写的,奈何总是写不出来,所以写了一个遍历3层结构的程序。以后来写递归的
这里写图片描述
这里写图片描述

VOID _GetResourceInfo1(PVOID pFileBuffer)
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNtHeaders = NULL;

    PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry1=NULL;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry2=NULL;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry3=NULL;
    PIMAGE_RESOURCE_DIRECTORY pResDir1=NULL;
    PIMAGE_RESOURCE_DIRECTORY pResDir2=NULL;
    PIMAGE_RESOURCE_DIRECTORY pResDir3=NULL;
    PIMAGE_RESOURCE_DIR_STRING_U pUStr=NULL;

    PIMAGE_RESOURCE_DATA_ENTRY pResDataEntry=NULL;

    DWORD dwUncodeAddr=0;
    BYTE szBuffer[1024]={0};
    BYTE szResName[256]={0};

    DWORD dwResourceAddr=0;
    DWORD dwSize,dwSize2,dwSize3;

    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    {
        printf("not a mz header!\n");
        return ;
    }
    pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
    if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
    {
        printf("not a PE header!\n");
        return ;
    }

    //资源表在文件中的偏移
    dwResourceAddr=(DWORD)pFileBuffer+_RVAToOffset(pFileBuffer,pNtHeaders->OptionalHeader.DataDirectory[2].VirtualAddress);

    //第一层
    pResDir1=(PIMAGE_RESOURCE_DIRECTORY)dwResourceAddr;
    pResDirEntry1=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResDir1+sizeof(IMAGE_RESOURCE_DIRECTORY));
    dwSize=pResDir1->NumberOfIdEntries+pResDir1->NumberOfNamedEntries;
    for(int i=0;i<dwSize;i++)
    {
        //第一层的name
        if(pResDirEntry1->NameIsString)
        {
            //用户自定义的资源类别
            pUStr=(PIMAGE_RESOURCE_DIR_STRING_U)(dwResourceAddr+pResDirEntry1->NameOffset);
            //跳过两字节,就是存储的名字地址。详见IMAGE_RESOURCE_DIR_STRING_U结构
            dwUncodeAddr=(DWORD)pUStr+2;
            //将UNICODE字符转换成多字节字符
            memset(szResName,0,sizeof(szResName));
            WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,(LPCWSTR)dwUncodeAddr,pUStr->Length,(char *)szResName,sizeof(szResName),NULL,NULL);
            printf("类型:%s\n",szResName);
            printf("-----------------------------------------\n");
        }
        else
        {
            //系统内定义的资源编号
            switch(pResDirEntry1->Id)
                {
                    case 1: printf("类型:光标\n");break;
                    case 2: printf("类型:位图\n");break;
                    case 3: printf("类型:图标\n");break;
                    case 4: printf("类型:菜单\n");break;
                    case 5: printf("类型:对话框\n");break;
                    case 6: printf("类型:字符串\n");break;
                    case 7: printf("类型:字体目录\n");break;
                    case 8: printf("类型:字体\n");break;
                    case 9: printf("类型:加速键\n");break;
                    case 0x0a: printf("类型:未格式化资源\n");break;
                    case 0x0b: printf("类型:消息表\n");break;
                    case 0x0c: printf("类型:光标组\n");break;
                    case 0x0d: printf("类型:图标组\n");break;
                    case 0x0e: printf("类型:版本信息\n");break;
                    default:
                        printf("类型: %x\n",pResDirEntry1->Id);
                        break;
                }
            printf("--------------------------------------------\n");
        }

        //第一层的offset //指向dir_entry
        if(pResDirEntry1->DataIsDirectory)
        {
            //第二层的结构
            pResDir2=(PIMAGE_RESOURCE_DIRECTORY)(dwResourceAddr+pResDirEntry1->OffsetToDirectory);
            pResDirEntry2=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResDir2+sizeof(IMAGE_RESOURCE_DIRECTORY));
            dwSize2=pResDir2->NumberOfIdEntries+pResDir2->NumberOfNamedEntries;
            for(int j=0;j<dwSize2;j++)
            {
                //name 如果以字符作为ID
                if(pResDirEntry2->NameIsString)
                {
                    pUStr=(PIMAGE_RESOURCE_DIR_STRING_U)(dwResourceAddr+pResDirEntry2->NameOffset);
                    dwUncodeAddr=(DWORD)pUStr+2;
                    memset(szResName,0,sizeof(szResName));
                    WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,(LPCWSTR)dwUncodeAddr,pUStr->Length,(char *)szResName,sizeof(szResName),NULL,NULL);
                    printf("ID:%s\n",szResName);
                }
                else
                {
                    printf("ID: %d\n",pResDirEntry2->Id);
                }

                //offset项
                if(pResDirEntry2->DataIsDirectory)
                {
                    //第三层的结构
                    pResDir3=(PIMAGE_RESOURCE_DIRECTORY)(dwResourceAddr+pResDirEntry2->OffsetToDirectory);
                    pResDirEntry3=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResDir3+sizeof(IMAGE_RESOURCE_DIRECTORY));
                    dwSize3=pResDir3->NumberOfIdEntries+pResDir3->NumberOfNamedEntries;
                    for(int k=0;k<dwSize3;k++)
                    {
                        //name指向的是代码页的编号,一般都为2056简体中文。这里省略
                        //offset
                        if(pResDirEntry3->DataIsDirectory==0)
                        {
                            pResDataEntry=(PIMAGE_RESOURCE_DATA_ENTRY)(dwResourceAddr+pResDirEntry3->OffsetToDirectory);
                            printf("偏移:0x%x   大小:0x%x\n",pResDataEntry->OffsetToData,pResDataEntry->Size);
                        }
                        else
                        {

                        }
                        pResDirEntry3++;
                    }
                }
                pResDirEntry2++;
            }
        }
        else
        {
            //第一层一般都是等于1的
        }
        pResDirEntry1++;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值