Aaron Ardiri
[Valid RSS] RSS/XML feed
198 entries available (show all)

 

Internet of Things (IoT)
   

PLEASE TAKE A MOMENT TO FOLLOW MY NEW VENTURE:
 
RIoT Secure AB
 
ALL SECURITY RELATED TOPICS ON IoT wILL BE POSTED THERE


2016-11-13
>> Pokémon GO - REVISITING THE "HACKING" SCENE (PART 4)

Some would say I am addicted to Pokémon GO - but I think I have found a new passion.

Once upon a time it was about filling the Pokédex (aka: "catch them all") which eventually moved onto finding Pokémon with perfect individual values; heck, 142/143 and the majority of my Pokémon with 80+% IV (all caught manually, no bots), not to mention winter in Europe - it is time to continue the #re series of blog posts to share the knowledge to get others up-to speed.

Starting with 0.41 - Niantic introduced a new level of obfuscation and between each release since, simply change a series of magic numbers that relate directly to the release version. The 0.45.0 magic numbers were found pretty quickly; however, only a limited number of people have the ability to extract these values from the thousands of ARM opcodes that are executed.

    // pogo 0.45.0
    uint64_t magic_table[16] = {
      0x2dd7caaefcf073eb, 0xa9209937349cfe9c,
      0xb84bfc934b0e60ef, 0xff709c157b26e477,
      0x3936fd8735455112, 0xca141bf22338d331,
      0xdd40e749cb64fd02, 0x5e268f564b0deb26,
      0x658239596bdea9ec, 0x31cedf33ac38c624,
      0x12f56816481b0cfd, 0x94e9de155f40f095,
      0x5089c907844c6325, 0xdf887e97d73c50e3,
      0xae8870787ce3c11d, 0xa6767d18c58d2117,
    };
    #define ROUND_MAGIC_HI 0xe3f0d44988bcdfab
    #define ROUND_MAGIC_LO 0x081570afdd535ec3
    #define FINAL_MAGIC0 0xce7c4801d683e824
    #define FINAL_MAGIC1 0x6823775b1daad522
    #define ROUND_MAGIC U128(ROUND_MAGIC_HI,ROUND_MAGIC_LO)

It is my prediction that Niantic will throw something new at the hacking community, they surely know that if they keep changing the magic numbers, they will never win the battle - in fact, a lot of the developers are anxious to see what challenge will come their way next. The bottom line is that tool development continues, waiting for the next update from Niantic to make the next step.

While the Unicorn CPU emulator has been used as a temporary solution to generate hash values - it is also a great tool for understanding what happens in the code. I spent the weekend cleaning up pogohash and including the Capstone disassembler - in addition to monitoring CPU registers.

With TRACE_DEBUG enabled; the code will now give a lot more information about what is going on with the CPU emulation. In addition; it will be possible to implement tracing and pattern detection to assist in finding the magic numbers as the application updates (of course, still must find function).

    address: 0x00002000
      R00* 0xe0001000 R01* 0x00000080 R02* 0x01b175c1 R03* 0x40000000
      R04: 0x00000000 R05: 0x00000000 R06: 0x00000000 R07: 0x00000000
      R08: 0x00000000 R09: 0x00000000 R10: 0x00000000 R11: 0x00000000
      R12: 0x00000000  SP* 0xe0002000  LR: 0x00000000  PC* 0x00002000
    opcodes: 90 47       :: blx     r2
    ---
    address: 0x01b175c0
      R00: 0xe0001000 R01: 0x00000080 R02: 0x01b175c1 R03: 0x40000000
      R04: 0x00000000 R05: 0x00000000 R06: 0x00000000 R07: 0x00000000
      R08: 0x00000000 R09: 0x00000000 R10: 0x00000000 R11: 0x00000000
      R12: 0x00000000  SP: 0xe0002000  LR* 0x00002003  PC* 0x01b175c0
    opcodes: f0 b5       :: push    {r4, r5, r6, r7, lr}

