Reverse engineering of R6 Cheat.
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.
VollRahm 0cc865ee56
2 years ago
patcher-source - Uploaded Source 2 years ago
.gitignore Added gitignore 2 years ago Update 2 years ago



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. 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:

Looks like a kernel communication using function hooking.

Uses something made by xerox

I'm unsure about this, but I think that means, that the driver was embedded directly into the source code.

They use 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:

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:

This is the start of main:

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.

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 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.

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 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

Here is a video that proves the concept, that someone who tested it sent me: