Android逆向-Kingroot原理简析(未完待续)

对安卓root软件Kingroot的Root原理的简单逆向分析。

1.背景知识

A.获取设备上正在运行的app信息

1、Android5.0以下——

((ActivityManager.RunningAppProcessInfo)((ActivityManager)paramContext.getSystemService("activity")).getRunningAppProcesses().get(0)).processName;

2、Android5.0——

((ActivityManager.RunningTaskInfo)((ActivityManager)paramContext.getSystemService("activity")).getRunningTasks(1).get(0)).topActivity;

3、Android5.1及以上——Android限制了此功能的使用,只有申请了permission.REAL_GET_TASKS权限的系统应用才能使用此功能。此种情况下可参考此处,选择其他方式(如AccessibilityService)进行获取。

android 5.1及以上获取正在运行的app(top app)

B.通过Thread,Looper和Handler实现线程通信

其实Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler。最终消息由looper交由Handler处理,即Handler的dispatchmessage方法会被调用,这是Handler就进入处理消息的阶段。图解Looper , Handler , Message 这三者关系。

如下述代码示例——

MainActivity.java

public class MainActivity extends Activity {
public static final String TAG = "Main Acticity";
Button btn = null;
Button btn2 = null;
Handler handler = null;
MyHandlerThread mHandlerThread = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = (Button)findViewById(R.id.button);
    btn2 = (Button)findViewById(R.id.button2);
    Log.d("MainActivity.myLooper()", Looper.myLooper().toString());
    Log.d("MainActivity.MainLooper", Looper.getMainLooper().toString());


    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mHandlerThread = new MyHandlerThread("onStartHandlerThread");
            Log.d(TAG, "创建myHandlerThread对象");
            mHandlerThread.start();
            Log.d(TAG, "start一个Thread");
        }
    });

    btn2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(mHandlerThread.mHandler != null){
                Message msg = new Message();
                msg.what = 1;
                mHandlerThread.mHandler.sendMessage(msg);
            }

        }
    });
}

MyHandlerThread.java

public class MyHandlerThread extends Thread {
public static final String TAG = "MyHT";

public Handler mHandler = null;

@Override
public void run() {
    Log.d(TAG, "进入Thread的run");
    Looper.prepare();
    Looper.prepare();
    mHandler = new Handler(Looper.myLooper()){
        @Override
        public void handleMessage(Message msg){
            Log.d(TAG, "获得了message");
            super.handleMessage(msg);
        }
    };
    Looper.loop();
}

Android中的Thread, Looper和Handler机制(附带HandlerThread与AsyncTask)
Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系

C.APP正版验证机制

从方法上分类可分为:文件完整性校验、签名校验、混合校验(二者都有);从校验代码所处层面进行分类可分为:Java层校验、So层校验和混合校验(如在Java层获取APP签名信息,在So层进行校验)。

在破解APP正版验证机制时,可从以下步骤入手——

  1. 解压APK,删除原签名,重打包,若安装后提示版本错误,则为签名验证机制,若能正常运行,则不包含签名验证机制;
  2. 修改APK中的代码后重打包,若安装后提示版本错误,而且程序中不包含签名验证机制或签名验证机制已被破解,则为DEX校验;
  3. 在判断出有以上校验机制后,断开网络连接,以判断校验机制是本地的还是服务器端的。

Android签名机制
Android签名攻与防
APP 完整性校验

2.逆向分析

该APP并未加壳,可直接分析其代码。

A.找入手点

一般Android APP逆向有以下快速定位到分析点的方式。

  • 根据运行过程中的日志信息,或界面上的关键字符串,在代码中搜索定位。
  • 根据资源文件(如string.xml)中的关键字符串进行搜索定位。
  • 根据抓到的关键数据包,在代码中搜索定位。
  • 根据APP包名和类名进行可疑类的定位和分析(如寻找包名目录下类名中带ROOT的关键类)。效率较低不推荐。
  • 直接在手机上运行到关键界面,然后获取界面信息(具体的Activity名字),就可以快速定位到关键代码。

B.具体分析

最开始分析的时候,定位到关键代码后,由于不是很熟悉HandlermessageLooper的具体操作(但是代码中采用了较多相关操作),所以分析起来比较吃力。于是去了解了相关的基础知识,再进行分析,看起来就轻松很多。另外,也不能一味的静态分析,在静态分析获取到关键类/方法后,可通过动态调试辅助分析(如获取参数等)。

由于动态调试需求,添加了android:debuggable=”true”,重打包了应用程序,但运行时触发了报错。解决这个问题的2种方法:(1)自定义Android系统;(2)破掉apk中的签名/apk完整性验证机制。

(1)破掉apk正版验证机制

通过关键词verificaionSignatureskillcheck等入手,先静态分析定位可能的关键代码位置,然后尝试动态调试辅助思考如何改变返回参数。

注意程序中可能存在的迷惑性方法,比如在分析过程中发现在2个smali类中都发现了checkSignatures方法,但只有方法的定义,在JAVA层中并没有对此方法的调用,当然有可能是在so层调用,但是在apk的so文件中也没有看到相关调用方法,所以对此方法的改变并没有办法破解掉正版验证机制。

首先判断出该APK的正版校验机制是本地的签名校验,接下来就需要找出关键验证函数(通过关键词缩小范围),实现破解。