This is a Generic App that will be used to help secure a very old Legacy game. It will use upnp, RSA Encryption, and Curl/OpenSSL, and be written in c/c++.
Ok, this is the scope. It's not the best, but it's good enough for our purposes for this small project. We will provide you with BOTH RSA Keys that the application will use. One key will be used for encrypting data and sending it to the server, the other key will be used to decrypt data that the server sends the client. This means that there are TWO pairs of keys (4 keys in all) that are in use. For example, you should NOT be able to encrypt text with the application and then decrypt it using the decryption functions in the application because the decryption key will be incorrect.
This scope will provide details on the project we wish to have completed. The application will be written in c/c++ in a Borland Project so that the sourcecode can be compiled by us once the project is complete. All 3rd libraries that are used such as openssl/curl should be included in the project files.
Goal: The goal of this scope is to enhance an application that already exists so that it can send hardware IDs to an SSL Webserver and based on the response open a UDP Port that the server defines using UPnP on the client's router that will enable them to host a game.
1. The first step in creating these new features will be to get the current "Launcher" app talking with the server. When the app is opened for the first time, it should initialize the transport methods so that it can send data to the server and wait for a response. To facilitate this communication a transport method must be developed using either LibCurl/OpenSSL or built in Windows API calls. To test this, you can send the HTML Form POST to http://*****/auth.php. It should have a form element called "data" that contains data. Once the app is sending and receiving data ok, you can move on to step 2. We will test this with you to make sure everything is working properly. We'll use test strings for now until we get the 2 way communication working. Then we will tackle the csv file format and other related things.
a. <[url removed, login to view]> This describes how to use base64 encoding/decoding with C/C++. This is used to base encrypted data back/forth in a non-binary type form. Before sending ANYTHING to the server, you must first encode it. Then when you receive data from the server, you must decode it. This is not the same as decrypting the RSA encrypted data, they are separate.
2. This part of the process will facilitate gathering information about the computer that the application is running on and placing it in a comma delimited file structure (csv file) but will NOT save this data to the harddrive at any time. We want this data cleared from memory as soon as possible (directly after its encrypted in step 3 of this document, dont even wait for the response from the server). The collected data will be the following. Not All data needs to be collected as it may not be possible, but if it is, these are the items we'd like the following. Also, during this process a window should be displayed stating that it's 'authenticating' as steps 2 through 4 may take several seconds ~3 - ~5 seconds:
a. Hard Drive VSN (Volume Serial Number) then md5sum() this value and store it in memory.
1. <[url removed, login to view]> This explains how to retrieve the VSN using the windows API
2. <[url removed, login to view]> This explains what the VSN actually is. It's NOT a volume label!!! Nor is it a hardware ID. Its about as close to a hardware ID that I know of. PunkBuster uses the same ID.
3. <[url removed, login to view]> Here you can read about how PunkBuster uses this ID. QUOTE: /"Even Balance has not disclosed which hardware parts are used to ban players, but trial and error has shown that the hardware GUID is based on the serial numbers of all available hard drives but not the MAC addresses./" I do NOT want to use this method. I only want the VSN of the C drive. I could careless about any other drives.
b. Mac Address of the IGD (Internet Gateway Device, that is the router/cable modem/dsl modem/computer/whatever). Use arp -a <ip address> to obtain the correct mac address for the IGD IE: arp -a 192.168.1.1 This works even when not using 192.168.x.x addresses. Then md5sum() this value and store it in memory
c. Mac Address of the local machine's Internet Network card. Use arp -a <ip address> OR ipconfig /all OR internal Windows API calls. Then md5sum() this value and store it in memory
d. md5sum() of the application itself starting from byte 69 and store it in memory.
1. What does Starting from byte 69 mean? It means you do NOT hash the entire file. Anybody can do this and get the correct hash. We want to at least try to be sneaky and only has the file starting from byte 69.
e. md5sum() of the game file [url removed, login to view] starting from byte 96 (see a pattern here? lol yea Im a perv haha ;) ) and store it in memory
f. Timestamp of the c:\[url removed, login to view] file (old file thats still around even on win7 machines so should cover all versions of winblowz). md5sum() this value and store it in memory
g. Random number between 0-9999999999999999 and then md5sum() it This will be used to create a random "Padding" that will ensure that the encrypted string is ALWAYS different. Please see RSA standards here: <[url removed, login to view]> under "Padding Schemes". Doing this is very primitive indeed but its fairly quick and in addition to the padding that PKCS#1 will provide. It also just adds some random crap to the memory just to mess with hackers heads lol. I might even add more bogus strings in here just to be cruel ;)
h. Their moms birthday, brothers birth place, and time of day they were born......... ok, not really lol. But the more info we have, the more accurate our bans will become and the harder they will be to circumvent. So add any of your own ideas here.
i. All of these values will be placed into a CSV style format so that the server can easily parse them. Any values that were not able to be retrieved will simply result in a blank entry, but it will STILL have a '', entry signifying that the cell was empty
3. ENCRYPT THE DATA AND DELETE IT. Ok, so here we are going to encrypt the data from Step 2 and store it in memory so that we can send it to the server. We will be using an RSA PKCS#1 method of encryption. This means that there will be a public key and a private key (RSA) and there will be some padding added (PKCS#1 is the padding method) to the string that will make the cipher text itself very secure. We will store the public key in the application itself and the private key will be hidden on the server. The public key can be used for encrypting data but it can NOT be used for decrypting data. Once the data has been encrypted, we will then send the data to the server in Step 4. For the encryption all I can do is provide you an example PHP RSA PKCS#1 methods as I do not have anything that can do this in c/c++. I assume Windows probably has APIs for using RSA/PKCS#1 standards. I hope.
a. <[url removed, login to view]> This is the PHP Library that I will be using to decrypt the RSA PKCS#1 data that the application sends to the server.
4. Next we simply send the encrypted data to the server and await a response. The response will either be an encrypted RSA cipher containing the actual results regardless of whether it was a true or false result. There will be a response every time. The TRUE response will be 16112 which is item 5a in this document and FALSE will be 06112 which is 5b in this document. The method of transport for this is in Step 1 of this document. IMPORTANT NOTE: The encrypted text cannot be sent to the php form. It MUST first be encoded using base64() so that it's HTML compatible. The server will then run the php code base64_decode($cipher_text) to unencode it and THEN it will decrypt it. This is an important step and cannot be skipped. The transport itself is going to be nothing more than a simple http form POST. Below you can find the source code of the form the server will be expecting:
<form method=post action='https://*****/[url removed, login to view]'>
<input type = 'hidden' name = 'data' value='encrypted string from Step 3'>
<input type = 'submit' name = 'submit'>
DO NOT send the source code above to the server lol. It will be expecting a response from a POST, the source from above is just an example if the app were a simple html file, this is what the form would look like. I use LibCurl/OpenSSL for posting form values to an SSL webserver, you can use whatever you want as long as it's a library in c/c++ that the app uses internally and not a command line application.
a. DELETE THE STORED ENCRYPTED DATA FROM MEMORY after the post has been sent, do not wait for a response from the server to trigger this deletion.
5. Waiting for a response from the server to determine if the application is authenticated to continue. The value will NOT be in plain text regardless of whether it was true or false. It will be an RSA encrypted text that uses a different RSA key than the key that it used to encrypt the data with. The key will be the private key and will be stored in the application. It will then need to de-crypt the cipher text and parse the response. The first character of the response code will be the true/false boolean (16112/06112) and the remainder of the string will be the port in which the application needs to work with. This is to prevent someone from using an entry in their hosts file and attempting to send the value to the application.
a. If the app is authenticated, it can then continue on to step 5c and then on to step 6 of this document.
b. If the app is NOT authenticated, the application halts and exits with a message that says simply "You are not authorized to use this application. Please contact the admin of the server to discuss this matter further." (it will also run step 5c as well!)
1. The application also needs to run a upnp call to CLOSE the 6112 UDP port (which is NOT hard coded in the app, it MUST use the string it got from the server which we know will be 6112 but that may change in the future) that it may have previously opened on the router. ALL PORTS WILL BE IN UDP. Our game does not use TCP, so the port must be specified as UDP. Otherwise it will not work.
c. DELETE THE STORED ENCRYPTED DATA FROM MEMORY.
6. Once the application has passed authentication, it now needs to prepare the user's router so that they can host games successfully. To do this, you parse off the 1 from the string the server sent you and use that as the port number. It will be 6112 but that may change in the future. The port is also in UDP ONLY. So now you use the upnp library to open port 6112 on their router. We will give you a copy of the game and we will test this with you to tell you if it works or not. It's very difficult to test it without 2 people and a working knowledge of upnp router capabilities. Lancelight will be able to help you test this.
These are the 2 keys that the application will use for encryption/decryption:
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----