Ingress Prime has been out for a few days now and I finally got some time to perform a big ol’ data-mine of the new scanner. Curious to see what was new inside, I expected a cake walk through Niantic’s code base. Boy was I wrong…

Tools and quick links

You can find all of the Ingress Prime icons, fonts, textures and sprites in this Github repository: github.com/apavlinovic/ingress-prime

We used the following tools to perform this data mine:

Some of these tools are harder to use than others, but we’re confident that with some practice you can replicate our data mining process and verify the results easily. With that being said, let’s dive into Ingress Prime’s code base.

The foundation of Ingress Prime

Ingress Prime
Ingress Prime

Niantic has officially stated that Ingress Prime is built on top of the same infrastructure as Pokemon GO and they were not messing around. Ingress Prime’s code base is eerily similar to Pokemon GO, and it employs the following technologies:

  • Unity3D powers the game engine, UI interactions, asset management and player interactions, Protobuff and RPC are used to perform server side communication
  • Both games use Niantic’s shared platform code:
    • Niantic.Platform,
    • Niantic.Zeppelin,
    • Niantic.Platform.Auth and
    • Niantic.Platform.Ditto
  • Both games use the same third party libraries: Zenject (dependency injection framework for Unity), Google Protobuff (lightweight, schema based communication) and Firebase (fast key value storage)

The similarity goes even further, as Unity’s default asset packing now compresses similar sprites into sprite sheets that are called SpriteAtlasTextures – the same as in Pokemon GO:

Ingress Prime Sprite Atlas example
Ingress Prime Sprite Atlas example

But that’s not the end. Ingress Prime ships with the same IAP (In App Purchases) technology that powers Pokemon GO’s in app store – it’s actually a part of the shared Niantic.Platform.Ditto package (shortened code excerpt below):

// Decompiled from IL2CPP#2: lib/armeabi-v7a/libil2cpp.so
using UnityEngine;

namespace Niantic.Platform.Ditto.Iap
{
    public class IapStoreItem
    {
        // Fields
        ...
        
        // Properties
        public System.String Sku { get; set; }
        public System.String LocalCurrencyPrice { get; set; }
        public System.Boolean IsVendorItem { get; set; }
        public System.Boolean CanBePurchased { get; set; }
        public IDictionary`2<System.String, System.Int32> VirtualCurrencyPrice { get; set; }
        public IDictionary`2<System.String, System.Int32> VirtualCurrencyGranted { get; set; }
        public IDictionary`2<System.String, System.String> PresentationData { get; set; }
        public IDictionary`2<System.String, System.Int32> ItemQuantities { get; set; }
        
        // Methods
        //
        // Offset in libil2cpp.so: 0x00B5A744 (11904836), len: 2664
        internal IapStoreItem()
        {
            
        }
        //
        // Offset in libil2cpp.so: 0x00B5B1AC (11907500), len: 0
        [CompilerGeneratedAttribute] // 0x307EEC
        public System.String get_Sku()
        {
            return default(System.String);
        }
        
        // ...
    }
}

If you were wondering how and why Niantic is able to switch around item bundles so frequently and with such ease in Prime, now you have your answer. The IAP infrastructure is here to stay and so is everything else that’s contained inside Niantic’s shared code base:

  • S2 cell management, map services, fused location provider (GPS works 100% the same in Ingress and Pokemon GO now)
  • Authentication, IAP, API, caching and scheduling infrastructure

Although we do not agree with Niantic’s decision to pull the complete in-app purchasing system into Ingress, we do see the value of reusing a stable code base that has been developed over the past two years.

With that being said, let’s see what’s new in Ingress Prime, or in other words, what wasn’t reused from Pokemon GO.

Niantic.Ingress.Core 🕵️

Ingress Prime

Here be dragons.

We went into Ingress.Core code base thinking we know everything, but Niantic has prepared a nasty surprise: code obfuscation. Code obfuscation is a technique of renaming various parts of your code base with cryptic and nonsensical names and it’s used to hide the true nature / names of your code.

Niantic has never used this technique in Pokemon GO and enumerations and protobuff class files are easily readable:

namespace Holoholo.Rpc
{
    public enum HoloPokemonId
    {
        // Fields
        POKEMON_UNSET = 0
        ,V0001_POKEMON_BULBASAUR = 1
        ,V0002_POKEMON_IVYSAUR = 2
        ,V0003_POKEMON_VENUSAUR = 3
        ,V0004_POKEMON_CHARMANDER = 4
        ,V0005_POKEMON_CHARMELEON = 5
        ,V0006_POKEMON_CHARIZARD = 6
        ,V0007_POKEMON_SQUIRTLE = 7
        ,V0008_POKEMON_WARTORTLE = 8
        ,V0009_POKEMON_BLASTOISE = 9

Now compare this with an example from Ingress Prime’s code base:

namespace Niantic.Ingress.Core.Proto.Story
{
    public enum ADDGLGKLGFD
    {
        // Fields
        JPLKKICEMKE = 0
        ,KOENOCLMBHP = 1
        ,LKJODNPEILN = 2
        ,HKLFJHGJEGK = 3                
    }    
}

The exact obfuscation software used is Beebyte’s Obfuscator that supports post build obfuscation and il2cpp build processes that Niantic uses. As far as we can tell, no performance loss should be experienced because of this, but Niantic will have problems reading through bug and crash reports as they now need a “before and after” dictionary.

Luckily not everything is obfuscated, with main obfuscation targets being protocol buffer files that can be used to reverse engineer the API requests. Niantic has clearly taken precautions to prevent protobuf scheme data mining and API abuse, but we lost the flexibility to freely explore the code base in the process.

What does this mean:

