The MASM Forum Archive 2004 to 2012

General Forums => The Laboratory => Topic started by: Ficko on July 08, 2010, 09:02:52 AM

Title: PE version patcher
Post by: Ficko on July 08, 2010, 09:02:52 AM
Some of you guys are propable aware of the fact that if you generate an executable with "Link.exe" - I think - above version 9.0 your executable will be refused by
OS Windows 2000 - and may by others as well -

This is due to the improper OS versioning in the PE header - too high -

"Link" has a switch to overwrite this number but intentionally - I suppose ::) - broken by MS.

I use this tool http://www.korosoft.net/programs/?year=2008 "PE Version patcher" to patch the executable.

However there is no source and like any other such utility you risk some unwanted trojans.

So the assignment: :bg

I think the program is ridiculously simple for some who knows a little about PE headers. - Not me :wink -

Maybe in "JJ" MASM Basic is just 3 commands


LoadPEheader "C:\My.exe"
PatchPEheader
SavePEheader "C:\My.exe"
:green2

I guess would be great if someone could post a somewhat equivalent prg to above with source. ::) :P
Title: Re: PE version patcher
Post by: gwapo on July 08, 2010, 09:34:33 AM
You can use /VERSION:major[.minor] linker option.
Title: Re: PE version patcher
Post by: Ficko on July 08, 2010, 09:44:20 AM
Quote from: gwapo on July 08, 2010, 09:34:33 AM
You can use /VERSION:major[.minor] linker option.

Try it like I sad dosn't work. :toothy

And you may wanna patch something you do not have the source, like the linker itself. :bg
Title: Re: PE version patcher
Post by: gwapo on July 08, 2010, 09:50:01 AM
Quote from: Ficko on July 08, 2010, 09:44:20 AM
Quote from: gwapo on July 08, 2010, 09:34:33 AM
You can use /VERSION:major[.minor] linker option.

Try it like I sad dosn't work. :toothy

It's working for me  :bg
I'm using: "Microsoft (R) Incremental Linker Version 10.00.30319.01"
Probably they've already fixed it with the linker version I'm using.
Title: Re: PE version patcher
Post by: Ficko on July 08, 2010, 10:05:14 AM
I think you are talking about the "Image Version".

That info is useless.

The OS by loading the exe is checking only the "Operating System Version" info - sofar I know - ::)
Title: Re: PE version patcher
Post by: evlncrn8 on July 08, 2010, 10:20:06 AM
totally correct, it checks the windows version (4.0 = 2k if i remember right) NOT the linker version,
could also be caused by an api used which is present in xp but not 2k etc..
Title: Re: PE version patcher
Post by: jj2007 on July 08, 2010, 12:00:12 PM
Quote from: Ficko on July 08, 2010, 09:02:52 AM
Maybe in "JJ" MASM Basic is just 3 commands

At least 4...
include \masm32\MasmBasic\MasmBasic.inc
Init
Open "U", #1, CL$()  ; open commandline arg for updating
Seek #1, 123
Print #1:2, Chr$(97, 0)  ; inserts "a" and a nullbyte at pos 123
Close
Exit
end start
Title: Re: PE version patcher
Post by: Ficko on July 08, 2010, 01:07:22 PM
Holly Sh.*?! I was just kidding.  :clap:

I wonder this really works in every case ?! ::)
Title: Re: PE version patcher
Post by: Ghandi on July 08, 2010, 02:31:31 PM
I'm sorry, but there is a little more involved with editing a PE32 header unless you are using precalculated offsets for patching. The most common method i have seen is to either map the file or read it into memory and taking this as the base address as well as a pointer to a structure named IMAGE_DOS_HEADER, adding the e_lfanew member of this structure to the base address yields the offset of the PE header (IMAGE_NT_HEADERS).

Another way i've seen is to use SetFilePointer and ReadFile:

1. Open file handle and read first 2 bytes of file, confirm they're 'MZ'
2. Set file pointer - SetFilePointer,hFile,3Ch,0,FILE_BEGIN
3. Read 4 bytes - e_lfanew
4. Set file pointer - SetFilePointer,hFile,e_lfanew,0,FILE_BEGIN
5. Read 4 bytes, confirm they're 'PE',0,0
6. Set file pointer - SetFilePointer,hFile,offset_of_desired_member - 4,0,FILE_CURRENT
7. Write desired data
8. Close file handle

