How to make a program portable the hacker way (the hardest way/the fun way)

If you frequently move and you don’t want to take your laptop with you all the time, or if you simply can’t use your computer, it’s really useful to bring with you a USB flash drive filled with your favourite/most useful programs.
A starting point to download free and already prepared apps is portableapps.com. They even have a custom menu to easily launch your programs and it’s ready to accept user-made apps.
There are tons of software ready to pack your programs in a sandbox to make them portable (cameyo.com, enigmaprotector.com, www.evalaze.de, spoon.net, vmware.com), so why would someone do this work by hand?

  • These apps make your program bigger
    They add an inevitable overhead for the sandbox code.
  • These apps usually make your program slower
    Apps created this way must intercept all calls to disk access and registry access to redirect them in a sandbox.
  • Sometimes these apps are flagged as viruses by your antivirus
    Badly coded antivirus programs flag your software as viruses due to the runtime decompression of the app’s code.
  • It’s Fun!
    Who doesn’t like challenges? This is definitely a hard goal to reach.

Required knowledge:
You must be a programmer, or at least you must be able to think like one, and you should definitely know Assembly language or be prepared to spend a lot of your time digging through a manual for opcode meanings!
You must also know Windows common file locations, like user directories, and how the Registry works and how it is used by programs to store configurations.

Tools Used:

Process Monitor v3.1 – http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
A program that logs file and registry usage by programs, used to spot registry and file access.

UPX 3.91 – http://upx.sourceforge.net/
A program used to compress executables and libraries, used to shrink the total size of the app executables.

OllyDbg 2.01 – http://www.ollydbg.de/version2.html
It’s a debugger and a disassembler, extensible with plugins and widely used in the decompiler and cracker scene. We will use it to find and change file load and read locations.

An x86 app to make portable. For this example I’ll use the game Braid; I’ve bought a DRM-free version on the Humble Bundle store http://www.humblebundle.com/store.
You can use the knowledge gathered from this particular example on any piece of software, but I suggest using, when available, a DRM-free version of games/programs, otherwise you first need to crack them in order to make them portable.

Step 0:
Sometimes programs are already portable-ready. Try to dig into readme files located in the installation folder or search in configuration files for save file paths. Also remember to have a look into the Windows Registry, and if those three methods fail try to search on Google – you’ll be surprised by the results. But keep away from cracked and packed pieces of software, as they usually hide malware.

Don’t try this at home!

First step: Play it!

In order to generate a savegame or some configuration files, you must try the program while executing Process Monitor.
First start Process Monitor, then click on the filter button.

Process monitor start

Now you must add a filter on process name.

Process Monitor Filters

Finally you can play your game or run your app to generate configuration files!

Finally Play it!

Second Step: Spot files location
After you’re sure that configuration files/savegames were created, exit the game and open the Process Monitor window.
Filter only for File System Activity and start looking for a possible configuration file/savegame path.

Spot your target

Third Step: Find the save location in the executable
Start OllyDbg and open the executable of your program.

Start OllyDbg


Right-click the code and select “Search for->All referenced strings”. In the following window, search the list of all recognized strings for the name of the savegame folder, in our case “Braid”.

Find the right one

This is the hardest part, you should find the right string, so follow each one with a double click and look for file access code.

Seems good enough

This is definitely the right place!

Fourth step: Understand what’s happening
In this small function some things are happening:
CALL DWORD PTR DS:[<&SHELL32.SHGetFolderPathA>]

After a quick Google search we can find the meaning of this CALL:
Gets the path of a folder identified by a CSIDL value.
HRESULT SHGetFolderPath(_In_ HWND hwndOwner, _In_ int nFolder, _In_ HANDLE hToken, _In_ DWORD dwFlags, _Out_ LPTSTR pszPath);
In this case the value 1A passed as dwFlags parameter means CSIDL_APPDATA <user name>\AppData\Roaming in Windows 8, and this is the basic path found in the second step that we must replace with the current directory.
The second CALL seems suspiciously like a sprintf that concatenates the 2 input strings: “C:\Users\<username>\AppData\Roaming” and “Braid” with a “\” in the middle.
So this must be the function that generates the value that is then returned.
If you don’t get what’s happening in the function, I suggest setting a breakpoint at the start and then running the program. In Braid’s case you will see a black screen because it’s a fullscreen program. To return to OllyDbg you should use the Ctrl + Alt + Del combination and start the Task Manager, or start Braid in windowed mode by adding “-windowed” to the arguments passed by OllyDbg when starting the program.

Use windowed mode

As you can see, at the end of the function the value 00BB47C8 that points to a memory region that contains the string: “C:\Users\Dege\AppData\Roaming\Braid” is in the EAX register, so our changed path should also be passed this way!

Try to debug your function to understand what’s going on

Fifth step: Make the magic happen
Now we’re gonna finally edit some code!
First we’ll fill the function with NOPs by selecting all commands and Right Click->Edit->Fill with NOPs. Now we have plenty of space to work with.
The first instruction will be a short JMP that uses 2 bytes, so we’ll copy the third NOP address by Right Click on it->Edit->Copy address.
Now we can use the space inside the cleaned function to store the new string that we’ll replace.
Start by right-clicking in the hex-dump section of the window, then Go to->Expression… and paste the address of the third NOP that we copied before.
Now we’ll select some of these 90 values and we’ll inject our string.
In this case we’ll use the replacement string “.\savegames”. The dot is a reference to the current directory, so the program will create the savegames in its own folder under a savegames directory.
The string is 11 characters long. We’ll add a binary 00 character as string terminator, so we can select 12 of the “90” red values.

Select the right chars

Then right click on them->Edit->Binary edit…
In the ASCII input write “.\savegames” and in the HEX input replace the last 90 with a 00.

Add your replacement text

Now back to the assembly section, we must select the last five NOPs, Right Click->Assemble… In the following window we must write the command “MOV EAX, " and paste the address of the third byte of the function, the one in which we put the new string, that should still be in our clipboard.

This is the new return value

Now for the last part of code edit we must copy the address of the command that we have just inserted with our usual Right Click->Edit->Copy Address.
Then after the selection of the first two NOPs Right Click->Assemble… it and write “JMP " followed by the address that you copied.

This JMP will move the execution to the MOV used to return the right value

The final result should be this one:

Final result

Now, to save our changes to the exe file, “Right Click->Edit->Copy all modifications to executable” and then in the following window “Right Click->Save File…” and save it.

Sixth step: Unused files removal
Every portable program should be as small as possible; this isn’t a step that you should skip.
We’ll start by copying all files of the Braid installation into a working directory.

Folder content before cleaning

By examining the contents of the folder we can choose to remove some files:
unins000.dat and unins000.exe are needed by Windows to uninstall the game and can go away.
READ_ME.txt is a readme file and isn’t necessary to make the game run so it can go away too.
braid.bak is a backup done by OllyDbg, and after a test to make sure that our modification works we should remove it.
The licenses folder contains various licenses; we will not redistribute the game so it can go too.
The folder DirectX_Redist contains a redistributable version of the DirectX library. If you think that some of your target computers will need it, you should keep it on your USB flash drive, but not in your Braid folder, so we’ll move it away.
After the first cleaning the situation will be this one:

Folder content after cleaning

Now by entering the data folder we’ll discover some archives and some folders with languages and fonts. If you plan to never play in an Asian language you can delete the fonts directory. You can also remove from the strings folder all languages that you’ll never play, but I suggest leaving English anyway as a fallback.

Seventh step: Archive recompression
Usually when you see archives you can try to recompress them with a higher compression rate. Unfortunately Braid doesn’t support zip compression, probably to keep load times low, so we can’t apply this step to the game.

Eighth step: Reduce images quality
It’s optional and I won’t do it in this case, because it would be terrible for the quality of the game. But when you do this step, remember to test all of your modifications and keep a backup copy of the entire untouched folder – errors always happen when you are doing something that the original creator hasn’t considered!

Ninth step: Compress executables and libraries
By using UPX you can compress even the executables, you just need to drag and drop the desired executable onto the upx.exe file.
On Braid I got a 50% compression ratio, with bigger executables it will significantly reduce total size. If you want to play with command line parameters you can even try to reach a higher compression ratio.

Results:
Start size: 165.342.514 bytes
End size: 123.325.587 bytes
We got a 40MB file reduction and now our program will keep savegames in its own directory.