Want to Join Us ?

you'll be able to discuss, share and send private messages.

Easy Software Reversing, No Experience Required

Discussion in 'Reverse engineering' started by Rip Cord, Mar 21, 2013.

Share This Page

  1. Rip Cord

    Administrator Staff Member Admin Developer

    An example of how easy it is to patch a windows program written in a .Net language. Knowledge of programming languages is unnecessary.

    GGname.png is super easy to patch. It is sold as a device for editing PS3 game saves to add cheats. Not mentioned in the advertising/sales literature is that it requires a persistant internet connection. It won't work if the servers are down, the company goes out of business, or on a pc without internet. We'll patch out all online connections and see if it still functions.

    What's required:
    .Net Reflector trial version
    Reflexil plugin for .Net Reflector
    A copy of their software. Their pdf manual has a link for downloading the software:
    Since they update the program occasionally, a link for the version used here:
    storm shadow likes this.
  2. Rip Cord

    Administrator Staff Member Admin Developer

    First a sample to show how with one small change the program will load.
    Without internet connection start the editor. You should see this box.
    and then this message
    It's non-functional by design, so click on Don't Send.
  3. Rip Cord

    Administrator Staff Member Admin Developer

    Install Reflector. Unzip the Reflexil plugin and copy Reflexil.Reflector.AIO.dll to the addin subfolder of Reflector (C:\Program Files\Red Gate\.NET Reflector\Desktop X.X\Addins). Start Reflector; in the drop down boxes on the toolbar choose IL and .Net 2.0. Under tools menu choose add-ins. In the dialog box click the plus button;
    then select Reflexil.Reflector.AIO.dll; click open; click close. Reflexil should show up on the tools menu.

    From the file menu open the exe. Right click on it in the explorer pane and choose Decompile
    On the Tools menu, choose Relfexil. The Reflexil Code window will appear in the bottom right corner. 8RCheckSerial.png

    Highlight the first line. Right click and choose create new. For the OpCode enter "br", for Operand Type select -> Instruction reference (use the drop down arrow), for Operand select ->(33)ldc.i4.1,
    and finally click insert before selection.
    Save the changes by right clicking exe in the explorer pane, choose Reflexil, save as. Close Reflector. (Adding an instruction at the beginning has increase all the following line numbers by 1, so it says 34 instead of 33 for the jump destination in the Reflexil code window).
  4. Rip Cord

    Administrator Staff Member Admin Developer

    Start the newly patched version.
    Click continue and the interface will appear.
    Testing the interface makes it clear the program is not fully functional.
    If you clicked details, the warning box gave a hint.
    It's trying to go online again in the CheckforVersion function.
    With a only few simple rules about .net programming anyone can apply these patches or make their own.
    storm shadow likes this.
  5. storm shadow

    Techbliss Owner Admin Ida Pro Expert Developer

    This is very nice. hx for the tut. :jimlad.png:
    Rip Cord likes this.
  6. Rip Cord

    Administrator Staff Member Admin Developer

    How we know to patch check serial.

    A program is divided into sections called functions. Each function performs a specific task.

    Looking at the code in the code window.
    Notice that MainForm_Load is followed by two terms in parentheses showing that when it is called it is handed 2 values (referred to as arg 0 and arg 1).

    Next is Max Stack 5. All the values that the instructions process are conveniently stacked in one place (called a stack). This tells the computer to make space for a stack of 5 objects.

    There are two variables listed next. In the instructions they are referred to as [0] and [1]. Next are the instructions. We only need to know 4 instruction codes: br, call, ld, and ret.

    The first instruction is: ld (load). It says to load a value(arg 0) on to the stack.

    The next instruction is: call ... CheckSerial(). Mainform_load() is calling a function (the parentheses show it's a function) to perform a specific task. The term bool before CheckSerial() specifies what type of value that it will hand back to MainForm_load when CheckSerial() finishes. Bool means it returns True or False (The Booleans are an alien race that don't have True and False; computer geeks love their Star Trek :p).

    So when MainForm_Load calls CheckSerial it wants to know if the result is 1 (True) or 0 (False). To find out why, look at the next instruction: brtrue.s L000f if the value is True, branch (or jump) to instruction L000f. There are 3 instructions between here and L000f: ldarg.0, call...Form.close, and ret. Looks like close the form, then return (to what started up MainForm_Load). To keep going we need to jump over those 3 instructions. That will happen if CheckSerial returns True. Let's make sure it returns True. :)
    storm shadow likes this.
  7. Rip Cord

    Administrator Staff Member Admin Developer

    In the MainForm_Load() code window, click on CheckSerial().
    The CheckSerial() code mentions the registry, something about a new object (SerialValidateGG), and something about a hash (math :p). Also, it looks like there are two possible endings to this function. L0042 and L005a both are ret (the instruction to return to MainForm_Load).

    ldc is a variation of the ld or load instruction. It means load a constant (a number) on to the stack so it's ready to be used. (i4 tells it how much space the number takes up in memory.)

    Before the ret at L0042, ldc.i4.0 loads the number 0 (False) and before the ret at L005a, ldc.i4.1 loads the number 1 (True). Which one it chooses depends on the other instructions in CheckSerial. So far we know it needs to return the value True for MainForm_Load to keep going. To see what happens we will have CheckSerial() jump over every instruction except load True and return.

    This can be done by adding a jump or branch instruction at the beginning and have it point to the load True instruction. We already did that when we chose br, instruction reference, and ->(33)ldc.i4.1 in a previous post.
  8. Rip Cord

    Administrator Staff Member Admin Developer

    To have the patched code displayed in the code window, click close assembly (in the file menu) and open the patched version that was saved in the post above.
  9. storm shadow

    Techbliss Owner Admin Ida Pro Expert Developer

    Im learning :rolleyes: , Rip Cord, i had givin up on Net since there where no easy reversing tuts out there.
    My hope is restored.Thx for the tuts m8 keep them comming
    Rip Cord likes this.
  10. Rip Cord

    Administrator Staff Member Admin Developer

    So far, we patched CheckSerial to jump over most of it's instructions and go straight to load 1 (True) and return to MainForm_Load, and the patched version of the program is opened in Reflector.

    After the program returns to MainForm_Load it starts with the next instruction after the call to CheckSerial:
    L_0006: brtrue.s L_00f
    Since CheckSerial has just handed the value 1 (True) to MainForm_Load brtrue.s (branch if true) will jump to instruction L_000f.
    In this next area a few items are loaded (ld) on the stack and there are some statements about menus and InsertMenu. "ldstr" is load a string (a group of characters strung together, like a word or sentence) on the stack. If you played around with the interface when it appeared on the screen, you might have noticed that when the title bar at the top is right-clicked, a menu appears. One of the entries was About... I guess this section causes that entry to be inserted in the menu.

    The next instruction "pop" is code for pop off, meaning pop the most recent value off the stack and throw it away. The last value placed on the stack was whatever bool InsertMenu returned(1 or 0). MainForm_Load doesn't use that value.

    The next interesting instruction is the call to bool....CheckForVersion(). After it returns from CheckForVersion(), there is brtrue.s L_004f (branch to instruction L_004f if True). This causes the computer to skip over the return instruction (at L_oo4c) and keep going if MainForm_load is handed the value True. We might want to make sure CheckForVersion returns True.

    (BTW, the s in brtrue.s means short version, since it's only a short hop; also we're going to ignore ldarg.0 many times cause we don't need to know about it to patch the program.)
    storm shadow likes this.
  11. Gh0st

    Australia's finest since 1981 Admin

    • Gh0st
    • Feb 5, 2013
    • 197
    • 219
    Nice one!!!
    Rip Cord and storm shadow like this.
  12. Rip Cord

    Administrator Staff Member Admin Developer

    Click on CheckforVersion() in instruction L_0047.
    Hmmm, the variables contain the words webclient and upgradedownloader.
    They are also in the instructions along with a web address that includes [​IMG] Looks like it's checking online for an upgrade. Also, remember the web address in the pdf (for downloading the software) contains "Setup/Setup.exe."

    5 occurrences of return
    after load false (ldc.i4.0, load constant 0(size i4) equals False) at L_0071, L_0086, L_00ce
    after load true (ldc.i4.1, load constant 1(size i4) equals True) at L_00b7, L_00d0

    branches to jump over sections of code (including different ret instructions)
    L_0053: ble (branch if less than or equal)
    L_0068: bne (branch if not equal)
    L_0090: bne
    L_009b: ble
    L_00b4: bne

    It's getting the current version number from an online text file and comparing it to the version of the program. If there is a higher version it calls UpgradeDownloader (not hard to guess what that does). If this version of the program (with checkserial patched) is started on a pc with online connection, the following dialog appears.
    upgrade.png Click no.
    Create a new instruction at the beginning to jump to the ldc.i4.1 (load True) instruction right before the final return.
    chfvnewinstruction.png chvnewcode.png
    Save the changes. With pc offline run the just patched exe.
    Startingup.png Behind that is a smaller popup. Erroroccurred.png Click ok.
    Doesn't look like progress, but it is.

    BTW, notice in the Reflexil window there are line numbers at the beginning of each line and then the offset number of the instruction. In the new line that's added it uses the line number to refer to the branch destination (85) ldc.i4.1; this will be changed to the offset number (like what can be seen in the branch instructions in the upper right window)by Reflexil when it actually injects the code into the exe (when it's saved).
  13. Rip Cord

    Administrator Staff Member Admin Developer

    Phase 1 of 2

    There are several ways to determine the order that the function are executed.
    Right click the assembly name in the explorer pane and choose go to entrypoint.
    Then right click on the highlighted function and choose analyze and follow all the dependencies by doing the same right click, choose analyze, or by following the code in the code window.

    Another simple way is to add trace statements to all the interesting functions that will print out as the program executes.
    Instructions on how to add trace output in post #6 on this page:
    Or run the program in a debugger. Can use Deblector, a debugging plug-in for Reflector. A little information about it can be found in post #2 on this page: http://techbliss.org/threads/basic-tools-for-patching-net-applications.272/

    Or use a full featured debugger such as visual studio. Discussed on this page:
  14. Rip Cord

    Administrator Staff Member Admin Developer

    MainForm_load() right after the call to (and return from) CheckforVersion().
    Since CheckforVersion returns true, the branch if true at 004c will jump over 004e ret, going straight to 004f.
    The next new object GameListDownloader .ctor()calls the function GameListDownLoader InitializeComponent(). Together they have the instructions for the objects related to downloading the gamelist.
    gldl_ctor.png gldl_ic.png
    In InitializeComponent() can be seen one of the messages shown in a popup "Please wait while the game list being downloaded.." (their typo) The game list is the list of games that have cheats. There is nothing of interest until near the end of GameListDownloader .ctor when GameListDownloader_Load is finally called.
    In GameListDosnloader_Load there is alot of code dealing with RSS channels and a web address for downloading RSS information in xml format, RSS.xml. This file is included in the download linked to in the first post (it can be obtained from anyone with a the device). Instead of downloading the RSS form, the patched program will load it from a file on the local hdd. All that needs to be changed is L_0018. With the file name already substituted for the url:
    In the reflexil code window highlight the instruction at line 07 (offset 18), right-click and choose edit. Type C:\genie\RSS.xml in the operand box to replace the web address.
    Click update. Then save the changes. Start the patched exe (pc offline).
    The top section is functioning hypertext which will display the content in the lower pane. Click ok.
    4Startingup.png Behind that is 5Erroroccurred.png Click ok.
    BTW, I tried all the acceptable syntax variations for file:// type of url and this is the only thing that worked.
    storm shadow likes this.
  15. Rip Cord

    Administrator Staff Member Admin Developer

    Right click GameListDownloader_Load in the explorer pane and choose analyze. In the analyzer window expand the tree, expand Depends On, expand GGSEPS3. Everything that GameListdownloader_Load depends on is RSS related except for one item, GetOnlineGamesList(). We fixed the RSS part, now to fix GetOnlineGamesList().
    Click on GetOnlineGamesList() in the code window or the explorer pane. First, several instructions related to web requests and a game list url.
    Then web response, creating a temp file, and writing to it.
    L_0147 call string ... GetTempFileName() calls system service to create a temp file and returns the name of the file as a string.
    L_014c stloc.s str2 stloc store in location, stores a value in location 6, that's variable number [6] in the list of variables at the top of the function which is str2 (Reflector has uses descriptive names for the variable numbers).

    Unzipping the file, storing the results as GameListXml(string), and deleting the files.
    L_01ca ldloc.s str2 this loads the value of str2 (variable [6]) on to the stack to be used by the next instruction, the zip utility.
    Clean up and error handling
  16. Rip Cord

    Administrator Staff Member Admin Developer

    We will use a branch statement to skip over all the web related instructions to right before invocation of the zip utility and insert an instruction to have a zip file located on the local hdd as input to the zip utility. Also insert a branch instruction to jump over the closing of the web response and the file deletion.
    Between L_0216 and L_0221 add br to instruction L_0243 ldnull
    Between L_01ca change ldloc.s str2 to ldstr "C:/Genie/Gameslist.zip"
    At the very beginning add branch to C:/Genie/Gameslist.zip
    (Edited in reverse order so I don't have to keep track of the shifting line numbers in the Relexil window.)
    Save the changes. gogl_changes1.png gogl_changes2.png gogl_changes3.png
    Place the file Gameslist.zip (included in the download in the first post and available from anyone with the device) in C:\Genie.
    Start the patched version.
    Click ok on the RSS form.
    The main interface with list of games and cheats. Double clicking on a game will display the list of cheats for that game.
  17. Rip Cord

    Administrator Staff Member Admin Developer

    Added a little information on determining the order that the instructions or functions are executed to post #13 above. Can also be used to find the location where a program crashes.

    Added couple of screenshots of the modified code to post #16.
    storm shadow likes this.
  18. Rip Cord

    Administrator Staff Member Admin Developer

    Attached the debug log of the fully patched exe. It is the trace ouput messages, basically a list of all the functions in order of execution.

    Attached Files:

  19. Rip Cord

    Administrator Staff Member Admin Developer

    If you plug in a usb stick with ps3 game save with correct folder structure (ex: PS3\SaveData\BLUS30127SGTA404), the game will be listed (uncheck show all box). Double click game name and right click save gives menu. Simple Mode will load, check boxes for applying cheats function, but errors out on applying changes. Advanced mode editor errors out trying to load, but it's easy to fix.
    storm shadow likes this.
  20. Rip Cord

    Administrator Staff Member Admin Developer

    Using the program process monitor to display information when any files are accessed, can find out what is happening with the save files in Quick Mode. A usb drive with ps3 game save is inserted, process monitor started, save editor started, double click a game title in the list of games from the usb drive. Right click one of the saves and choose Quick Mode...

    output from process monitor:

    Looking at the game files on the usb drive.

    check one of the cheat boxes, choose a profile, and click apply
    click yes
    and then
    output from process monitor:

    C:\Documents and Settings\Rip Cord\Local Settings\Temp\ps3_files_list.xml
    C:\Documents and Settings\Rip Cord\Local Settings\Temp\tmp100.tmp
    C:\Documents and Settings\Rip Cord\Local Settings\Temp\tmp101.tmp
    C:\Documents and Settings\Rip Cord\My Documents\Game Genie\PS3 Saves Backup\BLUS30127SGTA404_2013-04-01 15-02-30.bak

    The output displayed by process monitor includes a lot more details showing that the save editor created the ps3_files_list.xml file in a temporary directory. Created a temporary file which is a zip file including the 3 save files (Rage.sav, Param.pfd, Param.sfo) unaltered and the ps3_files_list.xml (containing a list of the save files and the cheat to be applied). Also, created another temporary file (a zip file containing a back up of the original save files) and it is moved to the back up directory and renamed with a .bak extension.

    For Quick Mode the editor only zips up the save files and a list of the desired cheats. This is uploaded to the game genie servers where the save is decrypted, the cheats are applied, it's re-encrypted, and downloaded to the usb drive.

    Process Monitor is very useful freeware, lots more information than shown here.
    storm shadow likes this.