2024 ByteCTF re wp

babyapk

jadx打开,我们可以发现是flutter逆向,然后打包出资源,用blutter来搞(因为reflutter和flutter逆向助手都已经停止更新),

可以直接从github上面git下来(代理环境下),windows或者linux都可以,但因为我的linux上面的g++版本小于13,所以我用的是windows,下面是项目源码

GitHub - worawit/blutter: Flutter Mobile Application Reverse Engineering Tool

然后在readme.md上面也说了怎么使用,这里我就只说一下一些可能遇到的报错,

-- Configuring incomplete, errors occurred!
Traceback (most recent call last):
  File "D:\android\flutter\blutter\blutter.py", line 235, in <module>
    main(args.indir, args.outdir, args.rebuild, args.vs_sln, args.no_analysis)
  File "D:\android\flutter\blutter\blutter.py", line 217, in main
    main2(libapp_file, libflutter_file, outdir, rebuild_blutter, create_vs_sln, no_analysis)
  File "D:\android\flutter\blutter\blutter.py", line 208, in main2
    build_and_run(input)
  File "D:\android\flutter\blutter\blutter.py", line 193, in build_and_run
    cmake_blutter(input)
  File "D:\android\flutter\blutter\blutter.py", line 145, in cmake_blutter
    subprocess.run([CMAKE_CMD, '-GNinja', f'-DCMAKE_MAKE_PROGRAM={NINJA_CMD}', '-B', builddir,
  File "D:\python3.8\lib\subprocess.py", line 512, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['C:/Program Files/CMake/bin/cmake.exe', '-GNinja', '-DCMAKE_MAKE_PROGRAM=C:/Game/ninja.exe', '-B', 'D:\\android\\flutter\\blutter\\build\\blutter_dartvm3.5.0_android_arm64', '-DDARTLIB=dartvm3.5.0_android_arm64', '-DNAME_SUFFIX=', '-DCMAKE_BUILD_TYPE=Release', '--log-level=NOTICE', '-DHAS_RECORD_TYPE=1', '-DNO_METHOD_EXTRACTOR_STUB=1']' returned non-zero exit status 1.

这个报错是说cmake的命令的执行返回了非零状态码,也就是遇到了一些环境依赖问题

所以可以用vs2022的命令行来执行脚本,这样cmake和ninja就不会出现问题,

打开x64 Native Tools Command Prompt,直接搜索就行,

然后blutter.py运行后,会出现下图的文件

  • asm文件夹里面存放dart文件的反编译结果
  • ida_script里面存放着可以在ida使用的脚本,用来恢复so文件的符号表
  • objs.txt和pp.txt有对象池的一些东西,逆向的时候作用不大
  • frida脚本是工具自动编写的,可以用来hook so文件的一些函数(需要自己替换偏移)

然后先打开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个‘-’,也许猜也可以,完整脚本如下:

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
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)])
    #     print(inp)
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}"+"}")
 
        

最新回复:
mb_xuzrrikq 2024-11-19 18:16:20
有遇到flutter的问题 能有偿帮忙解决么
大牛哥Blank 2025-04-17 17:11:16
请问flutter应用使用了混淆的,用blutter逆向出来完全看不出逻辑的怎么办