Windows PE资源表编程(枚举资源树)
資源枚舉
? ? 寫一個例子,枚舉一個PE文件的資源表。首先說下資源相關(guān)的作為鋪墊。
1.資源類型也是PE可選頭中數(shù)據(jù)目錄的一種。位于第三個類型。
2.資源目錄分為三層。第四層是描述文件相關(guān)的。這些結(jié)構(gòu)是按照二叉排序樹的結(jié)構(gòu)存的。每一個節(jié)點都可以看成是一段連續(xù)的數(shù)據(jù)塊(1個資源目錄頭+n個資源目錄項)。
3.整體基本結(jié)構(gòu):
OK,基礎(chǔ)知識就簡單說這些。如果還是不清楚,看下這里http://blog.csdn.net/u013761036/article/details/54562473這里我單獨針對資源表寫的一個博客。
說下寫這個枚舉資源表結(jié)構(gòu)的程序思路:
理解了PE里面怎么存資源的剩下的就很簡單了。
1.把PE加載到內(nèi)存里。拿出來PE頭,找到擴(kuò)展頭里面的第三個數(shù)據(jù)項。找到資源表RVA和大小。
2.根據(jù)RVA用函數(shù)換算出FOA的地址,這個地址指向的就是第一層目錄的目錄頭結(jié)構(gòu),根據(jù)這個目錄頭開始,緊跟在后面的就是n個以名稱命名的和m個以id命名的資源目錄項。
3.上面2可以把目錄頭看成節(jié)點,把目錄項看成連接到下一條節(jié)點的邊,這樣DFS或者BFS跑三層。依次枚舉經(jīng)過的信息。在第三層的時候直接把文件相關(guān)的也都輸出來就可以了。
[注:DFS-深度優(yōu)先搜索,就是平時說的遞歸?BFS-廣度優(yōu)先搜索,用隊列模擬的一個擴(kuò)散感覺的遍歷]。
剛剛寫了個例子,簡單跑了一遍沒發(fā)現(xiàn)啥問題:代碼如下:
注意兩個地方(這個我被坑了好一會):
(1)
? 結(jié)構(gòu)里面涉及的下一個目錄項和指向資源塊的地址都是相對于資源表的起始位置而不是文件起始位置。
(2)
?指針加法問題
?XXXX?*?y;
?DWORD?z;
?Y地址后偏移z長度得到x地址
?XXXX?*?x?=?(XXXX?*)((DWORD)?y?+?DWORD(z))
// GET_RES.cpp : 定義控制臺應(yīng)用程序的入口點。 //#include "stdafx.h" #include <windows.h> #include <winbase.h> #include <stdio.h> #include <tchar.h> #include <imagehlp.h> #include <vector> #include <string> #include <iostream> #include <string> using namespace std; //CP_ACP string ws2s(const wstring& wide, UINT CodePage){int wide_length = static_cast<int>(wide.length());if (wide_length == 0)return string();int charcount = WideCharToMultiByte(CodePage, 0, wide.data(), wide_length,NULL, 0, NULL, NULL);if (charcount == 0)return string();string mb;mb.resize(charcount);WideCharToMultiByte(CodePage, 0, wide.data(), wide_length,&mb[0], charcount, NULL, NULL);return mb; }VOID ShowRes_DFS(DWORD dwDeep ,IMAGE_RESOURCE_DIRECTORY* pNowResourceDesc ,IMAGE_RESOURCE_DIRECTORY* pBaseResourceDesc){/*一級子目錄按照資源類型分類。二級子目錄按照資源ID分類。三級子目錄按照資源代碼頁分類。三級子目錄后即為節(jié)點,也就是所說的文件。這里的文件其實就是包含了資源數(shù)據(jù)的指針和大小等信息的一個數(shù)據(jù)結(jié)構(gòu)而已。對于所有資源數(shù)據(jù)塊的訪問均可以從這里開始。*/dwDeep ++;IMAGE_RESOURCE_DIRECTORY_ENTRY *pResourceBaseAddress = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)((PBYTE) pNowResourceDesc + sizeof(IMAGE_RESOURCE_DIRECTORY)); for(int i = 0 ;i < pNowResourceDesc->NumberOfIdEntries + pNowResourceDesc->NumberOfNamedEntries ;i ++){IMAGE_RESOURCE_DIRECTORY_ENTRY *pNowResourceAddress = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)((DWORD)pResourceBaseAddress + i * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));for(int j = 1 ;j < (dwDeep-1) * 3 ;j ++){cout<<" ";}cout<<"Value: ";if(pNowResourceAddress->NameIsString){IMAGE_RESOURCE_DIR_STRING_U *wsName = (IMAGE_RESOURCE_DIR_STRING_U*)((DWORD)pNowResourceAddress->NameOffset + (DWORD)pBaseResourceDesc);wstring wsV = wstring(wsName->NameString ,wsName->Length);cout<<ws2s(wsV ,CP_ACP);}else{cout<<pNowResourceAddress->Id;}cout<<endl;if(pNowResourceAddress->DataIsDirectory){ShowRes_DFS(dwDeep ,(IMAGE_RESOURCE_DIRECTORY*)((DWORD)pNowResourceAddress->OffsetToDirectory + (DWORD)pBaseResourceDesc),pBaseResourceDesc);}else{for(int j = 1 ;j < (dwDeep) * 3 ;j ++){cout<<" ";}IMAGE_RESOURCE_DATA_ENTRY * pFileRes = (IMAGE_RESOURCE_DATA_ENTRY*)((DWORD)pNowResourceAddress->OffsetToDirectory + (DWORD)pBaseResourceDesc);cout<<"File: RVA-"<<pFileRes->OffsetToData;cout<<",Size-"<<pFileRes->Size;cout<<",Page-"<<pFileRes->CodePage;cout<<endl;}}return ; }typedef PVOID (CALLBACK* PFNEXPORTFUNC)(PIMAGE_NT_HEADERS,PVOID,ULONG,PIMAGE_SECTION_HEADER*);BOOL FindReso(const wstring &wsPeFilePath){HANDLE hFileHandle,hFileMapHandle;DWORD dwFileAttrib=0;void * pBaseAddress; hFileHandle=CreateFile(wsPeFilePath.c_str(),GENERIC_READ,0,0,OPEN_EXISTING,dwFileAttrib,0); if(hFileHandle == INVALID_HANDLE_VALUE){return FALSE;}hFileMapHandle=CreateFileMapping(hFileHandle,0,PAGE_READONLY,0,0,0); if(hFileMapHandle==NULL){ CloseHandle(hFileHandle); return FALSE; } pBaseAddress=MapViewOfFile(hFileMapHandle,FILE_MAP_READ,0,0,0); if (pBaseAddress==NULL) { CloseHandle(hFileMapHandle); CloseHandle(hFileHandle); return FALSE; } HMODULE hModule = ::LoadLibrary(L"DbgHelp.dll");if(!hModule){return FALSE;}PFNEXPORTFUNC ImageRvaToVax=(PFNEXPORTFUNC)GetProcAddress(hModule,"ImageRvaToVa");if(!ImageRvaToVax){FreeLibrary(hModule);return FALSE;}IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER*)pBaseAddress; IMAGE_NT_HEADERS * pNtHeader = (IMAGE_NT_HEADERS *)((BYTE*)pBaseAddress+ pDosHeader->e_lfanew);IMAGE_OPTIONAL_HEADER * pOptHeader = (IMAGE_OPTIONAL_HEADER *)((BYTE*)pBaseAddress + pDosHeader->e_lfanew + 24);IMAGE_RESOURCE_DIRECTORY* pResourceDesc = (IMAGE_RESOURCE_DIRECTORY*)ImageRvaToVax(pNtHeader,pBaseAddress,pOptHeader->DataDirectory[2].VirtualAddress,0); if(pResourceDesc->NumberOfIdEntries + pResourceDesc->NumberOfNamedEntries == 0){return TRUE;}ShowRes_DFS(0 ,pResourceDesc ,pResourceDesc);FreeLibrary(hModule);CloseHandle(hFileMapHandle); CloseHandle(hFileHandle); return TRUE; } int _tmain(int argc, _TCHAR* argv[]) {WCHAR wcLocalFilePath[MAX_PATH] = {0};GetModuleFileName(0 ,wcLocalFilePath ,MAX_PATH);FindReso(wcLocalFilePath);return 0; }總結(jié)
以上是生活随笔為你收集整理的Windows PE资源表编程(枚举资源树)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WindowsPE 第七章 资源表
- 下一篇: Windows PE 第八章 延迟加载导