Can Decompiler IL2CPP ?

Dear All
Pokemon Go made with Unity 3D and use IL2CPP. IL2CPP convert c# code to C++ and compiler to Assembly.
But Pokemon Go is hacked. Is Pokemon go decompiled?
Can deompiler a apk or ipa using IL2CPP ?

Anything can be reverse engineered. IL2CPP just makes it more difficult compared to mono but its not a 100% protection.

How has Pokemon Go been hacked? Link?

1 Like

This is link to reverse Pokemon Go
https://applidium.com/en/news/unbundling_pokemon_go/
Although All app can reverse. But with IL2CPP you can not archive orgin code with name class and function, it is only assembly code . But someone said that they can reverse IL2CPP to orgin code with name class and function

1 Like

So much this. As long as the application gets executed on end users machine, people will be able to look inside.

1 Like

Whether the vast majority of those interested in it are capable of making sense of the decompiled code is another thing. This is one of those worry threads that hasn’t any real basis because the people truly capable of making sense of the decompiled IL2CPP code are more than capable of building their own solutions. It’d have to be extremely valuable to be worthwhile.

Sure. Nobody would do that for plagiarizing code. That’d be super ineffective. Did people really do that when they could just decompile C#, though? I would find that surprising…

1 Like

Depends on the project. It would require one heck of an amazing game to make people wade through machine code. I remember that original Doom was repeatedly disassembled, that there people who fan-translated snes and ps2 games, sometimes hacking through the engine code as well, etc. I also remember that someone managed to write script extender dll for oblivion/skyrim, that adds new functions to the game’s built-in scripting language.

In case of unity whoever is trying to reverse engineer the project would probably be trying to make some sort of mod or unofficial bugfix. That doesn’t sound like enough motivation for me. Trying to steal the code is dead end route, anyone with a brain would understand that (at least I hope so).

1 Like

In the article you link to they only reverse engineered the java code, not IL2CPP.

2 Likes

IL2CPP builds are much harder to reverse engineer but strings and member information (class, method names etc) are visible in the global-metadata.dat file.
But Unity said that IL2CPP trip all class method name to number and very hard to understand.
Who is right ? Any one have used that asset to obfuscator
this is some class after decompiler Pokemon Go use IL2CPP. All class and function is meaningful.

