Disabling lagromancer effect in client
I got many questions whether it's possible to disable the necromancer healing effect in the client and if so, how, so I'm going to make a little tutorial.
First of all, I'd like to state here that I don't support this kind of modifications of the client, since it has to be updated after every new release and writing a proxy is much more profitable on the long run. (Disabling the lagromance effect takes 2 lines of code and never needs to be updated!)
I'm assuming here you are already familiar with rabcdasm, and you can search in files. Always use case sensitive seaching mode unless I state otherwise.
I use 13.2 client (1367279130), but it can be done with any version of clients (the names will differ though).
The effect is triggered by the SHOW_EFFECT packet, it is sent by the server to the client, so if someone uses the necro ability the server will tell your client that it should show the effect. There are limited number of effects, I used my proxy to find out which one it is but you can try blocking other effect too if you want to test it. (the earthquake is an effect too)
The necro effect is the effect number 9, called FlowEffect.
Find the class definition of the SHOW_EFFECT packet. I use the grep commandline tool for searching, you can use whatever you want:
Open _-0a/_-SZ.class.asasm, go to the end of the file you will see something like this:
We need the one with the value of 9. That's the _-KK.
Find which file it is used in:
They are the _-16i/_-AK.class.asasm and the _-0a/_-SZ.class.asasm (this one) files.
Open _-16i/_-AK.class.asasm and look for the _-KK in it:
The code is a bit obfuscated here it is after cleaning up the code a little bit:
It's part of a switch-case if you are familiar with other languages, you may know what it is. If local6 is not equal to _-0a._-SZ._-KK (9), jump to the next case (effect), if it is, then push 8 onto the top of the stack and jump to the swich table:
L582 is the default value (if the effect is not found), but now we need the 8th label (remember the pushbyte 8 before the jump). Start the count with zero.
After cleaning the code up a little bit:
This code calls the FlowEffect that we want to prevent. We can put a
right after the label, but we already know that L851 is just a label to returnvoid so we can directly put there a returnvoid:
That's it.
Note: In every method the obfuscator uses 2 locals to confuse you, you can check the code between the "code" tag and "getlocal0, pushscope", instructions, usually one of it will be false and the other true, so you will know what you should and should not ignore. In the method above, it's
so local7 and local8 are only there to confuse you with the values of true and false respectively.
tl;dr: Look for FlowEffect in the class of map_.gs_.gsc_, find the "label" instruction somewhere above it and put "returnvoid" right after the "label".
(I haven't tested it yet but it should work -_-)
First of all, I'd like to state here that I don't support this kind of modifications of the client, since it has to be updated after every new release and writing a proxy is much more profitable on the long run. (Disabling the lagromance effect takes 2 lines of code and never needs to be updated!)
I'm assuming here you are already familiar with rabcdasm, and you can search in files. Always use case sensitive seaching mode unless I state otherwise.
I use 13.2 client (1367279130), but it can be done with any version of clients (the names will differ though).
The effect is triggered by the SHOW_EFFECT packet, it is sent by the server to the client, so if someone uses the necro ability the server will tell your client that it should show the effect. There are limited number of effects, I used my proxy to find out which one it is but you can try blocking other effect too if you want to test it. (the earthquake is an effect too)
The necro effect is the effect number 9, called FlowEffect.
Find the class definition of the SHOW_EFFECT packet. I use the grep commandline tool for searching, you can use whatever you want:
Code:
$ grep -r SHOW_EFFECT _-0a/_-SZ.class.asasm: pushstring "SHOW_EFFECT"
Code:
trait const QName(PackageNamespace("", "#0"), "_-19G") slotid 1 type QName(PackageNamespace("", "#0"), "int") value Integer(0) end
trait const QName(PackageNamespace("", "#0"), "_-0EH") slotid 2 type QName(PackageNamespace("", "#0"), "int") value Integer(1) end
trait const QName(PackageNamespace("", "#0"), "_-1CI") slotid 3 type QName(PackageNamespace("", "#0"), "int") value Integer(2) end
trait const QName(PackageNamespace("", "#0"), "_-12Z") slotid 4 type QName(PackageNamespace("", "#0"), "int") value Integer(3) end
trait const QName(PackageNamespace("", "#0"), "_-1I-") slotid 5 type QName(PackageNamespace("", "#0"), "int") value Integer(4) end
trait const QName(PackageNamespace("", "#0"), "_-0Z6") slotid 6 type QName(PackageNamespace("", "#0"), "int") value Integer(5) end
trait const QName(PackageNamespace("", "#0"), "_-09H") slotid 7 type QName(PackageNamespace("", "#0"), "int") value Integer(6) end
trait const QName(PackageNamespace("", "#0"), "_-0FT") slotid 8 type QName(PackageNamespace("", "#0"), "int") value Integer(7) end
trait const QName(PackageNamespace("", "#0"), "_-0E8") slotid 9 type QName(PackageNamespace("", "#0"), "int") value Integer(8) end
trait const QName(PackageNamespace("", "#0"), "_-KK") slotid 10 type QName(PackageNamespace("", "#0"), "int") value Integer(9) end
trait const QName(PackageNamespace("", "#0"), "_-10L") slotid 11 type QName(PackageNamespace("", "#0"), "int") value Integer(10) end
trait const QName(PackageNamespace("", "#0"), "_-ME") slotid 12 type QName(PackageNamespace("", "#0"), "int") value Integer(11) end
trait const QName(PackageNamespace("", "#0"), "_-IO") slotid 13 type QName(PackageNamespace("", "#0"), "int") value Integer(12) end
trait const QName(PackageNamespace("", "#0"), "_-or") slotid 14 type QName(PackageNamespace("", "#0"), "int") value Integer(13) end
trait const QName(PackageNamespace("", "#0"), "_-1Sd") slotid 15 type QName(PackageNamespace("", "#0"), "int") value Integer(14) end
trait const QName(PackageNamespace("", "#0"), "_-1as") slotid 16 type QName(PackageNamespace("", "#0"), "int") value Integer(15) end
trait const QName(PackageNamespace("", "#0"), "_-1ZR") slotid 17 type QName(PackageNamespace("", "#0"), "int") value Integer(16) end
Find which file it is used in:
Code:
_-16i/_-AK.class.asasm: getproperty QName(PackageNamespace("", "#0"), "_-KK")
_-0a/_-SZ.class.asasm: findproperty QName(PackageNamespace("", "#0"), "_-KK")
_-0a/_-SZ.class.asasm: initproperty QName(PackageNamespace("", "#0"), "_-KK")
_-0a/_-SZ.class.asasm: trait const QName(PackageNamespace("", "#0"), "_-KK") slotid 10 type QName(PackageNamespace("", "#0"), "int") value Integer(9) end
Open _-16i/_-AK.class.asasm and look for the _-KK in it:
Code:
L718:
getlex QName(PackageNamespace("_-0a"), "_-SZ")
getproperty QName(PackageNamespace("", "#0"), "_-KK")
getlocal 7
iffalse L797
getlocal 6
getlocal 8
iftrue L738
L725:
ifstrictne L728
L726:
pushbyte 8
jump L849
Code:
L718:
getlex QName(PackageNamespace("_-0a"), "_-SZ")
getproperty QName(PackageNamespace("", "#0"), "_-KK")
getlocal 6
ifstrictne L728
pushbyte 8
jump L849
L728:
Code:
lookupswitch L582, [L27, L67, L79, L102, L154, L188, L224, L264, L306, L346, L390, L433, L470, L508, L513, L549, L582]
L851:
returnvoid
Code:
L306:
label
getlocal2
getproperty QName(PackageNamespace("", "#0"), "goDict_")
getlocal1
getproperty QName(PackageNamespace("", "#0"), "targetObjectId_")
getproperty MultinameL([PrivateNamespace("*", "_-16i:_-AK"), PackageNamespace("", "#0"), PackageNamespace("_-16i"), PackageNamespace("_-065"), PackageNamespace("_-0a"), PackageNamespace("com.company.assembleegameclient.objects"), PrivateNamespace("*", "_-16i:_-AK/instance"), PackageInternalNs("_-16i"), Namespace("http://adobe.com/AS3/2006/builtin"), PackageNamespace("_-pR"), PackageNamespace("_-1-D"), ProtectedNamespace("_-2W"), StaticProtectedNs("_-2W"), StaticProtectedNs("_-0uN")])
coerce QName(PackageNamespace("com.company.assembleegameclient.objects"), "GameObject")
setlocal3
getlocal 7
iffalse L319
getlocal3
pushnull
ifne L320
L319:
jump L851
L320:
findpropstrict QName(PackageNamespace("_-pR"), "FlowEffect")
getlocal1
getproperty QName(PackageNamespace("", "#0"), "pos1_")
getlocal3
getlocal1
getproperty QName(PackageNamespace("", "#0"), "color_")
constructprop QName(PackageNamespace("_-pR"), "FlowEffect"), 3
coerce QName(PackageNamespace("_-pR"), "_-1ZD")
setlocal 4
getlocal 7
dup
iftrue L335
pop
getlocal0
convert_b
L335:
iffalse L345
getlocal2
getlocal 4
getlocal1
getproperty QName(PackageNamespace("", "#0"), "pos1_")
getproperty QName(PackageNamespace("", "#0"), "x_")
getlocal1
getproperty QName(PackageNamespace("", "#0"), "pos1_")
getproperty QName(PackageNamespace("", "#0"), "y_")
callpropvoid QName(PackageNamespace("", "#0"), "addObj"), 3
L345:
jump L851
L346:
Code:
L306:
label
getlocal2
getproperty QName(PackageNamespace("", "#0"), "goDict_")
getlocal1
getproperty QName(PackageNamespace("", "#0"), "targetObjectId_")
getproperty MultinameL([PrivateNamespace("*", "_-16i:_-AK"), PackageNamespace("", "#0"), PackageNamespace("_-16i"), PackageNamespace("_-065"), PackageNamespace("_-0a"), PackageNamespace("com.company.assembleegameclient.objects"), PrivateNamespace("*", "_-16i:_-AK/instance"), PackageInternalNs("_-16i"), Namespace("http://adobe.com/AS3/2006/builtin"), PackageNamespace("_-pR"), PackageNamespace("_-1-D"), ProtectedNamespace("_-2W"), StaticProtectedNs("_-2W"), StaticProtectedNs("_-0uN")])
coerce QName(PackageNamespace("com.company.assembleegameclient.objects"), "GameObject")
setlocal3
getlocal3
pushnull
ifne L320
jump L851
L320:
findpropstrict QName(PackageNamespace("_-pR"), "FlowEffect")
getlocal1
getproperty QName(PackageNamespace("", "#0"), "pos1_")
getlocal3
getlocal1
getproperty QName(PackageNamespace("", "#0"), "color_")
constructprop QName(PackageNamespace("_-pR"), "FlowEffect"), 3
coerce QName(PackageNamespace("_-pR"), "_-1ZD")
setlocal 4
getlocal2
getlocal 4
getlocal1
getproperty QName(PackageNamespace("", "#0"), "pos1_")
getproperty QName(PackageNamespace("", "#0"), "x_")
getlocal1
getproperty QName(PackageNamespace("", "#0"), "pos1_")
getproperty QName(PackageNamespace("", "#0"), "y_")
callpropvoid QName(PackageNamespace("", "#0"), "addObj"), 3
jump L851
Code:
jump L851
Code:
L306:
label
returnvoid
Note: In every method the obfuscator uses 2 locals to confuse you, you can check the code between the "code" tag and "getlocal0, pushscope", instructions, usually one of it will be false and the other true, so you will know what you should and should not ignore. In the method above, it's
Code:
code
pushfalse ;stack:false
pushtrue ;stack:true,false
setlocal 7 ;local7 is set by the obfuscator to true -> stack:false
jump L10 ; jumps to L10
lessthan ;dead code
declocal 6 ;dead code
kill 7 ;dead code
inclocal 3 ;dead code
getlocal 7 ;dead code
declocal 5 ;dead code
L10:
setlocal 8 ;puts false into local8 -> stack:empty
getlocal0 ;here starts the "real" code
pushscope
tl;dr: Look for FlowEffect in the class of map_.gs_.gsc_, find the "label" instruction somewhere above it and put "returnvoid" right after the "label".
(I haven't tested it yet but it should work -_-)