HR,
Ghandi
Title: Re: PE version patcher
Post by: gwapo on July 08, 2010, 03:17:33 PM
The one he is looking is in Optional Header at offset C0h (Major OS version) and C2h (Minor OS version) respectively. As I said earlier, I was able to set these values with 4.0 using the linker option /VERSION:4.0
If you don't trust MS linker, then use Pelle's linker (polink.exe), it's included in MASM32 distribution as well.
Title: Re: PE version patcher
Post by: jj2007 on July 08, 2010, 06:00:35 PM
Quote from: gwapo on July 08, 2010, 03:17:33 PM
The one he is looking is in Optional Header at offset C0h (Major OS version) and C2h (Minor OS version) respectively.
With polink, the /version switch sets C4h and C6h for me - major and minor image versions. Same for link 9.0, but at offsets FC and FE...
Title: Re: PE version patcher
Post by: qWord on July 08, 2010, 06:19:20 PM
maybe also interesting:  CFF Explorer (http://www.ntcore.com/exsuite.php)
Title: Re: PE version patcher
Post by: gwapo on July 08, 2010, 06:27:38 PM
Quote from: jj2007 on July 08, 2010, 06:00:35 PM
With polink, the /version switch sets C4h and C6h for me - major and minor image versions. Same for link 9.0, but at offsets FC and FE...

You're right, /VERSION is for image version, and not for OS version. Thanks for correcting me  :toothy
Title: Re: PE version patcher
Post by: clive on July 08, 2010, 07:25:40 PM
Perhaps you want /SUBSYSTEM:WINDOWS,4.00 or /SUBSYSTEM:CONSOLE,4.00
Title: Re: PE version patcher
Post by: Ficko on July 09, 2010, 07:22:58 AM
Quote from: clive on July 08, 2010, 07:25:40 PM
Perhaps you want /SUBSYSTEM:WINDOWS,4.00 or /SUBSYSTEM:CONSOLE,4.00

Quote
LINK : warning LNK4010: invalid subsystem version number 4.00; default subsystem version assumed

That what I was talking about above MS "intentionally" crippled the linker. ::)
Prehabs they want to prevent something else like not to try run .NET 3.0 on Windows 2000 or god knows.

Quote from: qWord on July 08, 2010, 06:19:20 PM
maybe also interesting:  CFF Explorer (http://www.ntcore.com/exsuite.php)

Nice finding! :U
Title: Re: PE version patcher
Post by: jj2007 on July 09, 2010, 10:05:29 AM
Quote from: Ficko on July 08, 2010, 01:07:22 PM
Holly Sh.*?! I was just kidding.  :clap:

I wonder this really works in every case ?! ::)

You can patch a file with a known offset with this four-liner. But as shown later, the offset is not fixed...
Title: Re: PE version patcher
Post by: Ghandi on July 09, 2010, 10:13:50 AM
Is the subsystem version of any importance with this 'problem' of running newer linked executables on Win2000?

The code isn't pretty, but it uses memory mapped files to edit the MajorOperatingSystemVersion and MinorOperatingSystemVersion members of the PE header. I haven't commented the code but it should be pretty plain what it does. Don't pay attention to my poor coding, just take the concept out of there and make what you want with it if you so desire. :D Any questions, feel free to ask, if i'll answer them the best i can.

Btw, i know there is a typo in at least one of the messagebox texts, it should read "must" not "muse", a distance of two keys. Which if you look at it from a different perspective, isn't too bad an effort, because i totally missed 'r' when doing that particular typo and i didn't even notice it until i'd uploaded the zip file to the forum, o0.

HR,
Ghandi
Title: Re: PE version patcher
Post by: gwapo on July 09, 2010, 10:30:58 AM
Quote from: Ficko on July 09, 2010, 07:22:58 AM
Quote from: clive on July 08, 2010, 07:25:40 PM
Perhaps you want /SUBSYSTEM:WINDOWS,4.00 or /SUBSYSTEM:CONSOLE,4.00

Quote
LINK : warning LNK4010: invalid subsystem version number 4.00; default subsystem version assumed

That what I was talking about above MS "intentionally" crippled the linker. ::)
Prehabs they want to prevent something else like not to try run .NET 3.0 on Windows 2000 or god knows.


Windows OS version 4.0 is Windows 95. If you want your program to run on Windows 2000 and above, the default version 5.0 should work. Windows 2000 = 5.0
Title: Re: PE version patcher
Post by: jj2007 on July 09, 2010, 01:02:50 PM
For testing...

include \masm32\MasmBasic\MasmBasic.inc
memwrd MACRO memptr
  movzx eax, word ptr memptr
  EXITM <eax>
ENDM
Init
Let esi=FileRead$(CL$())  ; utterly inefficient to read in the whole file ;-)
mov ebx, [esi+3Ch]
Print Str$("MajorOS    \t%i\n", memwrd(IMAGE_NT_HEADERS.OptionalHeader.MajorOperatingSystemVersion[esi+ebx]))
Print Str$("MinorOS    \t%i\n", memwrd(IMAGE_NT_HEADERS.OptionalHeader.MinorOperatingSystemVersion[esi+ebx]))
Print Str$("MajorImage\t%i\n", memwrd(IMAGE_NT_HEADERS.OptionalHeader.MajorImageVersion[esi+ebx]))
Print Str$("MinorImage\t%i\n", memwrd(IMAGE_NT_HEADERS.OptionalHeader.MinorImageVersion[esi+ebx]))
Print Str$("MajorSubSys\t%i\n", memwrd(IMAGE_NT_HEADERS.OptionalHeader.MajorSubsystemVersion[esi+ebx]))
Print Str$("MinorSubSys\t%i\n", memwrd(IMAGE_NT_HEADERS.OptionalHeader.MinorSubsystemVersion[esi+ebx]))
Inkey "-- info refers to ", CL$(), " --"
Exit
end start


Output:
MajorOS         4
MinorOS         0
MajorImage      10
MinorImage      0
MajorSubSys     4
MinorSubSys     0
-- info refers to C:\Program Files\Microsoft Office\Office12\WINWORD.EXE --


The executable is attached.
Title: Re: PE version patcher
Post by: Ghandi on July 09, 2010, 03:15:47 PM
If you are worried about file size, you can read in 40h bytes from the file and check the DOS signature, then use the e_lfanew member to set the file pointer again so its pointing at the actual PE header signature. From there you can access any part of the PE header and this approach is used a fair bit in applications i've seen which handle larger PE file access without loading it fully to memory.

A question regarding memory mapped files, if you have mapped a large file but not accessed the memory, is it paged in from the word go or does that happen automagically? I was under the impression that it would be paged in as the access demanded it, otherwise it would suck all of the memory from the OS.

HR,
Ghandi
Title: Re: PE version patcher
Post by: jj2007 on July 09, 2010, 03:53:32 PM
Quote from: Ghandi on July 09, 2010, 03:15:47 PM
If you are worried about file size,

No, I am not worried. Just lazy.
; Let esi=FileRead$(CL$())  ; utterly inefficient to read in the whole file ;-)
Let esi=New$(4096)
Open "I", #1, CL$()
Input #1, esi, Lof(#1)
Close
Title: Re: PE version patcher
Post by: Ficko on July 09, 2010, 03:53:58 PM
I made some tests with the CFF Explorer and just wanna make some clarification.

Looks like the "MinorSubsystemVersion" + has to be (0) to run under W2.
So 5.0 is ok.

The problem is SOLVED. :toothy

Since
Quote/SUBSYSTEM:CONSOLE,5.00
is OK.

No more patching. :U
Title: Re: PE version patcher
Post by: Ghandi on July 09, 2010, 04:40:04 PM
I wasn't referring to your code jj, i meant my code, i mapped the whole file with MapViewOfFile.

HR,
Ghandi
Title: Re: PE version patcher
Post by: Queue on July 09, 2010, 04:48:59 PM
Quote from: Ficko on July 09, 2010, 03:53:58 PM
I made some tests with the CFF Explorer and just wanna make some clarification.

Looks like the "MinorSubsystemVersion" + has to be (0) to run under W2.
So 5.0 is ok.

The problem is SOLVED. :toothy

Since
Quote/SUBSYSTEM:CONSOLE,5.00
is OK.

No more patching. :U
Unless you want it to run on all 32-bit versions of Windows, in which case 5.0 is inadequate.

http://www.steelbytes.com/?mid=47

That's the best utility I've seen for achieving this, and does more than simply changing the subsystem version.

Queue
Title: Re: PE version patcher
Post by: jj2007 on July 09, 2010, 05:10:17 PM
Quote from: Ghandi on July 09, 2010, 04:40:04 PM
I wasn't referring to your code jj, i meant my code, i mapped the whole file with MapViewOfFile.

So we have the same bad habits :wink
Title: Re: PE version patcher
Post by: Ficko on July 09, 2010, 06:23:11 PM

Unless you want it to run on all 32-bit versions of Windows, in which case 5.0 is inadequate.


You right and still need a patcher for prgs you don't have the source. :wink
Title: Re: PE version patcher
Post by: GregL on July 09, 2010, 09:05:39 PM
I did a little research of what the default version is when the version is not specified in /SUBSYSTEM.

VS 6.0               4.00
VS 2003 (7.0)        4.00
VS 2005 (8.0)        4.00
VS 2008 (9.0)        5.00
VS 2010 (10.0)       5.00

See /SUBSYSTEM (http://msdn.microsoft.com/en-us/library/fcc1zstk.aspx)


Title: Re: PE version patcher
Post by: clive on July 09, 2010, 09:33:54 PM
Quote from: Ficko
You right and still need a patcher for prgs you don't have the source. :wink

Microsoft (R) COFF Binary File Editor Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

usage: EDITBIN [options] [files]

   options:

      /BIND[:PATH=path]
      /HEAP:reserve[,commit]
      /LARGEADDRESSAWARE[:NO]
      /NOLOGO
      /REBASE[:[BASE=address][,BASEFILE][,DOWN]]
      /RELEASE
      /SECTION:name[=newname][,[[!]{cdeikomprsuw}][a{1248ptsx}]]
      /STACK:reserve[,commit]
      /SUBSYSTEM:{NATIVE|WINDOWS|CONSOLE|WINDOWSCE|POSIX}[,#[.##]]
      /SWAPRUN:{[!]CD|[!]NET}
      /VERSION:#[.#]
      /WS:[!]AGGRESSIVE


The other Microsoft tool that comes to mind is REBASE.EXE, but it doesn't have options to change the SUBSYSTEM stuff.
Title: Re: PE version patcher
Post by: Queue on July 09, 2010, 09:43:01 PM
Like DUMPBIN and LIB, EDITBIN is simply a forwarder to LINK.EXE.

DUMPBIN = LINK.EXE -dump
EDITBIN = LINK.EXE -edit
LIB = LINK.EXE -lib

Queue