首页
论坛
课程
招聘
[原创]#30天写作挑战#Android记去花指令还原算法
2020-9-17 18:10 4194

[原创]#30天写作挑战#Android记去花指令还原算法

2020-9-17 18:10
4194

0x00 前言

小伙伴给我发来一道android题,涉及花指令,记录一下去除花指令和算法还原的过程。

样本

强网杯 flower.apk

0x01 花指令

花指令是企图隐藏掉不想被逆向工程的代码块(或其它功能)的一种方法,在真实代码中插入一些垃圾代码的同时还保证原有程序的正确执行,而程序无法很好地反编译, 难以理解程序内容,达到混淆视听的效果。
主要目的加大静态分析难度

1、不可执行的花指令

运行是不执行的汇编指令,会对反汇编造成影响,影响静态分析(如ida无法f5)

2、可执行的花指令

可执行花指令一般都是无意义的汇编指令,会被反汇编正常识别
参考:
http://dyf.ink/reverse/windows/anti-debug/junk-code/
https://www.anquanke.com/post/id/208682

0x02 算法还原

1、样本分析

(1) java层

图片描述

(2) native层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int __fastcall Java_com_a_flower_MainActivity_check(int a1, int a2, int a3)
{
  int v3; // r5
  int v4; // r4
  char *v5; // r6
  int v6; // r8
 
  v3 = a1;
  v4 = a3;
  v5 = (*(*a1 + 676))(a1, a3, 0);
  v6 = sub_F34(v5);
  (*(*v3 + 680))(v3, v4, v5);
  return v6;
}
sub_F34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall sub_F34(char *s)
{
  char *v1; // r8
  size_t v2; // r0
  int v3; // r4
 
  v1 = s;
  v2 = strlen(s);
  if ( v2 <= 0x80 )
  {
    if ( (signed int)v2 >= 1 )
    {
      v3 = (unsigned __int8)*v1 << 8;
      sub_F8E((int)&dword_0 + 3);
    }
    sub_FD0((int)&dword_0 + 3);
  }
  return 1;
}

sub_F8E
图片描述
sub_FD0
图片描述
遇到JUMPOUT要进行path修复
JUMPOUT修复参考:https://bbs.pediy.com/thread-259062.htm

修复 sub_F8E
 

根据ida的提示sub_F8E应该跳转的位置是 0xFA4 = 0xF98 + 0xC
patch脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
def put_unconditional_branch(source, destination):
    offset = (destination - source - 4) >> 1
    if offset > 2097151 or offset < -2097152:
        raise RuntimeError("Invalid offset")
    if offset > 1023 or offset < -1024:
        instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
        instruction2 = 0xb800 | (offset & 0x7ff)
        PatchWord(source, instruction1)
        PatchWord(source + 2, instruction2)
    else:
        instruction = 0xe000 | (offset & 0x7ff)
        PatchWord(source, instruction)
put_unconditional_branch(0xF98, 0xFA4)

path之后要重建函数(神奇的P键)
图片描述

 

修复前
图片描述
图片描述
图片描述

 

修复后
图片描述
图片描述
图片描述
使用如上方法对sub_FD0可以进行函数重建,让ida识别成功后可以使用F5.

2、去花指令

动态调试可以发现不可以执行的花指令
图片描述
经过分析可以将可以执行的花指令识别出来

1
2
3
4
5
6
7
8
9
10
11
8F 46 7D 46 00 DF 8F BD BF 46 70 47 02 BC 8E BC 08 46 11 46 1A 46 3B 46 80 BC
 
8F 46 FF 46 00 DF 8F BD BF 46 70 47 04 BC 8E BC 08 46 11 46 1A 46 3B 46 80 BC
 
8F 46 7B 46 00 DF 8F BD BF 46 70 47 80 BC 8E BC 08 46 11 46 1A 46 3B 46 80 BC
 
8F 46 79 46 00 DF 8F BD BF 46 70 47 04 BC 8E BC 08 46 11 46 1A 46 3B 46 80 BC
 
8F 46 7e 46 00 DF 8F BD BF 46 70 47 08 BC 8E BC 08 46 11 46 1A 46 3B 46 80 BC
 
8F 46 FE 46 00 DF 8F BD BF 46 70 47 04 BC 8E BC 08 46 11 46 1A 46 3B 46 80 BC

将以上替换成

