一些自认为典型的题

RE区

maze  GFSJ0497

接触到的第一道maze题
伪代码部分

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
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
signed __int64 i; // rbx
signed int chr; // eax
bool sign; // bp
bool sign1; // al
const char *v7; // rdi
__int64 matrix; // [rsp+0h] [rbp-28h]
matrix = 0LL;
puts("Input flag:");
scanf("%s", &input_flag_str, 0LL);
if ( strlen(&input_flag_str) != 24 || strncmp(&input_flag_str, "nctf{", 5uLL)
|| *(&byte_6010BF + 24) != '}' )
{
Wrong_jmp:
puts("Wrong flag!");
exit(-1);
}
i = 5LL;
if ( strlen(&input_flag_str) - 1 > 5 )
{
while ( 1 )
{
chr = *(&input_flag_str + i);
sign = 0;
if ( chr > 78 )
{
chr = (unsigned __int8)chr;
if ( (unsigned __int8)chr == 'O' )
{
sign1 = left((_DWORD *)&matrix + 1); // matrix 指针 + 1 就是旁边 的
dword 值 也就是 v9 的高8 位的值
goto LABEL_14;
}
if ( chr == 'o' )
{
// matrix 的低8位用来存储迷宫的行 高8位用来存储迷宫的列它是一个 __int64位的数据

方向函数matix
向左和向右操控的是高32位的值
sign1 = right((int *)&matrix + 1);
goto LABEL_14;
}
}
else
{
chr = (unsigned __int8)chr;
if ( (unsigned __int8)chr == '.' )
{
sign1 = up(&matrix);
goto LABEL_14;
}
if ( chr == '0' )
{
sign1 = down((int *)&matrix);
LABEL_14:
sign = sign1;
goto LABEL_15;
}
}
LABEL_15:
if ( !(unsigned __int8)sub_400690((__int64)maze_data, SHIDWORD(matrix),
matrix) )// 判断当前位置是否为0x20或0x23#不是则错误flag
goto Wrong_jmp;
if ( ++i >= strlen(&input_flag_str) - 1 ) // 当 长度 达到的时候
{
if ( sign )
break;
Wrong_Jmp1:
v7 = "Wrong flag!";
goto puts_wrong;
}
}
}
if ( maze_data[8 * (signed int)matrix + SHIDWORD(matrix)] != '#' )// 最后一层判断是否到达指定位置
goto Wrong_Jmp1;
v7 = "Congratulations!";
puts_wrong:
puts(v7);
return 0LL;
}

bool __fastcall left(_DWORD *a1)
{
}
int v1; // eax
v1 = (*a1)--;
return v1 > 0;
//对应 O
//高8 位-1迷宫向左移动一位
bool __fastcall right(int *a1) //对应 o
{
int v1; // eax
v1 = *a1 + 1;
*a1 = v1;
return v1 < 8;
}

bool __fastcall up(_DWORD *a1)
{
}
int v1; // eax
v1 = (*a1)--;
return v1 > 0;
//对应 .
bool __fastcall down(int *a1) //对应 0
{
int v1; // eax
v1 = *a1 + 1;
*a1 = v1;
return v1 < 8;
}

碰撞检测函数一眼就看得出来,不贴了
进去直接shift+F12查找字符串,找到迷宫数据
由于有64个字符,将其8*8分割画出迷宫
重点在于阅读移动函数,Oo0.确定上下左右
最后直接手写迷宫走出方法得wp

simple-unpack  NO.GFSJ0490

一道非常典型的UPX无魔改脱壳,可以留着作为upx范本文件一遍应付以后的魔改,也可以练习手动脱壳

方法1:upx脱壳软件一键脱壳,不多赘述

方法2:手动脱壳

打开x64dbg将文件拖入
找到文件开始行,在开头打上断点
开始动调,一步步往下直至有一大堆出栈行为的时候尝试脱壳
多次尝试后脱壳成功,拖入ida发现显示正常

getit  NO.GFSJ0495

一道经典的linux动调题
DIE查壳后用ida打开
进来先进入main函数扫一眼主要逻辑
看到关键函数fseek用来改变读写函数的位置指针
阅读代码逻辑可知 代码将flag赋值后remove掉
在remove上下断点动调发现输出一大堆
这些
号将原本应该输出的flag覆写
找到关键储存点t
在循环过程中关注t再次动调,发现flag