  • Data mining will be more difficult than before, no doubt
  • Not everything is obfuscated – especially in the already discussed IAP category – which means something still can be inferred / leaked from analyzing the code
  • Currently, we don’t have any means for defeating the obfuscated code

With that being said, let’s see what did we find inside Ingress Prime.

In the belly of the beast

Ingress Prime data mine
Ingress Prime data mine

Now that you know what we were up against, here is what we managed to find in the not-obfuscated enumerations:

  • POI types and a lot of non essential enums
  • IAP items and categories,
  • a ton of Comm related enumerations,
  • a lot of FMOD related stuff that deals with sound effects (new in comparison with GO)
  • map view types,
  • portal swipe shortcuts,
  • Recursion dialog steps,
  • etc…

In short: we found a lot of non essential code hints that are helpful to data mine new features, but do not help us understand how Ingress Prime works deeply under the hood.

For example, we found a IngressIapItem enumeration. The contents of the enumeration could be panic inducing, but take it with a grain of salt:

namespace Niantic.Ingress.IapStore
{
    public enum IngressIapItem
    {
        UNKNOWN = 0
        ,SOFT_CURRENCY = 1
        ,RESONATOR_1 = 2
        ,RESONATOR_2 = 3
        ,RESONATOR_3 = 4
        ,RESONATOR_4 = 5
        ,RESONATOR_5 = 6
        ,RESONATOR_6 = 7
        ,RESONATOR_7 = 8
        ,RESONATOR_8 = 9
        ,BURSTER_1 = 10
        ,BURSTER_2 = 11
        ,BURSTER_3 = 12
        ,BURSTER_4 = 13
        ,BURSTER_5 = 14
        ,BURSTER_6 = 15
        ,BURSTER_7 = 16
        ,BURSTER_8 = 17
        ,ULTRASTRIKE_1 = 18
        ,ULTRASTRIKE_2 = 19
        ,ULTRASTRIKE_3 = 20
        ,ULTRASTRIKE_4 = 21
        ,ULTRASTRIKE_5 = 22
        ,ULTRASTRIKE_6 = 23
        ,ULTRASTRIKE_7 = 24
        ,ULTRASTRIKE_8 = 25
        ,POWERCUBE_1 = 26
        ,POWERCUBE_2 = 27
        ,POWERCUBE_3 = 28
        ,POWERCUBE_4 = 29
        ,POWERCUBE_5 = 30
        ,POWERCUBE_6 = 31
        ,POWERCUBE_7 = 32
        ,POWERCUBE_8 = 33
        ,POWERCUBE_L = 34
        ,POWERCUBE_K = 35
        ,ADA_REFACTOR = 36
        ,JARVIS_VIRUS = 37
        ,FORCE_AMP = 38
        ,HEAT_SINK_C = 39
        ,HEAT_SINK_R = 40
        ,HEAT_SINK_VR = 41
        ,LINK_AMP_R = 42
        ,LINK_AMP_VR = 43
        ,ULTRA_LINK = 44
        ,MULTI_HACK_C = 45
        ,MULTI_HACK_R = 46
        ,MULTI_HACK_VR = 47
        ,PORTAL_SHIELD_C = 48
        ,PORTAL_SHIELD_R = 49
        ,PORTAL_SHIELD_VR = 50
        ,AEGIS_SHIELD = 51
        ,TURRET = 52
        ,TRANSMUTER_P = 53
        ,TRANSMUTER_M = 54
        ,CAPSULE = 55
        ,INTEREST_CAPSULE = 56
        ,KEY_CAPSULE = 57
        ,KEY_CAPSULE_GREEN = 58
        ,KEY_CAPSULE_GOLD = 59
        ,KEY_CAPSULE_WHITE = 60
        ,KEY_CAPSULE_BLUE = 61
        ,KEY_CAPSULE_RED = 62
        ,KEY_CAPSULE_SPECIAL_1 = 63
        ,FRACK = 64
        ,ENL = 65
        ,RES = 66
        ,LOOK = 67
        ,MEET = 68
        ,OBSIDIAN = 69
        ,INITIO = 70
        ,AEGISNOVA = 71
        ,VIALUX = 72
        ,VIANOIR = 73
        ,MAGNUSRE = 74
        ,EXO5 = 75
        ,NIA = 76               
    }    
}

As we said above, take it all in with a grain of salt – the fact Niantic included all of these items as an option to become purchasable items doesn’t mean they will.

But this enumeration does prove one thing in particular… The obfuscation efforts mentioned above, after all, are not here to keep data miners and game researchers out, but rather to prevent rampant bot madness that plagued Pokemon GO’s early months.

For that, we salute Niantic and we think that we should be able to successfully data mine this game for the months to come, discovering new items, new categories and item additions.

In addition to the enumerations mentioned above, we’ve found a metric ton of useful Ingress assets and some really, really weird ones:

Parting words

Personally, data mining Ingress Prime was one of the most exciting and overwhelming experiences in a while. Niantic has clearly taken their software development practices up a notch, introducing new security measures through obfuscation and hiding the parts of the API they don’t want to be publicly exposed.

Result wise, we’re happy with what we’ve got – the initial metadata analysis does indicate that future data mining could reveal upcoming features and new items.

Until next time, keep hacking.