吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9397|回复: 27
收起左侧

[Android CTF] 钉钉CTF+AliCTF2015第三题+Android逆向小助手使用详解

  [复制链接]
Anonymous、 发表于 2018-9-30 16:50
本帖最后由 Anonymous、 于 2018-10-12 20:39 编辑

一、说明
钉钉CTF是一个网友昨晚给我的,比较简单,但是思路和AliCTF非常像,所以就放在一起了,一些坛友问工具怎么使用
其实很简单,在这也稍微加下使用说明,自己技术比较菜,全程靠猜~~~~~有什么不对的地方,还请各位师傅指点.

二、钉钉CTF
这一题比较简单,先打开app看下
1.png
随便输入
3.png
错了,但是有个welcome to flag blank!根据题目意思,尝试什么都不输入
QQ截图20180930143731.png
什么??????居然就对了!!!!!
好了,开始看Ali的吧...............

算啦算啦,还是看看内部怎么实现的这么牛逼的功能的吧
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
protected void onCreate(Bundle arg3) {
    super.onCreate(arg3);
    this.setContentView(2130968603);
    this.text = this.findViewById(2131427416);
    this.textView1 = this.findViewById(2131427418);
    this.button = this.findViewById(2131427415);
    this.button.setOnClickListener(new View$OnClickListener() {
        public void onClick(View arg4) {
            MainActivity.this.c = new CheckClass();
            MainActivity.this.c.a(MainActivity.this.text.getText().toString());  //先获取输入的字符串
            if(MainActivity.this.c.check()) {  //关键点
                MainActivity.this.textView1.setText("flag is XMAN{" + MainActivity.this.text.getText().toString() + "}");   
            }
            else {
                MainActivity.this.textView1.setText("WORING!");
            }
        }
    });
}

onCreate方法中,先看MainActivity.this.c.a
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
public void a(String arg5) {
        int v1 = 30;
        this.A = new byte[v1];
        this.B = arg5.getBytes();
        int v0;
        for(v0 = 0; v0 < arg5.length(); ++v0) {
            this.A[v0] = this.B[v0];
        }
 
        this.B = new byte[v1];
    }

获取输入的字符串,再看MainActivity.this.c.check()
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public boolean check() {
        boolean v9 = false;
        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};
        byte[] v5 = new byte[]{52, 111, 102, 113, 52, 52, 98};
        int v2 = 0;
        int v4 = 0;
        int v7 = 0;
        int v1;
        for(v1 = 0; v1 < v0.length; ++v1) {
            int v8 = this.b(v0[v1]);
            new String();
            Log.d("now array:", String.valueOf(v8));
            switch(v8) {
                case 0: {
                    this.A[v7] = ((byte)(this.A[v7] ^ v7));
                    break;
                }
                case 1: {
                    if(this.A[v4] != 0) {
                        ++v4;
                    }
                    else {
                    }
 
                    break;
                }
                case 2: {
                    v5[v4] = ((byte)(v5[v4] ^ v4));
                    ++v4;
                    break;
                }
                case 3: {
                    if(v5[v7] == this.A[v7]) {
                        ++v7;
                    }
                    else {
                    }
 
                    break;
                }
                case 4: {
                    if(v7 == v4) {
                        v9 = true;
                    }
 
                    return v9;
                }
                case 5: {
                    if(v4 != v5.length) {
                        v1 = v0.length - 3;
                    }
                    else {
                        v4 = 0;
                    }
 
                    break;
                }
                default: {
                    ++v2;
                    break;
                }
            }
        }
 
        return v9;
    }
 
public int b(int arg4) {
        int v0 = 181 & arg4;
        return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7);
  }

此函数为关键点,看着挺复杂的,只要返回为true即可
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
case 4: {
                   if(v7 == v4) {
                       v9 = true;
                   }
                   return v9;
               }

case 4里的判断执行,下面再接着分析v8
[Java] 纯文本查看 复制代码
1
int v8 = this.b(v0[v1]);

