Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Open Source Software protection system - Part 1

0.00/5 (No votes)
18 Apr 2004 3  
Outlines in developing an open source implementation of a new software protection system.

License

You MUST agree to the following to continue reading this document

  • Publication of this article as a whole or in part(s) is prohibited without authorization from Kamal Shankar.
  • Commercial exploitation/distribution of the software(s) in conjunction with this article is allowed provided an arrangement exists between Kamal Shankar and the licensee.
  • The software(s) packaged with this article comes with NO WARRANTIES EXTENDED. Use at your own risk.

Anybody interested in building a PE Loader just for the sake of it - Thanks. Read on..

Background

This is intended to be a free, open software protection system based upon a simple assumption that makes this protection system viable only for small software companies or actually a single programmer.

The philosophy of this program is different from almost ALL the currently available (commercial) software protection systems, and it is simple: We will NOT be depending on preventive measures (which can ALWAYS be bypassed by a clever computer student) but rather upon the first and most basic idea behind ALL encryption algorithms - you have the key, you have the data (otherwise try to break down the titanium vault!)

The USP of this protection system will be this : Anybody having the software can make infinite copies of it, but they will just crash on an unauthorized machine. They will however, run transparently on the correct machine as if it was not protected at all!

In this way, it's not really a copy protection system in the true sense, but more of a one machine - one software kind of protection. Those using this protection do NOT need to use protection calls or APIs in their program, nor will the net executable code be changed in anyway - code obfuscation, IAT modification, section merging, entry point hiding or whatever. In short, what you compiled is what is finally loaded into the user's computer (provided it's the correct machine)

As the great +ORC had once said - "Anything that runs can be cracked".

What we do is fully leave the user to run our program(s) on his system. The program is encrypted using a machine dependent key and only the correct key will produce the correct decoded program file(s), else it will be just plain garbage.

The encryption/decryption key will be calculated dynamically at run time by a program, let's call it HardwareID. The user/customer will be required to run HardwareID on his machine. The resultant key (it's length depending upon the particular encyption algorithm) will be sent in plaintext to the software publisher, who will encrypt all or the important program files using that key and send the distribution to the customer along with the program loader (let's call the loader Loader32), which will again calculate the key dynamically and just decrypt and run the files from primary memory. We will NOT be decrypting the files to secondary memory (HDD) and this will make our distribution about .1% secure from being cracked.

[Anything which runs can be cracked. And if you have the correct tools , you just need to click].

Stumbling Block

We can approach the problem in two ways:

  • Decrypt data directly to memory, and try to make the Win32 program loader run the image.

    Now, as far as I am aware, none of the SDK APIs allow us to run a image directly from memory, they ALL want a disk image\valid filename. What we could do is to decrypt to memory, and then write our own Win32 loader (never mind that the memory could be dumped). (Please refer to Open Source Software protection system - Part 2 to see the implementation )

  • Write our own Win32 loader to read the encrypted file directly from disk, decrypt it and then load it ;)

(Embarrassed Grin) Well, the heart of the idea - the PE loader is probably beyond me : (I just cannot think of rewriting something which will be able to handle relocations, function lookups and ordinal lookups and translation, image handling, CS:EIP management, the stack and ...

The program packaged with this article will extract the encrypted data to HDD and run it from there ;).

For direct in memory binary code patching solution, refer to Open Source Software protection system - Part 2.

Anybody with a working idea/implementation of anything able to decrypt a encrypted PE file directly to memory and from there run it - welcome if you wish! So actually what I am asking is code to a program packer. Obviously the open UPX comes to mind, but why can we not use it? Because:

  • I cannot think of writing CAST or TWOFISH in assembly.
  • The external modules used by me will be too much of a pain in the you-know-what to port to be NASM compatible.
  • The code for UPX Win32PE loader is BEYOND my easy comprehension (I do program in assembly but this?)

Why not use one of the many commercial packers ?

First of all, I wanted to do it to LEARN rather than EARN ;)

I am sure that this initiative will be looked upon NOT as my own, but all. Thank you and happy coding!

And then, the biggest disadvantage of almost all currently packers is that they implement preventive measures.

From my experience, preventive measures succeed in keeping out the beginners. Real crackers just need to find the locations where the preventive measures are operating, and can bust them easily !