class HoloPokemonId
{
// Fields
int value__;
static HoloPokemonId POKEMON_UNSET = 0;
static HoloPokemonId V0001_POKEMON_BULBASAUR = 1;
static HoloPokemonId V0002_POKEMON_IVYSAUR = 2;
static HoloPokemonId V0003_POKEMON_VENUSAUR = 3;
static HoloPokemonId V0004_POKEMON_CHARMANDER = 4;
static HoloPokemonId V0005_POKEMON_CHARMELEON = 5;
static HoloPokemonId V0006_POKEMON_CHARIZARD = 6;
static HoloPokemonId V0007_POKEMON_SQUIRTLE = 7;
static HoloPokemonId V0008_POKEMON_WARTORTLE = 8;
static HoloPokemonId V0009_POKEMON_BLASTOISE = 9;
static HoloPokemonId V0010_POKEMON_CATERPIE = 10;
static HoloPokemonId V0011_POKEMON_METAPOD = 11;
static HoloPokemonId V0012_POKEMON_BUTTERFREE = 12;
static HoloPokemonId V0013_POKEMON_WEEDLE = 13;
static HoloPokemonId V0014_POKEMON_KAKUNA = 14;
static HoloPokemonId V0015_POKEMON_BEEDRILL = 15;
static HoloPokemonId V0016_POKEMON_PIDGEY = 16;
static HoloPokemonId V0017_POKEMON_PIDGEOTTO = 17;
static HoloPokemonId V0018_POKEMON_PIDGEOT = 18;
static HoloPokemonId V0019_POKEMON_RATTATA = 19;
static HoloPokemonId V0020_POKEMON_RATICATE = 20;
static HoloPokemonId V0021_POKEMON_SPEAROW = 21;
static HoloPokemonId V0022_POKEMON_FEAROW = 22;
static HoloPokemonId V0023_POKEMON_EKANS = 23;
static HoloPokemonId V0024_POKEMON_ARBOK = 24;
static HoloPokemonId V0025_POKEMON_PIKACHU = 25;
static HoloPokemonId V0026_POKEMON_RAICHU = 26;
static HoloPokemonId V0027_POKEMON_SANDSHREW = 27;
static HoloPokemonId V0028_POKEMON_SANDSLASH = 28;
static HoloPokemonId V0029_POKEMON_NIDORAN = 29;
static HoloPokemonId V0030_POKEMON_NIDORINA = 30;
static HoloPokemonId V0031_POKEMON_NIDOQUEEN = 31;
static HoloPokemonId V0032_POKEMON_NIDORAN = 32;
static HoloPokemonId V0033_POKEMON_NIDORINO = 33;
static HoloPokemonId V0034_POKEMON_NIDOKING = 34;
static HoloPokemonId V0035_POKEMON_CLEFAIRY = 35;
static HoloPokemonId V0036_POKEMON_CLEFABLE = 36;
static HoloPokemonId V0037_POKEMON_VULPIX = 37;
static HoloPokemonId V0038_POKEMON_NINETALES = 38;
static HoloPokemonId V0039_POKEMON_JIGGLYPUFF = 39;
static HoloPokemonId V0040_POKEMON_WIGGLYTUFF = 40;
static HoloPokemonId V0041_POKEMON_ZUBAT = 41;
static HoloPokemonId V0042_POKEMON_GOLBAT = 42;
static HoloPokemonId V0043_POKEMON_ODDISH = 43;
static HoloPokemonId V0044_POKEMON_GLOOM = 44;
static HoloPokemonId V0045_POKEMON_VILEPLUME = 45;
static HoloPokemonId V0046_POKEMON_PARAS = 46;
static HoloPokemonId V0047_POKEMON_PARASECT = 47;
static HoloPokemonId V0048_POKEMON_VENONAT = 48;
static HoloPokemonId V0049_POKEMON_VENOMOTH = 49;
static HoloPokemonId V0050_POKEMON_DIGLETT = 50;
static HoloPokemonId V0051_POKEMON_DUGTRIO = 51;
static HoloPokemonId V0052_POKEMON_MEOWTH = 52;
static HoloPokemonId V0053_POKEMON_PERSIAN = 53;
static HoloPokemonId V0054_POKEMON_PSYDUCK = 54;
static HoloPokemonId V0055_POKEMON_GOLDUCK = 55;
static HoloPokemonId V0056_POKEMON_MANKEY = 56;
static HoloPokemonId V0057_POKEMON_PRIMEAPE = 57;
static HoloPokemonId V0058_POKEMON_GROWLITHE = 58;
static HoloPokemonId V0059_POKEMON_ARCANINE = 59;
static HoloPokemonId V0060_POKEMON_POLIWAG = 60;
static HoloPokemonId V0061_POKEMON_POLIWHIRL = 61;
static HoloPokemonId V0062_POKEMON_POLIWRATH = 62;
static HoloPokemonId V0063_POKEMON_ABRA = 63;
static HoloPokemonId V0064_POKEMON_KADABRA = 64;
static HoloPokemonId V0065_POKEMON_ALAKAZAM = 65;
static HoloPokemonId V0066_POKEMON_MACHOP = 66;
static HoloPokemonId V0067_POKEMON_MACHOKE = 67;
static HoloPokemonId V0068_POKEMON_MACHAMP = 68;
static HoloPokemonId V0069_POKEMON_BELLSPROUT = 69;
static HoloPokemonId V0070_POKEMON_WEEPINBELL = 70;
static HoloPokemonId V0071_POKEMON_VICTREEBEL = 71;
static HoloPokemonId V0072_POKEMON_TENTACOOL = 72;
static HoloPokemonId V0073_POKEMON_TENTACRUEL = 73;
static HoloPokemonId V0074_POKEMON_GEODUDE = 74;
static HoloPokemonId V0075_POKEMON_GRAVELER = 75;
static HoloPokemonId V0076_POKEMON_GOLEM = 76;
static HoloPokemonId V0077_POKEMON_PONYTA = 77;
static HoloPokemonId V0078_POKEMON_RAPIDASH = 78;
static HoloPokemonId V0079_POKEMON_SLOWPOKE = 79;
static HoloPokemonId V0080_POKEMON_SLOWBRO = 80;
static HoloPokemonId V0081_POKEMON_MAGNEMITE = 81;
static HoloPokemonId V0082_POKEMON_MAGNETON = 82;
static HoloPokemonId V0083_POKEMON_FARFETCHD = 83;
static HoloPokemonId V0084_POKEMON_DODUO = 84;
static HoloPokemonId V0085_POKEMON_DODRIO = 85;
static HoloPokemonId V0086_POKEMON_SEEL = 86;
static HoloPokemonId V0087_POKEMON_DEWGONG = 87;
static HoloPokemonId V0088_POKEMON_GRIMER = 88;
static HoloPokemonId V0089_POKEMON_MUK = 89;
static HoloPokemonId V0090_POKEMON_SHELLDER = 90;
static HoloPokemonId V0091_POKEMON_CLOYSTER = 91;
static HoloPokemonId V0092_POKEMON_GASTLY = 92;
static HoloPokemonId V0093_POKEMON_HAUNTER = 93;
static HoloPokemonId V0094_POKEMON_GENGAR = 94;
static HoloPokemonId V0095_POKEMON_ONIX = 95;
static HoloPokemonId V0096_POKEMON_DROWZEE = 96;
static HoloPokemonId V0097_POKEMON_HYPNO = 97;
static HoloPokemonId V0098_POKEMON_KRABBY = 98;
static HoloPokemonId V0099_POKEMON_KINGLER = 99;
static HoloPokemonId V0100_POKEMON_VOLTORB = 100;
static HoloPokemonId V0101_POKEMON_ELECTRODE = 101;
static HoloPokemonId V0102_POKEMON_EXEGGCUTE = 102;
static HoloPokemonId V0103_POKEMON_EXEGGUTOR = 103;
static HoloPokemonId V0104_POKEMON_CUBONE = 104;
static HoloPokemonId V0105_POKEMON_MAROWAK = 105;
static HoloPokemonId V0106_POKEMON_HITMONLEE = 106;
static HoloPokemonId V0107_POKEMON_HITMONCHAN = 107;
static HoloPokemonId V0108_POKEMON_LICKITUNG = 108;
static HoloPokemonId V0109_POKEMON_KOFFING = 109;
static HoloPokemonId V0110_POKEMON_WEEZING = 110;
static HoloPokemonId V0111_POKEMON_RHYHORN = 111;
static HoloPokemonId V0112_POKEMON_RHYDON = 112;
static HoloPokemonId V0113_POKEMON_CHANSEY = 113;
static HoloPokemonId V0114_POKEMON_TANGELA = 114;
static HoloPokemonId V0115_POKEMON_KANGASKHAN = 115;
static HoloPokemonId V0116_POKEMON_HORSEA = 116;
static HoloPokemonId V0117_POKEMON_SEADRA = 117;
static HoloPokemonId V0118_POKEMON_GOLDEEN = 118;
static HoloPokemonId V0119_POKEMON_SEAKING = 119;
static HoloPokemonId V0120_POKEMON_STARYU = 120;
static HoloPokemonId V0121_POKEMON_STARMIE = 121;
static HoloPokemonId V0122_POKEMON_MR_MIME = 122;
static HoloPokemonId V0123_POKEMON_SCYTHER = 123;
static HoloPokemonId V0124_POKEMON_JYNX = 124;
static HoloPokemonId V0125_POKEMON_ELECTABUZZ = 125;
static HoloPokemonId V0126_POKEMON_MAGMAR = 126;
static HoloPokemonId V0127_POKEMON_PINSIR = 127;
static HoloPokemonId V0128_POKEMON_TAUROS = 128;
static HoloPokemonId V0129_POKEMON_MAGIKARP = 129;
static HoloPokemonId V0130_POKEMON_GYARADOS = 130;
static HoloPokemonId V0131_POKEMON_LAPRAS = 131;
static HoloPokemonId V0132_POKEMON_DITTO = 132;
static HoloPokemonId V0133_POKEMON_EEVEE = 133;
static HoloPokemonId V0134_POKEMON_VAPOREON = 134;
static HoloPokemonId V0135_POKEMON_JOLTEON = 135;
static HoloPokemonId V0136_POKEMON_FLAREON = 136;
static HoloPokemonId V0137_POKEMON_PORYGON = 137;
static HoloPokemonId V0138_POKEMON_OMANYTE = 138;
static HoloPokemonId V0139_POKEMON_OMASTAR = 139;
static HoloPokemonId V0140_POKEMON_KABUTO = 140;
static HoloPokemonId V0141_POKEMON_KABUTOPS = 141;
static HoloPokemonId V0142_POKEMON_AERODACTYL = 142;
static HoloPokemonId V0143_POKEMON_SNORLAX = 143;
static HoloPokemonId V0144_POKEMON_ARTICUNO = 144;
static HoloPokemonId V0145_POKEMON_ZAPDOS = 145;
static HoloPokemonId V0146_POKEMON_MOLTRES = 146;
static HoloPokemonId V0147_POKEMON_DRATINI = 147;
static HoloPokemonId V0148_POKEMON_DRAGONAIR = 148;
static HoloPokemonId V0149_POKEMON_DRAGONITE = 149;
static HoloPokemonId V0150_POKEMON_MEWTWO = 150;
static HoloPokemonId V0151_POKEMON_MEW = 151;

// VTable
virtual boolean Equals(mvar obj); // 0 - 4d5e77c
virtual void Finalize(); // 1 - 4da8e94
virtual int GetHashCode(); // 2 - 4d5e794
virtual String ToString(); // 3 - 4d5d9a8
virtual String ToString(String format, String provider); // 4 - 4d5e61c
virtual TypeCode GetTypeCode(); // 5 - 4d5b570
virtual boolean System.IConvertible.ToBoolean(Boolean provider); // 6 - 4d5a9c0
virtual byte System.IConvertible.ToByte(Byte provider); // 7 - 4d5aa78
virtual char System.IConvertible.ToChar(Char provider); // 8 - 4d5ab2c
virtual DateTime System.IConvertible.ToDateTime(DateTime provider); // 9 - 4d5abe0
virtual Decimal System.IConvertible.ToDecimal(Decimal provider); // 10 - 4d5aca4
virtual double System.IConvertible.ToDouble(Double provider); // 11 - 4d5ad68
virtual short System.IConvertible.ToInt16(Int16 provider); // 12 - 4d5ae1c
virtual int System.IConvertible.ToInt32(Int32 provider); // 13 - 4d5aed0
virtual long System.IConvertible.ToInt64(Int64 provider); // 14 - 4d5af84
virtual sbyte System.IConvertible.ToSByte(SByte provider); // 15 - 4d5b038
virtual float System.IConvertible.ToSingle(Single provider); // 16 - 4d5b0ec
virtual String ToString(String provider); // 17 - 4d5db8c
virtual mvar System.IConvertible.ToType(Object targetType, Object provider); // 18 - 4d5b1a0
virtual ushort System.IConvertible.ToUInt16(UInt16 provider); // 19 - 4d5b354
virtual uint System.IConvertible.ToUInt32(UInt32 provider); // 20 - 4d5b408
virtual ulong System.IConvertible.ToUInt64(UInt64 provider); // 21 - 4d5b4bc
virtual int CompareTo(mvar target); // 22 - 4d5d838
}

