一、目标

一、目标

从这篇文章开始,我们一步一步介绍如何 填坑、调试并修改原工程 代码 ExAndroidNativeEmu 到跑出某电商Appsign的过程。

本文使用的原始代码在 AndroidNativeEmu使用指南中。

二、步骤

先跑起来,报错

RuntimeError: Could not find class 'com/jingdong/common/utils/BitmapkitUtils' for JNIEnv.

Unicorn是一个虚拟cpu,它模拟的cpu的执行,所以一些纯算法的函数,可以直接用Unicorn跑出来。我们学过计算机组成原理,计算机在硬件cpu之上还跑着一个操作系统,windows、linux、Android、ios和mac这些就是操作系统。

那么要执行so,我们还需要把操作系统给模拟出来。理论上来说我们需要把操作系统的库函数malloc、free等等都给重写一遍,那肯定疯了,所以AndroidEmu已经处理好了,把libc.so libstdc++.so libdvm.so等等都给跑通了,严格意义上说,已经完整的跑通了一个Mini linux。

那为什么很多so都不能顺利执行呢?因为还有个拦路虎是 JNI ,JNI不仅赋予了java程序调用c(Native)的能力,也赋予了c(Native)程序调用java的能力,所以很多大厂so故意在Native层大量 恶意 的调用java层的函数来做逻辑,从而抵抗AndroidEmu和Unidbg之类的模拟器来模拟执行。

androidemu/java/classes 下面是 AeonLucid 大神 Orz 预先写好的几个类来模拟同名的java类,我们创建的新类可以参照这里。

先解释一下

class BitmapkitUtils(metaclass=JavaClassDef, jvm_name='com/jingdong/common/utils/BitmapkitUtils',jvm_fields=[JavaFieldDef("a", "Landroid/app/Application;", True, Application())]):

class BitmapkitUtils : 说明定义一个Python类,类名是 BitmapkitUtils。

metaclass=JavaClassDef : 这个 metaclass是什么鬼?这是Python一个很magic的用法,神奇到我都没搞明白,你只要记住加上这个标志的类,在实例化的时候会首先进入到 JavaClassDef. init()做初始化工作,这样统一改变了这些实例的属性和初始化公共部分。

jvm_name : 这个就好理解了,它描述了BitmapkitUtils这个类在jvm虚拟机里面的类名,Native代码调用它就靠这个名字。

完整代码如下:

class BitmapkitUtils(metaclass=JavaClassDef, jvm_name='com/jingdong/common/utils/BitmapkitUtils'):

    def __init__(self):
        pass

# 在虚拟机里注册 BitmapkitUtils类
emulator.java_classloader.add_class(BitmapkitUtils)

再跑一下

RuntimeError: Could not find static field ('a', 'Landroid/app/Application;') in class com/jingdong/common/utils/BitmapkitUtils.

说明BitmapkitUtils类里面有个叫 a 的 静态变量被调用了,加上他,

class BitmapkitUtils(metaclass=JavaClassDef, jvm_name='com/jingdong/common/utils/BitmapkitUtils',jvm_fields=[JavaFieldDef("a", "Landroid/app/Application;", True, Application())]):

jvm_fields : 是类的成员变量, 参考 androidemu/java/java_field_def.py 的定义

由于这是个静态的成员变量,类型是 Application , 所以咱们还得搞个 Application 类。

完整代码如下:

class Application(metaclass=JavaClassDef, jvm_name='android/app/Application'):
    def __init__(self):
        pass

class BitmapkitUtils(metaclass=JavaClassDef, jvm_name='com/jingdong/common/utils/BitmapkitUtils',jvm_fields=[JavaFieldDef("a", "Landroid/app/Application;", True, Application())]):

    def __init__(self):
        pass

emulator.java_classloader.add_class(Application)
emulator.java_classloader.add_class(BitmapkitUtils)

继续跑

RuntimeError: Could not find class 'android/app/Activity' for JNIEnv.

搞上它

class Application(metaclass=JavaClassDef, jvm_name='android/app/Application'):
    def __init__(self):
        pass

class Activity(metaclass=JavaClassDef, jvm_name='android/app/Activity'):
    def __init__(self):
        pass

class BitmapkitUtils(metaclass=JavaClassDef, jvm_name='com/jingdong/common/utils/BitmapkitUtils',jvm_fields=[JavaFieldDef("a", "Landroid/app/Application;", True, Application())]):

    def __init__(self):
        pass


    emulator.java_classloader.add_class(Application)
    emulator.java_classloader.add_class(Activity)
    emulator.java_classloader.add_class(BitmapkitUtils)

还跑

RuntimeError: Could not find class 'android/content/pm/Signature' for JNIEnv.

再搞

RuntimeError: Could not find method ('getPackageManager', '()Landroid/content/pm/PackageManager;') in class android/app/Activity.

这说明啥,说明在 android/app/Activity 类中有个成员函数 getPackageManager, 参数为空 () 返回值是 Landroid/content/pm/PackageManager;

类咱们今天就搞到这里吧,成员函数明天搞 m(._.)m

100

关注微信公众号,最新技术干货实时推送

100