2016腾讯游戏安全竞赛第一轮Android题分析

最近在学习Android SO库逆向方面的知识,以2016腾讯游戏安全竞赛第一轮Android题练手,参考了一些资料,其中也有些不足的地方,希望未来好好学习逆向方面的知识。

0x01. 分析思路

本题用JEB看了一下,对于输入的Name和Code进行验证,主要的验证逻辑在SO库中。因此直接逆向SO库,找到导出的函数NativeCheckRegister(String name, String code)。

0x02. SO库逆向

根据对SO中NativeCheckRegister函数的分析,该函数对Name字符串处理了2次,产生长度为20的字符数组;对Code字符串处理了1次,也产生长度为20的字符数组;做好对这两个数组进行比较。

  1. 对Name字符串的第一次处理
    函数刚开始就检查输入字符串Name的长度,是否在6和20之间;然后对Name字符串进行第一次处理,得到长为20的字符串。处理过程:每次会从Name字符串取一个字节,操作公式为:字节×(0x1339e7e+循环次数)×Name长度+上一次得到的4字节高3字节(第一次为0),然后将得到的4字节的低字节存入新数组。循环次数为0x10次,多出来的4个长度为维护得到的4字节数的高3字节以及一个0。

  2. 对Code字符串的处理
    在对Code字符串进行处理时用了2个子例程,分别是sub_146c和sub_1498。sub_1498是对注册码进行一些操作,得到一个数组;之后对数组长度进行判断,是否为0x14(即20),等于0x20则进行后面的处理;反之直接结束。

sub_1498子例程处理过程:
该子例程传入的参数是 Code字符串首地址(R1) 和 **栈上新数组首地址(R0)*
执行流程: 先通过查表操作判断Code字符串是否满足约束条件(Code字节对应的表值不能超过0x3F),如果不满足,则进行截断。因此查询的表需要dump下来,后面的字符串也要用到这个表。然后对满足约束条件的字符串进行处理。将字符串以4字节为单位,进行处理生成新的3字节字符存入栈上新数组;不足4字节的,分别进行一下处理:剩下1字节,直接退出;剩下2字节,经过操作生成1字节退出;剩下3字节,经过操作生成2字节退出;根据前面的数组长度要求为0x14,可以推断出注册码长度必须为27位:20/3=6…2 , 6
4+3 = 27 。
将字符串以4字节为单位操作的步骤:
1)通过查表,将第1个字节对应的表值逻辑左移2位,与第2个字节对应的表值逻辑右移4位进行或运算,产生第1个新字节;
2)通过查表,将第2个字节对应的表值逻辑左移4位,与第3个字节对应的表值逻辑右移2位进行或运算,产生第2个新字节;
3)通过查表,将第3个字节对应的表值逻辑左移6位,与第4个字节对应的表值进行或运算,产生第3个新字节;

  1. 对Name字符串的第二次处理
    将20位的Name字符串数组,每个元素除以0xA,然后重新保存。

  2. 比较
    将Name进行2次操作生成的长度20的数组,与注册码进行了1次操作生成的长度20的数组进行5次比较;
    根据5次比较,设Name每4字节对应一个变量,那么就有5个已知的变量a1(对应数组0x00)、a2(0x04)、a3(0x08)、a4(0x0c)、a5(0x10);设注册码的20位数组每4个字节对应一个未知变量,那么就有5个未知变量x1(0x00)、x2(0x04)、x3(0x08)、x4(0x0c)、x5(0x10);根据比较列出方程:

    1
    2
    3
    4
    5
    1) a1 + x5 = x3
    2) a2 + x5 + a1 = x5 * 2
    3) x4 + a3 = x1
    4) a4 + x4 + a3 = x4 * 2
    5) x2 + a5 = a3 * 3