This system is different - it has no preventive measures for the cracker to crack in the first place !

To Make it Simple - outlines for fabricating such a system

First of all, this system must satisfy the following clauses:

  • It must not employ any preventive measures (antidebugging, blacklists, dead code..).
  • Must be as transparent as possible to the end user.
  • Must not require source level modification. Ideally should work with just binaries.

For the time being, let's limit ourselves to Win32 and PE images, protected mode and 32 bit addressing. Code should be Visual C++, but if ASM does come in, the algorithm should be mentioned and code well documented. No other language. [If you come across something similar but in another language, it's welcome anyway, but try to be C++ ;)] [Might I suggest that we try to use existing code which has already been tried and tested?. Has anybody got suggestions about this ?]

Of course, Win32 APIs (as well as debugging APIs) are allowed.

Something tells me that perhaps referring to the implementation of the Win32 loader of WINE will help us out, but they have implemented EVERYTHING themselves - actually, many APIs written by them behave VERY differently from the orignal Microsoft API's. In fact, their code implements page aligned relocations and addressing rather than byte alignment used on Microsoft Windows. I will gladly stand corrected on this aspect if I got it wrong.

I might take this opportunity to make you all aware that it's just a beginning, we will soon be having more features once the Stumbling Block (the Loader) is done. I promise ;).

The Source

As you will see, I have uploaded a source package. It contains the HashLibProper files. Include the header file and link to the .lib. Put SysInfo.dll and HashLibProper.dll with the program and you are done.

SysInfo.dll is part of the SysInfo package most generously let out by Paul Wendt [p-wendt@home.com] and available at CodeGuru's 'system' category.

HashLibProper package is a simple Win32 dll which uses SysInfo classes to get Processor name, speed, OS and installed RAM. It uses a single linked list to hold logical drive information, their labels and serial numbers. It concatenates all this info and returns a C type string. It also returns an MD5 of this string.

You will find ALL these detailed in the ReadMe.

NOW BEFORE YOU START CRYING OUT LOUD - "Where is the source code for HashLibProper package?", I will release the source once the Stumbling Block materializes and we get a concrete solution. [The code for the library is easy and small anyway, and I just want to see a little contribution to this project - if that happens I WILL release the code]

Current Implementation

  • Software packaged with this article.

    This is best understood by going through the source package. In short we put ALL the obtained system info into a C type string and do an MD5 on it. We may use the MD5 digest as the encryption key itself but later we will do a little more math to increase security - BUT AFTER the Stumbling Block has seen some light. This key will also be produced dynamically on the user's system and the encrypted files will be decrypted using this key.

    Needless to say, the person with the correct system will create the correct MD5 and thus only he gets the program to run (on other systems the decrypted output should be un-executable garbage).

    So select a program file copy it to the directory to which you extracted all our files and rename it to OriginalData.dat; run Encrypt.exe and click on 'OK'. The application will encrypt the chosen file to EncryptedData.dat. Then run Encrypt.exe and select 'Cancel'. You will see a file DecryptedData.dat created - it's the program chosen. Rename it to an EXE (or whatever extension it was) - it will running correctly. Now copy these files to a machine of a different configuration and see what happens!

    This is a VERY ROUGH implementation of my idea, but without getting the Stumbling Block cleared, I just cannot see an alternative solution!

  • A more mature solution.

    I wrote a solution which very closely follows the outline laid in this article. Read it here : Open Source Software protection system - Part 2.

Special Thanks

  • Paul Wendt for his great SysInfo class
  • R!SC and +ORC (the reversers out there will know why ;)
  • CounterPane labs - for the BlowFish implementation
  • Chris Maunder and his dedicated team - thank you all for this GREAT site
  • Nir Dremer for his FileEnc code from which the BlowFish encryption routine has been taken

Anyone who can create a solution to the Stumbling Block (You can see how much I am mad about it!) or a good workaround to it?

History

  • 14th April 2004 : Rewrote some parts
  • 10th April 2003 : Mailed project to CodeProject and expecting response ;)
  • 15th May 2003 : Updated article to reflect implementation of Stumbling block I. Please refer to Part 2 of this article to clear up any confusion ;)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here