由于v0是固定的,所以v8也是固定的,那么switch语句就好分析了
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
 
public class DCtf {
         private static byte[] A;
         private static byte[] B;
        public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
                a("4");
                check();
          }       
         
        public static void a(String arg5) {
        int v1 = 30;
        A = new byte[v1];
        B = arg5.getBytes();
        int v0;
        for(v0 = 0; v0 < arg5.length(); ++v0) {
            A[v0] = B[v0];
        }
 
        B = new byte[v1];
    }
 
    public static int b(int arg4) {
        int v0 = 181 & arg4;
        return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7);
    }
 
    public static boolean check() {
        boolean v9 = false;
        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};
        byte[] v5 = new byte[]{52, 111, 102, 113, 52, 52, 98};
        int v2 = 0;
        int v4 = 0;
        int v7 = 0;
        int v1;
        for(v1 = 0; v1 < v0.length; ++v1) {
            int v8 = b(v0[v1]);
            new String();
            System.out.println("now array:" + String.valueOf(v8));
            switch(v8) {
                case 0: {
                    A[v7] = ((byte)(A[v7] ^ v7));
                    break;
                }
                case 1: {
                    if(A[v4] != 0) {
                        ++v4;
                    }
                    else {
                    }
                    break;
                }
                case 2: {
                    v5[v4] = ((byte)(v5[v4] ^ v4));
                    ++v4;
                    break;
                }
                case 3: {
                    if(v5[v7] == A[v7]) {
                            System.out.println("v5[v7] "+v5[v7]+"------A[v7] "+A[v7]+" "+v7);
                        ++v7;
                    }
                    else {
                    }
                    break;
                }
                case 4: {
                    if(v7 == v4) {
                        v9 = true;
                    }
                    System.out.println("v7 "+v7+"------v4 "+v4);
 
                    return v9;
                }
                case 5: {
                    if(v4 != v5.length) {
                        v1 = v0.length - 3;
                    }
                    else {
                        v4 = 0;
                    }
 
                    break;
                }
                default: {
                    ++v2;
                    break;
                }
                 
            }
        }
 
        return v9;
    }
}

运行上面的代码,可以得到v8的值分别是
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
now array:1
now array:1
now array:1
now array:1
now array:1
now array:0
now array:0
now array:1
now array:1
now array:1
now array:5
now array:3
now array:4

最后执行的就是case 4,符合我们前面的分析,但是v7 == v4,能影响v7的只有case 3这个分支,看上面v8的值,知道下面的代码只执行了一次
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
case 3: {
                    if(v5[v7] == this.A[v7]) {
                        ++v7;
                    }
                    else {
                    }
                    break;
                }

所以要想v7 == v4,v7和v4只能为1或者0,0就是什么都不输入,++v7执行之后为1,执行之前v7为就为0,所以A[v7]=52,查找ascall码表结果为4
4.png
分析到这,你就认为完了?然后并没有结束、、、、
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
9
case 5: {
                                if (v4 != v5.length) {
                                        v1 = v0.length - 3;
                                } else {
                                        v4 = 0;
                                }
 
                                break;
                        }

上面的分析的是v4 != v5.length结果,如果v4 = v5.length呢,继续往下分析吧,也就是输入的字符串为7位
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
now array:1
now array:1
now array:1
now array:1
now array:1
now array:0
now array:0
now array:1
now array:1
now array:1
now array:5
now array:2
now array:0
now array:0
now array:3
v5[v7] 52------A[v7] 52 v7 0
now array:2
now array:3
now array:2
now array:3
now array:2
now array:0
now array:0
now array:3
now array:2
now array:3
now array:2
now array:3
now array:2
now array:3
now array:4
v7 1------v4 7

控制v7的的case只有一个
[Asm] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
case 3: {
                                if (v5[v7] == A[v7]) {
                                        System.out.println("v5[v7] " + v5[v7] + "------A[v7] " + A[v7] + " v7 " + v7);
                                        ++v7;
                                } else {
                                }
                                break;
                        }

