jadx打开,我们可以发现是flutter逆向,然后打包出资源,用blutter来搞(因为reflutter和flutter逆向助手都已经停止更新),
可以直接从github上面git下来(代理环境下),windows或者linux都可以,但因为我的linux上面的g++版本小于13,所以我用的是windows,下面是项目源码
GitHub - worawit/blutter: Flutter Mobile Application Reverse Engineering Tool
然后在readme.md上面也说了怎么使用,这里我就只说一下一些可能遇到的报错,
这个报错是说cmake的命令的执行返回了非零状态码,也就是遇到了一些环境依赖问题
所以可以用vs2022的命令行来执行脚本,这样cmake和ninja就不会出现问题,
打开x64 Native Tools Command Prompt
,直接搜索就行,
然后blutter.py运行后,会出现下图的文件
然后先打开asm文件夹里面babyapk文件夹的main.dart,用vscord打开就行
首先就是审到这个,看到了用户输入后的逻辑,是先验证是否是’ByteCTF{’开头以及’}’结尾,继续审计代码可以发现字符串长度为43,并且通过frida hook几个地址时,会发现在m3N4B5V6这个函数这里有一些输出,
ida9(可以反汇编arm架构)打开libapp.so
运行重命名脚本后,恢复符号表,搜索m3N4B5V6
发现逻辑混乱,但还是出现了许多simple或者src的字符
于是回去看dart
然后会发现具体m3N4B5V6的实现需要在[package:babyapk/src/rust/api/simple.dart] ::m3N4B5V6这个里面去找,还是vscord打开simple.dart,
又发现提示这个dart文件,
这个dart主要实现一个与 Rust 库的交互接口,并且还有一些utf8编码解码函数,猜测加密会在flutter与rust交互的so里面,
也就是librust_lib_babyapk.so里面,于是ida打开,又出现了src/api/simple的字样,直接点进去
发现了一段数据,猜测密文,直接交叉引用,
果然是加密逻辑,审一审,先是一长串的判断’-’的位置是否在输入字符串的指定位置,然后是检查去掉了‘-’的字符串是否满足一系列条件,所以可以先z3解出未带’-’的字符串,然后再抄一下逻辑,爆破出‘-’的位置,反正只有4个‘-’,也许猜也可以,完整脚本如下:
from
z3
import
*
import
itertools
char
=
['']
*
4
for
j
in
range
(
4
):
flag
=
[BitVec(f
'flag[{i}]'
,
32
)
for
i
in
range
(
8
)]
data
=
[
0x0001EE59
,
0x0000022A
,
0x00001415
,
0x00040714
,
0x000013E0
,
0x000008B8
,
0xFFFDCEA0
,
0x0000313B
,
0x0003D798
,
0xFFFFFE6B
,
0x00000C4E
,
0x00023884
,
0x0000008D
,
0x00001DB4
,
0xFFFC1328
,
0x00001EAC
,
0x00043C64
,
0x0000142B
,
0xFFFFF622
,
0x00023941
,
0xFFFFEF6D
,
0x0000120C
,
0xFFFBD30F
,
0x00001EBE
,
0x00045158
,
0xFFFFEF66
,
0x00001D3F
,
0x0004C46B
,
0xFFFFF97A
,
0x00001BFD
,
0xFFFBA235
,
0x00001ED2
]
s
=
Solver()
for
i
in
range
(
8
):
s.add(flag[i]>
=
0
,flag[i]<
=
0x10FFFF
)
v45
=
flag[
2
]
v44
=
flag[
3
]
v46
=
flag[
0
]
v47
=
flag[
1
]
v48
=
flag[
4
]
v49
=
flag[
5
]
v50
=
flag[
6
]
v51
=
flag[
7
]
v52
=
v46
*
v49
v53
=
v48
*
v46
v54
=
v44
-
v51
-
(v47
+
v49)
s.add(v51
+
v47
*
v44
*
v49
-
(v46
+
v50
+
v45
*
v48)
=
=
data[
0
+
j
*
8
])
s.add(v44
-
v48
-
v46
*
v49
+
v51
*
v47
+
v45
+
v50
=
=
data[
1
+
j
*
8
])
s.add(v52
-
(v48
+
v51
*
v47)
+
v45
+
v50
*
v44
=
=
data[
2
+
j
*
8
])
s.add(v47
+
v48
*
v46
-
(v51
+
v45)
+
v50
*
v49
*
v44
=
=
data[
3
+
j
*
8
])
s.add(v49
*
v44
+
v47
+
v45
*
v48
-
(v50
+
v51
*
v46)
=
=
data[
4
+
j
*
8
])
s.add(v52
+
v47
*
v44
+
v45
-
(v50
+
v48
*
v51)
=
=
data[
5
+
j
*
8
])
s.add(v51
-
v47
+
v45
*
v49
+
v50
-
v53
*
v44
=
=
data[
6
+
j
*
8
])
s.add(v54
+
v53
+
v50
*
v45
=
=
data[
7
+
j
*
8
])
if
s.check()
=
=
sat:
m
=
s.model()
inp
=
[m.evaluate(flag[i]).as_long()
for
i
in
range
(
8
)]
char[j]
=
''.join([
chr
(inp[i])
for
i
in
range
(
8
)])
byte_18E46
=
[
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x04
,
0x04
,
0x04
,
0x04
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
]
def
check(input_str):
a1
=
[
ord
(i)
for
i
in
input_str]
v2
=
byte_18E46[a1[
0
]]
if
v2
=
=
36
:
return
0
v3
=
byte_18E46[a1[v2]]
+
v2
if
v3
=
=
36
:
return
0
v4
=
v3
+
byte_18E46[a1[v3]]
if
v4
=
=
36
:
return
0
v5
=
v4
+
byte_18E46[a1[v4]]
if
v5
=
=
36
:
return
0
v6
=
v5
+
byte_18E46[a1[v5]]
if
v6
=
=
36
:
return
0
v7
=
v6
+
byte_18E46[a1[v6]]
if
v7
=
=
36
:
return
0
v8
=
v7
+
byte_18E46[a1[v7]]
if
v8
=
=
36
:
return
0
v9
=
v8
+
byte_18E46[a1[v8]]
if
v9
=
=
36
:
return
0
v10
=
a1[v9]
if
v10 !
=
ord
(
'-'
):
return
0
v12
=
v9
+
byte_18E46[a1[v9]]
if
v12
=
=
36
:
return
0
v13
=
v12
+
byte_18E46[a1[v12]]
if
v13
=
=
36
:
return
0
v14
=
v13
+
byte_18E46[a1[v13]]
if
v14
=
=
36
:
return
0
v15
=
v14
+
byte_18E46[a1[v14]]
if
v15
=
=
36
:
return
0
v16
=
v15
+
byte_18E46[a1[v15]]
if
v16
=
=
36
:
return
0
v18
=
a1[v16]
if
v18 !
=
ord
(
'-'
):
return
0
v20
=
v16
+
byte_18E46[a1[v16]]
if
v20
=
=
36
:
return
0
v21
=
v20
+
byte_18E46[a1[v20]]
if
v21
=
=
36
:
return
0
v22
=
v21
+
byte_18E46[a1[v21]]
if
v22
=
=
36
:
return
0
v23
=
v22
+
byte_18E46[a1[v22]]
if
v23
=
=
36
:
return
0
v24
=
v23
+
byte_18E46[a1[v23]]
if
v24
=
=
36
:
return
0
v25
=
a1[v24]
if
v25 !
=
ord
(
'-'
):
return
0
v27
=
v24
+
byte_18E46[a1[v24]]
if
v27
=
=
36
:
return
0
v28
=
v27
+
byte_18E46[a1[v27]]
if
v28
=
=
36
:
return
0
v29
=
v28
+
byte_18E46[a1[v28]]
if
v29
=
=
36
:
return
0
v30
=
v29
+
byte_18E46[a1[v29]]
if
v30
=
=
36
:
return
0
v31
=
v30
+
byte_18E46[a1[v30]]
if
v31
=
=
36
:
return
0
v32
=
a1[v31]
if
v32 !
=
ord
(
'-'
):
return
0
return
1
str
=
char[
0
]
+
char[
1
]
+
char[
2
]
+
char[
3
]
table
=
list
(itertools.combinations(
range
(
len
(
str
)
+
1
),
4
))
c
=
0
success
=
0
for
i
in
table:
tmp
=
str
for
i,j
in
enumerate
(i):
tmp
=
tmp[:j
+
i]
+
'-'
+
tmp[j
+
i:]
if
check(tmp):
print
(
"ByteCTF{"
+
f
"{tmp}"
+
"}"
)
from
z3
import
*
import
itertools
char
=
['']
*
4
for
j
in
range
(
4
):
flag
=
[BitVec(f
'flag[{i}]'
,
32
)
for
i
in
range
(
8
)]
data
=
[
0x0001EE59
,
0x0000022A
,
0x00001415
,
0x00040714
,
0x000013E0
,
0x000008B8
,
0xFFFDCEA0
,
0x0000313B
,
0x0003D798
,
0xFFFFFE6B
,
0x00000C4E
,
0x00023884
,
0x0000008D
,
0x00001DB4
,
0xFFFC1328
,
0x00001EAC
,
0x00043C64
,
0x0000142B
,
0xFFFFF622
,
0x00023941
,
0xFFFFEF6D
,
0x0000120C
,
0xFFFBD30F
,
0x00001EBE
,
0x00045158
,
0xFFFFEF66
,
0x00001D3F
,
0x0004C46B
,
0xFFFFF97A
,
0x00001BFD
,
0xFFFBA235
,
0x00001ED2
]
s
=
Solver()
for
i
in
range
(
8
):
s.add(flag[i]>
=
0
,flag[i]<
=
0x10FFFF
)
v45
=
flag[
2
]
v44
=
flag[
3
]
v46
=
flag[
0
]
v47
=
flag[
1
]
v48
=
flag[
4
]
v49
=
flag[
5
]
v50
=
flag[
6
]
v51
=
flag[
7
]
v52
=
v46
*
v49
v53
=
v48
*
v46
v54
=
v44
-
v51
-
(v47
+
v49)
s.add(v51
+
v47
*
v44
*
v49
-
(v46
+
v50
+
v45
*
v48)
=
=
data[
0
+
j
*
8
])
s.add(v44
-
v48
-
v46
*
v49
+
v51
*
v47
+
v45
+
v50
=
=
data[
1
+
j
*
8
])
s.add(v52
-
(v48
+
v51
*
v47)
+
v45
+
v50
*
v44
=
=
data[
2
+
j
*
8
])
s.add(v47
+
v48
*
v46
-
(v51
+
v45)
+
v50
*
v49
*
v44
=
=
data[
3
+
j
*
8
])
s.add(v49
*
v44
+
v47
+
v45
*
v48
-
(v50
+
v51
*
v46)
=
=
data[
4
+
j
*
8
])
s.add(v52
+
v47
*
v44
+
v45
-
(v50
+
v48
*
v51)
=
=
data[
5
+
j
*
8
])
s.add(v51
-
v47
+
v45
*
v49
+
v50
-
v53
*
v44
=
=
data[
6
+
j
*
8
])
s.add(v54
+
v53
+
v50
*
v45
=
=
data[
7
+
j
*
8
])
if
s.check()
=
=
sat:
m
=
s.model()
inp
=
[m.evaluate(flag[i]).as_long()
for
i
in
range
(
8
)]
char[j]
=
''.join([
chr
(inp[i])
for
i
in
range
(
8
)])
byte_18E46
=
[
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x02
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x03
,
0x04
,
0x04
,
0x04
,
0x04
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
]
def
check(input_str):
a1
=
[
ord
(i)
for
i
in
input_str]
v2
=
byte_18E46[a1[
0
]]
if
v2
=
=
36
:
return
0
v3
=
byte_18E46[a1[v2]]
+
v2
if
v3
=
=
36
:
return
0
v4
=
v3
+
byte_18E46[a1[v3]]
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)