1
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

去花指令之前
图片描述

 

去花指令之后(函数重建之后ida识别成功)
图片描述

 

去花指令之前伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall sub_F34(char *s)
{
  char *v1; // r8
  size_t v2; // r0
  int v3; // r4
 
  v1 = s;
  v2 = strlen(s);
  if ( v2 <= 0x80 )
  {
    if ( (signed int)v2 >= 1 )
    {
      v3 = (unsigned __int8)*v1 << 8;
      sub_F8E();
    }
    sub_FD0();
  }
  return 1;
}

去花指令之后伪代码

1
2
3
4
5
6
7
8
9
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
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
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
210
211
212
213
214
215
216
217
218
219
220
221
222
// write access to const memory has been detected, the output may be wrong!
int __fastcall sub_F34(char *s)
{
  char *v1; // r8
  _DWORD *v2; // r10
  size_t v3; // r0
  int v4; // r9
  unsigned int v5; // r3
  int v6; // r0
  int v7; // r1
  char *v8; // r2
  int v9; // r4
  signed int v10; // r3
  int v11; // r6
  int v12; // r10
  unsigned int v13; // r6
  int v14; // r3
  void *v15; // r11
  char *i; // r0
  unsigned int v17; // r1
  int v18; // r10
  char *v19; // r2
  int v20; // t1
  int *v21; // r2
  int v22; // lr
  int v23; // r1
  unsigned __int8 *v24; // r8
  int v25; // r12
  int j; // r4
  int k; // r4
  int v28; // r9
  int v29; // r5
  int v30; // r1
  int v31; // r4
  char v32; // r5
  int v33; // r1
  int l; // r0
  int v35; // r0
  char v36; // r2
  int v37; // r4
  unsigned __int8 v38; // r3
  int result; // r0
  int v40; // [sp+0h] [bp-11Ch]
  int *v41; // [sp+4h] [bp-118h]
  int v42; // [sp+8h] [bp-114h]
  __int64 *v43; // [sp+Ch] [bp-110h]
  int *v44; // [sp+10h] [bp-10Ch]
  int v45; // [sp+14h] [bp-108h]
  int *v46; // [sp+18h] [bp-104h]
  int v47; // [sp+1Ch] [bp-100h]
  __int64 *v48; // [sp+20h] [bp-FCh]
  char *v49; // [sp+28h] [bp-F4h]
  int v50; // [sp+2Ch] [bp-F0h]
  int *v51; // [sp+30h] [bp-ECh]
  int v52; // [sp+34h] [bp-E8h]
  __int64 *v53; // [sp+38h] [bp-E4h]
  unsigned int v54; // [sp+3Ch] [bp-E0h]
  int v55; // [sp+40h] [bp-DCh]
  int v56; // [sp+44h] [bp-D8h]
  char *v57; // [sp+48h] [bp-D4h]
  unsigned int v58; // [sp+4Ch] [bp-D0h]
  __int64 *v59; // [sp+50h] [bp-CCh]
  int *v60; // [sp+54h] [bp-C8h]
  void *v61; // [sp+58h] [bp-C4h]
  int v62; // [sp+5Ch] [bp-C0h]
  char *v63; // [sp+60h] [bp-BCh]
  int v64; // [sp+64h] [bp-B8h]
  __int64 *v65; // [sp+68h] [bp-B4h]
  int v66; // [sp+74h] [bp-A8h]
  int v67; // [sp+98h] [bp-84h]
  __int64 savedregs; // [sp+11Ch] [bp+0h]
 
  v1 = s;
  v2 = &_stack_chk_guard;
  v3 = strlen(s);
  if ( v3 <= 0x80 )
  {
    v4 = v3;
    v5 = 0;
    v6 = 4129;
    v7 = v4;
    v8 = v1;
    while ( v7 >= 1 )
    {
      v9 = v5 ^ (*v8 << 8);
      v10 = 8;
      while ( v10 )
      {
        v11 = v6 ^ 2 * v9;
        if ( !(v9 & 0x8000) )
          v11 = 2 * v9;
        v61 = v6;
        v62 = v7;
        v63 = v8;
        v64 = v10;
        v65 = &savedregs;
        v8 = &loc_F8E;
        v60 = (&dword_0 + 3);
        v6 = 4 * (&dword_0 + 3);
        v7 = 4 * (&dword_0 + 3) + 3992;
        --v10;
        v9 = v11;
      }
      --v7;
      v5 = v9;
      ++v8;
    }
    v61 = &_stack_chk_guard;
    v55 = 128;
    v56 = v7;
    v57 = v8;
    v58 = v5;
    v59 = &savedregs;
    v54 = v5;
    v12 = v5 & 0xF;
    v13 = (v5 >> 8) & 0x3F;
    v15 = malloc(4 * (&dword_0 + 3));
    for ( i = 0; v13 != i; ++i )
      i[v15] = *v1;
    v17 = v13 + v4;
    v18 = v12 + 16;
    v19 = v1;
    while ( v13 < v17 )
    {
      v20 = *v19++;
      v14 = v20;
      *(v15 + v13++) = v20;
    }
    while ( v13 <= 0x7F )
      *(v15 + v13++) = v1[v4 - 1];
    v21 = &v56;
    v57 = 0x88776655;
    v22 = 0;
    v23 = 0x44332211;
    v24 = v15;
    v56 = 0x44332211;
    while ( v22 != 16 )
    {
      v25 = 8 * v22;
      for ( j = 0; j != 8; ++j )
      {
        v49 = i;
        v50 = v23;
        v51 = v21;
        v52 = v14;
        v53 = &savedregs;
        i = &dword_0 + 3;
        v21 = &loc_1076;
        v23 = v24[j] ^ *(&loc_1076 + j);
        *(&loc_1076 + j) = v23;
      }
      for ( k = 0; k != 8; ++k )
        *(v21 + k) ^= byte_2B98[k];
      v28 = 0;
      while ( v28 != v18 )
      {
        v14 = HIBYTE(v51);
        v29 = 0;
        v30 = HIBYTE(v51);
        while ( v29 + 6 >= 0 )
        {
          v44 = (v21 + v29);
          v45 = v30;
          v46 = v21;
          v47 = HIBYTE(v51);
          v48 = &savedregs;
          v21 = &loc_10E2;
          --v29;
          byte_9[1] = (v30 & 0xF0) + (byte_9[0] & 0xF);
          v30 = byte_9[0];
        }
        v31 = 0;
        v32 = v46 & 0xF0;
        LOBYTE(v46) = (HIBYTE(v51) & 0xF) + (v46 & 0xF0);
        while ( v31 != 7 )
        {
          v33 = v21 + v31;
          v40 = v21 + v31;
          v41 = v21;
          v42 = v14;
          v43 = &savedregs;
          v21 = &loc_1140;
          *(&loc_1140 + v31) = (*(&loc_1140 + v31) & 0xF) + (*(v33 + 1) & 0xF0);
          ++v31;
        }
        ++v28;
        HIBYTE(v42) = HIBYTE(v42) & 0xF | v32;
      }
      v23 = v42;
      v24 += 8;
      *(v15 + v25) = v41;
      i = v15 + v25;
      ++v22;
      *(v15 + v25 + 4) = v42;
    }
    _aeabi_memcpy8(&v43, &unk_2BA0, 128);
    v2 = v40;
    for ( l = 0; ; l = v35 + 1 )
    {
      if ( l == 128 )
      {
        free(v15);
        result = 0;
        goto LABEL_43;
      }
      v35 = 4 * (&dword_0 + 3);
      v36 = *(&v43 + 4 * (&dword_0 + 3));
      v37 = *(v15 + 4 * (&dword_0 + 3));
      v38 = v36 ^ (4 * (&dword_0 + 3) - 30);
      *(&v43 + 4 * (&dword_0 + 3)) = v38;
      if ( v37 != v38 )
        break;
      *(&v43 + v35) = v36;
    }
    free(v15);
  }
  result = 1;
LABEL_43:
  if ( *v2 == v66 )
    JUMPOUT(__CS__, v67);
  return result;
}

