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 });
发现若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 }
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),
可得到结果为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