别笑,你试你也过不了第二关
构造变量 hilogo
使其值等于指定的 ASCII 艺术图案,代码长度必须小于 285 字符
第一关通过尝试,发现题目存在沙箱,禁了import,print,base64等,同时禁用使用字符串格式化
我们采用Code Golf的方法一句话直接绕过
a=' # ';b='##### ';c=' # #';d='# # #';e=' # # ';f='##### ';g=' ### #';h=' #####';hilogo=f+f+g+a+h+' '+b+b+f+g+a+h+'\n'+'# '+a+d+a+c+e+a+d+a+c+'\n'+'# '+a+f+'#'+a+c+e+a+f+'#'+a+c+'\n'+'# '+a+d+a+c+e+a+d+a+c+'\n'+f+f+d+'####'+h+h+' '+b+b+f+d+'####'+h+h
第二关
我们使用同样的方法,进行字符串切片,异或和链式比较
'tsnrhtdd'[n%5*(n%100^15>4>n%10)::4]
可得flag
帅的被人砍
流量包中tcp流传输的data提取出来
from scapy.all import rdpcap, TCP, UDP, Rawdef extract_payloads_from_pcap(pcap_file):packets = rdpcap(pcap_file)payloads = []for pkt in packets:# 只处理包含 Raw 层(即有 payload)的包if Raw in pkt:payload = bytes(pkt[Raw])payloads.append(payload)print(f"[+] 提取到 {len(payload)} 字节数据")return payloads# 使用示例
pcap_path = r"C:\Users\Alexander\Desktop\Desktop\3.pcapng" # 替换为你的 pcap 文件路径
all_payloads = extract_payloads_from_pcap(pcap_path)# 合并所有 payload(如果数据是连续传输的)
full_data = b''.join(all_payloads)# 保存原始流量 data 部分
with open("extracted_raw_data.bin", "wb") as f:f.write(full_data)print(f"✅ 共提取 {len(full_data)} 字节的原始 data")
发现是个倒装的7z,我们翻转回来
得到一个jpg和.c代码文件
//gcc -o decryptor decryptor.c -lssl -lcrypto
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/evp.h>#define HEADER_SIZE 128 // 文件头部大小void decrypt_file(const char *input_file, const char *output_file, unsigned char *key) {FILE *in = fopen(input_file, "rb");if (!in) {perror("Unable to open input file");return;}unsigned char header[HEADER_SIZE];fread(header, 1, HEADER_SIZE, in);unsigned char iv[AES_BLOCK_SIZE];fread(iv, 1, AES_BLOCK_SIZE, in);fseek(in, 0, SEEK_END);long encrypted_size = ftell(in) - HEADER_SIZE - AES_BLOCK_SIZE;fseek(in, HEADER_SIZE + AES_BLOCK_SIZE, SEEK_SET);unsigned char *encrypted_data = malloc(encrypted_size);fread(encrypted_data, 1, encrypted_size, in);fclose(in);AES_KEY decrypt_key;AES_set_decrypt_key(key, 256, &decrypt_key);unsigned char *decrypted_data = malloc(encrypted_size);AES_cbc_encrypt(encrypted_data, decrypted_data, encrypted_size, &decrypt_key, iv, AES_DECRYPT);FILE *out = fopen(output_file, "wb");if (!out) {perror("Unable to open output file");free(encrypted_data);free(decrypted_data);return;}fwrite(header, 1, HEADER_SIZE, out);fwrite(decrypted_data, 1, encrypted_size, out);fclose(out);free(encrypted_data);free(decrypted_data);
}int main() {unsigned char key[32] = {'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X','X', 'X', 'X', 'X', 'X', 'X', 'X', 'X','X', 'X', 'X', 'X', 'X', 'X', 'X', 'X','X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'};
// Ҫ 任 ɻ õ key decrypt_file(" ̬KEY .lock", " ̬KEY .re", key);system("chmod +x ̬KEY .re");return 0;
}
图片steghide隐写
PZNCKSLLLNWUMILYTNQSXCIDUNBHBDFV
但是我们单独逆向flag生成器
lzonc2550f12s3964f5spqornmzjfgg7
用户输入传入multipe_shift_decrypt与字符串进行对比,我们还原算法
多表凯撒。周期性移位密钥 [3, 5, 2]
对输入字符串进行还原
def encrypt(plain):shifts = [3,5,2]res = []for i, c in enumerate(plain):if c.isalpha():base = ord('a')shift = shifts[i % 3]enc = (ord(c) - base + shift) % 26 + baseres.append(chr(enc))else:res.append(c)return ''.join(res)print(encrypt("lzonc2550f12s3964f5spqornmzjfgg7"))
oeqqh2550i12v3964h5xrtttqrbmkij7
这是个假的key
传入程序只会回显success并不会给flag。
我们根据图片拿到32位的key我们还原aes加密过程并解密得到key.re二进制文件
from Crypto.Cipher import AES
import os# 配置
HEADER_SIZE = 128
INPUT_FILE = r"C:\Users\Alexander\Desktop\Desktop\动态KEY生成器.lock" # 替换为你的实际加密文件名
OUTPUT_FILE = "KEY.re" # 输出文件名
KEY = b"PZNCKSLLLNWUMILYTNQSXCIDUNBHBDFV" # 32字节密钥def decrypt_file(input_file, output_file, key):with open(input_file, "rb") as f:# 读取128字节头部header = f.read(HEADER_SIZE)if len(header) != HEADER_SIZE:raise ValueError("文件太短,无法读取头部")# 读取16字节IViv = f.read(AES.block_size)if len(iv) != AES.block_size:raise ValueError("文件太短,无法读取IV")# 读取剩余加密数据encrypted_data = f.read()# 创建AES解密器(CBC模式)cipher = AES.new(key, AES.MODE_CBC, iv)# 解密decrypted_data = cipher.decrypt(encrypted_data)# 去除PKCS#7填充(如果存在)# 注意:原始C代码没有去填充,但实际加密通常会填充# 这里安全地尝试去除填充try:pad_len = decrypted_data[-1]if isinstance(pad_len, str):pad_len = ord(pad_len)if 1 <= pad_len <= AES.block_size and all(b == pad_len for b in decrypted_data[-pad_len:]):decrypted_data = decrypted_data[:-pad_len]except Exception:# 如果不是标准填充,保留原始数据(兼容C代码行为)pass# 写入:头部 + 解密后数据with open(output_file, "wb") as f:f.write(header)f.write(decrypted_data)print(f"[+] 解密完成: {output_file}")if __name__ == "__main__":# 如果文件名包含特殊Unicode字符,请确保正确指定# 例如:INPUT_FILE = "\u0020\u032cKEY\u0020\u0020\u0020\u0020\u0020\u0020.lock"decrypt_file(INPUT_FILE, OUTPUT_FILE, KEY)# 添加可执行权限(Linux/macOS)if os.name != 'nt':os.chmod(OUTPUT_FILE, 0o755)print(f"[+] 已添加可执行权限: {OUTPUT_FILE}")
得到KEY.re二进制文件,我们逆向分析
得到key的逻辑
key.re是动态key生成器,以time为基准进行生成
题目说
小杜在2021年7月1日17时30分的时候使用动态密钥生成器,生成了一组KEY。而你怎样才能让FLAG生成器输出正确的flag呢。对了,他在使用动态密钥生成器的时候,被定位在了上海。
获取时间戳2021年7月1日17时30分
通过仿写key匹配去获取flag
完整的exp
import datetime# ===== 配置参数 =====
TARGET = "lzonc2550f12s3964f5spqornmzjfgg7" # 目标 FLAG 前缀(32字符)
CENTER_EPOCH = 1625131800 # 初始猜测时间戳(2021-07-01 17:30 CST)
SEARCH_WINDOW = 3600# byte_B60 数组(65字节,实际使用前64)
BYTE_B60 = [0x5E, 0x55, 0x44, 0x42, 0x5C, 0x07, 0x04, 0x0D,0x07, 0x51, 0x01, 0x0B, 0x42, 0x01, 0x0E, 0x00,0x05, 0x58, 0x00, 0x4B, 0x46, 0x41, 0x45, 0x4C,0x46, 0x4A, 0x52, 0x54, 0x5F, 0x5B, 0x5D, 0x01,0x76, 0x76, 0x60, 0x75, 0x6D, 0x7D, 0x4A, 0x57,0x5C, 0x49, 0x53, 0x09, 0x07, 0x07, 0x04, 0x55,0x5E, 0x40, 0x41, 0x46, 0x40, 0x59, 0x53, 0x48,0x02, 0x01, 0x09, 0x0E, 0x02, 0x50, 0x05, 0x4B,0x00
]# 移位规则(用于还原 FLAG)
SHIFTS = [3, 5, 2]def generate_dynamic_key(t: int) -> str:"""根据时间戳 t 生成 64 字符动态 KEY"""sq = t * tsq_str = str(sq)if len(sq_str) > 16:base16 = sq_str[-16:]else:base16 = sq_str.zfill(16)# 重复4次得到64字节明文plain64 = (base16 * 4).encode('ascii')# 与 byte_B60 异或key_bytes = bytes(plain64[i] ^ BYTE_B60[i] for i in range(64))return key_bytes.decode('latin1') # 允许非ASCII字符def reverse_shift_decrypt(s: str) -> str:"""对字符串 s 应用反向移位(用于还原 FLAG)"""result = []for i, ch in enumerate(s):if ch.isalpha():base = ord('a') if ch.islower() else ord('A')# 反向移位:减去 shift,模26shifted = (ord(ch) - base - SHIFTS[i % len(SHIFTS)]) % 26result.append(chr(shifted + base))else:result.append(ch)return ''.join(result)def main():print(f"🔍 正在搜索时间戳范围: {CENTER_EPOCH - SEARCH_WINDOW} ~ {CENTER_EPOCH + SEARCH_WINDOW}")print(f"🎯 目标 FLAG 前缀: {TARGET}\n")for t in range(CENTER_EPOCH - SEARCH_WINDOW, CENTER_EPOCH + SEARCH_WINDOW + 1):dynamic_key = generate_dynamic_key(t)decrypted_flag = reverse_shift_decrypt(dynamic_key[:32])if decrypted_flag == TARGET:# 获取可读时间(UTC 和 北京时间)dt_utc = datetime.datetime.fromtimestamp(t, tz=datetime.timezone.utc)dt_cst = dt_utc.astimezone(datetime.timezone(datetime.timedelta(hours=8)))print(f"\n🔑 原始动态 KEY (64字符):")print(repr(dynamic_key))print(f"\n🔐 AES-256 密钥 (前32字节,原始字节):")aes_key_bytes = dynamic_key[:32].encode('latin1')print("Hex: ", aes_key_bytes.hex())print("Str: ", repr(dynamic_key[:32]))print(f"\n🎯 验证 FLAG: {decrypted_flag}")returnprint(f"❌ 在 ±{SEARCH_WINDOW} 秒范围内未找到匹配。")if __name__ == "__main__":main()
成功男人背后的女人
图片放进010
有mkBT块,明显是使用adobe firework这个软件
我们打开
发现男生和女生图案,然后转01数据
01000100 01000001 01010011 01000011 01010100 01000110 01111011 01110111 00110000 01101101 01000101 01001110 01011111 01100010 01100101 01101000 00110001 01101110 01000100 01011111 01001101 01000101 01101110 01111101
得到flag
polar
cursor直接解决
题目得到
-
使用8个比特位(信道)传输4比特信息
-
每个信道擦除率为0.5
-
需要每个信息比特的恢复率超过50%,并且至少2个比特恢复率>0.7
二进制极化变换,该函数对输入向量
u
进行逐级蝶形运算,最终输出编码后的码字
x=u⋅GN=u⋅BNF ⊗n
采用BEC 信道极化码构造的经典方法
最终提交的exp
def polarTransform(u, N):n = int(np.log2(N))x = u.copy()for stage in range(n):stride = 2 ** (stage + 1)for start in range(0, N, stride):mid = start + stride // 2for i in range(stride // 2):a = x[start + i]b = x[mid + i]x[start + i] = (a + b) % 2x[mid + i] = breturn xdef computeChannelReliability(N, eps):if N == 1:return np.array([eps])Whalf = computeChannelReliability(N // 2, eps)Wminus = 2 * Whalf - Whalf ** 2Wplus = Whalf ** 2W = np.zeros(N)W[0::2] = WminusW[1::2] = Wplusreturn Wdef construction(N, K, eps):reliabilities = computeChannelReliability(N, eps)infoIdx = np.argsort(reliabilities)[:K]infoIdx = np.sort(infoIdx)frozenIdx = np.array([i for i in range(N) if i not in infoIdx])return infoIdx, frozenIdx, reliabilitiesdef encode(u, N):return polarTransform(u, N)def decode(y, frozenIdx):N = len(y)bestU = NonebestScore = -1for attempt in range(10):uHat = np.zeros(N, dtype=int)if attempt > 0:for i in range(N):if i not in frozenIdx:uHat[i] = np.random.randint(0, 2)for iteration in range(3):for i in range(N):if i in frozenIdx:uHat[i] = 0else:uHat[i] = findBestBit(y, uHat, i, N)xHat = polarTransform(uHat, N)score = 0for j in range(N):if y[j] is not None and xHat[j] == y[j]:score += 1if score > bestScore:bestScore = scorebestU = uHat.copy()return bestUdef findBestBit(y, uCurrent, bitIdx, N):bestScore = -1bestBit = 0for bitVal in [0, 1]:uTest = uCurrent.copy()uTest[bitIdx] = bitValxTest = polarTransform(uTest, N)score = 0for j in range(N):if y[j] is not None:if xTest[j] == y[j]:score += 1else:score -= 1if score > bestScore:bestScore = scorebestBit = bitValreturn bestBit
交互exp
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
import timeHOST = "45.40.247.139"
PORT = 30832print("正在连接靶机...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
print("✅ 连接成功!\n")# 接收欢迎消息
time.sleep(0.5)
data = s.recv(4096).decode('utf-8', errors='ignore')
print(data)# 发送选项 2
print(">>> 发送: 2")
s.send(b"2\n")
time.sleep(1)# 接收提示
data = s.recv(4096).decode('utf-8', errors='ignore')
print(data)# 读取并发送极化码
print(">>> 读取极化码...")
with open('polar_code_complete.py', 'r', encoding='utf-8') as f:polar_code = f.read()print(f">>> 发送代码 ({len(polar_code)} 字节)...")
s.send(polar_code.encode('utf-8') + b"\n")
time.sleep(0.5)# 发送 END
print(">>> 发送: END")
s.send(b"END\n")# 接收响应
print("\n等待服务器响应...\n")
print("=" * 70)for i in range(10): # 最多等待10次time.sleep(1)try:s.settimeout(3)data = s.recv(4096).decode('utf-8', errors='ignore')if data:print(data)if 'flag' in data.lower():print("\n" + "=" * 70)print("🎉🎉🎉 成功获取 Flag! 🎉🎉🎉")print("=" * 70)breakexcept socket.timeout:continueexcept:breaks.close()
print("\n任务完成!")