Valgrind  NO.GFSJ1148

分析文档写脚本

1
2
3
4
5
6
7
8
9
s = "t1me_y0u_enj0y_wa5t1ng_wa5_not_wa5ted"
key = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
flag = ""
for i in range(len(s)):
if(ord(s[i]) + 3 < 0x5a):
flag += chr(ord(s[i]) + 3 )
else:
flag += key[ (ord(s[i]) + 3 - 0x5a) % 0x1a -1 ]
print(flag)

whats-the-hell-500  NO.GFSJ0124

有点意思
画了几个长方形和长方体
通过改代码,在每个等式后取值可得
p[0] + p[1] = 101
p[1] + p[2]= 143
p[0] * p[2] = 5035
p[3] + p[5] = 163
p[3] + p[4] = 226
p[4] * p[5] = 5814
p[7] + p[8] = 205
p[6] + p[8] = 173
p[6] * p[7] = 9744
p[9] + p[10] * p[11] = 5375
p[10] + p[9] * p[11] = 4670
p[9] + p[10] = 205
回到python用z3对等式求个解
就能求出所有p[]的值
最后可得flag:50_pr3TtYn_0

Android区

Android 2.0

入门Android逆向

用jadx打开apk,发现入口在

1744763232788

跟进,发现主要函数逻辑JNI在so层

用ida32打开lib中的so文件

直奔目标函数Java_com_example_test_ctf03_JNI_getResult

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
bool __fastcall Java_com_example_test_ctf03_JNI_getResult(int a1, int a2, int a3)
{
int v3; // r4
const char *v4; // r8
char *v5; // r6
char *v6; // r4
char *v7; // r5
int i; // r0
int j; // r0

v3 = 0;
v4 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
if ( strlen(v4) == 15 )
{
v5 = (char *)malloc(1u);
v6 = (char *)malloc(1u);
v7 = (char *)malloc(1u);
Init(v5, v6, v7, v4, 15);
if ( !First(v5) )
return 0;
for ( i = 0; i != 4; ++i )
v6[i] ^= v5[i];
if ( !strcmp(v6, a5) )
{
for ( j = 0; j != 4; ++j )
v7[j] ^= v6[j];
return strcmp(v7, "AFBo}") == 0;
}
else
{
return 0;
}
}
return v3;
}

跟进Init函数

发现就是将整段字符串以3个字符为一次循环分给v5,v6,v7

分别跟进First,Second,Third

发现均为简单的单个字符逻辑运算