3、算法还原

(1) 动态调试

根据伪代码结合动态调试进行算法还原
图片描述
这里需要动态调试获取值
图片描述
调试的时候断点参考 loc_11B0 loc_10AA

(2) 加密算法

加密过程

1
2
3
4
5
6
7
8
9
10
11
12
data1 = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]
 
data2 = [0x77, 0x23, 0x9D, 0xAC, 0x13, 0x27, 0xCF, 0xFE]
 
data3 = [0xA8, 0xAF, 0x56, 0x98, 0x88, 0xEF, 0x40, 0x06, 0xFD, 0xAE, 0xE9, 0x9E, 0xB9, 0xEA, 0xAD, 0x52,
        0xCC, 0xAB, 0x04, 0xCA, 0xEC, 0xEB, 0x12, 0x54, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00,
        0xA8, 0xAF, 0x56, 0x98, 0x88, 0xEF, 0x40, 0x06, 0xFD, 0xAE, 0xE9, 0x9E, 0xB9, 0xEA, 0xAD, 0x52,
        0xCB, 0xAA, 0x19, 0xE5, 0xEC, 0xEB, 0x12, 0x5E, 0xA0, 0xA6, 0xA8, 0xF3, 0x8B, 0xD6, 0xCD, 0x6F,
        0xCB, 0xC0, 0x4F, 0xC1, 0xE0, 0xDA, 0x74, 0x00, 0x91, 0xBE, 0xC6, 0x83, 0xD0, 0xA6, 0x8D, 0x2E,
        0xBE, 0xFC, 0x3F, 0xAD, 0x9B, 0xE0, 0x26, 0x52, 0xF5, 0xBA, 0x94, 0xD1, 0xB4, 0xA2, 0xDF, 0x7C,
        0xDA, 0xF8, 0x6D, 0xFF, 0xFF, 0xE4, 0x74, 0x00, 0x91, 0xBE, 0xC6, 0x83, 0xD0, 0xA6, 0x8D, 0x2E,
        0xBE, 0xFC, 0x3F, 0xAD, 0x9B, 0xE0, 0x26, 0x52, 0xF5, 0xBA, 0x94, 0xD1, 0xB4, 0xA2, 0xDF, 0x7C]