根据上面的代码循环,可以慢慢倒推出来结果为4ndr01d,真是一波三折呀。。。
QQ截图20181012203342.png
放下分析的代码
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
 
public class ctf1 {
        private static byte[] A;
        private static byte[] B;
 
        public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
                a("4ndr01d");
                check();
        }
 
        public static void a(String arg5) {
                int v1 = 30;
                A = new byte[v1];
                B = arg5.getBytes();
                int v0;
                for (v0 = 0; v0 < arg5.length(); ++v0) {
                        A[v0] = B[v0];
                }
 
                B = new byte[v1];
        }
 
        public static int b(int arg4) {
                int v0 = 181 & arg4;
                return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 32) >> 5) + ((v0 & 128) >> 7);
        }
 
        public static boolean check() {
                boolean v9 = false;
                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 };
                byte[] v5 = new byte[] { 52, 111, 102, 113, 52, 52, 98 };
                int v2 = 0;
                int v4 = 0;
                int v7 = 0;
                int v1;
                for (v1 = 0; v1 < v0.length; ++v1) {
                        int v8 = b(v0[v1]);
                        new String();
                        System.out.println("now array:" + String.valueOf(v8));
                        switch (v8) {
                        case 0: {
                                A[v7] = ((byte) (A[v7] ^ v7));
                                break;
                        }
                        case 1: {
                                if (A[v4] != 0) {
                                        ++v4;
                                } else {
                                }
                                break;
                        }
                        case 2: {
                                v5[v4] = ((byte) (v5[v4] ^ v4));
                                ++v4;
                                break;
                        }
                        case 3: {
                                if (v5[v7] == A[v7]) {
                                        System.out.println("v5[v7] " + v5[v7] + "------A[v7] " + A[v7] + " v7 " + v7);
                                        ++v7;
                                } else {
                                }
                                break;
                        }
                        case 4: {
                                if (v7 == v4) {
                                        v9 = true;
                                }
                                System.out.println("v7 " + v7 + "------v4 " + v4);
                                return v9;
                        }
                        case 5: {
                                if (v4 != v5.length) {
                                        v1 = v0.length - 3;
                                } else {
                                        v4 = 0;
                                }
 
                                break;
                        }
                        default: {
                                ++v2;
                                break;
                        }
 
                        }
                }
 
                return v9;
        }
}


三、Alictf
好啦,终于可以上主菜了~~~~~~

先用jeb反编译
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.ali.mobisecenhance;
 
import android.app.Application;
import android.content.Context;
 
public class StubApplication extends Application {
    static {
        try {
            Class v2 = Class.forName("android.os.SystemProperties");
            Object v1 = v2.getDeclaredMethod("get", String.class).invoke(v2, "ro.product.cpu.abi");
        }
        catch(Exception v3) {
            v3.printStackTrace();
        }
 
        if(((String)v1).equalsIgnoreCase("x86")) {
            System.loadLibrary("mobisecx");
        }
        else {
            System.loadLibrary("mobisec");
        }
    }
 
    public StubApplication() {
        super();
    }
 
    protected native void attachBaseContext(Context arg1) {
    }
 
    public native void onCreate() {
    }
}

加了壳子~~~~关键代码看不到,那就先用IDA脱壳
先打开DDMS
5.png
获取入口点
6.png
一键挂起
7.png
用ida附加
9.png
在ibdvm的dvmDefineClass下了个断点,通过DvmDex的指针,把odex dump下来,下好断点,点jdb启动
11.png
查看r0地址
13.png
跟随上面的地址
14.png
用脚步dump下来
[C] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
static main(void)
{
auto fp, dex_addr, end_addr;
fp = fopen("C:\\dump.dex", "wb");
end_addr = 0x75512000 + 0x00010000;
for ( dex_addr = 0x75512000; dex_addr < end_addr; dex_addr ++ )
fputc(Byte(dex_addr), fp);
}

然后修复,最后用版主的Apktool工具,反编译dex,再回编译,就可以用jeb打开了
15.png