I have highlighted changes registers in bold; it is obvious that the PC (program counter) register will change for every instruction; but you can also see that R0..R3 relate to the code that we used before calling uc_emu_start. The LR register also contains the address to return to when done.

    uint64_t Hash(uint8_t* buffer, int size)
    {
      uint32_t r0 = 0xE0001000;  // buffer
      uint32_t r1 = size;        // size
      uint32_t r2 = HashFunctionAddr + 1;
      uint64_t ret;
      uc_err err;
    
      uc_reg_write(uc, UC_ARM_REG_R0, &r0);
      uc_reg_write(uc, UC_ARM_REG_R1, &r1);
      uc_reg_write(uc, UC_ARM_REG_R2, &r2);

Ok; so, what does all this mean - why are we bothering with making such a pretty output of what is going on. Well; one of the flaws Niantic did with the latest update (actually, the compiler does it) - is that all the magic numbers are loaded into registers as hard coded values. Let's look at the lower 32-bits of the FINAL_MAGIC1 value, which is 0x1daad522, simply find where this value was loaded.

    address: 0x01d8d2c6
      R00: 0x00000000 R01: 0xe9c69562 R02* 0xddbb933d R03: 0xe0001f40
      R04: 0x8e4338e2 R05: 0xddbb933d R06: 0xe0001c60 R07: 0xe0001cf4
      R08: 0x02ea9800 R09: 0x2a6cabbf R10: 0xffffffff R11: 0xe0001c7c
      R12: 0xe0001ed0  SP: 0xe0001c5c  LR: 0x01b1842d  PC* 0x01d8d2c6
    opcodes: 4d f2 22 55 :: movw    r5, #0xd522
    ---
    address: 0x01d8d2ca
      R00: 0x00000000 R01: 0xe9c69562 R02: 0xddbb933d R03: 0xe0001f40
      R04: 0x8e4338e2 R05* 0x0000d522 R06: 0xe0001c60 R07: 0xe0001cf4
      R08: 0x02ea9800 R09: 0x2a6cabbf R10: 0xffffffff R11: 0xe0001c7c
      R12: 0xe0001ed0  SP: 0xe0001c5c  LR: 0x01b1842d  PC* 0x01d8d2ca
    opcodes: c1 f6 aa 55 :: movt    r5, #0x1daa
    ---
    address: 0x01d8d2ce
      R00: 0x00000000 R01: 0xe9c69562 R02: 0xddbb933d R03: 0xe0001f40
      R04: 0x8e4338e2 R05* 0x1daad522 R06: 0xe0001c60 R07: 0xe0001cf4
      R08: 0x02ea9800 R09: 0x2a6cabbf R10: 0xffffffff R11: 0xe0001c7c
      R12: 0xe0001ed0  SP: 0xe0001c5c  LR: 0x01b1842d  PC* 0x01d8d2ce
    opcodes: c3 e9 00 12 :: strd    r1, r2, [r3]

The movt and movw instructions are typically used to load a 32-bit value into a register; as someone has documented on stackoverflow.com. With all known magic numbers for 0.45.0 you can find exactly where in the flow of execution these numbers are loaded. Unfortunately; the code-flow will definitely change with the next release, the obfuscation engine being used will definitely want to make it more difficult to trace - but, de-obfuscating the code will solve this.

I have put together a bare-bones version that you can extend to your content - either to trace the branching, or try to put some auto-detect in the code to know when registers are loaded in this manner et al. You will depend on the Unicorn and Capstone libraries - check the README.


 

advertisement (self plug):
need assistance in an IoT project? contact us for a free consultation.

 



Pokémon GO - Revisiting the "hacking" scene (part 5)
 
Pokémon GO - Revisiting the "hacking" scene (part 3)

DISCLAIMER:
All content provided on this blog is for informational purposes only.
All comments are generated by users and moderated for inappropriateness periodically.
The owner will not be liable for any losses, injuries, or damages from the display or use of this information.