📜 ⬆️ ⬇️

Reverse engineering and game patch on Unity3d

The article is aimed at an audience that does not have any experience. It does not contain a description of any hacking and "bad" patches.

Foreword


Once I got into the hands of the game Unturned, built on the Unity3d engine. Later it turned out that it is not without flaws. It is in the alpha version, so the server does not even notify players about the killing of another character, which was not convenient in PvP battles. Before this incident, I had no experience with cil and reverse engineering c # applications, especially Unity.

The software that we need




We open the program


The code that may be of interest to us is in the Assembly-CSharp.dll file.
Without hesitation, open it at dotPeek and see something like this:
')
image

We try to decompile all the code, load the project into the studio and get a bunch of errors. Visual Studio was unable to properly handle a bunch of variables with a name of 1 UTF-8 character.

Okay, let's try another way: open ildasm and load our file into it, press dump and save to a convenient place. We got a bunch of CIL code. CIL code is like an assembler for .NET, but much easier.

Now you need to try to compile it back into the dll, otherwise further actions will be in vain.

Open the console and write:

ilasm /DLL < /.cil>

Hooray! Happened. Now we can change the code and compile it back.
We go in dotPeek and write die in search, we find some Life :: die (), we look at the code and we understand that this is not the same.
Okay, right click on die, Usages of Symbol, and go to some Life :: damage ()
As an argument, this function takes a string, click Usages of Symbol and go, for example, to shootPlayer (), look at the code:

string[] strArray = new string[7];
int index1 = 0;
string str2 = "You were shot in the ";
strArray[index1] = str2;
int index2 = 1;
string str3 = str1;
strArray[index2] = str3;
int index3 = 2;
string str4 = " with the ";
strArray[index3] = str4;
int index4 = 3;
string name = ItemName.getName(this.GetComponent().\u0014);
strArray[index4] = name;

int index5 = 4;
string str5 = " by ";
strArray[index5] = str5;
int index6 = 5;
string str6 = this.GetComponent().\u0841.\u0887;
strArray[index6] = str6;

int index7 = 6;
string str7 = "!";
strArray[index7] = str7;
string str8 = string.Concat(strArray);
component.damage(num2, str8);

, " DEAD ( 2)".
, shootPlayer():

NetworkTools.kick(this.networkView.owner, "Kicking " + this.name + " for cheating their ammo.");

cil:

IL_002f: ldstr "Kicking "
IL_0034: ldarg.0
IL_0035: call instance string [UnityEngine]UnityEngine.Object::get_name()
IL_003a: ldstr " for cheating their ammo."
IL_003f: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0044: call void NetworkTools::kick(valuetype [UnityEngine]UnityEngine.NetworkPlayer,
string)

.
cil "connceted."", :

call void NetworkChat::sendAlert(string)


Life::damage() CIL.
die :

ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //

ilasm, , , , .... 3 , 1- 2 .
damage() 1.
:

ldarg.1 // 1 ( )
ldc.i4.s 1 // 1
ble.s IL_0061 // IL_0061
ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //
IL_0061:


CIL .

string name = ItemName.getName(this.GetComponent().\u0014);
strArray[index4] = name;

int index5 = 4;
string str5 = " by ";
strArray[index5] = str5;
int index6 = 5;
string str6 = this.GetComponent().\u0841.\u0887;
strArray[index6] = str6;

int index7 = 6;
string str7 = "!";
strArray[index7] = str7;
string str8 = string.Concat(strArray);
component.damage(num2, str8);

, " DEAD ( 2)".
, shootPlayer():

NetworkTools.kick(this.networkView.owner, "Kicking " + this.name + " for cheating their ammo.");

cil:

IL_002f: ldstr "Kicking "
IL_0034: ldarg.0
IL_0035: call instance string [UnityEngine]UnityEngine.Object::get_name()
IL_003a: ldstr " for cheating their ammo."
IL_003f: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0044: call void NetworkTools::kick(valuetype [UnityEngine]UnityEngine.NetworkPlayer,
string)

.
cil "connceted."", :

call void NetworkChat::sendAlert(string)


Life::damage() CIL.
die :

ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //

ilasm, , , , .... 3 , 1- 2 .
damage() 1.
:

ldarg.1 // 1 ( )
ldc.i4.s 1 // 1
ble.s IL_0061 // IL_0061
ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //
IL_0061:


