[ Hey guys. I wanna start a new series of tutorials for reversing
the S4 League Game Client since it is very easy. ]
To get started we need a few things set-up:
[0. x86 (intel syntax) asm knowledge and the ability to think logically]
1. Disassembler (I prefer IDA Pro 6.9 with Hex-Rays plugin)
2. Struct Analyzing tool (ReClass 2015 or Cheat Engine)
3. Executable Dumper (Scylla)
4. Fundamental IDA Pro plugins (Class Informer and String Associate Plugin)
5. C++ knowledge for better understanding of the compiler
After that let's first get a fresh dump of the client. Start up the game with a bypass and dump it with scylla once you are in the lobby to make sure everything is initialized. In this episode we are only applying static analysis so we can close the client again and drag the dumped file into ida pro; it will start to analyze the binary which can take about 5-10 minutes with an average pc. You will notice that the IAT and EAT is broken. Of course it'd be better if it wasn't but we don't need it in this episode. Since I have no point to start reversing we will just use strings.
I found an interesting format string that could give us alot of information:
This string will get us to know the following points:
The most useful thing in here is the class ptr. If you got the instance you can reverse it at runtime(ingame) and find really much stuff out.
Let's now reverse some code by going to the cross-reference of the string.
We can immediately identify the calling convention by looking after the call instruction. The stack is cleaned by the caller. Thus it's __cdecl.
(https://en.wikipedia.org/wiki/X86_calling_conventions)
We can also count the arguments that were passed to this function by dividing 48h with 4 and then convert it to decimal. [ATTENTION: for optimization some compilers only use one add instruction and you cant really see if its only cleaning up one call or few)
Now let's continue with finding out what actually is passed to our function.
The first argument is eax which is &var_A0. Sooo find out what var_A0 is:
Scroll up and lookup an instruction that involves var_A0 as operand.
Nothing is being moved(copied) in var_A0 so it's just used as a reference or pointer to fill some value in it(buffer). Second argument is the format string...
Third argument seems to be a string which is passed in edx, whereas edx is var_60. Let's dig deeper.
here's where var_60 is being set. var_10 is probably some player class or actor class. then the address of the virtual table get's copied into eax and it's calling the 53th virtual function of this class (0D4h / 4 to decimal)[basic index calculating]. This function can be compared to
. The result of this function gets tested and if it returned true the string which gets copied into var_60 is "Alive" and otherwise "Death".
Wow this took longer to explain than I expected. We will continue this shxt in the next episode. cya.
the S4 League Game Client since it is very easy. ]
To get started we need a few things set-up:
[0. x86 (intel syntax) asm knowledge and the ability to think logically]
1. Disassembler (I prefer IDA Pro 6.9 with Hex-Rays plugin)
2. Struct Analyzing tool (ReClass 2015 or Cheat Engine)
3. Executable Dumper (Scylla)
4. Fundamental IDA Pro plugins (Class Informer and String Associate Plugin)
5. C++ knowledge for better understanding of the compiler
After that let's first get a fresh dump of the client. Start up the game with a bypass and dump it with scylla once you are in the lobby to make sure everything is initialized. In this episode we are only applying static analysis so we can close the client again and drag the dumped file into ida pro; it will start to analyze the binary which can take about 5-10 minutes with an average pc. You will notice that the IAT and EAT is broken. Of course it'd be better if it wasn't but we don't need it in this episode. Since I have no point to start reversing we will just use strings.
I found an interesting format string that could give us alot of information:
PHP Code:
.text:01A2A3B8 0000006E C %s [%s Actor %p] TeamID: %I64d, ActorID: %I64u, P2PID:{%d,%d,%d}, StateID: 0x%X, 0x%x, HP: %d(%d), MP: %d(%d)
- Live status (dead or alive)
- Spectator or Player
- Class ptr
- TeamID
- ActorID
- P2PID
- StateID
- HP
- MP
The most useful thing in here is the class ptr. If you got the instance you can reverse it at runtime(ingame) and find really much stuff out.
Let's now reverse some code by going to the cross-reference of the string.
PHP Code:
.text:00AF7B77 mov eax, [ebp+var_10]
.text:00AF7B7A push eax
.text:00AF7B7B mov ecx, [ebp+var_64]
.text:00AF7B7E push ecx
.text:00AF7B7F mov edx, [ebp+var_60]
.text:00AF7B82 push edx
.text:00AF7B83 push offset aSSActorPTeamid ; "%s [%s Actor %p] TeamID: %I64d, ActorID"...
.text:00AF7B88 lea eax, [ebp+var_A0]
.text:00AF7B8E push eax
.text:00AF7B8F call sub_168B4C0
.text:00AF7B94 add esp, 48h
(https://en.wikipedia.org/wiki/X86_calling_conventions)
We can also count the arguments that were passed to this function by dividing 48h with 4 and then convert it to decimal. [ATTENTION: for optimization some compilers only use one add instruction and you cant really see if its only cleaning up one call or few)
Now let's continue with finding out what actually is passed to our function.
The first argument is eax which is &var_A0. Sooo find out what var_A0 is:
Scroll up and lookup an instruction that involves var_A0 as operand.
Nothing is being moved(copied) in var_A0 so it's just used as a reference or pointer to fill some value in it(buffer). Second argument is the format string...
Third argument seems to be a string which is passed in edx, whereas edx is var_60. Let's dig deeper.
PHP Code:
.text:00AF7A40 loc_AF7A40: ; CODE XREF: sub_AF78A0+197j
.text:00AF7A40 mov edx, [ebp+var_10]
.text:00AF7A43 mov eax, [edx]
.text:00AF7A45 mov ecx, [ebp+var_10]
.text:00AF7A48 mov edx, [eax+0D4h]
.text:00AF7A4E call edx
.text:00AF7A50 movzx eax, al
.text:00AF7A53 test eax, eax
.text:00AF7A55 jz short loc_AF7A60
.text:00AF7A57 mov [ebp+var_60], offset aLive ; "Live"
.text:00AF7A5E jmp short loc_AF7A67
.text:00AF7A60 ; ---------------------------------------------------------------------------
.text:00AF7A60
.text:00AF7A60 loc_AF7A60: ; CODE XREF: sub_AF78A0+1B5j
.text:00AF7A60 mov [ebp+var_60], offset aDeath ; "Death"
PHP Code:
virtual bool IsAlive() = 0;
Wow this took longer to explain than I expected. We will continue this shxt in the next episode. cya.