一、目标

一、目标

今天的我们来尝试载入某电商App的签名so文件来计算签名,在调用这个so的过程中有一些需要我们处理的坑,不过在之前的 AndroidNativeEmu模拟执行计算出某电商App sign 的教程中,我们已经了解了如何处理,不熟悉的同学可以复习下。

二、步骤

先把目标so放到我们的工程目录 /app/src/main/jniLibs 中,目录结构如下:

dir
1:dir

构造调用so签名函数的类

utilscls
1:utilscls

我们要调用这个 getSignFromJni 函数,就需要在我们的工程里面构造 com.xxx.common.utils.xxxUtils 这个类。

package com.xxx.common.utils;

import android.app.Application;
import android.content.Context;
public class xxxUtils {

    // 载入 lib
       static {
        System.loadLibrary("xxxkit");
    }

    public static native String getSignFromJni(Context context, String str, String str2, String str3, String str4, String str5);
}

这里我们先用静态的方法自动载入so。然后调用 BitmapkitUtils.getSignFromJni函数。

duang…​. 程序闪退。 我们从Logcat窗口看到如下报错信息:

JNI GetStaticObjectField called with pending exception java.lang.NoSuchFieldError: no "Landroid/app/Application;" field "a" in class "Lcom/xxx/common/utils/xxxUtils;" or its superclasses

哦,com.xxx.common.utils.xxxUtils 这类里面有个成员变量 a 类型是 android/app/Application, 没有找到。那就补上它,光补上还不行,从jadx的结果可以看到这个 a 变量是个静态成员,还需要初始化。 我们在 MyApp::onCreate()中初始化它:

public void onCreate() {
...
         BitmapkitUtils.a = this;
 ...
 }

继续执行,这次的报错是

JNI DETECTED ERROR IN APPLICATION: can't call android.content.pm.PackageManager android.content.ContextWrapper.getPackageManager() on null object

这个有点摸不着头脑,貌似是说有个null指针被访问了。这就体现之前学过 AndroidNativeEmu模拟执行计算出某电商App sign 的好处了,我们知道在so的 JNI_OnLoad 函数中, Application 这个对象被使用了。

说明 BitmapkitUtils.a = this; 这个初始化要在 载入so运行JNI_OnLoad之前。我们之前的做法是静态载入的so,JNI_OnLoad的函数执行要早于 BitmapkitUtils.a = this;, 所以我们改一下:

package com.xxx.common.utils;

import android.app.Application;
import android.content.Context;
public class xxxUtils {

        public static Application a;

    public static void loadso(){
        try {
            System.loadLibrary("jdbitmapkit");
        }catch(Throwable ex){
            ex.printStackTrace();
        }
    }
    public static native String getSignFromJni(Context context, String str, String str2, String str3, String str4, String str5);
}

// MyApp::onCreate
public void onCreate() {
...
        BitmapkitUtils.a = this;
    BitmapkitUtils.loadso();
 ...
 }

确保在loadso之前初始化好 a

开始Hook了

这so在做签名之前,会先检查自己的包名和包签名,所以我们要hook这两个函数,给它返回原本的值

// com/fenfei/loadso/SignatureHooker.java
@HookClass(Signature.class)
public class SignatureHooker {
    @HookMethodBackup("toByteArray")
    static Method onToByteArrayBackup;

    @HookMethod("toByteArray")
    public static byte[] onToByteArray(@ThisObject Signature thiz) throws Throwable {
        Log.e("SignatureHooker", thiz + "hooked toByteArray success ");

        return hexStringToBytes("30820247308201b0a00302010202044d6c5dae300d06092a.......");
    }


    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

        }
        return d;
    }
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

}


// com/fenfei/loadso/MainActivityHooker.java
@HookClass(ContextWrapper.class)
public class MainActivityHooker {

    @HookMethodBackup("getPackageName")
    static Method onGetPackageNameBackup;

    @HookMethod("getPackageName")
    public static String onGetPackageName(@ThisObject ContextWrapper thiz) throws Throwable {
        String strPkg = (String)SandHook.callOriginByBackup(onGetPackageNameBackup, thiz);

       if (thiz.getClass().equals(MyApp.class)){
           Log.e("MainActivityHooker", thiz + "hooked getPackageName success rc= com.xxx.app.mall");
           return "com.xxx.app.mall";
       }else{
            return strPkg;
        }
    }
}

这次再调用下 BitmapkitUtils.getSignFromJni函数,就可以成功返回签名了

st=1608693949758&sign=1e1cd9e02f639fc4dacab8c71710bfd4&sv=111

但是如果不解决这个问题,so还是没法载入的。 在 借鸡生蛋之某电商App签名so的使用(三) 中我们介绍如何 Patch so 来填这个坑。

三、总结

看来借鸡生蛋还是不容易的,如果没有之前 AndroidNativeEmu模拟执行计算出某电商App sign 的经验,可能我们就已经放弃了。

不过这样间接的说明了AndroidNativeEmu和unidbg的价值,可以辅助我们分析so的执行流程。起码比直接面对Arm汇编要强。

100

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

100