CIL .

string name = ItemName.getName(this.GetComponent().\u0014);
strArray[index4] = name;

int index5 = 4;
string str5 = " by ";
strArray[index5] = str5;
int index6 = 5;
string str6 = this.GetComponent().\u0841.\u0887;
strArray[index6] = str6;

int index7 = 6;
string str7 = "!";
strArray[index7] = str7;
string str8 = string.Concat(strArray);
component.damage(num2, str8);

, " DEAD ( 2)".
, shootPlayer():

NetworkTools.kick(this.networkView.owner, "Kicking " + this.name + " for cheating their ammo.");

cil:

IL_002f: ldstr "Kicking "
IL_0034: ldarg.0
IL_0035: call instance string [UnityEngine]UnityEngine.Object::get_name()
IL_003a: ldstr " for cheating their ammo."
IL_003f: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0044: call void NetworkTools::kick(valuetype [UnityEngine]UnityEngine.NetworkPlayer,
string)

.
cil "connceted."", :

call void NetworkChat::sendAlert(string)


Life::damage() CIL.
die :

ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //

ilasm, , , , .... 3 , 1- 2 .
damage() 1.
:

ldarg.1 // 1 ( )
ldc.i4.s 1 // 1
ble.s IL_0061 // IL_0061
ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //
IL_0061:


CIL .

string name = ItemName.getName(this.GetComponent().\u0014);
strArray[index4] = name;

int index5 = 4;
string str5 = " by ";
strArray[index5] = str5;
int index6 = 5;
string str6 = this.GetComponent().\u0841.\u0887;
strArray[index6] = str6;

int index7 = 6;
string str7 = "!";
strArray[index7] = str7;
string str8 = string.Concat(strArray);
component.damage(num2, str8);

, " DEAD ( 2)".
, shootPlayer():

NetworkTools.kick(this.networkView.owner, "Kicking " + this.name + " for cheating their ammo.");

cil:

IL_002f: ldstr "Kicking "
IL_0034: ldarg.0
IL_0035: call instance string [UnityEngine]UnityEngine.Object::get_name()
IL_003a: ldstr " for cheating their ammo."
IL_003f: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0044: call void NetworkTools::kick(valuetype [UnityEngine]UnityEngine.NetworkPlayer,
string)

.
cil "connceted."", :

call void NetworkChat::sendAlert(string)


Life::damage() CIL.
die :

ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //

ilasm, , , , .... 3 , 1- 2 .
damage() 1.
:

ldarg.1 // 1 ( )
ldc.i4.s 1 // 1
ble.s IL_0061 // IL_0061
ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //
IL_0061:


CIL .

string name = ItemName.getName(this.GetComponent().\u0014);
strArray[index4] = name;

int index5 = 4;
string str5 = " by ";
strArray[index5] = str5;
int index6 = 5;
string str6 = this.GetComponent().\u0841.\u0887;
strArray[index6] = str6;

int index7 = 6;
string str7 = "!";
strArray[index7] = str7;
string str8 = string.Concat(strArray);
component.damage(num2, str8);

, " DEAD ( 2)".
, shootPlayer():

NetworkTools.kick(this.networkView.owner, "Kicking " + this.name + " for cheating their ammo.");

cil:

IL_002f: ldstr "Kicking "
IL_0034: ldarg.0
IL_0035: call instance string [UnityEngine]UnityEngine.Object::get_name()
IL_003a: ldstr " for cheating their ammo."
IL_003f: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0044: call void NetworkTools::kick(valuetype [UnityEngine]UnityEngine.NetworkPlayer,
string)

.
cil "connceted."", :

call void NetworkChat::sendAlert(string)


Life::damage() CIL.
die :

ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //

ilasm, , , , .... 3 , 1- 2 .
damage() 1.
:

ldarg.1 // 1 ( )
ldc.i4.s 1 // 1
ble.s IL_0061 // IL_0061
ldarg.0 // 0
call instance string [UnityEngine]UnityEngine.Object::get_name() // ( )
ldstr " DEAD (" //
ldarg.2 // 2 ( )
ldstr ")" //
call string [mscorlib]System.String::Concat(string, //
string,
string,
string)
call void NetworkChat::sendAlert(string) //
IL_0061:


CIL .

Source: https://habr.com/ru/post/234101/


All Articles