VirtualBox

Ignore:
Timestamp:
Dec 26, 2017 3:56:20 PM (7 years ago)
Author:
vboxsync
Message:

VBoxPeSetVersion: Dialed it back to NT 3.1.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bldprogs/VBoxPeSetVersion.cpp

    r69500 r70348  
    2323#include <iprt/formats/pecoff.h>
    2424#include <stdio.h>
     25#include <stdlib.h>
    2526#include <string.h>
    2627
    2728
    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*********************************************************************************************************************************/
     32static const char *g_pszFilename;
     33
     34
     35static int Error(const char *pszFormat, ...)
    3036{
    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}
    3945
    40     if (fseek(pFile, MzHdr.e_lfanew, SEEK_SET) != 0)
    41         return 3;
    4246
     47static 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));
    4364    IMAGE_NT_HEADERS32 NtHdrs;
    4465    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     */
    4671    if (NtHdrs.Signature != IMAGE_NT_SIGNATURE)
    47         return 5;
     72        return Error("Invalid PE signature: %#x", NtHdrs.Signature);
    4873    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);
    5077    if (NtHdrs.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    51         return 7;
     78        return Error("Invalid optional header magic: %#x", NtHdrs.OptionalHeader.Magic);
    5279
    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;
    5588
    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
    5893    {
    5994        NtHdrsNew.OptionalHeader.MajorOperatingSystemVersion = 4;
    6095        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;
    6699    }
    67100
     
    71104        NtHdrsNew.OptionalHeader.CheckSum = 0;
    72105
    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));
    75108        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));
    77110    }
    78111
    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;
    82159}
    83160
     161
     162/** @todo Rewrite this so it can take options and print out error messages. */
     163int 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.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette