deft flux

A portal into the creative workings of David Meyer

Installing home software on Windows Server at home

It seems to be a popular business model with software vendors to offer two classes of licenses--a less expensive license for personal/home/non-profit use, and a more expensive license for professional/business/profit use.  They may even try to feign this business model as natural and necessary by having two different versions of the software.  (Many vendors actually do have feature-limited versions for less than professional use.  This article does not concern those.  It concerns scenarios where the two versions are actually identical except for what they allow themselves to be used for.)  How is a vendor to enforce this restriction on use, however?  Well, unfortunately, many have made the following mistaken assumption:

"Only businesses use Windows Server.  Windows Server is never used by home users for personal use."

Well, you could say I'm not your typical home user.  My home server is running Windows Server 2008, and I use it for nothing but personal use.  I have no business, and I make no profit from its use.  However, soon after I installed Windows Server on my home server, I discovered that certain home versions of software that I was using before will not install on Windows Server, either claiming that it is not licensed for professional use or that the operating system is not supported.

So I was faced with a moral dilemma.  Do I give in and pay a significant amount of money for the same software just so it will run on Windows Server when I already have a license to use it for personal use?  Or do I find a way to trick the installer program to think it's not actually running on Windows Server?

Windows Version "Masking"

I'm sure anyone who knows me already figured that I chose the latter.  Two days ago I found success, installing a program that supposedly does not support Windows Server on my server.  It installed perfectly and is working flawlessly ever since.

You see, I made the correct assumption that at their core Windows Server 2008 and Windows Vista are the same operating system, that the program did not actually depend on any features exclusive to non-server Windows versions, and that any features included in Windows Server would not interfere with the program.  In fact, the restriction on Windows Server was entirely artificial.  That being the case, it was totally unnecessary to do any emulation.  All that was necessary was to get past the code that checks what version of Windows is running.  Hence, what I needed was a "mask".  I use the term "mask" because a mask is very superficial.  It superficially changes the apparent identity of the wearer, but underneath, they are still the same person.

Now just how would I go about masking Windows Server?  And for that matter, how would I limit it so it only affects certain programs?

Let's start by considering how one would detect what version of Windows is running.  Well, I'm a programmer, so if I were writing that code, how would I figure out how to do it?  Well, Microsoft makes it easy: Getting the System Version (Windows)  This article tells you exactly how to do so.  It even gives source code.  In short, it calls a few Win32 API functions, such as GetVersionEx.  Of course!  API functions!  But how do I intercept API calls and change their behavior?  It turns out this concept is called "API hooking" and there is lots of information online about how to do it.

API Hooking

I found this article extremely helpful: API hooking revealed.  I determined that injecting into a single process and using a "user-level" hook (since I needed to hook a Win32 API, not a native NT API) was the answer.  Modifying the Import Address Tables sounded like my best bet. 

Then I found some source code: HookAPI source code.  This solution was not quite right for a number of reasons.  First off, it was designed to inject into every running process.  I just want to inject into a single process right when it starts.  And more importantly, when I ran the demo application, it crashed every process it injected into!  So it doesn't even work!  (At least on Vista/Server 2008)  When I tried to troubleshoot it, I found out that the author used a massive amount of inline assembly code.  But, I saw what it was trying to do.

It wasn't modifying the Import Address Tables at all.  It was so simple, actually.  It used GetProcAddress to get the address of where the function was loaded into memory, then it overwrote the first 5 bytes with a jump instruction!  That would transfer execution to the address given in the jump instruction, which was the address of a different function, thus overriding the underlying API.  Of course, gaining write access to that memory was a trick, not to mention injecting the DLL into the remote process.

My Proof-of-concept

So, I wrote my own API hooking and DLL injecting code (using no inline assembly, I might add) based on my newfound knowledge, and after some troubleshooting, I was in business.  After I discovered (of course) that the installer extracted some files into a temporary folder and executed one of them, I used the solution on the extracted installer and what do you know?  It called GetVersionEx to check the Windows version, and my hook function returned all the same version information a normal call to GetVersionEx would on Windows Server 2008 except the product type - "workstation" instead of "server".  Voilá!  It downloaded and installed the application.  Interestingly, the application itself runs fine on its own.  It does not check the Windows version.  Only the installer did.

So this is, of course, only a proof-of-concept.  I'm working on making it into a polished solution.  It needs to cover some other ways programs could detect the Windows version and automatically inject into processes started by the masked process before I'd be comfortable offering it for others to use. :)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Development
Posted by deftflux on Thursday, November 20, 2008 12:22 PM
Permalink | Comments (2) | Post RSSRSS comment feed

Comments