1、输入字符串
2、按首字符填充长度为首字符10进制长度 + 字符串长度 + 尾字符填充 = 128长度
3、循环128位字符 先与data1和data2进行异或,再循环 28x16(1-7 6-0) 次 进行高/低四位保留(0xf0 0xf 与运算),最后异或0x88
4、结果与data3进行比较

(3) 算法还原

加密

1
2
3
4
5
6
7
8
9
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
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
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
int sub_F34(char *s){
 
    char *v1; // r8
    char *v2;
    size_t v3; // r0
    int v4; // r9
    unsigned int v5; // r3
    int v6; // r0
    int v7; // r1
    char *v8; // r2
    int v9; // r4
    signed int v10; // r3
    int v11; // r6
    int v12; // r10
    unsigned int v13; // r6
    int v14; // r3
    char *v15; // r11
    char *v16;
    int i; // r0
    unsigned int v17; // r1
    int v18; // r10
    char *v19; // r2
    int v20; // t1
    int *v21; // r2
    int v22; // lr
    int v23; // r1
    char *v24; // r8
    int v25; // r12
    int j; // r4
    int k; // r4
    int v28; // r9
    int v29; // r5
    int v30; // r1
    int v31; // r4
    int v32; // r4
    int v33; // r5
    int v34; // r0
    int v59;
 
 
 
    v1 = s;
    v3 = strlen(s);
    if ( v3 <= 128 )
    {
        v4 = v3;
        v5 = 0;
        v6 = 0x1021;
        v7 = v4;
        v8 = v1;
 
        while ( v7 >= 1 )
        {
            v9 = v5 ^ (*v8 << 8);
            v10 = 8;
            while ( v10 )
            {
                v11 = v6 ^ 2 * v9;
                if ( !(v9 & 0x8000) )
                    v11 = 2 * v9;
 
                --v10;
                v9 = v11;
            }
            --v7;
            v5 = v9;
            ++v8;
        }
        v59 = 128;
 
        v12 = v5 & 0xF;
        v13 = (v5 >> 8) & 0x3F;
        v15 = (char *)malloc(128);
 
        for ( i = 0; v13 != i; ++i )
            v15[i] = *v1;
        v17 = v13 + v4;
        v18 = v12 + 16;
        v19 = v1;
 
        printf("before %s %d \n",v15, strlen(v15));
 
        while ( v13 < v17 )
        {
            v20 = *v19++;
            v14 = v20;
            v15[v13++] = v20;
        }
        printf("input %s %d \n",v15, strlen(v15));
        while ( v13 <= 0x7F )
            v15[v13++] = v1[v4 - 1];
        printf("after %s %d \n",v15, strlen(v15));
 
 
        unsigned char byte_2B98[8] = {0x77, 0x23, 0x9D, 0xAC, 0x13, 0x27, 0xCF, 0xFE};
        unsigned char v21[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
 
 
        while ( v22 != 16 )
        {
            v25 = 8 * v22;
            for ( j = 0; j != 8; ++j )
                v21[j] ^= v15[v25 + j];
 
            for ( k = 0; k != 8; ++k )
                *(v21 + k) ^= byte_2B98[k];
 
 
            v28 = 0;
 
            while ( v28 != v18 )
            {
 
                v14 = v21[7];
                v29 = 7;
                while ( v29 >= 1 )
                {
                    v21[v29] = (v21[v29]&0xf0) + (v21[v29-1]&0xf);
                    --v29;
                }
 
 
 
                v32 = 0;
                v33 = v21[0] & 0xF0;
                v21[0] = (v14 & 0xF) + v33;
                v34 = v21[0];
 
                while ( v32 != 7 )
                {
                    v21[v32] = (v21[v32]&0xf) + (v21[v32+1]&0xf0);
                    ++v32;
                }
                v21[7] = (v21[7]&0xf) + (v34&0xf0);
 
                ++v28;
            }
 
            v30 = 0;
 
            while(v30 != 8){
                printf("0x%x ", v21[v30] ^ 0x88);
                ++v30;
            }
            printf("\n");
 
            ++v22;
 
        }
 
    }
 
    return 0;
}

解密

1
2
3
4
5
6
7
8
9
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
97
98
99
100
101
102
void decrypt(){
 
    char *v1; // r8
    char *v2;
    size_t v3; // r0
    int v4; // r9
    unsigned int v5; // r3
    int v6; // r0
    int v7; // r1
    char *v8; // r2
    int v9; // r4
    signed int v10; // r3
    int v11; // r6
    int v12; // r10
    unsigned int v13; // r6
    int v14; // r3
    char *v15; // r11
    char *v16;
    int i; // r0
    unsigned int v17; // r1
    int v18; // r10
    char *v19; // r2
    int v20; // t1
    int v22; // lr
    int v23; // r1
    char *v24; // r8
    int v25; // r12
    int j; // r4
    int k; // r4
    int v28; // r9
    int v29; // r5
 
    int v32; // r4
    int v33; // r5
    int v34; // r0
 
    unsigned char byte_2B98[8] = {0x77, 0x23, 0x9D, 0xAC, 0x13, 0x27, 0xCF, 0xFE};
    unsigned char v21[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
    unsigned char unk_2BA0[128] = {
            0xA8, 0xAF, 0x56, 0x98, 0x88, 0xEF, 0x40, 0x06, 0xFD, 0xAE, 0xE9, 0x9E, 0xB9, 0xEA, 0xAD, 0x52,
            0xCC, 0xAB, 0x04, 0xCA, 0xEC, 0xEB, 0x12, 0x54, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00,
            0xA8, 0xAF, 0x56, 0x98, 0x88, 0xEF, 0x40, 0x06, 0xFD, 0xAE, 0xE9, 0x9E, 0xB9, 0xEA, 0xAD, 0x52,
            0xCB, 0xAA, 0x19, 0xE5, 0xEC, 0xEB, 0x12, 0x5E, 0xA0, 0xA6, 0xA8, 0xF3, 0x8B, 0xD6, 0xCD, 0x6F,
            0xCB, 0xC0, 0x4F, 0xC1, 0xE0, 0xDA, 0x74, 0x00, 0x91, 0xBE, 0xC6, 0x83, 0xD0, 0xA6, 0x8D, 0x2E,
            0xBE, 0xFC, 0x3F, 0xAD, 0x9B, 0xE0, 0x26, 0x52, 0xF5, 0xBA, 0x94, 0xD1, 0xB4, 0xA2, 0xDF, 0x7C,
            0xDA, 0xF8, 0x6D, 0xFF, 0xFF, 0xE4, 0x74, 0x00, 0x91, 0xBE, 0xC6, 0x83, 0xD0, 0xA6, 0x8D, 0x2E,
            0xBE, 0xFC, 0x3F, 0xAD, 0x9B, 0xE0, 0x26, 0x52, 0xF5, 0xBA, 0x94, 0xD1, 0xB4, 0xA2, 0xDF, 0x7C
    };
 
 
 
    unsigned char flag[128];
 
    for(int i=0;i<16;i++){
 
        unsigned char data[8];
        unsigned char data1[8];
 
        for(int j=0;j<8;j++){
            data[j] = unk_2BA0[i*8 + j] ^ 0x88;
            data1[j] = data[j];
        }
 
        v28 = 0;
 
        while ( v28 != 28 )
        {
 
            v34 = data[0];
 
            v32 = 0;
            while ( v32 != 7 )
            {
                data[v32] = (data[v32]&0xf) + (data[v32+1]&0xf0);
                ++v32;
            }
            data[7] = (data[7]&0xf) + (v34&0xf0);
 
            v14 = data[7];
            v29 = 7;
            while ( v29 >= 1 )
            {
                data[v29] = (data[v29]&0xf0) + (data[v29-1]&0xf);
                --v29;
            }
 
            v33 = data[0] & 0xF0;
            data[0] = (v14 & 0xF) + v33;
 
 
            ++v28;
        }
 
        for(j=0; j<8; j++) {
            data[j] ^= byte_2B98[j];
            data[j] ^= v21[j];
            v21[j] = data1[j];
            printf("%c", data[j]);
        }
 
    }
}

运行结果:
图片描述

0x03 总结

1、识别花指令
2、对Jumpout进行修复
3、动态调试
4、算法还原


[看雪官方]《安卓高级研修班》线下班,网课(12月)班开始同步招生!!

最后于 2020-9-19 11:56 被neilwu编辑 ,原因:
上传的附件:
收藏
点赞8
打赏
分享
最新回复 (9)
雪    币: 434
活跃值: 活跃值 (265)
能力值: ( LV2,RANK:18 )
在线值:
发帖
回帖
粉丝
xjklewh 活跃值 2020-9-18 11:21
2
0
和大佬学习了
雪    币: 227
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_foyotena 活跃值 2020-9-18 13:46
3
0
不可执行代码一定要调试才能知道么
雪    币: 5664
活跃值: 活跃值 (1911)
能力值: ( LV7,RANK:108 )
在线值:
发帖
回帖
粉丝
neilwu 活跃值 2020-9-18 13:52
4
0
mb_foyotena 不可执行代码一定要调试才能知道么
也能看 看你功力 
雪    币: 1105
活跃值: 活跃值 (197)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
琅環玉碎 活跃值 2020-9-29 21:58
5
0

为什么我的ida F34 转伪代码跟你的不一样,你是已经脱离之后的吗?

雪    币: 5664
活跃值: 活跃值 (1911)
能力值: ( LV7,RANK:108 )
在线值:
发帖
回帖
粉丝
neilwu 活跃值 2020-9-30 10:26
6
0
琅環玉碎 为什么我的ida F34 转伪代码跟你的不一样,你是已经脱离之后的吗?
要重建函数 ida才能识别 
雪    币: 227
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_foyotena 活跃值 2020-10-1 09:28
7
0
neilwu 也能看 看你功力
我是想自动调试,而不是手动调试
雪    币: 402
活跃值: 活跃值 (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
暗街之王 活跃值 2020-10-5 16:53
8
0
说真的,我觉得这个和某音那个怎么这么像,不是我乱说哈,你基本一定能在cms里面找到这一段:

        "PUSH   {R1}\n" \
        "MOVS   R1,#4\n" \
        "MULS   R0,R0,R1\n" \
        "MOV    R1,PC\n" \
        "ADDS   R1,R1,R0\n" \
        "MOV    PC,R1\n" \
        "MOV    R0,PC\n" \
雪    币: 402
活跃值: 活跃值 (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
暗街之王 活跃值 2020-10-5 16:55
9
0
且不说cms各种往里面乱塞SVC 0,基本一看就是那逼的。。。难不成谣传说cms离职的传闻是真的?出来搞CTF外快了?
雪    币: 5664
活跃值: 活跃值 (1911)
能力值: ( LV7,RANK:108 )
在线值:
发帖
回帖
粉丝
neilwu 活跃值 2020-10-5 18:09
10
0
暗街之王 说真的,我觉得这个和某音那个怎么这么像,不是我乱说哈,你基本一定能在cms里面找到这一段: "PUSH {R1}\n" \ " ...
懂球
游客
登录 | 注册 方可回帖
返回