接着上面的分析过程,继续
本次分析下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层的分析,有时间再写吧!