Changeset 70348 in vbox for trunk/src/bldprogs/VBoxPeSetVersion.cpp
- Timestamp:
- Dec 26, 2017 3:56:20 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/VBoxPeSetVersion.cpp
r69500 r70348 23 23 #include <iprt/formats/pecoff.h> 24 24 #include <stdio.h> 25 #include <stdlib.h> 25 26 #include <string.h> 26 27 27 28 28 /** @todo Rewrite this so it can take options and print out error messages. */ 29 int main(int argc, char **argv) 29 /********************************************************************************************************************************* 30 * Global Variables * 31 *********************************************************************************************************************************/ 32 static const char *g_pszFilename; 33 34 35 static int Error(const char *pszFormat, ...) 30 36 { 31 if (argc != 2)32 return 30;33 FILE *pFile = fopen(argv[1], "r+b");34 if (!pFile)35 return 1;36 IMAGE_DOS_HEADER MzHdr;37 if (fread(&MzHdr, sizeof(MzHdr), 1, pFile) != 1)38 return 2; 37 va_list va; 38 va_start(va, pszFormat); 39 char szTmp[1024]; 40 _vsnprintf(szTmp, sizeof(szTmp), pszFormat, va); 41 va_end(va); 42 fprintf(stderr, "VBoxPeSetVersion: %s: error: %s\n", g_pszFilename, szTmp); 43 return RTEXITCODE_FAILURE; 44 } 39 45 40 if (fseek(pFile, MzHdr.e_lfanew, SEEK_SET) != 0)41 return 3;42 46 47 static int UpdateFile(FILE *pFile, bool fNt31, PIMAGE_SECTION_HEADER *ppaShdr) 48 { 49 /* 50 * Locate and read the PE header. 51 */ 52 unsigned long offNtHdrs; 53 { 54 IMAGE_DOS_HEADER MzHdr; 55 if (fread(&MzHdr, sizeof(MzHdr), 1, pFile) != 1) 56 return Error("Failed to read MZ header: %s", strerror(errno)); 57 if (MzHdr.e_magic != IMAGE_DOS_SIGNATURE) 58 return Error("Invalid MZ magic: %#x", MzHdr.e_magic); 59 offNtHdrs = MzHdr.e_lfanew; 60 } 61 62 if (fseek(pFile, offNtHdrs, SEEK_SET) != 0) 63 return Error("Failed to seek to PE header at %#lx: %s", offNtHdrs, strerror(errno)); 43 64 IMAGE_NT_HEADERS32 NtHdrs; 44 65 if (fread(&NtHdrs, sizeof(NtHdrs), 1, pFile) != 1) 45 return 4; 66 return Error("Failed to read PE header at %#lx: %s", offNtHdrs, strerror(errno)); 67 68 /* 69 * Validate it a little bit. 70 */ 46 71 if (NtHdrs.Signature != IMAGE_NT_SIGNATURE) 47 return 5;72 return Error("Invalid PE signature: %#x", NtHdrs.Signature); 48 73 if (NtHdrs.FileHeader.Machine != IMAGE_FILE_MACHINE_I386) 49 return 6; 74 return Error("Not I386 machine: %#x", NtHdrs.FileHeader.Machine); 75 if (NtHdrs.FileHeader.SizeOfOptionalHeader != sizeof(NtHdrs.OptionalHeader)) 76 return Error("Invalid optional header size: %#x", NtHdrs.FileHeader.SizeOfOptionalHeader); 50 77 if (NtHdrs.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) 51 return 7;78 return Error("Invalid optional header magic: %#x", NtHdrs.OptionalHeader.Magic); 52 79 53 if (NtHdrs.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) 54 return 7; 80 /* 81 * Do the header modifications. 82 */ 83 IMAGE_NT_HEADERS32 NtHdrsNew = NtHdrs; 84 if (fNt31) 85 { 86 NtHdrsNew.OptionalHeader.MajorOperatingSystemVersion = 1; 87 NtHdrsNew.OptionalHeader.MinorOperatingSystemVersion = 0; 55 88 56 IMAGE_NT_HEADERS32 NtHdrsNew = NtHdrs; 57 if (NtHdrsNew.OptionalHeader.MajorOperatingSystemVersion > 4) 89 NtHdrsNew.OptionalHeader.MajorSubsystemVersion = 3; 90 NtHdrsNew.OptionalHeader.MinorSubsystemVersion = 10; 91 } 92 else 58 93 { 59 94 NtHdrsNew.OptionalHeader.MajorOperatingSystemVersion = 4; 60 95 NtHdrsNew.OptionalHeader.MinorOperatingSystemVersion = 0; 61 } 62 if (NtHdrsNew.OptionalHeader.MajorSubsystemVersion > 4) 63 { 64 NtHdrsNew.OptionalHeader.MajorSubsystemVersion = 4; 65 NtHdrsNew.OptionalHeader.MinorSubsystemVersion = 0; 96 97 NtHdrsNew.OptionalHeader.MajorSubsystemVersion = 4; 98 NtHdrsNew.OptionalHeader.MinorSubsystemVersion = 0; 66 99 } 67 100 … … 71 104 NtHdrsNew.OptionalHeader.CheckSum = 0; 72 105 73 if (fseek(pFile, MzHdr.e_lfanew, SEEK_SET) != 0)74 return 10;106 if (fseek(pFile, offNtHdrs, SEEK_SET) != 0) 107 return Error("Failed to seek to PE header at %#lx: %s", offNtHdrs, strerror(errno)); 75 108 if (fwrite(&NtHdrsNew, sizeof(NtHdrsNew), 1, pFile) != 1) 76 return 11;109 return Error("Failed to write PE header at %#lx: %s", offNtHdrs, strerror(errno)); 77 110 } 78 111 79 if (fclose(pFile) != 0) 80 return 29; 81 return 0; 112 /* 113 * Make the IAT writable for NT 3.1. 114 */ 115 if ( fNt31 116 && NtHdrsNew.FileHeader.NumberOfSections > 0 117 && NtHdrsNew.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size > 0) 118 { 119 uint32_t cbShdrs = sizeof(IMAGE_SECTION_HEADER) * NtHdrsNew.FileHeader.NumberOfSections; 120 PIMAGE_SECTION_HEADER paShdrs = (PIMAGE_SECTION_HEADER)calloc(1, cbShdrs); 121 if (!paShdrs) 122 return Error("Out of memory"); 123 *ppaShdr = paShdrs; 124 125 unsigned long offShdrs = offNtHdrs 126 + RT_UOFFSETOF(IMAGE_NT_HEADERS32, 127 OptionalHeader.DataDirectory[NtHdrsNew.OptionalHeader.NumberOfRvaAndSizes]); 128 if (fseek(pFile, offShdrs, SEEK_SET) != 0) 129 return Error("Failed to seek to section headers at %#lx: %s", offShdrs, strerror(errno)); 130 if (fread(paShdrs, cbShdrs, 1, pFile) != 1) 131 return Error("Failed to read section headers at %#lx: %s", offShdrs, strerror(errno)); 132 133 uint32_t const uRvaIat = NtHdrsNew.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress; 134 uint32_t uRvaEnd = NtHdrsNew.OptionalHeader.SizeOfImage; 135 uint32_t i = NtHdrsNew.FileHeader.NumberOfSections; 136 while (i-- > 0) 137 if (!(paShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD)) 138 { 139 uint32_t uRva = paShdrs[i].VirtualAddress; 140 if (uRvaIat >= uRva && uRvaIat < uRvaEnd) 141 { 142 if (!(paShdrs[i].Characteristics & IMAGE_SCN_MEM_WRITE)) 143 { 144 paShdrs[i].Characteristics |= IMAGE_SCN_MEM_WRITE; 145 unsigned long offShdr = offShdrs + i * sizeof(IMAGE_SECTION_HEADER); 146 if (fseek(pFile, offShdr, SEEK_SET) != 0) 147 return Error("Failed to seek to section header #%u at %#lx: %s", i, offShdr, strerror(errno)); 148 if (fwrite(&paShdrs[i], sizeof(IMAGE_SECTION_HEADER), 1, pFile) != 1) 149 return Error("Failed to write IAT section header header at %#lx: %s", offShdr, strerror(errno)); 150 } 151 break; 152 } 153 uRvaEnd = uRva; 154 } 155 156 } 157 158 return RTEXITCODE_SUCCESS; 82 159 } 83 160 161 162 /** @todo Rewrite this so it can take options and print out error messages. */ 163 int main(int argc, char **argv) 164 { 165 /* 166 * Parse arguments. 167 */ 168 if (argc != 2) 169 { 170 fprintf(stderr, "VBoxPeSetVersion: syntax error: Expected a only single argument!\n"); 171 return RTEXITCODE_SYNTAX; 172 } 173 const char *pszFilename = argv[1]; 174 g_pszFilename = pszFilename; 175 176 /* 177 * Process the file. 178 */ 179 int rcExit; 180 FILE *pFile = fopen(pszFilename, "r+b"); 181 if (pFile) 182 { 183 PIMAGE_SECTION_HEADER paShdrs = NULL; 184 rcExit = UpdateFile(pFile, true /*fNt31*/, &paShdrs); 185 if (paShdrs) 186 free(paShdrs); 187 if (fclose(pFile) != 0) 188 rcExit = Error("fclose failed on '%s': %s", pszFilename, strerror(errno)); 189 } 190 else 191 rcExit = Error("Failed to open '%s' for updating: %s", pszFilename, strerror(errno)); 192 return rcExit; 193 } 194
Note:
See TracChangeset
for help on using the changeset viewer.