18/10/05-6-BugKu-安卓-rev1(XMAN)

0x00

题目链接:https://pan.baidu.com/s/1eDt1Hv4zxihjKDZ85lqasQ
提取码:gyve

0x01

 1 public void onClick(View arg4) {
 2     MainActivity.this.c = new CheckClass();
 3     MainActivity.this.c.a(MainActivity.this.text.getText().toString());
 4     if(MainActivity.this.c.check()) {
 5         MainActivity.this.textView1.setText("flag is XMAN{" + MainActivity.this.text.getText().toString() + "}");
 6     }
 7     else {
 8         MainActivity.this.textView1.setText("WORING!");
 9     }
10 }
11 });
View Code

发现若MainActivity.this.c.check()为真,则flag正确。

0x02

分析CheckClass类。

 1 package com.rev1.xman.rev1;
 2 
 3 import android.util.Log;
 4 
 5 public class CheckClass {
 6     private byte[] A;
 7     private byte[] B;
 8 
 9     public CheckClass() {
10         super();
11     }
12 
13     public void a(String arg5) {
14         int v1 = 30;
15         this.A = new byte[v1];
16         this.B = arg5.getBytes();
17         int v0;
18         for(v0 = 0; v0 < arg5.length(); ++v0) {
19             this.A[v0] = this.B[v0];
20         }
21 
22         this.B = new byte[v1];
23     }
24 
25     public int b(int arg4) {
26         int v0 = 181 & arg4;
27         return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7);
28     }
29 
30     public boolean check() {
31         boolean v9 = false;
32         int[] v0 = new int[]{40, 42, 65, 67, 68, 2, 64, 70, 96, 98, 181, 7, 10, 64, 23, 17, 37, 20, 45, 91, 74, 72, 135, 33, 57, 43, 87, 99, 147, 53};
33         byte[] v5 = new byte[]{52, 111, 102, 113, 52, 52, 98};
34         int v2 = 0;
35         int v4 = 0;
36         int v7 = 0;
37         int v1;
38         for(v1 = 0; v1 < v0.length; ++v1) {
39             int v8 = this.b(v0[v1]);
40             new String();
41             Log.d("now array:", String.valueOf(v8));
42             switch(v8) {
43                 case 0: {
44                     this.A[v7] = ((byte)(this.A[v7] ^ v7));
45                     break;
46                 }
47                 case 1: {
48                     if(this.A[v4] != 0) {
49                         ++v4;
50                     }
51                     else {
52                     }
53 
54                     break;
55                 }
56                 case 2: {
57                     v5[v4] = ((byte)(v5[v4] ^ v4));
58                     ++v4;
59                     break;
60                 }
61                 case 3: {
62                     if(v5[v7] == this.A[v7]) {
63                         ++v7;
64                     }
65                     else {
66                     }
67 
68                     break;
69                 }
70                 case 4: {
71                     if(v7 == v4) {
72                         v9 = true;
73                     }
74 
75                     return v9;
76                 }
77                 case 5: {
78                     if(v4 != v5.length) {
79                         v1 = v0.length - 3;
80                     }
81                     else {
82                         v4 = 0;
83                     }
84 
85                     break;
86                 }
87                 default: {
88                     ++v2;
89                     break;
90                 }
91             }
92         }
93 
94         return v9;
95     }
96 }
View Code

a方法在MainActivity中用到,将输入的字符串转化为CheckClass中byte A[]成员。

b方法对传入的int值进行运算。

check方法主要是for循环中的switch-case语句,int v8 = this.b(v0[v1]),v0数组是固定的,b方法又是固定的,所以循环中v8值的出现是固定的。

写脚本求出循环中v8依次的值。

1 def fun_b(num):
2     v0 = 181 & num
3     return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7)
4 
5 array = [40, 42, 65, 67, 68, 2, 64, 70, 96, 98, 181, 7, 10, 64, 23, 17, 37, 20, 45, 91, 74, 72, 135, 33, 57, 43, 87, 99, 147, 53]
6 for i in array:
7     print fun_b(i),
View Code

可得到结果为1 1 1 1 1 0 0 1 1 1 5 2 0 0 3 2 3 2 3 2 0 0 3 2 3 2 3 2 3 4。

0x03

分析switch-case语句

重点是case 4和case 5,case 4当v7==v4时候返回true,观察循环中v8出现的值,最后一次会执行case 4。

case 5 判断v4与v5.length是否相等,v5.length为7。

若不相等则 v1 = v0.length - 3,然后这时候v8在循环中出现的值会改变,5后跳到倒数第二个,则整个循环v8出现的值变为1 1 1 1 1 0 0 1 1 1 5 3 4。

若相等则v4置零,循环中v8出现的值不变,仍为1 1 1 1 1 0 0 1 1 1 5 2 0 0 3 2 3 2 3 2 0 0 3 2 3 2 3 2 3 4。

0x04

分析flag

经过分析case 5,发现flag多解,分v4与v5.length相等与不相等。最终比较的是v4与v7,若相等则flag正确,影响v4值的有case 1和case 2,影响v7值的有case 3。

1)case 5中不相等

若不相等,v8值依次为1 1 1 1 1 0 0 1 1 1 5 3 4,出现一次3,执行case 3时候若v5[v7] == this.A[v7]则++v7变为1,若不相等则为0。若v7为0要想v4也为0,就什么不输入,app上会显示“flag is XMAN{}”。若v7为1就满足v5[v7] == this.A[v7],v5[0]为52,ascii码为‘4’,只输入一个字符时最后v4的值也为1,满足返回true条件。在app中输入4会显示“flag is XMAN{4}”

2)case5中相等

若相等,即输入的字符串个数为7,。v8值依次为1 1 1 1 1 0 0 1 1 1 5 2 0 0 3 2 3 2 3 2 0 0 3 2 3 2 3 2 3 4,并且执行case5后v4置零,此时v7也为0。后面的v8值出现2和3的次数相等,都为7,执行case2时候v4加1,执行case3时候v7加1,所以输入的字符要满足v4和v7最后都加到7。需要注意的是case 0会改变byte数组A,case 3会比较byte数组A。

逆向算法写出脚本,即可得到flag

1 str = [52, 111, 102, 113, 52, 52, 98]
2 str1 = ''
3 for i in range(len(str)):
4     str1 += chr(str[i] ^ i)
5 print str1
View Code

猜你喜欢

转载自www.cnblogs.com/Fingerprint/p/9745825.html
rev