Author | Message | Time |
---|---|---|
shadypalm88 | For BNCSutil, I've been working on some code to read a portable executable (PE) file in order to locate the resource section, and in that section, the version information, and in that, the VS_FIXEDFILEINFO structure that contains the file version information needed to get the EXE version on non-Windows systems. (Code: pe.h pe.c) It's able to locate the resource section and parse its directory tree, and get each resource's information (i.e. size) just fine. But then there's a problem. Entries in the directory tree point to a small information stub that gives (most importantly) a file's size and its relative virtual address, or RVA. An RVA is defined by the Microsoft documentation as: [quote author=Microsoft]Relative Virtual Address. In an image file, an RVA is always the address of an item once loaded into memory, with the base address of the image file subtracted from it. The RVA of an item will almost always differ from its position within the file on disk (File Pointer).[/quote] The gotcha is in the last sentence: I can't figure out how to resolve an RVA to an actual position in the file. I tried subtracting the difference between the resource section's file pointer and its RVA from the structure's RVA, and although it came reasonably close, it undershot the start of the structure significantly. The way it works right now is to just start at the resource information stub and move forward through the file to find the structure signature, but that's a crude hack. Anyone have a better idea of how to get this working? | August 17, 2005, 4:42 PM |
Arta | There's a base address in the header. There's an easier way to get the version from resource information though: [code] char Filename[MAX_PATH]; GetModuleFileName(NULL, Filename, MAX_PATH); DWORD Temp, Size = GetFileVersionInfoSize(Filename, &Temp); if(!Size) { // Uhoh... } LPVOID VersionInfo = new BYTE[Size]; GetFileVersionInfo(Filename, 0, Size, VersionInfo); VS_FIXEDFILEINFO *Info; UINT Len; VerQueryValue(VersionInfo, "\\", (LPVOID*)&Info, &Len); printf("\nProgram Version %u.%u\n", Info->dwProductVersionMS >> 16, Info->dwProductVersionLS); [/code] | August 17, 2005, 5:01 PM |
Arta | Oh, sorry - didn't see this was for non-windows. The base address is somewhere in the NT header. I wrote this to patch the Import Address Table, it might help: [code] bool PatchIAT(DWORD ImageBase, DWORD Find, DWORD Replace) { // Get ImageBase address if(!ImageBase) { return false; } IMAGE_DOS_HEADER *DosHeaders = (IMAGE_DOS_HEADER*)(__int64)ImageBase; IMAGE_NT_HEADERS *Header = (IMAGE_NT_HEADERS*)(__int64)(ImageBase+DosHeaders->e_lfanew); // Get an address for the IAT DWORD IATSize = Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size; DWORD *IAT = (DWORD*)(ImageBase+Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress); // Search for Find and overwrite it with Replace for(DWORD *i=IAT; i<=IAT+IATSize; i+=4) { if(*i == Find) { DWORD Old; if(!VirtualProtect((LPVOID)i, 4, PAGE_READWRITE, &Old)) { return false; } *i = Replace; return true; } } return false; } [/code] The resource table is in one of the data directories: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/image_data_directory_str.asp | August 17, 2005, 5:03 PM |
Myndfyr | Rofl, I have been looking up info on PE because I'm trying to find out how to emit a DLL because I want my skin engine to support the .msstyles file format, which is just a resource DLL. :) Anyway: http://www.windowsitlibrary.com/Content/356/11/1.html There's a function there called ImageRvaToVa. It might be able to help you out. :) | August 17, 2005, 5:22 PM |
shadypalm88 | Thanks Arta, the following formula worked: [quote]resource_offset = resource_section->raw_data_offset + (resource_rva - resource_section->virtual_address)[/quote] | August 17, 2005, 5:28 PM |