小伙伴给我发来一道android题,涉及花指令,记录一下去除花指令和算法还原的过程。
强网杯 flower.apk
花指令是企图隐藏掉不想被逆向工程的代码块(或其它功能)的一种方法,在真实代码中插入一些垃圾代码的同时还保证原有程序的正确执行,而程序无法很好地反编译, 难以理解程序内容,达到混淆视听的效果。
主要目的加大静态分析难度
运行是不执行的汇编指令,会对反汇编造成影响,影响静态分析(如ida无法f5)
可执行花指令一般都是无意义的汇编指令,会被反汇编正常识别
参考:
http://dyf.ink/reverse/windows/anti-debug/junk-code/
https://www.anquanke.com/post/id/208682
sub_F8E
sub_FD0
遇到JUMPOUT要进行path修复
JUMPOUT修复参考:https://bbs.pediy.com/thread-259062.htm
根据ida的提示sub_F8E应该跳转的位置是 0xFA4 = 0xF98 + 0xC
patch脚本
path之后要重建函数(神奇的P键)
修复前
修复后
使用如上方法对sub_FD0可以进行函数重建,让ida识别成功后可以使用F5.
动态调试可以发现不可以执行的花指令
经过分析可以将可以执行的花指令识别出来
将以上替换成
去花指令之前
去花指令之后(函数重建之后ida识别成功)
去花指令之前伪代码
去花指令之后伪代码
根据伪代码结合动态调试进行算法还原
这里需要动态调试获取值
调试的时候断点参考 loc_11B0 loc_10AA
加密过程
1、输入字符串
2、按首字符填充长度为首字符10进制长度 + 字符串长度 + 尾字符填充 = 128长度
3、循环128位字符 先与data1和data2进行异或,再循环 28x16(1-7 6-0) 次 进行高/低四位保留(0xf0 0xf 与运算),最后异或0x88
4、结果与data3进行比较
加密
解密
运行结果:
1、识别花指令
2、对Jumpout进行修复
3、动态调试
4、算法还原
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;
}
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;
}
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
;
}
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
;
}
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
)
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
)
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
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
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
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
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
;
}
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
;
}
/
/
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;
}
/
/
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;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2020-9-19 11:56
被neilwu编辑
,原因: