You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
5.1 KiB

# godtier-patcher
## Preamble
Recently I got sent a R6 Cheat, with the wish of getting it "cracked". When I saw that it was an unpacked console app, I decided to accept the challenge and now I'm posting this write-up to help upcoming reverse engineers and to help software developers protect their code. I only ran this cheat inside of my Virtual Machine, its not malicious, but if you run it its under your own risk.
__You can download this release [HERE](https://githacks.org/VollRahm/godtier-r6-patcher/-/tags/1.0.0)__. I would really appreciate it if you read along though.
## Step 0: Identification
As I already said, it is a native x64 console application that has not been packed. I started it, and it asks you for a client id and password. Upon entering wrong information, the app prints our an error message and closes after a short amount of time. The first thing I obviously did was to throw it into IDA and have a look at the strings.
I did not find the string that gets written when the authentication fails, which means, that they we're encrypted.
These are some interesting strings I found:
![](https://i.imgur.com/RUYRhAn.png)
Looks like a kernel communication using function hooking.
![](https://i.imgur.com/iPWUn0p.png)
Uses something made by [xerox](https://githacks.org/xerox/)
![](https://i.imgur.com/WOcN8ZN.png)
I'm unsure about this, but I think that means, that the driver was embedded directly into the source code.
![](https://i.imgur.com/tr1Zj7O.png)
They use auth.gg as backend.
## Step 1: Checking out the xrefs
A really interesting string was `Please press F1 when in menu...` which lead me right to this function:
![](https://i.imgur.com/6MaSfeK.png)
I renamed the function to `StartCheat`. I reversed `LoadKernelDriver` by finding the `GetProcAddress` call containing the string `NtLoadDriver` and then I just took a look at the cross references until I eventually ended up in `StartCheat` again. `GetProcessByName` was pretty obvious.
Now we already know which function we need to call in order for the cheat to start! Great! I will come back to that later.
## Step 2: Taking a look at main()
After finding `StartCheat`, I found, that it was getting called in `main`. But before continuing on my actual goal, I took a look around too see, what happens in `main`. One of the things I noticed right away was the string encryption:
![](https://i.imgur.com/5abVrBm.png)
This is the start of `main`:
![](https://i.imgur.com/ghyXApJ.png)
I found `DoHttpRequests` by going back to the URL string and checking out the xrefs. It gets called right at the start of `main`. It contained a call to `WinHttpOpen`, so I guessed that somewhere deeper in the code there should obviously be a call to `WinHttpSendRequest`.
By getting the xrefs to it, I found the exact place and debugged it, to see, what is requested.
![](https://i.imgur.com/v12CQ5L.png)
![](https://i.imgur.com/PtP8GNk.png)
My guess it, that the first request gets a token of some kind that is needed for the second request, that probably gets some variables, like offsets from the auth.gg API.
I didn't bother about reversing it further, so I went back to my original goal.
## Step 3: Finding the right place to patch
In Step 1 I found `StartCheat` and that it gets called at the very end of `main` after the user has put in the login credentials.
![](https://i.imgur.com/UBcudYK.png)
An assumption I made is that the return value of the function inside of the `if` condition is the success of the login process. By going into the debugger and setting a breakpoint there, I saw, that the code reached this line, but after calling the function the Program just exited.
Inside of this function, there was a reference to the auth.gg URL string and I found 4 calls to `exit()` that came right after a 2 second `sleep`. Exactly the behavior I explained in Step 0. Essentially this it the authenticate function. This simply means, that we have to patch out the call completely, because the function itself exits when the credentials are wrong. I could have gone further and reversed the exact conditional jump that needs to be patched, but I had already reached my goal.
The call consist of 4 bytes and it is expected to return a single byte.
We can simple NOP those 4 bytes located at `godtier.exe + 0x4A49`, then the function won't be called and the `al` register, which should contain the return value, already has a value, which means, that the expression evaluates to `TRUE`.
## Step 4: Wrapping things up
I could have now simply byte patched the binary file and called it a day, but I decided to write a program that patches it, just for fun. The source code of this App is in this repository.
It was a pretty fun experience and I hope you had fun reading.
I'm probably not the right person to give tips like this, but this application could have been better protected if it:
- was packed
- all strings we're encrypted
- The variables from the API get pulled AFTER a successful login
![enter image description here](https://i.imgur.com/Gxt9e83.png)
Here is a video that proves the concept, that someone who tested it sent me: [https://streamable.com/fyxiai](https://streamable.com/fyxiai)