【i春秋】第十届全国大学生信息安全大赛之逆向--apk题目
本帖最后由 skywilling 于 2017-7-20 20:02 编辑0x00前言
今天很高兴为大家带来第十届全国大学生信息安全大赛之逆向--apk题目的writeup。到目前为止,我还没看过官方的writeup或者其他人的writeup,所以不保证本文章的解题思路是最简单易懂,当然,我会尽量讲解的详细一点。需要注意的是,本文章需要读者熟悉smali语言。下面正式开始讲解。
0x01运行
一般像这种比赛的apk题目是不会加壳的,所以,直接跳过查壳的步骤,运行apk。
标准模式的Android题目,一个输入框,一个按钮以及一个输出框,输出的数据也十分简单。
0x02反编译
看了apk的运行效果之后,直接放入jadx中进行反编译(相比于其他的反编译软件,我更喜欢jadx)。
首先,我们需要找到入口Activity,在AndroidManifest.xml中我们可以很清楚的看到入口Activity为com.example.ichunqiu2.P_ichunqiu
接下来直接打开对应的类P_ichunqiu,可以看到反编译后的Java代码:
public class P_ichunqiu extends Activity {
public static String A = "";
public static String B = "";
private Class<?> clazz;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_p_ichunqiu);
((Button) findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
TextView show = (TextView) P_ichunqiu.this.findViewById(R.id.textView1);
String words = ((EditText) P_ichunqiu.this.findViewById(R.id.editText1)).getText().toString();
wick.show(words);
if (new simple(words).check()) {
show.setText(P_ichunqiu.A);
} else {
show.setText(P_ichunqiu.B);
}
}
});
}
这段Java代码的逻辑很清晰,变量words中保存着要输入的数据,然后传入wick类的show方法中,接下来就是一个条件判断语句,条件成立要求simple类中的check方法返回值为true。下面依次查看wick类和simple类:
wick类:
public class wick {
public static native boolean a();
static {
System.loadLibrary("P_jni");
}
public static String show(String A) {
return a() ? A : A;
}
}
show方法就是直接返回了传入的字符串,并没有对字符串做什么处理,如果要深究的话,show方法中调用native层中的方法a为P_ichunqiu.A和P_ichunqiu.B赋值,也就是要输出的数据。
simple类:
package com.example.ichunqiu2;
public class simple {
private byte[] A = new byte;
private byte[] B;
public simple(String a) {
this.B = a.getBytes();
for (int i = 0; i < this.B.length; i++) {
this.A = this.B;
}
this.B = new byte;
}
/* JADX WARNING: inconsistent code. */
/* Code decompiled incorrectly, please refer to instructions dump. */
public boolean check() {
/*
r14 = this;
r13 = 77;
r12 = 49;
r11 = 57;
r10 = 50;
r9 = 48;
r7 = 203; // 0xcb float:2.84E-43 double:1.003E-321;
r2 = new byte;
r7 = 0;
r8 = 47;
r2 = r8;
r7 = 1;
r2 = r9;
r7 = 2;
r8 = 81;
r2 = r8;
r7 = 3;
r8 = 82;
r2 = r8;
r7 = 4;
r8 = 79;
r2 = r8;
r7 = 5;
r8 = 54;
r2 = r8;
r7 = 6;
r2 = r13;
r7 = 7;
r2 = r9;
r7 = 8;
r2 = r10;
r7 = 9;
r2 = r9;
r7 = 10;
r2 = r9;
r7 = 11;
r8 = 47;
r2 = r8;
r7 = 12;
r2 = r9;
r7 = 13;
r8 = 65;
r2 = r8;
r7 = 14;
r8 = 54;
r2 = r8;
r7 = 15;
r2 = r13;
r7 = 16;
r2 = r9;
r7 = 17;
r2 = r10;
r7 = 18;
r2 = r9;
r7 = 19;
r2 = r9;
r7 = 20;
r8 = 47;
r2 = r8;
r7 = 21;
r2 = r11;
r7 = 22;
r2 = r11;
r7 = 23;
r8 = 70;
r2 = r8;
r7 = 24;
r2 = r9;
r7 = 25;
r8 = 47;
r2 = r8;
r7 = 26;
r2 = r12;
r7 = 27;
r2 = r9;
r7 = 28;
r8 = 56;
r2 = r8;
r7 = 29;
r8 = 70;
r2 = r8;
r7 = 30;
r2 = r12;
r7 = 31;
r8 = 47;
r2 = r8;
r7 = 32;
r2 = r12;
r7 = 33;
r2 = r12;
r7 = 34;
r2 = r12;
r7 = 35;
r8 = 70;
r2 = r8;
r7 = 36;
r2 = r10;
r7 = 37;
r8 = 47;
r2 = r8;
r7 = 38;
r8 = 53;
r2 = r8;
r7 = 39;
r8 = 51;
r2 = r8;
r7 = 40;
r8 = 70;
r2 = r8;
r7 = 41;
r8 = 51;
r2 = r8;
r7 = 42;
r8 = 47;
r2 = r8;
r7 = 43;
r2 = r12;
r7 = 44;
r2 = r9;
r7 = 45;
r2 = r12;
r7 = 46;
r8 = 70;
r2 = r8;
r7 = 47;
r8 = 52;
r2 = r8;
r7 = 47;
r2 = r7;
r2 = r12;
r2 = r12;
r7 = 51;
r8 = 52;
r2 = r8;
r7 = 52;
r8 = 70;
r2 = r8;
r7 = 53;
r8 = 53;
r2 = r8;
r7 = 54;
r8 = 47;
r2 = r8;
r7 = 55;
r2 = r9;
r7 = 56;
r8 = 70;
r2 = r8;
r7 = 54;
r2 = r7;
r7 = 58;
r8 = 79;
r2 = r8;
r7 = 59;
r2 = r9;
r7 = 60;
r8 = 71;
r2 = r8;
r7 = 61;
r2 = r9;
r7 = 62;
r2 = r13;
r7 = 63;
r2 = r9;
r7 = 64;
r2 = r9;
r7 = 65;
r2 = r10;
r7 = 66;
r2 = r9;
r7 = 67;
r2 = r9;
r7 = 68;
r8 = 65;
r2 = r8;
r7 = 69;
r2 = r9;
r7 = 70;
r8 = 68;
r2 = r8;
r7 = 71;
r2 = r9;
r7 = 72;
r2 = r13;
r7 = 73;
r2 = r9;
r7 = 74;
r2 = r9;
r7 = 75;
r2 = r10;
r7 = 76;
r2 = r9;
r2 = r9;
r7 = 78;
r8 = 79;
r2 = r8;
r7 = 79;
r2 = r12;
r7 = 80;
r8 = 71;
r2 = r8;
r7 = 81;
r2 = r12;
r7 = 82;
r2 = r13;
r7 = 83;
r2 = r9;
r7 = 84;
r2 = r9;
r7 = 85;
r2 = r10;
r7 = 86;
r2 = r9;
r7 = 87;
r2 = r9;
r7 = 88;
r8 = 65;
r2 = r8;
r7 = 89;
r2 = r12;
r7 = 90;
r8 = 68;
r2 = r8;
r7 = 91;
r2 = r12;
r7 = 92;
r2 = r13;
r7 = 93;
r2 = r9;
r7 = 94;
r2 = r9;
r7 = 95;
r2 = r10;
r7 = 96;
r2 = r9;
r7 = 97;
r2 = r9;
r7 = 98;
r8 = 79;
r2 = r8;
r7 = 99;
r2 = r10;
r7 = 100;
r8 = 71;
r2 = r8;
r7 = 101; // 0x65 float:1.42E-43 double:5.0E-322;
r2 = r10;
r7 = 102; // 0x66 float:1.43E-43 double:5.04E-322;
r2 = r13;
r7 = 103; // 0x67 float:1.44E-43 double:5.1E-322;
r2 = r9;
r7 = 104; // 0x68 float:1.46E-43 double:5.14E-322;
r2 = r9;
r7 = 105; // 0x69 float:1.47E-43 double:5.2E-322;
r2 = r10;
r7 = 106; // 0x6a float:1.49E-43 double:5.24E-322;
r2 = r9;
r7 = 107; // 0x6b float:1.5E-43 double:5.3E-322;
r2 = r9;
r7 = 108; // 0x6c float:1.51E-43 double:5.34E-322;
r8 = 65;
r2 = r8;
r7 = 109; // 0x6d float:1.53E-43 double:5.4E-322;
r2 = r10;
r7 = 110; // 0x6e float:1.54E-43 double:5.43E-322;
r8 = 68;
r2 = r8;
r7 = 111; // 0x6f float:1.56E-43 double:5.5E-322;
r2 = r10;
r7 = 112; // 0x70 float:1.57E-43 double:5.53E-322;
r2 = r13;
r7 = 113; // 0x71 float:1.58E-43 double:5.6E-322;
r2 = r9;
r7 = 114; // 0x72 float:1.6E-43 double:5.63E-322;
r2 = r9;
r7 = 115; // 0x73 float:1.61E-43 double:5.7E-322;
r2 = r10;
r7 = 116; // 0x74 float:1.63E-43 double:5.73E-322;
r2 = r9;
r7 = 117; // 0x75 float:1.64E-43 double:5.8E-322;
r2 = r9;
r7 = 118; // 0x76 float:1.65E-43 double:5.83E-322;
r8 = 79;
r2 = r8;
r7 = 119; // 0x77 float:1.67E-43 double:5.9E-322;
r8 = 51;
r2 = r8;
r7 = 120; // 0x78 float:1.68E-43 double:5.93E-322;
r8 = 71;
r2 = r8;
r7 = 121; // 0x79 float:1.7E-43 double:6.0E-322;
r8 = 51;
r2 = r8;
r7 = 122; // 0x7a float:1.71E-43 double:6.03E-322;
r2 = r13;
r7 = 123; // 0x7b float:1.72E-43 double:6.1E-322;
r2 = r9;
r7 = 124; // 0x7c float:1.74E-43 double:6.13E-322;
r2 = r9;
r7 = 125; // 0x7d float:1.75E-43 double:6.2E-322;
r2 = r10;
r7 = 126; // 0x7e float:1.77E-43 double:6.23E-322;
r2 = r9;
r7 = 127; // 0x7f float:1.78E-43 double:6.27E-322;
r2 = r9;
r7 = 128; // 0x80 float:1.794E-43 double:6.32E-322;
r8 = 65;
r2 = r8;
r7 = 129; // 0x81 float:1.81E-43 double:6.37E-322;
r8 = 51;
r2 = r8;
r7 = 130; // 0x82 float:1.82E-43 double:6.4E-322;
r8 = 68;
r2 = r8;
r7 = 131; // 0x83 float:1.84E-43 double:6.47E-322;
r8 = 51;
r2 = r8;
r7 = 132; // 0x84 float:1.85E-43 double:6.5E-322;
r2 = r13;
r7 = 133; // 0x85 float:1.86E-43 double:6.57E-322;
r2 = r9;
r7 = 134; // 0x86 float:1.88E-43 double:6.6E-322;
r2 = r9;
r7 = 135; // 0x87 float:1.89E-43 double:6.67E-322;
r2 = r10;
r7 = 136; // 0x88 float:1.9E-43 double:6.7E-322;
r2 = r9;
r7 = 137; // 0x89 float:1.92E-43 double:6.77E-322;
r2 = r9;
r7 = 138; // 0x8a float:1.93E-43 double:6.8E-322;
r8 = 79;
r2 = r8;
r7 = 139; // 0x8b float:1.95E-43 double:6.87E-322;
r8 = 52;
r2 = r8;
r7 = 140; // 0x8c float:1.96E-43 double:6.9E-322;
r8 = 71;
r2 = r8;
r7 = 141; // 0x8d float:1.98E-43 double:6.97E-322;
r8 = 52;
r2 = r8;
r7 = 142; // 0x8e float:1.99E-43 double:7.0E-322;
r2 = r13;
r7 = 143; // 0x8f float:2.0E-43 double:7.07E-322;
r2 = r9;
r7 = 144; // 0x90 float:2.02E-43 double:7.1E-322;
r2 = r9;
r7 = 145; // 0x91 float:2.03E-43 double:7.16E-322;
r2 = r10;
r7 = 146; // 0x92 float:2.05E-43 double:7.2E-322;
r2 = r9;
r7 = 147; // 0x93 float:2.06E-43 double:7.26E-322;
r2 = r9;
r7 = 148; // 0x94 float:2.07E-43 double:7.3E-322;
r8 = 65;
r2 = r8;
r7 = 149; // 0x95 float:2.09E-43 double:7.36E-322;
r8 = 52;
r2 = r8;
r7 = 150; // 0x96 float:2.1E-43 double:7.4E-322;
r8 = 68;
r2 = r8;
r7 = 151; // 0x97 float:2.12E-43 double:7.46E-322;
r8 = 52;
r2 = r8;
r7 = 152; // 0x98 float:2.13E-43 double:7.5E-322;
r2 = r13;
r7 = 153; // 0x99 float:2.14E-43 double:7.56E-322;
r2 = r9;
r7 = 154; // 0x9a float:2.16E-43 double:7.6E-322;
r2 = r9;
r7 = 155; // 0x9b float:2.17E-43 double:7.66E-322;
r2 = r10;
r7 = 156; // 0x9c float:2.19E-43 double:7.7E-322;
r2 = r9;
r7 = 157; // 0x9d float:2.2E-43 double:7.76E-322;
r2 = r9;
r7 = 158; // 0x9e float:2.21E-43 double:7.8E-322;
r8 = 79;
r2 = r8;
r7 = 159; // 0x9f float:2.23E-43 double:7.86E-322;
r8 = 53;
r2 = r8;
r7 = 160; // 0xa0 float:2.24E-43 double:7.9E-322;
r8 = 71;
r2 = r8;
r7 = 161; // 0xa1 float:2.26E-43 double:7.95E-322;
r8 = 53;
r2 = r8;
r7 = 162; // 0xa2 float:2.27E-43 double:8.0E-322;
r2 = r13;
r7 = 163; // 0xa3 float:2.28E-43 double:8.05E-322;
r2 = r9;
r7 = 164; // 0xa4 float:2.3E-43 double:8.1E-322;
r2 = r9;
r7 = 165; // 0xa5 float:2.31E-43 double:8.15E-322;
r2 = r10;
r7 = 166; // 0xa6 float:2.33E-43 double:8.2E-322;
r2 = r9;
r7 = 167; // 0xa7 float:2.34E-43 double:8.25E-322;
r2 = r9;
r7 = 168; // 0xa8 float:2.35E-43 double:8.3E-322;
r8 = 65;
r2 = r8;
r7 = 169; // 0xa9 float:2.37E-43 double:8.35E-322;
r8 = 53;
r2 = r8;
r7 = 170; // 0xaa float:2.38E-43 double:8.4E-322;
r8 = 68;
r2 = r8;
r7 = 171; // 0xab float:2.4E-43 double:8.45E-322;
r8 = 53;
r2 = r8;
r7 = 172; // 0xac float:2.41E-43 double:8.5E-322;
r2 = r13;
r7 = 173; // 0xad float:2.42E-43 double:8.55E-322;
r2 = r9;
r7 = 174; // 0xae float:2.44E-43 double:8.6E-322;
r2 = r9;
r7 = 175; // 0xaf float:2.45E-43 double:8.65E-322;
r2 = r10;
r7 = 176; // 0xb0 float:2.47E-43 double:8.7E-322;
r2 = r9;
r7 = 177; // 0xb1 float:2.48E-43 double:8.74E-322;
r2 = r9;
r7 = 178; // 0xb2 float:2.5E-43 double:8.8E-322;
r8 = 47;
r2 = r8;
r7 = 179; // 0xb3 float:2.51E-43 double:8.84E-322;
r2 = r12;
r7 = 200; // 0xc8 float:2.8E-43 double:9.9E-322;
r8 = 47;
r2 = r8;
r7 = 201; // 0xc9 float:2.82E-43 double:9.93E-322;
r2 = r9;
r3 = 0;
r0 = 0;
r1 = 0;
r7 = 1000; // 0x3e8 float:1.401E-42 double:4.94E-321;
r5 = new byte;
r4 = 0;
r6 = 0;
L_0x0365:
r7 = r2;
switch(r7) {
case 0: goto L_0x053a;
case 47: goto L_0x0521;
case 65: goto L_0x041d;
case 66: goto L_0x04e8;
case 67: goto L_0x04de;
case 68: goto L_0x0455;
case 69: goto L_0x0377;
case 70: goto L_0x0471;
case 71: goto L_0x048d;
case 72: goto L_0x04a9;
case 73: goto L_0x03cc;
case 74: goto L_0x04c5;
case 75: goto L_0x04ca;
case 76: goto L_0x04cf;
case 77: goto L_0x0506;
case 78: goto L_0x04ed;
case 79: goto L_0x03e5;
case 80: goto L_0x0401;
case 81: goto L_0x036d;
case 82: goto L_0x037c;
case 83: goto L_0x0439;
case 84: goto L_0x0381;
case 85: goto L_0x03b3;
case 86: goto L_0x04e3;
case 87: goto L_0x0372;
case 88: goto L_0x04d9;
case 89: goto L_0x039a;
case 90: goto L_0x04d4;
default: goto L_0x036a;
};
L_0x036a:
r3 = r3 + 1;
goto L_0x0365;
L_0x036d:
r5 = r0;
r4 = r4 + 1;
goto L_0x036a;
L_0x0372:
r4 = r4 + -1;
r0 = r5;
goto L_0x036a;
L_0x0377:
r5 = r1;
r4 = r4 + 1;
goto L_0x036a;
L_0x037c:
r4 = r4 + -1;
r1 = r5;
goto L_0x036a;
L_0x0381:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x0396;
L_0x0390:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x0381;
L_0x0396:
r0 = r5;
r6 = 0;
goto L_0x036a;
L_0x039a:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x03af;
L_0x03a9:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x039a;
L_0x03af:
r5 = r0;
r6 = 0;
goto L_0x036a;
L_0x03b3:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x03c8;
L_0x03c2:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x03b3;
L_0x03c8:
r1 = r5;
r6 = 0;
goto L_0x036a;
L_0x03cc:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x03e1;
L_0x03db:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x03cc;
L_0x03e1:
r5 = r1;
r6 = 0;
goto L_0x036a;
L_0x03e5:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x03fa;
L_0x03f4:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x03e5;
L_0x03fa:
r7 = r14.A;
r0 = r7;
r6 = 0;
goto L_0x036a;
L_0x0401:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x0416;
L_0x0410:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x0401;
L_0x0416:
r7 = r14.A;
r7 = r0;
r6 = 0;
goto L_0x036a;
L_0x041d:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x0432;
L_0x042c:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x041d;
L_0x0432:
r7 = r14.A;
r1 = r7;
r6 = 0;
goto L_0x036a;
L_0x0439:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x044e;
L_0x0448:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x0439;
L_0x044e:
r7 = r14.A;
r7 = r1;
r6 = 0;
goto L_0x036a;
L_0x0455:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x046a;
L_0x0464:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x0455;
L_0x046a:
r7 = r14.B;
r0 = r7;
r6 = 0;
goto L_0x036a;
L_0x0471:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x0486;
L_0x0480:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x0471;
L_0x0486:
r7 = r14.B;
r7 = r0;
r6 = 0;
goto L_0x036a;
L_0x048d:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x04a2;
L_0x049c:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x048d;
L_0x04a2:
r7 = r14.B;
r1 = r7;
r6 = 0;
goto L_0x036a;
L_0x04a9:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x04be;
L_0x04b8:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x04a9;
L_0x04be:
r7 = r14.B;
r7 = r1;
r6 = 0;
goto L_0x036a;
L_0x04c5:
r7 = r0 ^ r1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04ca:
r7 = r0 | r1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04cf:
r7 = r0 & r1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04d4:
r7 = r0 ^ -1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04d9:
r7 = r0 + r1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04de:
r7 = r0 - r1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04e3:
r7 = r0 * r1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04e8:
r7 = r0 / r1;
r0 = (byte) r7;
goto L_0x036a;
L_0x04ed:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x0502;
L_0x04fc:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x04ed;
L_0x0502:
r3 = r6;
r6 = 0;
goto L_0x0365;
L_0x0506:
if (r0 >= r1) goto L_0x036a;
L_0x0508:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x051d;
L_0x0517:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x0508;
L_0x051d:
r3 = r6;
r6 = 0;
goto L_0x0365;
L_0x0521:
r3 = r3 + 1;
r6 = r6 * 10;
r7 = r2;
r7 = r7 + r6;
r6 = r7 + -48;
r7 = r3 + 1;
r7 = r2;
if (r7 > r11) goto L_0x0536;
L_0x0530:
r7 = r3 + 1;
r7 = r2;
if (r7 >= r9) goto L_0x0521;
L_0x0536:
r0 = (byte) r6;
r6 = 0;
goto L_0x036a;
L_0x053a:
if (r0 == 0) goto L_0x053e;
L_0x053c:
r7 = 1;
L_0x053d:
return r7;
L_0x053e:
r7 = 0;
goto L_0x053d;
*/
throw new UnsupportedOperationException("Method not decompiled: com.example.ichunqiu2.simple.check():boolean");
}
}
看到这里,我们可以发现,这道题目的重点就是这个不能正确反编译为Java代码的check方法。
这道题目一个难点就是还原check方法的Java代码,下面就开始还原Java代码。
0x03还原Java代码
我们直接在IDA中打开apk的classes.dex文件,定位到simple类的check方法
CODE:000009C4 # Source file: simple.java
CODE:000009C4 public boolean com.example.ichunqiu2.simple.check()
CODE:000009C4 this = v14 # CODE XREF: P_ichunqiu$1_onClick@VL+4Cj
CODE:000009C4 const/16 v13, 0x4D
CODE:000009C8 const/16 v12, 0x31
CODE:000009CC const/16 v11, 0x39
CODE:000009D0 const/16 v10, 0x32
CODE:000009D4 const/16 v9, 0x30
CODE:000009D8 .prologue_end
CODE:000009D8 .line 17
CODE:000009D8 const/16 v7, 0xCB
CODE:000009DC new-array v2, v7, <t: byte[]> # 长度为v7的数组v2
CODE:000009E0 const/4 v7, 0
CODE:000009E2 .line 18
CODE:000009E2 const/16 v8, 0x2F
CODE:000009E6 aput-byte v8, v2, v7 # v2=0x2F
CODE:000009EA const/4 v7, 1
CODE:000009EC aput-byte v9, v2, v7 # v2=0x30
CODE:000009F0 const/4 v7, 2
CODE:000009F2 const/16 v8, 0x51
CODE:000009F6 aput-byte v8, v2, v7 # v2=0x51
CODE:000009FA const/4 v7, 3
CODE:000009FC const/16 v8, 0x52
大体看一下smali代码,可以大致的分为两部分,第一部分是为数组v2赋值,第二部分是执行switch语句。
第一部分:
(1)可以直接复制jadx反编译出来的这一段Java代码
(2)也可以进行动态调试,直接将数组复制出来
最后我们得到的数组内容如下:
{'/','0','Q','R','O','6','M','0','2','0','0','/','0','A','6','M',
'0','2','0','0','/','9','9','F','0','/','1','0','8','F','1','/',
'1','1','1','F','2','/','5','3','F','3','/','1','0','1','F','4',
'/','1','1','4','F','5','/','0','F','6','O','0','G','0','M','0',
'0','2','0','0','A','0','D','0','M','0','0','2','0','0','O','1',
'G','1','M','0','0','2','0','0','A','1','D','1','M','0','0','2',
'0','0','O','2','G','2','M','0','0','2','0','0','A','2','D','2',
'M','0','0','2','0','0','O','3','G','3','M','0','0','2','0','0',
'A','3','D','3','M','0','0','2','0','0','O','4','G','4','M','0',
'0','2','0','0','A','4','D','4','M','0','0','2','0','0','O','5',
'G','5','M','0','0','2','0','0','A','5','D','5','M','0','0','2',
'0','0','/','1','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','/','0','\0'}
这个数组很有意思呢。{:301_988:}
第二部分:
其实这道题目作者就是利用了现在大部分反编译工具不能完整反编译大量switch分支语句的缺点,来给解题者制造障碍的。(如果有谁知道可以完美反编译大量switch分支语句的,欢迎分享)
CODE:0000107C .local name:'code' type:'[B'
CODE:0000107C code = v2
CODE:0000107C .line 34
CODE:0000107C const/4 v3, 0
CODE:0000107E .local name:'cur' type:'I'
CODE:0000107E cur = v3
CODE:0000107E .line 35
CODE:0000107E const/4 v0, 0
CODE:00001080 .local name:'a' type:'B'
CODE:00001080 a = v0
CODE:00001080 const/4 v1, 0
CODE:00001082 .local name:'b' type:'B'
CODE:00001082 b = v1
CODE:00001082 .line 36
CODE:00001082 const/16 v7, 0x3E8
CODE:00001086 new-array v5, v7, <t: byte[]>
CODE:0000108A .local name:'stack' type:'[B'
CODE:0000108A stack = v5
CODE:0000108A .line 37
CODE:0000108A const/4 v4, 0
CODE:0000108C .local name:'depth' type:'I'
CODE:0000108C depth = v4
CODE:0000108C .line 38
CODE:0000108C const/4 v6, 0
CODE:0000108E
像这些局部变量,大部分反编译工具是识别不出来的,其实在某种程度上,降低手工还原Java代码的难度,因为这些局部变量命名都有特定的意义,像stack(堆),depth(深度),这两者很容易就联系到了一起。
接下来就是switch分支语句了,要还原出Java代码需要花费一些时间了。
下面是我还原出来的代码:
public int check() {
int []r2 = {'/','0','Q','R','O','6','M','0','2','0','0','/','0','A',
'6','M','0','2','0','0','/','9','9','F','0','/','1','0','8','F','1','/',
'1','1','1','F','2','/','5','3','F','3','/','1','0','1','F','4',
'/','1','1','4','F','5','/','0','F','6','O','0','G','0','M','0',
'0','2','0','0','A','0','D','0','M','0','0','2','0','0','O','1',
'G','1','M','0','0','2','0','0','A','1','D','1','M','0','0','2',
'0','0','O','2','G','2','M','0','0','2','0','0','A','2','D','2',
'M','0','0','2','0','0','O','3','G','3','M','0','0','2','0','0',
'A','3','D','3','M','0','0','2','0','0','O','4','G','4','M','0',
'0','2','0','0','A','4','D','4','M','0','0','2','0','0','O','5',
'G','5','M','0','0','2','0','0','A','5','D','5','M','0','0','2',
'0','0','/','1','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','/','0','\0'};
//set_data(r2);
int code[]=r2;
int cur=0;
int a=0,b=0;
int stack[]=new int;
int depth=0;
int temp=0;
int v7;
int v13 = 77;
int v12 = 49;
int v11 = 57;//'9'
int v10 = 50;
int v9 = 48;//'0'
while(true){
v7=code;
System.out.printf("v7=%d--cur=%d--code=%c--a=%d--b=%c\n",v7,cur,code,a,b);
switch (v7){
default:
cur++;
break;
case 81://Q
stack=a;
depth++;
cur++;
break;
case 82://R
depth--;
b=stack;
cur++;
break;
case 87://W
depth--;
a=stack;
cur++;
break;
case 69://E
stack=b;
depth++;
cur++;
break;
case 84://T
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
a=stack;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
a=stack;
temp=0;
cur++;
break;
}
}
}
break;
case 89://Y
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
stack=a;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
stack=a;
temp=0;
cur++;
break;
}
}
}
break;
case 73://I
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
stack=b;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
stack=b;
temp=0;
cur++;
break;
}
}
}
break;
case 85://U
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
b=stack;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
b=stack;
temp=0;
cur++;
break;
}
}
}
break;
case 79://O
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
//System.out.printf("v7=%c--cur=%d--temp=%d--a=%c--b=%c\n",v7,cur,temp,a,b);
if(v7>v11){
a=A;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
a=A;
temp=0;
cur++;
break;
}
}
}
break;
case 80://P
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
A=(byte) a;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
A=(byte) a;
temp=0;
cur++;
break;
}
}
}
break;
case 65://A
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
//System.out.printf("v7=%c--cur=%d--temp=%d--a=%c--b=%c\n",v7,cur,temp,a,b);
if(v7>v11){
b=A;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
b=A;
temp=0;
cur++;
break;
}
}
}
break;
case 83://S
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
A=(byte) b;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
A=(byte) b;
temp=0;
cur++;
break;
}
}
}
break;
case 68://D
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
a=B;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
a=B;
temp=0;
cur++;
break;
}
}
}
break;
case 70://F
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
B=(byte) a;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
B=(byte) a;
temp=0;
cur++;
break;
}
}
}
break;
case 71://G
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
b=B;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
b=B;
temp=0;
cur++;
break;
}
}
}
break;
case 72://H
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
B=(byte) b;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
B=(byte) b;
temp=0;
cur++;
break;
}
}
}
break;
case 74://J
v7=a^b;
a=v7;
cur++;
break;
case 75://K
v7=a|b;
a=v7;
cur++;
break;
case 76://L
v7=a&b;
a=v7;
cur++;
break;
case 90://Z
v7=a^(-1);
a=v7;
break;
case 88://X
v7=a+b;
a=v7;
break;
case 67://C
v7=a-b;
a=v7;
break;
case 86://V
v7=a*b;
a=v7;
break;
case 66://B
v7=a/b;
a=v7;
break;
case 78://N
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
cur=temp;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
cur=temp;
temp=0;
break;
}
}
}
break;
case 77://M
if(a>=b){
cur++;
break;
}else{
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
if(v7>v11){
cur=temp;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
cur=temp;
temp=0;
break;
}
}
}
}
break;
case 47:// /
while(true){
cur++;
temp*=0xA;
v7=code;
v7+=temp;
temp=v7-0x30;
v7=cur+1;
v7=code;
//System.out.printf("v7=%c--cur=%d--temp=%d--a=%c--b=%c\n",v7,cur,temp,a,b);
if(v7>v11){
a=temp;
temp=0;
cur++;
break;
}else{
v7=cur+1;
v7=code;
if(v7<v9){
a=temp;
temp=0;
break;
}
}
}
break;
case 0:// \0
if(a==0){
v7=0;
}else{
v7=1;
}
return v7;
}
}
}
就算还原出来代码,要理解代码要实现的功能也是相当困难的,这就是第二大难点了。
所以我们就需要仔细分析代码运行过程中一些变量了。
0x04分析代码运行过程
首先我是输入不同的内容,然后分析switch分支语句的执行情况。
不同的输入,却执行相同的流程{:301_1009:}
这个问题困扰了我一些时间,不过静下心来仔细想一想,可能输入的数据需要满足某种条件吧。
接下来,我们按照switch分支语句执行的顺序来分析一下,到底进行了怎样的运算过程。
下面是我分析的结果
我们发现程序对数组A(存放了我们输入的数据)中下标为6的地方访问了两次,这就值得分析一下了。
我输入的数据长度都是大于6的,所以A一定不为0,接下来,我测试了长度大于6的大量数据,发现执行流程都是一样的。
所以真相只有一个,输入数据的长度要求小于等于6(A一定为0)。
下面是我对一个长度小于6数据的测试结果:
v7=47--cur=0--code=/
v7=81--cur=2--code=Q
v7=82--cur=3--code=R
v7=79--cur=4--code=O
v7=77--cur=6--code=M
v7=48--cur=7--code=0
v7=50--cur=8--code=2
v7=48--cur=9--code=0
v7=48--cur=10--code=0
v7=47--cur=11--code=/
v7=65--cur=13--code=A
v7=77--cur=15--code=M
v7=48--cur=16--code=0
v7=50--cur=17--code=2
v7=48--cur=18--code=0
v7=48--cur=19--code=0
v7=47--cur=20--code=/a=99
v7=70--cur=23--code=FB=a
v7=47--cur=25--code=/a=108
v7=70--cur=29--code=FB=a
v7=47--cur=31--code=/a=111
v7=70--cur=35--code=FB=a
v7=47--cur=37--code=/a=53
v7=70--cur=40--code=FB=a
v7=47--cur=42--code=/a=101
v7=70--cur=46--code=FB=a
v7=47--cur=48--code=/a=114
v7=70--cur=52--code=FB=a
v7=47--cur=54--code=/a=0
v7=70--cur=56--code=FB=a
v7=79--cur=58--code=Oa=A
v7=71--cur=60--code=Gb=B
v7=77--cur=62--code=Mif a>=b
v7=48--cur=201--code=0
v7=0--cur=202--code=
前半段与之前的一样,后半段才是重点,通过我对switch分支语句的分析,我得到了后半段的代码执行过程。
首先是向数组B中填充了6个数据,然后分别从数组A,B中得到下标相同的数据,然后进行比较。
那么,答案很可能就是数组B里面的数据了,{99,108,111,53,101,114,0}(10进制)。
如上图,我们得到数组B里面的数据,先放到代码里面运行一下,
重点是要看最后一行变量a的值,a=1,所以返回的值就是true了。
到这里,就已经解出了答案。
0x05后记
总体来看,这道题目还算简单,毕竟没有涉及到加密算法。题目中的code数组说白了就是指令集和数据集的集合。
老规矩,题目和代码会在附件中给出。
成功截图:
附件: http://pan.baidu.com/s/1gf1QO0b 密码: 72bc
版权声明:允许转载,但是一定要注明出处。 leovim 发表于 2018-3-20 14:53
JEB可以看,有很多goto语句,但比自己去分析好点吧.
JEB是一个反编译java的利器,但是如我在文章中所说,这些工具都不能识别变量名,这就是说,你反编译出来的Java源码,虽然可以正常使用,但是在你分析的时候,会很痛苦 兄弟666啊 先给代码风格加点分 感谢大神分享 看完了 这个很强 强在分析思路啊 谢谢兄弟挺不错的,谢谢了 谢谢兄弟了 打断点的话,在最后ret那里看局部变量,会看到clo5er的 不过我很欣赏LZ分析逻辑的过程,这些类型的题目有点脚本解析器的味道 感谢分享。。