16.png
下面就是分析java代码了
主要是根据这个表对我们输入的字符串,进行置换
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
static {
        e.a = new HashMap();
        e.a("a", ". _");
        e.a("b", "_ . . .");
        e.a("c", "_ . _ .");
        e.a("d", "_ . .");
        e.a("e", ".");
        e.a("f", ". . _ .");
        e.a("g", "_ _ .");
        e.a("h", ". . . .");
        e.a("i", ". .");
        e.a("j", ". _ _ _");
        e.a("k", "_ . _");
        e.a("l", ". _ . .");
        e.a("m", "_ _");
        e.a("n", "_ .");
        e.a("o", "_ _ _");
        e.a("p", ". _ _ .");
        e.a("q", "_ _ . _");
        e.a("r", ". _ .");
        e.a("s", ". . .");
        e.a("t", "_");
        e.a("u", ". . _");
        e.a("v", ". . . _");
        e.a("w", ". _ _");
        e.a("x", "_ . . _");
        e.a("y", "_ . _ _");
        e.a("z", "_ _ . .");
        e.a("2", ". _ _ _ _");
        e.a("1", ". . _ _ _");
        e.a("3", ". . . _ _");
        e.a("4", ". . . . _");
        e.a("0", ". . . . .");
        e.a("6", "_ . . . .");
        e.a("9", "_ _ . . .");
        e.a("8", "_ _ _ . .");
        e.a("7", "_ _ _ _ .");
        e.a("5", "_ _ _ _ _");
    }
 
    public e() {
        super();
    }
 
    public String a(String arg8) {
        String v0;
        dn.b(dn.a());
        if(arg8.equals("...___...")) {
            v0 = "sos";
        }
        else {
            StringBuilder v2 = new StringBuilder();
            String[] v3 = arg8.split("\\s+");  //根据空格进行分割
            int v4 = v3.length;
            int v1 = 0;
            while(true) {
                if(v1 < v4) {
                    Object v0_1 = e.a.get(v3[v1]); //替换
                    if(v0_1 != null) {
                        v2.append(((String)v0_1));//连接
                        ++v1;
                        continue;
                    }
                    else {
                        break;
                    }
                }
                else {
                    goto label_26;
                }
 
                return v0;
            }
 
            throw new IllegalArgumentException();
        label_26:
            v0 = v2.toString();
        }
        return v0;
    }

下面这部分代码,根据压缩包里的strings.xml和public.xml可以分析run()返回值为0时,提示成功的字符
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public void handleMessage(Message arg5) {
        dn.b(dn.a());
        int v2 = -65536;
        this.a.b.setEnabled(true);
        switch(arg5.what) {
            case 0: {
                goto label_10;
            }
            case 1: {
                goto label_27;
            }
            case 2: {
                goto label_51;
            }
            case 3: {
                goto label_66;
            }
        }
        return;
    label_66:
        this.a.a.setTextColor(v2);
        TextView v1 = this.a.a;
        int v0 = Main.a(this.a).nextBoolean() ? 2130968582 : 2130968581;
        v1.setText(v0);
        return;
        try {
        label_51:
            this.a.a.setTextColor(-65536);
        }
        catch(Exception v0_1) {
            this.a.a.setTextColor(-7829368);
        }
 
        this.a.a.setText(2130968580);
        return;
    label_10:
        this.a.a.setTextColor(-16776961);
        try {
            this.a.a.setText(103 / arg5.what);
        }
        catch(Exception v0_1) {
            this.a.a.setText(2130968586);
        }
        return;
    label_27:
        this.a.a.setTextColor(v2);
        switch(Main.a(this.a).nextInt(3)) {
            case 0: {
                goto label_36;
            }
            case 1: {
                goto label_41;
            }
            case 2: {
                goto label_46;
            }
        }
        return;
    label_36:
        this.a.a.setText(2130968583);
        return;
    label_41:
        this.a.a.setText(2130968585);
        return;
    label_46:
        this.a.a.setText(2130968584);
    }

