对某APP的逆向之旅(2)

来源:互联网 发布:mysql破解教程 编辑:程序博客网 时间:2024/06/05 06:46

接着上面的分析过程,继续
本次分析下java层和ndk通信的框架
首先,执行上一节分析中解密的文件,如下:
这里写图片描述

继续分析:

private static int a(Context context, String arg13) {        int v9 = 3;        int v4 = -1;        int v1 = 0;        Runtime.getRuntime().exec("chmod 755 " + arg13);        String[] v0 = new String[v9];        v0[0] = "su";        v0[1] = "-c";        v0[2] = arg13;        Log.d("TAG", Build.CPU_ABI + " - -" + Build.CPU_ABI2 + " -- " + System.getProperty("os.arch"));        Process decodeExe = Runtime.getRuntime().exec(v0);        q ServerSocketThread = new q();        ServerSocketThread.start();        RootManager.waitThread(((Thread)ServerSocketThread));        int v2 = decodeExe.getErrorStream().read();        if(v2 != 120) {            Log.d("TAG", "RE:" + v2);            return v4;        }        ServerSocketThread.getPort();        q serverSocket_1 = ServerSocketThread;        int v0_2 = 0;    label_51:        if(!serverSocket_1.isAlive()) {            serverSocket_1 = new q();            serverSocket_1.start();        }        RootManager.waitThread(((Thread)serverSocket_1));        int localPort = serverSocket_1.getPort();        if(v0_2 > v9 && localPort == 0) {            v0_2 = 1;            goto label_60;        }        long v7 = 100;        try {            Thread.sleep(v7);        }        catch(InterruptedException v7_1) {            v7_1.printStackTrace();        }        ++v0_2;        if(localPort == 0) {            goto label_51;        }        v0_2 = 0;    label_60:        OutputStreamWriter v3 = new OutputStreamWriter(decodeExe.getOutputStream());        v3.write(String.valueOf(localPort) + "\n");        v3.flush();        if(v0_2 != 0) {            g.a(context).setProcess(decodeExe);            g.a(context).initStream(decodeExe.getInputStream(), decodeExe.getOutputStream());            return v1;        }        try {            serverSocket_1.join();            long v6_1 = SystemClock.uptimeMillis();        label_89:            Socket receiveSocket = serverSocket_1.getReceiveSocket();            if(receiveSocket == null) {                if(SystemClock.uptimeMillis() - v6_1 > 32000) {                    return -3;                }                serverSocket_1.run();                Log.d("TAG", "Check alive2");                goto label_89;            }            g.a(context).setProcess(decodeExe);            g.a(context).initStream(receiveSocket.getInputStream(), receiveSocket.getOutputStream());        }        catch(InterruptedException v0_3) {            Log.d("TAG", "InterruptedExceptioned");            decodeExe.destroy();            v1 = v4;        }        return v1;    }

里面函数名我已经改成了容易识别的名字。该函数的流程如下:
1、修改执行文件的权限,执行文件。
2、创建socket服务端,监听socket连接数据。
3、通过检查socket服务端的本地端口,检查创建是否成功,成功,则通过socket通信(receiveSocket.getInputStream()、 receiveSocket.getOutputStream()),否则直接通过进程通信(decodeExe.getInputStream(), decodeExe.getOutputStream())。
下面看下通信框架,主要在下面的两个函数中
1、g.a(context).setProcess()
2、g.a(context).initStream(,)
第一个函数比较简单,就是将子进程传递进去。如下:

    public void setProcess(Process arg1) {        this.c = arg1;    }

主要看第二个函数,如下:

    public void initStream(InputStream arg3, OutputStream arg4) {        this.d = new BufferedReader(new InputStreamReader(arg3));        this.e = new DataOutputStream(arg4);        new p(this, null).start();    }

初始化了输入输出流,然后执行了一个线程,来到线程p看看,

public void run() {        long v1_1;        String v0_3;        Object v1;        BufferedReader v5 = null;        if(g.a(this.a) != null) {            try {                while(true) {                label_5:                    v1 = g.a;                    __monitor_enter(v1);                    break;                }            }            catch(InterruptedException v0) {                goto label_40;            }            catch(IOException v0_1) {                goto label_29;            }            try {                Log.w("xltest", "get lock mReader");                v0_3 = g.a(this.a).readLine();                Log.w("xltest", "release lock..mReader,=" + v0_3);                __monitor_exit(v1);                v1_1 = 10;            }            catch(Throwable v0_2) {                goto label_37;            }            try {                Thread.sleep(v1_1);                if(v0_3 == null) {                    goto label_5;                }                g.a(this.a, v0_3);                goto label_5;            }            catch(InterruptedException v0) {                goto label_40;            }            catch(IOException v0_1) {                goto label_29;            }            try {            label_37:                __monitor_exit(v1_1);            }            catch(Throwable v0_2) {                goto label_37;            }            try {                throw v0_2;            }            catch(InterruptedException v0) {            label_40:                v0.printStackTrace();            }            catch(IOException v0_1) {            label_29:                Log.w("GameSpeed", "reader thread", ((Throwable)v0_1));                g.a(this.a, v5);                g.a(this.a, ((DataOutputStream)v5));            }            super.run();        }    }

看起来比较复杂,其实实质的内容很少,主要逻辑如下:

v0_3 = g.a(this.a).readLine();Thread.sleep(v1_1);g.a(this.a, v0_3);

我们再来看最后一个函数,这个函数主要是用来接收socket消息的,函数名已经修改过:

    static boolean a(g arg1, String arg2) {        return arg1.sendLocalBroadcast(arg2);    }    private boolean sendLocalBroadcast(String arg6) {        boolean v0 = true;        if(!arg6.startsWith("key")) {            goto label_24;        }        if(as.b(this.h, "setting_volume", false)) {            String v1 = arg6.split(":")[1];            c v2 = c.a(this.h);            Intent v3 = new Intent();            v3.setAction("sb.key.pressed");            v3.putExtra("key", v1);            v2.a(v3);  // 发送本地广播        }        else {            Log.d("key", arg6);            return v0;        label_24:            Log.d("xltest", "update=" + arg6);            v0 = false;        }        return v0;    }

发送消息的函数为(只列举设置和停止):

    public void sendMsg(int arg4) {        try {            this.e.writeBytes("t set " + arg4 + "\n");            this.e.flush();        }        catch(IOException v0) {            v0.printStackTrace();            this.b();        }    }    public void a() {        Log.d("xltest", "resetSystemTime");        try {            this.e.writeBytes("t stop\n");            this.e.flush();        }        catch(IOException v0) {            v0.printStackTrace();            this.b();        }    }

就是通过本地广播,实现java层和ndk层的通信。
NDK层的分析,有时间再写吧!

0 0
原创粉丝点击