In that link is the best that I can search through Google. It just decompiler java plugin of unity 3d by java tool. But someone must can revert IL2CPP if class and method name is stored in metadata.
Do you think project should be obfuscator before release

Hmm the “they be stealin my codez” circle jerk once again. Yes if your using the mono backend people can easily decompile it back to IL code again, or even back to any language that compiles to IL. Yes even with il2cpp you will never stop the dedicated ones from breaking into it as well. No you should not worry, or waste your time caring. No you cant stop it. Yes you must live with it.

If someone made a straight up clones of your game, and you lose sales as a result, well that is just your fault, for not marketing it well enough, or monetizing off it well enough. Not to mention, people who have the skills to do the above, and market it better than you are most likely just going to build their own product.

I just think unity should replace name class and method, varibles in metada by a random number .
It is hard to understand a code with nonsense class method varibles. No one try to decompiler that code, it take more time than code by themself.
You many time to imlement algorithm, test bug, … But like mono backen just 5 minutes to decompiler .apk or .ipa to orgin C# code. It lead people steal code than code by themself.

I’d rather have UT devote development time to improving their own product than wasting time in the endless and lost battle of piracy and code protection

6 Likes

None of those functions are meaningful in the slightest.

It is just virtual function. can be override

What does that have to do with my statement? Show me some functions and code stored within them and then I’ll care.

also even then you should not care

1 Like

I am not person decompiler and hack pokemon go. So I can’t show full code for you.
I just confuse about if IL2CPP can be decompiled like mono.
I am freelancer and use unity 3d to dev App. My customer need a native code, they don’t want their opponent can decompiler in 5 minutes. So I need to sure IL2CPP can convert to assembly code. With Assembly code all name class and function is triped to random number. It is very hard to understand.
But IL2CPP still store name class and name method in meta-data, so it is still reverted like mono.
Although Pokemon Go is hacked but I think they just hack third-party plugin java language. And sniff packed to fake message with server. I don’t think they can mod IL2CPP.
But SomeOne show me the code they try to decompiler , and they said IL2CPP covert C# → C++ but all name class and methed still store in meta-data.
I think Unity can replace All name class and method in meta-data by random number. No one try to read an assembly code. It is good for all developer.

IL2CPP produces native code. Problem solved.

Your customer is concerned about their code. Class and method names are not code.

1 Like