下面的run()函数为关键点,只要返回0即可,分析逻辑和上面那个CTF很类似
[Java] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
b(a arg1, Handler arg2, String arg3) {
        this.d = arg1;
        this.b = arg2;
        this.input = arg3;
        super();
    }
 
    public void run() {
        int v0_6;
        String v0_5;
        String v1_5;
        byte[] v2_3;
        Cipher v1_1;
        MessageDigest v0_3;
        String str;
        dn.b(dn.a());
        MessageDigest v1 = null;
        if(Build$VERSION.SDK_INT >= 10 && (Debug.isDebuggerConnected())) {
            this.b.sendEmptyMessage(1);
            return;
        }
 
        try {
            str = new e().a(this.input);  //a函数的主要目的,在莫尔斯码表中置换
        }
        catch(Exception v0) {
            this.b.sendEmptyMessage(3);
            return;
        }
 
        try {
            if(str.equals("sos")) {
                this.b.sendEmptyMessage(2);
                return;
            }
 
            CRC32 v0_1 = new CRC32();  //crc加密
            v0_1.update(str.getBytes());
            v0_1.getValue();
            str.hashCode();
            try {
                v0_3 = MessageDigest.getInstance("sha1"); //sha1加密
            }
            catch(NoSuchAlgorithmException v0_2) {
                v0_2.printStackTrace();
                v0_3 = v1;
            }
 
            try {
                v1_1 = Cipher.getInstance("AES");  
            }
            catch(NoSuchPaddingException v0_4) {
                v0_4.printStackTrace();
                return;
            }
            catch(NoSuchAlgorithmException v2) {
                v2.printStackTrace();
            }
 
            if(!b.a && v1_1 == null) {
                throw new AssertionError();
            }
        }
        catch(Exception v0) {
            goto label_26;
        }
 
        int v2_1 = 2;
        try {
            v1_1.init(v2_1, new SecretKeySpec(Base64.decode("GXiQHT1CZ2elMzwpvvAoPA==".getBytes(), 0), "AES")); //AES设置key
            goto label_69;
        }
        catch(Exception v0) {
        }
        catch(InvalidKeyException v2_2) {
        label_69:
            try {
                new byte[0];
                try {
                    v2_3 = v1_1.doFinal(Base64.decode("hjdsUjIT5je69WXIZP7Kzw==".getBytes("UTf-8"), 0));  //AES解密,值固定
                    goto label_78;
                }
                catch(UnsupportedEncodingException v1_2) {
                    try {
                        v1_2.printStackTrace();
                    label_78:
                        String v6 = new String(v2_3);   //上面AES解密的
                        v0_3.update(new byte[]{127});
                        v0_3.update(str.getBytes());  
                        v0_3.update(new byte[]{1});
                    }
                    catch(Exception v0) {
                        goto label_26;
                    }
                }
                catch(BadPaddingException v1_3) {
                    goto label_78;
                }
                catch(IllegalBlockSizeException v1_4) {
                    goto label_78;
                }
            }
            catch(Exception v0) {
                goto label_26;
            }
 
            try {
                v1_5 = new String(Base64.encode(v0_3.digest(), 0));  //
                goto label_99;
            }
            catch(Exception v0) {
                try {
                    v0.printStackTrace();
                    return;
                label_99:
                    if(!str.equals(v6)) {
                        goto label_190;
                    }
                    else if(Arrays.equals(v1_5.getBytes(), "2398lj2n".getBytes())) {
                        this.b.sendEmptyMessage(0);
                        return;
                    }
                    else {
                        v0_5 = "234";
                    }
 
                    goto label_117;
                }
                catch(Exception v0) {
                    goto label_26;
                }
            }
 
        label_190:
            v0_5 = v1_5;
            try {
            label_117:
                if(v0_5.equals("lsdf==")) {
                    this.b.sendEmptyMessage(0);
                    return;
                }
 
                char[] v1_6 = str.toCharArray();
                v0_6 = str.substring(0, 2).hashCode();
                if(v0_6 > 3904) {
                    this.b.sendEmptyMessage(4);
                    return;
                }
 
                if(v0_6 == 3618) {
                    if(v1_6[0] + v1_6[1] != 168) {
                        goto label_178;
                    }
 
                    do {
                    label_144:
                        byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes();
                        if(v1_6.length - 2 == v5_1.length) {
                            v0_6 = 0;
                            while(true) {
                                if(v0_6 >= v5_1.length) {
                                    goto label_188;
                                }
                                else if(v1_6[v0_6 + 2] != v5_1[v0_6]) {
                                    v0_6 = 0;
                                }
                                else {
                                    ++v0_6;
                                    continue;
                                }
 
                                goto label_170;
                            }
                        }
 
                        goto label_177;
                    }
                    while(true);
                }
 
                goto label_178;
            }
            catch(Exception v0) {
                goto label_26;
            }
 
        label_188:
            v0_6 = 1;
            try {
            label_170:
                if(v0_6 != 0) {
                    this.b.sendEmptyMessage(0);
                    return;
                }
 
            label_177:
                if(v2_3 == null) {
                    goto label_144;
                }
 
            label_178:
                this.b.sendEmptyMessage(1);
            }
            catch(Exception v0) {
            label_26:
                this.b.sendEmptyMessage(1);
            }
        }
    }

