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++;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章