I'm trying to learn how to hack a game, and i just wanted to start by adding some functionality. I found a likely function and wanted to add a bit of code before the main execution, but the game reports invalid IL when running. I don't understand what's wrong though.
The original decompiled code was like this:
public void InitializeAfterInventory()
{
if ((this.thisCharacterInstance.spawn_type == SpawnType.SpawnType_Avatar) && (this.inventory.curDeck != null))
{
ItemDef def = this.inventory.curDeck.def;
base.baseAttributes.armor = def.decking_hardening;
base.baseAttributes.body = def.decking_body;
base.baseSkills.dodge = def.decking_evasion;
base.baseAttributes.ap = def.decking_max_ap;
base.baseAttributes.hp = def.decking_max_ip;
base.SetHP(this.inventory.curDeck.CurrentHealth);
base.SetAP(base.baseAttributes.ap);
base.SetRP(StatsUtil.GetMaxArmor(this));
this.inventory.InitializeAvatarItems(def.decking_default_weapon);
}
if ((this.thisCharacterInstance.spawn_type == SpawnType.SpawnType_Avatar) && (this.inventory.curDeck == null))
{
Logger.LogError(LogChannel.PLYR, base.name + " is of type avatar, but has no deck. Stats unchanged");
}
}
with this IL:
Offset OpCode Operand
0 ldarg.0
1 ldfld isogame.CharacterInstance Player::thisCharacterInstance
6 callvirt isogame.SpawnType isogame.CharacterInstance::get_spawn_type()
11 ldc.i4.2
12 bne.un -> (60) ldarg.0
17 ldarg.0
18 ldfld PlayerInventory Player::inventory
23 ldfld Item PlayerInventory::curDeck
28 brfalse -> (60) ldarg.0
33 ldarg.0
34 ldfld PlayerInventory Player::inventory
39 ldfld Item PlayerInventory::curDeck
44 ldfld isogame.ItemDef Item::def
49 stloc.0
50 ldarg.0
51 ldfld isogame.Attributes Actor::baseAttributes
56 ldloc.0
57 callvirt System.Int32 isogame.ItemDef::get_decking_hardening()
62 callvirt System.Void isogame.Attributes::set_armor(System.Int32)
67 ldarg.0
68 ldfld isogame.Attributes Actor::baseAttributes
73 ldloc.0
74 callvirt System.Int32 isogame.ItemDef::get_decking_body()
79 callvirt System.Void isogame.Attributes::set_body(System.Int32)
84 ldarg.0
85 ldfld isogame.Skills Actor::baseSkills
90 ldloc.0
91 callvirt System.Int32 isogame.ItemDef::get_decking_evasion()
96 callvirt System.Void isogame.Skills::set_dodge(System.Int32)
101 ldarg.0
102 ldfld isogame.Attributes Actor::baseAttributes
107 ldloc.0
108 callvirt System.Int32 isogame.ItemDef::get_decking_max_ap()
113 callvirt System.Void isogame.Attributes::set_ap(System.Int32)
118 ldarg.0
119 ldfld isogame.Attributes Actor::baseAttributes
124 ldloc.0
125 callvirt System.Int32 isogame.ItemDef::get_decking_max_ip()
130 callvirt System.Void isogame.Attributes::set_hp(System.Int32)
135 ldarg.0
136 ldarg.0
137 ldfld PlayerInventory Player::inventory
142 ldfld Item PlayerInventory::curDeck
147 callvirt System.Int32 Item::get_CurrentHealth()
152 call System.Void Actor::SetHP(System.Int32)
157 ldarg.0
158 ldarg.0
159 ldfld isogame.Attributes Actor::baseAttributes
164 callvirt System.Int32 isogame.Attributes::get_ap()
169 call System.Void Actor::SetAP(System.Int32)
174 ldarg.0
175 ldarg.0
176 call System.Int32 StatsUtil::GetMaxArmor(Actor)
181 call System.Void Actor::SetRP(System.Int32)
186 ldarg.0
187 ldfld PlayerInventory Player::inventory
192 ldloc.0
193 callvirt System.String isogame.ItemDef::get_decking_default_weapon()
198 callvirt System.Boolean PlayerInventory::InitializeAvatarItems(System.String)
203 pop
204 ldarg.0
205 ldfld isogame.CharacterInstance Player::thisCharacterInstance
210 callvirt isogame.SpawnType isogame.CharacterInstance::get_spawn_type()
215 ldc.i4.2
216 bne.un -> (75) ret
221 ldarg.0
222 ldfld PlayerInventory Player::inventory
227 ldfld Item PlayerInventory::curDeck
232 brtrue -> (75) ret
237 ldsfld LogChannel LogChannel::PLYR
242 ldarg.0
243 call System.String UnityEngine.Object::get_name()
248 ldstr is of type avatar, but has no deck. Stats unchanged
253 call System.String System.String::Concat(System.String,System.String)
258 call System.Void Logger::LogError(LogChannel,System.String)
263 ret
while my edit is this:
public void InitializeAfterInventory()
{
// This item is obfuscated and can not be translated.
Item tempDataJack = PlayerInventory.GetTempDataJack(this);
if (((this.inventory.curDeck == null) && (tempDataJack != null)) && (tempDataJack.def.decking_default_weapon != null))
{
this.inventory.curDeck = tempDataJack;
}
if ((this.thisCharacterInstance.spawn_type == SpawnType.SpawnType_Avatar) && (this.inventory.curDeck != null))
{
ItemDef def = this.inventory.curDeck.def;
base.baseAttributes.armor = def.decking_hardening;
base.baseAttributes.body = def.decking_body;
base.baseSkills.dodge = def.decking_evasion;
base.baseAttributes.ap = def.decking_max_ap;
base.baseAttributes.hp = def.decking_max_ip;
base.SetHP(this.inventory.curDeck.CurrentHealth);
base.SetAP(base.baseAttributes.ap);
base.SetRP(StatsUtil.GetMaxArmor(this));
this.inventory.InitializeAvatarItems(def.decking_default_weapon);
}
if ((this.thisCharacterInstance.spawn_type == SpawnType.SpawnType_Avatar) && (this.inventory.curDeck == null))
{
Logger.LogError(LogChannel.PLYR, base.name + " is of type avatar, but has no deck. Stats unchanged");
}
}
(notice the auto-inserted comment)
with this IL:
Offset OpCode Operand
0 ldarg.0
1 ldfld PlayerInventory Player::inventory
6 ldarg.0
7 callvirt Item PlayerInventory::GetTempDataJack(Player)
12 stloc.0
13 ldarg.0
14 ldfld PlayerInventory Player::inventory
19 ldfld Item PlayerInventory::curDeck
24 brtrue -> (19) ldarg.0
29 ldloc.0
30 brfalse -> (19) ldarg.0
35 ldloc.0
36 ldfld isogame.ItemDef Item::def
41 callvirt System.String isogame.ItemDef::get_decking_default_weapon()
46 brfalse -> (19) ldarg.0
51 ldarg.0
52 ldfld PlayerInventory Player::inventory
57 ldloc.0
58 stfld Item PlayerInventory::curDeck
63 ldarg.0
64 ldfld isogame.CharacterInstance Player::thisCharacterInstance
69 callvirt isogame.SpawnType isogame.CharacterInstance::get_spawn_type()
74 ldc.i4.2
75 bne.un -> (79) ldarg.0
80 ldarg.0
81 ldfld PlayerInventory Player::inventory
86 ldfld Item PlayerInventory::curDeck
91 brfalse -> (79) ldarg.0
96 ldarg.0
97 ldfld PlayerInventory Player::inventory
102 ldfld Item PlayerInventory::curDeck
107 ldfld isogame.ItemDef Item::def
112 stloc.1
113 ldarg.0
114 ldfld isogame.Attributes Actor::baseAttributes
119 ldloc.1
120 callvirt System.Int32 isogame.ItemDef::get_decking_hardening()
125 callvirt System.Void isogame.Attributes::set_armor(System.Int32)
130 ldarg.0
131 ldfld isogame.Attributes Actor::baseAttributes
136 ldloc.1
137 callvirt System.Int32 isogame.ItemDef::get_decking_body()
142 callvirt System.Void isogame.Attributes::set_body(System.Int32)
147 ldarg.0
148 ldfld isogame.Skills Actor::baseSkills
153 ldloc.1
154 callvirt System.Int32 isogame.ItemDef::get_decking_evasion()
159 callvirt System.Void isogame.Skills::set_dodge(System.Int32)
164 ldarg.0
165 ldfld isogame.Attributes Actor::baseAttributes
170 ldloc.1
171 callvirt System.Int32 isogame.ItemDef::get_decking_max_ap()
176 callvirt System.Void isogame.Attributes::set_ap(System.Int32)
181 ldarg.0
182 ldfld isogame.Attributes Actor::baseAttributes
187 ldloc.1
188 callvirt System.Int32 isogame.ItemDef::get_decking_max_ip()
193 callvirt System.Void isogame.Attributes::set_hp(System.Int32)
198 ldarg.0
199 ldarg.0
200 ldfld PlayerInventory Player::inventory
205 ldfld Item PlayerInventory::curDeck
210 callvirt System.Int32 Item::get_CurrentHealth()
215 call System.Void Actor::SetHP(System.Int32)
220 ldarg.0
221 ldarg.0
222 ldfld isogame.Attributes Actor::baseAttributes
227 callvirt System.Int32 isogame.Attributes::get_ap()
232 call System.Void Actor::SetAP(System.Int32)
237 ldarg.0
238 ldarg.0
239 call System.Int32 StatsUtil::GetMaxArmor(Actor)
244 call System.Void Actor::SetRP(System.Int32)
249 ldarg.0
250 ldfld PlayerInventory Player::inventory
255 ldloc.1
256 callvirt System.String isogame.ItemDef::get_decking_default_weapon()
261 callvirt System.Boolean PlayerInventory::InitializeAvatarItems(System.String)
266 pop
267 ldarg.0
268 ldfld isogame.CharacterInstance Player::thisCharacterInstance
273 callvirt isogame.SpawnType isogame.CharacterInstance::get_spawn_type()
278 ldc.i4.2
279 bne.un -> (94) ret
284 ldarg.0
285 ldfld PlayerInventory Player::inventory
290 ldfld Item PlayerInventory::curDeck
295 brtrue -> (94) ret
300 ldsfld LogChannel LogChannel::PLYR
305 ldarg.0
306 call System.String UnityEngine.Object::get_name()
311 ldstr is of type avatar, but has no deck. Stats unchanged
316 call System.String System.String::Concat(System.String,System.String)
321 call System.Void Logger::LogError(LogChannel,System.String)
326 ret
I also added a variable of type 'Item' at index 0 on the 'Variables' tab of the Reflexil menu for the method (to join the other of type ItemDef'), that was the only way that it wouldn't crash right away when trying to display the code. I don't understand what's wrong, the game always shows:
[...]
ERROR -1 * PlayerInventory.EquipAvailableFromBackpack ()
ERROR -1 EXCEPTION: InvalidProgramException: Invalid IL code in Player:InitializeAfterInventory (): IL_0146: ret
in the log
edit: requested output of linux mono version peverify errors, original:
Shadowrun Dragonfall/Shadowrun Dragonfall/Dragonfall_Data/Managed$ peverify Assembly-CSharp\ \(ORIGINAL\).dll
Missing method .ctor in assembly /home/i30817/Desktop/Shadowrun Dragonfall/Shadowrun Dragonfall/Dragonfall_Data/Managed/Assembly-CSharp (ORIGINAL).dll, type System.Runtime.CompilerServices.ExtensionAttribute
Error: Invalid CustomAttribute content row 1 Value field 0x00003c18
Error: CustomAttribute: Invalid constructor
Error count: 2
(original works fine in game) edited:
Shadowrun Dragonfall/Dragonfall_Data/Managed$ peverify Assembly-CSharp.dll
Missing method .ctor in assembly /home/i30817/Desktop/Shadowrun Dragonfall/Shadowrun Dragonfall/Dragonfall_Data/Managed/Assembly-CSharp.dll, type System.Runtime.CompilerServices.ExtensionAttribute
Error: Invalid CustomAttribute content row 1 Value field 0x00000048
Error: CustomAttribute: Invalid constructor
Error count: 2
edit 2: this is the CIL of the method output from monodis (slightly different because i redid the edit, but the same error and structure):
// method line 5554
.method public hidebysig
instance default void InitializeAfterInventory () cil managed
{
// Method begins at RVA 0xa4de0
// Code size 312 (0x138)
.maxstack 4
.locals init (
class [ShadowrunDTO]isogame.ItemDef V_0,
class Item V_1)
IL_0000: ldarg.0
IL_0001: ldfld class PlayerInventory Player::inventory
IL_0006: ldarg.0
IL_0007: callvirt class Item class PlayerInventory::GetTempDataJack(class Player)
IL_000c: stloc.1
IL_000d: ldarg.0
IL_000e: ldfld class PlayerInventory Player::inventory
IL_0013: ldfld class Item PlayerInventory::curDeck
IL_0018: brtrue.s IL_0036
IL_001a: ldloc.1
IL_001b: brfalse.s IL_0036
IL_001d: ldloc.1
IL_001e: ldfld class [ShadowrunDTO]isogame.ItemDef Item::def
IL_0023: callvirt instance string class [ShadowrunDTO]isogame.ItemDef::get_decking_default_weapon()
IL_0028: brfalse.s IL_0036
IL_002a: ldarg.0
IL_002b: ldfld class PlayerInventory Player::inventory
IL_0030: ldloc.1
IL_0031: stfld class Item PlayerInventory::curDeck
IL_0036: ldarg.0
IL_0037: ldfld class [ShadowrunDTO]isogame.CharacterInstance Player::thisCharacterInstance
IL_003c: callvirt instance valuetype [ShadowrunDTO]isogame.SpawnType class [ShadowrunDTO]isogame.CharacterInstance::get_spawn_type()
IL_0041: ldc.i4.2
IL_0042: bne.un IL_0102
IL_0047: ldarg.0
IL_0048: ldfld class PlayerInventory Player::inventory
IL_004d: ldfld class Item PlayerInventory::curDeck
IL_0052: brfalse IL_0102
IL_0057: ldarg.0
IL_0058: ldfld class PlayerInventory Player::inventory
IL_005d: ldfld class Item PlayerInventory::curDeck
IL_0062: ldfld class [ShadowrunDTO]isogame.ItemDef Item::def
IL_0067: stloc.0
IL_0068: ldarg.0
IL_0069: ldfld class [ShadowrunDTO]isogame.Attributes Actor::baseAttributes
IL_006e: ldloc.0
IL_006f: callvirt instance int32 class [ShadowrunDTO]isogame.ItemDef::get_decking_hardening()
IL_0074: callvirt instance void class [ShadowrunDTO]isogame.Attributes::set_armor(int32)
IL_0079: ldarg.0
IL_007a: ldfld class [ShadowrunDTO]isogame.Attributes Actor::baseAttributes
IL_007f: ldloc.0
IL_0080: callvirt instance int32 class [ShadowrunDTO]isogame.ItemDef::get_decking_body()
IL_0085: callvirt instance void class [ShadowrunDTO]isogame.Attributes::set_body(int32)
IL_008a: ldarg.0
IL_008b: ldfld class [ShadowrunDTO]isogame.Skills Actor::baseSkills
IL_0090: ldloc.0
IL_0091: callvirt instance int32 class [ShadowrunDTO]isogame.ItemDef::get_decking_evasion()
IL_0096: callvirt instance void class [ShadowrunDTO]isogame.Skills::set_dodge(int32)
IL_009b: ldarg.0
IL_009c: ldfld class [ShadowrunDTO]isogame.Attributes Actor::baseAttributes
IL_00a1: ldloc.0
IL_00a2: callvirt instance int32 class [ShadowrunDTO]isogame.ItemDef::get_decking_max_ap()
IL_00a7: callvirt instance void class [ShadowrunDTO]isogame.Attributes::set_ap(int32)
IL_00ac: ldarg.0
IL_00ad: ldfld class [ShadowrunDTO]isogame.Attributes Actor::baseAttributes
IL_00b2: ldloc.0
IL_00b3: callvirt instance int32 class [ShadowrunDTO]isogame.ItemDef::get_decking_max_ip()
IL_00b8: callvirt instance void class [ShadowrunDTO]isogame.Attributes::set_hp(int32)
IL_00bd: ldarg.0
IL_00be: ldarg.0
IL_00bf: ldfld class PlayerInventory Player::inventory
IL_00c4: ldfld class Item PlayerInventory::curDeck
IL_00c9: callvirt instance int32 class Item::get_CurrentHealth()
IL_00ce: call instance void class Actor::SetHP(int32)
IL_00d3: ldarg.0
IL_00d4: ldarg.0
IL_00d5: ldfld class [ShadowrunDTO]isogame.Attributes Actor::baseAttributes
IL_00da: callvirt instance int32 class [ShadowrunDTO]isogame.Attributes::get_ap()
IL_00df: call instance void class Actor::SetAP(int32)
IL_00e4: ldarg.0
IL_00e5: ldarg.0
IL_00e6: call int32 class StatsUtil::GetMaxArmor(class Actor)
IL_00eb: call instance void class Actor::SetRP(int32)
IL_00f0: ldarg.0
IL_00f1: ldfld class PlayerInventory Player::inventory
IL_00f6: ldloc.0
IL_00f7: callvirt instance string class [ShadowrunDTO]isogame.ItemDef::get_decking_default_weapon()
IL_00fc: callvirt instance bool class PlayerInventory::InitializeAvatarItems(string)
IL_0101: pop
IL_0102: ldarg.0
IL_0103: ldfld class [ShadowrunDTO]isogame.CharacterInstance Player::thisCharacterInstance
IL_0108: callvirt instance valuetype [ShadowrunDTO]isogame.SpawnType class [ShadowrunDTO]isogame.CharacterInstance::get_spawn_type()
IL_010d: ldc.i4.2
IL_010e: bne.un.s IL_0137
IL_0110: ldarg.0
IL_0111: ldfld class PlayerInventory Player::inventory
IL_0116: ldfld class Item PlayerInventory::curDeck
IL_011b: brtrue.s IL_0137
IL_011d: ldsfld class LogChannel LogChannel::PLYR
IL_0122: ldarg.0
IL_0123: call instance string class [UnityEngine]UnityEngine.Object::get_name()
IL_0128: ldstr " is of type avatar, but has no deck. Stats unchanged"
IL_012d: call string string::Concat(string, string)
IL_0132: call void class Logger::LogError(class LogChannel, string)
IL_0137: ret
} // end of method Player::InitializeAfterInventory
I needed a pop after calling the first static method (which returned a object). I thought that just assigning it with stloc would pop but no such thing, i needed to add a pop after the assignement.
User contributions licensed under CC BY-SA 3.0