只有为这个的时候this.b.sendEmptyMessage(0);才会提示成功, label_188: ---label_117:---label_190:,跳转这三个点才能成功,
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
label_190:
           v0_5 = v1_5;
           try {
           label_117:
               if(v0_5.equals("lsdf==")) {
                   this.b.sendEmptyMessage(0);
                   return;
               }

[Java] 纯文本查看 复制代码
1
2
3
4
v0_3.update(new byte[]{127});v0_3.update(str.getBytes());
v0_3.update(new byte[]{1});
v1_5 = new String(Base64.encode(v0_3.digest(), 0));
v0_5 = v1_5;

由于前面对v0_3的处理,导致不能相等,所以只剩下label_170:这个独苗,然后看可以谁跳转到label_170:
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
char[] v1_6 = str.toCharArray();
              v0_6 = str.substring(0, 2).hashCode();
              if(v0_6 > 3904) {
                  this.b.sendEmptyMessage(4);
                  return;
              }
 
              if(v0_6 == 3618) {
                  if(v1_6[0] + v1_6[1] != 168) {
                      goto label_178;
                  }
 
                  do {
                  label_144:
                      byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes();
                      if(v1_6.length - 2 == v5_1.length) {
                          v0_6 = 0;
                          while(true) {
                              if(v0_6 >= v5_1.length) {
                                  goto label_188;
                              }
                              else if(v1_6[v0_6 + 2] != v5_1[v0_6]) {
                                  v0_6 = 0;
                              }
                              else {
                                  ++v0_6;
                                  continue;
                              }
 
                              goto label_170;
                          }
                      }
 
                      goto label_177;
                  }
                  while(true);
              }
 
              goto label_178;
          }

分析可知,v0_6 == 3618 和 v1_6[0] + v1_6[1] = 168必须同时成立,v0_6 = str.substring(0, 2).hashCode();,由于前面置换表只有小写字母和数字,所以可以直接遍历
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
 
 
int main()
{
        int arry[] = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122 };
        int n = sizeof(arry) / sizeof(arry[0]);
        for (int i = 0; i < n; i++)
        {
                for (int j = 0; j < n; j++)
                {
                        if ((arry[i] * 31 + arry[j]) == 3618)
                        {
                                printf("%d----%d\n", arry[i],arry[j]);
                        }
                }
        }
        system("pause");
        return 0;
}