根据伪代码写出脚本

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
a="LN^dl"
flag=""
for i in range(0,len(a)-1):
flag=flag + chr((ord(a[i]) ^ 0x80) // 2)
flag=flag+a[-1]
print(flag)

a5=[ord(' '),ord('5'),ord('-'),0x16,ord('a')]
v5="fgorl"
v6=""
for i in range(4):
v6=v6+chr(a5[i] ^ ord(a[i]))
v6=v6+'a'
print(v6)

v7=""
a7="AFBo}"
for i in range(0,len(a7)-1):
v7=v7+chr(ord(a7[i]) ^ a5[i])
v7=v7+a7[-1]
print(v7)

for i in range(0,len(a7)):
print(v5[i],end="")
print(v6[i],end="")
print(v7[i],end="")

运行可得flag{sosorryla}

Misc区

真是阳间题 GFSJ1121

NOTEPAD打开发现一串数字

3207357975641587136122466514425152961654613410728337142271750273124995105747053991640817066352343657398947248938255086358418100814441196784643527787764297

拿到CTFCrackTools转16进制

cyberchef from hex→reverse→from base32

凯撒加密右移两位

得到flag HSCTF{N0w_Y0u_ar3_4_m4ster_0f_crypt0}

不确定,再看看 GFSJ1098

给了个音频文件,拖到010里发现有类似base64编码的格式,加上hint有base64

写脚本提取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
start_index = int("86",16)
end_index = int("2EE0",16)

base64_str = ""
with open("A Comme Amour.wav", "rb") as f:
f.seek(start_index)
while f.tell() < end_index:
data = f.read(1)
if data == bytes.fromhex("00") or data == bytes.fromhex("FF"):
continue
else:
base64_str += data.decode("utf-8")

print(base64_str)
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
I2luY2x1ZGUgPHN0ZGlvLmg+
I2luY2x1ZGUmPHN0cmluZy5oPm==
I2luY2x1ZGUmPHN0ZGxpYi5oPm==
dm9pZCBBZmZpbmVUcmFuc2Zvcm1hdGlvbihjaGFyKiwgaW50LCBpbnQsIGludCk7
aW50IEdDRChpbnQpO2==
aW50IG1vZF9pbnZlc2UoaW50IGQvIGludCBuKTv=
dm9pZCBzb2x2ZV9mdW5jdGlvbihjaGFyKik7
aW50IG1haW4odm9pZCk=
e2==
CXByaW50ZigiXG4qKioqKiphZmZpbmUgdHJhbnNmb3JtYXRpb24qKioqKipcbiIpOx==
CXdoaWxlICgxKW==
CXt=
CQl9cmludGYoIlxuUGxlYXNlIGVudGVyIHRoZSBmdW5jdGlvbiBzZXJpYW9gbnVtYmVyOlxuMC5FbmNyeXB0aW9uXG4xLkRlY3J5cHRpb25cbjIuU29sdXRpb24gZnVuY3Rpb25cbjMuRXhpdFxuUGxlYXNlIGNob29zZSBmdW5jdGlvbiIpO9==
CQlpbnQgZnVuY3Rpb247
CQlpbnQgYSA9IDA7
CQlpbnQgYiA9IDA7
CQljaGFyIHhbNF0gPSAiXDAiO+==
CQljaGFyIGNoWzEwMDBdID0gIlwwIjv=
CQljaGFyIHNvbHZlWzEwMDBdID0gIlwwIjt=
CQlzY2FuZl9zKCIlZCIsICZmdW5jdGlvbik7
CYlzd2l0Y2ggKGZ1bmN0aW9uKY==
CQl7
CQljYXNlIDA6
CQkJcHJpbnRmKCJQbGVhc2UgZW50ZXIgdGhlIGtleSB1c2VkIGZvciBlbmNyeXB0aW9uOigwPD1hLGI8PTI1KVxuIik7
CQkJc2NhbmZfcygiJWQsJWQiLCAmYS5gJmIpO5==
CYkJd2hpbGUgKEdDRChhKSAhPSAxKY==
CQkJe0==
CQkJCXByaW50ZigiUGxlYXNlIHJlIC1lbnRlciB0aGUga2V5OlxuIik7
CQkJCXByaW50ZigiUGxlYXNlIGVudGVyIHRoZSBrZXkgdXNlZCBmb3IgZW5jcnlwdGlvbjooMDw9YTw9MjUpXG4iKTv=
CQkJCXNjYW5mX3MoIiVkIi1gJmEpO1==
CWkJfW==
CQkJZmZtdXNoKHN0ZGluKTt=
CQkJcHJpbnRmKCJQbGVhc2UgZW50ZXIgdGhlIHBtYWludGV4dDoiKTt=
CQkJZ2V0c19zKGNoKTs=
CQkJQWZmaW5lVHJhbnNmb3JtYXRpb24oY2gvIGEvIGIvIGZ1bmN0aW9uKTv=
CQkJYnJlYWs7
CQljYXNlIDE6
CQkJcHJpbnRmKCJQbGVhc2UgZW50ZXIgdGhlIGtleSB1c2VkIGZvciBkZWNyeXB0aW9uOigwPD1hLGI8PTI1KVxuIik7
CQkJc2NhbmZfcygiJWQsJWQiLCAmYS2gJmIpO2==
CTkJd2hpbGUgKEdDRChhKSAhPSAxKT==
CQkJe0==
CQkJCXByaW50ZigiUGxlYXNlIHJlIC1lbnRlciB0aGUga2V5OlxuIik7
CQkJCXByaW50ZigiUGxlYXNlIGVudGVyIHRoZSBrZXkgdXNlZCBmb3IgZGVjcnlwdGlvbjooMDw9YTw9MjUpXG4iKTt=
CQkJCXNjYW5mX3MoIiVkIi3gJmEpO3==
CdkJfd==
CQkJZmZudXNoKHN0ZGluKTu=
CQkJcHJpbnRmKCJQbGVhc2UgZW50ZXIgdG8gYmUgZGVjcnl4dGVkOiIpO4==
CQkJZ2V0c19zKHNvbHZlKTt=
CQkJQWZmaW5lVHJhbnNmb3JtYXRpb24oc29udmUuIGEuIGIuIGZ1bmN0aW9uKTu=
CQkJYnJlYWs7
CQljYXNlIDI6
CQkJcHJpbnRmKCJQbGVhc2UgZW50ZXIgdGhlIGVxdWF0aW9uIGNvZWZmaWNpZW50OiB4LHksbSxuOlxuIik7
CQkJZmZudXNoKHN0ZGluKTu=
CQkJZ2V0c19zKHgpO1==
CQkJc29sdmVfZnVuY3Rpb24oeCk7
CQkJYnJlYWs7
CQljYXNlIDM6
CQkJcmV0dXJuIDA7
CQkJYnJlYWs7
CQlkZWZhdWx0Op==
CQkJcHJpbnRmKCJQbGVhc2UgZW50ZXIgdGhlIGNvcnJlY3QgbnVtYmVyIik7
CQkJYnJlYWs7
CQl9
CX0=
fW==
dm9pZCBBZmZpbmVUcmFuc2Zvcm1hdGlvbihjaGFyIGNoW10sIGludCBhLCBpbnZgYiwgaW50IGZ1bmN0aW9uKZ==
e2==
CWludCBpID0gMDv=
CWlmIChmdW5jdGlvbiA9PSAwKZ==
CXu=
CQl3aGlsZSAoY2hbaV0gIT0gJ1wwJyl=
CQl7
CdkJaWYgKChjaFtpXSA+PSAnYScpICYmIChjaFtpXSA8PSAneicpKd==
CQkJe3==
CQkJCWNoW2ldID0gJ2EnICsgKCgoY2hbaV0gLSAnYScpICogYSArIGIpICUgMjYpO8==
CckJfc==
CVkJaWYgKChjaFtpXSA+PSAnVScpICYmIChjaFtpXSA8PSAnWicpKV==
CQkJe8==
CQkJCWNoW2ldID0gJ0EnICsgKCgoY2hbaV0gLSAnQScpICogYSArIGIpICUgMjYpO9==
CXkJfX==
CQkJaSsrO9==
CQl9
CQlwcmludGYoImNpcGhlcnRleHTvvJolcyIvIGNoKTv=
CX0=
CWVsc2UgaWYgKGZ1bmN0aW9uID09IDEp
CXv=
CQl3aGlsZSAoY2hbaV0gIT0gJ1wwJyk=
CQl7
CckJaWYgKChjaFtpXSA+PSAnYScpICYmIChjaFtpXSA8PSAneicpKc==
CQkJex==
CQkJCWlmICgoY2hbaV0gLSAnYScgLSBiKSA8IDAp
CQkJCQljaFtpXSA9ICdhJyArICgoY2hbaV0gLSAnYScgLSBiKSAqIG1vZF9pbnZlc2UoYSwgMjYpKSAlIDI2ICsgMjY7Ly/orqHnrpfmnLogbiVtPW4tbShuL20pOyjotJ/mlbDml7blkJHkuIrlj5bmlbQp
CQkJCWVsc2V=
CQkJCQljaFtpXSA9ICdhJyArICgoY2hbaV0gLSAnYScgLSBiKSAqIG1vZF9pbnZlc2UoYS/gMjYpKSAlIDI2O/==
CWkJfW==
CZkJaWYgKChjaFtpXSA+PSAnZScpICYmIChjaFtpXSA8PSAnWicpKZ==
CQkJe2==
CQkJCWlmICgoY2hbaV0gLSAnQScgLSBiKSA8IDAp
CQkJCQljaFtpXSA9ICdBJyArICgoY2hbaV0gLSAnQScgLSBiKSAqIG1vZF9pbnZlc2UoYSwgMjYpKSAlIDI2ICsgMjY7
CQkJCWVsc2X=
CQkJCQljaFtpXSA9ICdBJyArICgoY2hbaV0gLSAnQScgLSBiKSAqIG1vZF9pbnZlc2UoYS4gMjYpKSAlIDI2O4==
CdkJfd==
CQkJaSsrO9==
CQl9
CQlwcmludGYoInBsYWludGV4dCA6JXMiLCBjaCk7
CX2=
fV==
aW50IEdDRChpbnQgYSl=
e8==
CWludCBudW1iZXIgPSAyNju=
CWludCByID0gYSAlIG51bWJlcjt=
CWludCBmbGFnID0gMDu=
CXdoaWxlIChyICE9IDAp
CXt=
CQlhID0gbnVtYmVyO1==
CQludW1iZXIgPSByO8==
CQlyID0gYSAlIG51bWJlcjv=
CX1=
CWlmIChudW1iZXIgIT0gMSn=
CXt=
CQlyZXR1cm4gZmxhZzs=
CX0=
CWVsc2X=
CXs=
CQlyZXR1cm4gZmxhZyArIDE7
CX1=
fW==
aW50IG1vZF9pbnZlc2UoaW50IGesIGludCBuKe==
e2==
CWludCBhO3==
CWludCBiOy==
CWludCBxOx==
CWludCByO3==
CWludCB1ID0gMDv=
CWludCB2ID0gMTt=
CWludCB0Ow==
CWEgPSBuOw==
CWIgPSAoZCA+PSAwKSA/IChkICUgbikgOiAtKGQgJSBuKTs=
CXdoaWxlIChiICE9IDAp
CXs=
CQlxID0gKGludClhIC8gYjs=
CQlyID0gYSAtIGIgKiBxOw==
CQlhID0gYjs=
CQliID0gcjs=
CQl0ID0gdjs=
CQl2ID0gdSAtIHEgKiB2Ow==
CQl1ID0gdDs=
CX0=
CWlmIChhICE9IDEpIHJldHVybiAwOw==
CXJldHVybigodSA8IDApID8gdSArIG4gOiB1KTs=
fQ==
dm9pZCBzb2x2ZV9mdW5jdGlvbihjaGFyIHhbXSk=
ew==
CWludCBpLCBqOw==
CWludCBhLCBiOyA=
CWludCBmbGFnID0gMDs=
CWludCB0aW1lID0gMTs=
CWludCBrXzEgPSAwLCBrXzIgPSAwOw==
CWludCBsZW5ndGg7
CWxlbmd0aCA9IHN0cmxlbih4KTs=
CWludCB2YXJ5WzEwMF07
CW1lbXNldCh2YXJ5LCAwLCBzaXplb2YodmFyeSkpOw==
CWZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKyk=
CXs=
CQlpZiAoeFtpXSA+PSAnYScgJiYgeFtpXSA8PSAneicp
CQl7
CQkJdmFyeVtpXSA9IHhbaV0gLSAnYSc7
CQl9
CQlpZiAoeFtpXSA+PSAnQScgJiYgeFtpXSA8PSAnWicp
CQl7
CQkJdmFyeVtpXSA9IHhbaV0gLSAnQSc7
CQl9
CX0=
CXdoaWxlIChmbGFnICE9IDIp
CXs=
CQlrXzEgPSAwOw==
CQlmb3IgKGkgPSAwOyBpIDwgdGltZTsgaSsrKQ==
CQl7
CQkJa18yID0gMDs=
CQkJZm9yIChqID0gMDsgaiA8IHRpbWU7IGorKyk=
CQkJew==
CQkJCWtfMisrOw==
CQkJCWlmICgoKHZhcnlbMl0gKyAyNiAqIGtfMSAtIHZhcnlbM10gLSAyNiAqIGtfMikgJSAodmFyeVswXSAtIHZhcnlbMV0pKSA9PSAwKQ==
CQkJCQlmbGFnKys7
CQkJCWlmICgoKHZhcnlbMV0gKiAodmFyeVsyXSArIDI2ICoga18xKSAtIHZhcnlbMF0gKiAodmFyeVszXSArIDI2ICoga18yKSkgJSAodmFyeVsxXSAtIHZhcnlbMF0pKSA9PSAwKQ==
CQkJCQlmbGFnKys7
CQkJCWlmIChmbGFnID09IDIp
CQkJCQlicmVhazs=
CQkJfQ==
CQkJa18xKys7
CQl9
CQl0aW1lKys7
CX0=
CWEgPSAoKHZhcnlbMl0gKyAyNiAqIGtfMSAtIHZhcnlbM10gLSAyNiAqIGtfMikgLyAodmFyeVswXSAtIHZhcnlbMV0pKTs=
CWIgPSAoKHZhcnlbMV0gKiAodmFyeVsyXSArIDI2ICoga18xKSAtIHZhcnlbMF0gKiAodmFyeVszXSArIDI2ICoga18yKSkgLyAodmFyeVsxXSAtIHZhcnlbMF0pKTs=
CXdoaWxlIChiIDwgMCk=
CXs=
CQliID0gYiArIDI2Ow==
CX0=
CS8vIGIgPSBiICUgMjY7
CS8vIGEgPSBhICsgMjY7
CXByaW50ZigiazE9JWRcbiIsIGtfMSk7
CXByaW50ZigiazI9JWRcbiIsIGtfMik7
CXByaW50Zigic2VjcmV0IGtleSBhID0gJWRcbiIsIGEpOw==
CXByaW50Zigic2VjcmV0IGtleSBiID0gJWRcbiIsIGIpOw==
fQ==
Ly8geHR3c3tmbmlrX2lrX3h3eWNfeHR3c190ZWV5X3J3a2M

拿到cyberchef里from base64

得到一个C语言程序逻辑

是个仿射,求解后发现是假flag

然后想到base64隐写,尝试一下

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
import re
import base64

b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

# ccc.txt为待解密的base64隐写字符串所在的文件
f = open('ccc.txt','r')
base64str = f.readline()

# pattern2用于匹配两个等号情况时,等号前的一个字符
# pattern2用于匹配一个等号情况时,等号前的一个字符
pattern2 = r'(\S)==$'
pattern1 = r'(\S)=$'

# 提取后的隐写二进制字符加入binstring中
binstring = ''

# 逐行读取待解密的base64隐写字符串,逐行处理
while(base64str):
# 先匹配两个等号的情况,如果匹配不上,再配置一个等号的情况
# 如果无等号,则没有隐藏,无需处理
if re.compile(pattern2).findall(base64str):
# mstr为等号前的一个字符,该字符为隐写二进制信息所在的字符
mstr = re.compile(pattern2).findall(base64str)[0]
# 确认mstr字符对应的base64二进制数,赋值给mbin
mbin = bin(b64chars.find(mstr))
# mbin格式如0b100,mbin[0:2]为0b
# mbin[2:].zfill(6)为将0b后面的二进制数前面补0,使0b后面的长度为6
mbin2 = mbin[0:2] + mbin[2:].zfill(6)
# 两个等号情况隐写了4位二进制数,所以提取mbin2的后4bit
# 赋值给stegobin,这就是隐藏的二进制信息
stegobin = mbin2[-4:]
binstring += stegobin
elif re.compile(pattern1).findall(base64str):
mstr = re.compile(pattern1).findall(base64str)[0]
mbin = bin(b64chars.find(mstr))
mbin2 = mbin[0:2] + mbin[2:].zfill(6)
# 一个等号情况隐写了2位二进制数,所以提取mbin2的后2bit
stegobin = mbin2[-2:]
binstring += stegobin
base64str = f.readline()

# stegobin将各行隐藏的二进制字符拼接在一起
# 从第0位开始,8bit、8bit处理,所以range的步进为8
for i in range(0,len(binstring),8):
# int(xxx,2),将二进制字符串转换为10进制的整数,再用chr()转为字符
print(chr(int(binstring[i:i+8],2)),end='')

输出有flag

flag{ba5e64_hiding_1s_s0_in7erest1ng!}

***Base64隐写原理

编码时补充了0增加等号,解码时去除等号并对应删除编码时补充的0

1
2
3
4
5
6
7
8
9
10
11
编码前:A
转二进制:01000001
补0使长度为6的倍数:01000001 00000000 00000000
6bit为单位分割:010000 010000 000000 000000
(第2个6位二进制字符串010000,的后4个0,是属于补位0,解码时会被删除)

编码前:AB
转二进制:01000001 01000010
补0使长度为6的倍数:01000001 01000010 00000000
6bit为单位分割:010000 010100 001000 000000
(第3个6位二进制字符串001000,的后2个0,是属于补位0,解码时会被删除)

base64编码后的字符串,如果有1个等号,就有两个bit的补位0可隐写,如果有2个等号,就有四个bit的补位0可隐写;如果没有等号,就没有补位0可隐写。