c语言很垃圾,只能写这个了.........结果有两个113----115和115----53,只有后面的符合要求,转换成acsll为s5,接着往下看
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
byte[] v5_1 = e.class.getAnnotation(f.class).a() + a.class.getAnnotation(f.class).a().getBytes(); //获取后面四个字符
                       if(v1_6.length - 2 == v5_1.length) {
                           v0_6 = 0;
                           while(true) {
                               if(v0_6 >= v5_1.length) {
                                   goto label_188;
                               }
                               else if(v1_6[v0_6 + 2] != v5_1[v0_6]) {
                                   v0_6 = 0;
                               }
                               else {
                                   ++v0_6;
                                   continue;
                               }
 
                               goto label_170;
                           }
                       }

下面就可以看出来是比较了,要长度相等,字符相等,所以后面的为7e1p,加上前面的s5为s57e1p,然后再置换一下就行了,结果为... _____ ____. . ..___ .__.
贴下java的分析代码,很垃圾····························
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
 
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
 
public class aestest {
         
        public static void main(String[] args) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException  {
                byte[] v2_3;
                Cipher v1_1;
                String v5 = "s57e1p";
                String v1_5;
                int v0_6;
                MessageDigest v0_3;
                char[] v1_6 = v5.toCharArray();
                v0_3 = MessageDigest.getInstance("sha1");
                v1_1 = Cipher.getInstance("AES");
                Decoder decoder = Base64.getDecoder();
                Encoder encode = Base64.getEncoder();
                v1_1.init(2, new SecretKeySpec(decoder.decode("GXiQHT1CZ2elMzwpvvAoPA==".getBytes()), "AES"));
                v2_3 = v1_1.doFinal(decoder.decode("hjdsUjIT5je69WXIZP7Kzw==".getBytes("UTf-8")));
                System.out.println(v2_3);
                v0_3.update(new byte[]{127});
                v0_3.update(v5.getBytes());
                v0_3.update(new byte[]{1});
                String v6 = new String(v2_3);
                v1_5 = new String(encode.encode(v0_3.digest()));
                System.out.println(v1_5);
                v0_6 = v5.substring(0, 2).hashCode();
                System.out.println(v0_6);
          }       
}

CTF.zip

1.62 MB, 下载次数: 15, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 6威望 +1 吾爱币 +13 热心值 +6 收起 理由
poisonbcat + 1 + 1 谢谢@Thanks!
科技技能 + 1 热心回复!
cxp521 + 1 + 1 谢谢@Thanks!
xwzj20170829 + 1 + 1 谢谢@Thanks!
bolipapadu + 1 + 1 用心讨论,共获提升!
Sound + 1 + 9 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

C_Ryan 发表于 2018-10-4 03:07
钉钉CTF这一道,还有一种情况没有分析,就是当case5时候v4 = v5.length,会是一个另一个截然不同的分析方向,大致就是v4先加累加到7,然后case5后v7再累加到7,这就需要对输入的字符串有要求了,会进行些亦或比较操作,这个flag答案为4ndr01d。

点评

谢谢提醒,已经更新~  发表于 2018-10-12 20:38
 楼主| Anonymous、 发表于 2018-10-4 09:07
C_Ryan 发表于 2018-10-4 03:07
钉钉CTF这一道,还有一种情况没有分析,就是当case5时候v4 = v5.length,会是一个另一个截然不同的分析方向 ...

666,这么多答案吗....当时分析出一个,就没再仔细看了
sqln0324 发表于 2018-9-30 16:56
90182si 发表于 2018-9-30 17:17
看不懂系列,哈哈哈
hechenpi 发表于 2018-9-30 18:22
看不懂系列, 不知所云
多瑙河下 发表于 2018-9-30 19:18

看不懂系列, 不知所云
雨落丶千寒 发表于 2018-9-30 19:19
向大佬致敬
kanxue2018 发表于 2018-9-30 20:13


感谢楼主分享,支持一下!
onmiuncai 发表于 2018-9-30 20:17
请问下LZ dump后的odex怎么修复,是直接用baksmali -x 转dex 还是需要手动修复什么?
linuxprobe 发表于 2018-9-30 21:09
你即便把它全部逆向了又能怎么样呢?
kk1212 发表于 2018-9-30 21:41
能把这几个学会也挺厉害的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-5-24 16:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表