n00bzCTF 2024
Crypto
Vinegar
题目:
Encrypted flag: nmivrxbiaatjvvbcjsf
Key: secretkey
exp:
维吉尼亚密码
flag:n00bz{vigenerecipherisfun}
RSA
题目:
e = 3 n = 135112325288715136727832177735512070625083219670480717841817583343851445454356579794543601926517886432778754079508684454122465776544049537510760149616899986522216930847357907483054348419798542025184280105958211364798924985051999921354369017984140216806642244876998054533895072842602131552047667500910960834243 c = 13037717184940851534440408074902031173938827302834506159512256813794613267487160058287930781080450199371859916605839773796744179698270340378901298046506802163106509143441799583051647999737073025726173300915916758770511497524353491642840238968166849681827669150543335788616727518429916536945395813
思路:
低加密指数攻击
exp :
from Crypto.Util.number import *
import gmpy2e = 3
n = 135112325288715136727832177735512070625083219670480717841817583343851445454356579794543601926517886432778754079508684454122465776544049537510760149616899986522216930847357907483054348419798542025184280105958211364798924985051999921354369017984140216806642244876998054533895072842602131552047667500910960834243
c = 13037717184940851534440408074902031173938827302834506159512256813794613267487160058287930781080450199371859916605839773796744179698270340378901298046506802163106509143441799583051647999737073025726173300915916758770511497524353491642840238968166849681827669150543335788616727518429916536945395813m = gmpy2.iroot(c, e)[0]print(long_to_bytes(m))
Vinegar 2
题目:
-
chall.py
alphanumerical = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*(){}_?' matrix = [] for i in alphanumerical:matrix.append([i])idx=0 for i in alphanumerical:matrix[idx][0] = (alphanumerical[idx:len(alphanumerical)]+alphanumerical[0:idx])idx += 1flag=open('../src/flag.txt').read().strip() key='5up3r_s3cr3t_k3y_f0r_1337h4x0rs_r1gh7?' assert len(key)==len(flag) flag_arr = [] key_arr = [] enc_arr=[] for y in flag:for i in range(len(alphanumerical)):if matrix[i][0][0]==y:flag_arr.append(i)for y in key:for i in range(len(alphanumerical)):if matrix[i][0][0]==y:key_arr.append(i)for i in range(len(flag)):enc_arr.append(matrix[flag_arr[i]][0][key_arr[i]]) encrypted=''.join(enc_arr) f = open('enc.txt','w') f.write(encrypted)
-
enc.txt
*fa4Q(}$ryHGswGPYhOC{C{1)&_vOpHpc2r0({
exp:
# 定义字符集
alphanumerical = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*(){}_?'# 构建矩阵
matrix = []
for i in alphanumerical:matrix.append([i])idx = 0
for i in alphanumerical:matrix[idx][0] = (alphanumerical[idx:len(alphanumerical)] + alphanumerical[0:idx])idx += 1# 读取加密后的文件
with open('enc.txt', 'r') as f:encrypted = f.read().strip()# 定义key
key = '5up3r_s3cr3t_k3y_f0r_1337h4x0rs_r1gh7?'# 将key转换为索引数组
key_arr = []
for y in key:for i in range(len(alphanumerical)):if matrix[i][0][0] == y:key_arr.append(i)break# 解密加密后的字符串
decrypted_arr = []
for i in range(len(encrypted)):enc_char = encrypted[i]key_idx = key_arr[i]for row in range(len(matrix)):if matrix[row][0][key_idx] == enc_char:decrypted_arr.append(matrix[row][0][0])break# 将解密后的字符数组转换为字符串
decrypted = ''.join(decrypted_arr)# 输出解密后的flag
print(decrypted)
Random
题目:
I hid my password behind an impressive sorting machine. The machine is very luck based, or is it?!?!?!?
我把密码藏在一台令人印象深刻的分拣机后面。这台机器非常靠运气,或者是吗?!?!?!?
#include<chrono>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<string>
#include<fstream>
#include<thread>
#include<map>
using namespace std;bool amazingcustomsortingalgorithm(string s) {int n = s.size();for (int i = 0; i < 69; i++) {cout << s << endl;bool good = true;for (int i = 0; i < n - 1; i++)good &= s[i] <= s[i + 1];if (good)return true;random_shuffle(s.begin(), s.end());this_thread::sleep_for(chrono::milliseconds(500));}return false;
}int main() {string s;getline(cin, s);map<char, int> counts;for (char c : s) {if (counts[c]) {cout << "no repeating letters allowed passed this machine" << endl;return 1;}counts[c]++;}if (s.size() < 10) {cout << "this machine will only process worthy strings" << endl;return 1;}if (s.size() == 69) {cout << "a very worthy string" << endl;cout << "i'll give you a clue'" << endl;cout << "just because something says it's random mean it actually is" << endl;return 69;}random_shuffle(s.begin(), s.end());if (amazingcustomsortingalgorithm(s)) {ifstream fin("flag.txt");string flag;fin >> flag;cout << flag << endl;}else {cout << "UNWORTHY USER DETECTED" << endl;}
}
Misc
Addition
题目:
import time
import randomquestions = int(input("how many questions do you want to answer? "))for i in range(questions):a = random.randint(0, 10)b = random.randint(0, 10)yourans = int(input("what is " + str(a) + ' + ' + str(b) + ' = '))print("calculating")totaltime = pow(2, i)print('.')time.sleep(totaltime / 3)print('.')time.sleep(totaltime / 3)print('.')time.sleep(totaltime / 3)if yourans != a + b:print("You made my little brother cry")exit(69)f = open('/flag.txt', 'r')
flag = f.read()
print(flag[:questions])
思路: 很明显计算对一次就会读取一个 flag 的值,但是有个问题,延迟的时间呈指数级增长,做 8 个以上的问题很痛苦,我以开始没注意到,写了个脚本一直跑,出不来,最后看了一下题目,发现输入 -1 可以绕过这个循环, print(flag[:-1]) 也可以把 flag 打印出来
exp: 错误的
import pwn
import re
import timep = pwn.remote('24.199.110.35', 42189)# 接收
bytes = p.recv(1024)
print(bytes)# 发送
p.sendline(b'20')bytes = p.recv(1024)
print(bytes)
# b'what is 8 + 10 = ' 写个正则表达式匹配 8 + 10 =
# eval_result = re.findall(r'\d+', bytes.decode())
# sum = int(eval_result[0]) + int(eval_result[1])
# print(sum)for i in range(20):eval_result = re.findall(r'\d+', bytes.decode())sum = int(eval_result[0]) + int(eval_result[1])print(sum)p.sendline(str(sum).encode())# time.sleep(1)bytes = p.recv(1024)print(bytes)
web
Passwordless
题目:
#!/usr/bin/env python3
from flask import Flask, request, redirect, render_template, render_template_string
import subprocess
import urllib
import uuid
global leetapp = Flask(__name__)
flag = open('/flag.txt').read()
leet=uuid.UUID('13371337-1337-1337-1337-133713371337')@app.route('/',methods=['GET','POST'])
def main():global usernameif request.method == 'GET':return render_template('index.html')elif request.method == 'POST':username = request.values['username']if username == 'admin123':return 'Stop trying to act like you are the admin!'uid = uuid.uuid5(leet,username) # super secure!return redirect(f'/{uid}')@app.route('/<uid>')
def user_page(uid):if uid != str(uuid.uuid5(leet,'admin123')):return f'Welcome! No flag for you :('else:return flagif __name__ == '__main__':app.run(host='0.0.0.0', port=1337)
思路:
看路由 **/<uid>** ,当 uid = uuid.uuid5(leet,'admin123') 时可以 return flag,
学习:
[探索 Python 中的 uuid 模块:生成唯一标识符_python uuid-CSDN博客](https://blog.csdn.net/Trb601012/article/details/135744410)
exp:
所以我们本地可以生成这个 uid
import uuidleet=uuid.UUID('13371337-1337-1337-1337-133713371337')
uid = uuid.uuid5(leet,"admin123")
print(uid)
Rev
Brain
题目:
+++++++++++[<++++++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++++++++[<+++++++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[<++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++[<+++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>+++++++++++++[<++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++++[<++++++++++>-]<[-]>+++++++++++++++++[<+++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>++++++++++++++[<+++++++>-]<[-]>+++++++++++++++++++[<++++++>-]<[-]>+++++++++++++[<++++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++[<++++++>-]<[-]>+++++++[<++++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<[-]>+++++++++++[<+++>-]<[-]>+++++++++++++++++++++++++[<+++++>-]<[-]
思路:
Brainfuck 解密,解密失败,说明需要将给的BF转成python代码,
学习:记一次brainfuck的解密思路 - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn
exp:
def shrinkBFCode(code):cPos2Vars = {} #位置对应的变量cPos2Change = {} #位置中 + 号 增加的值varPos = 0nCode = []incVal = 0lc = NonedataChangeOp = set(['+', '-'])dataShiftOp = set(['>', '<'])for i in range(len(code)):c = code[i]if c not in dataChangeOp and lc in dataChangeOp:cPos2Change[len(nCode)] = incValcPos2Vars[len(nCode)] = varPosnCode.append('+')incVal = 0if c == '>':varPos += 1elif c == '<':varPos -= 1else:if c in dataChangeOp:incVal += 1 if c == '+' else -1else:#if lc == '>' or lc == '<':# cPos2Vars[len(nCode)] = varPoscPos2Vars[len(nCode)] = varPosnCode.append(c)lc = creturn ''.join(nCode), cPos2Vars, cPos2Change
def generatePyCode(shellCode, pVars, pChange):pyCodes = []bStacks = []whileVarCache = {}for i, c in enumerate(shellCode):d_pos = i if i not in pVars else pVars[i]d_change = 1 if i not in pChange else pChange[i]indentLevel = len(bStacks)indentStr = ' '*(4*indentLevel)if c == '[':pyCodes.append('{}while data[{}] != 0:'.format(indentStr, d_pos))bStacks.append((c, i))whileVarCache[i] = {}elif c == ']':if bStacks[-1][0] != '[':raise Exception('miss match of {}] found between {} and {}'.format(bStacks[-1][0], bStacks[-1][1], i))cNum = i-bStacks[-1][1]if cNum == 2:del pyCodes[-1]del pyCodes[-1]d_pos_l = i-1 if i-1 not in pVars else pVars[i-1]pyCodes.append('{}data[{}] = 0'.format(' '*(4*(indentLevel-1)), d_pos_l))whileCode = shellCode[bStacks[-1][1]+1 : i]if cNum>2 and '[' not in whileCode and not '%' in whileCode: # nested loop is a bit complicated, just skiploopCondvar = bStacks[-1][1]d_pos_l = loopCondvar if loopCondvar not in pVars else pVars[loopCondvar]whileVars = whileVarCache[bStacks[-1][1]]cVarChange = whileVars[d_pos_l]# remove statement of same indentwhile len(pyCodes)>0 and pyCodes[-1].startswith(indentStr) and pyCodes[-1][len(indentStr)]!=' ':pyCodes.pop()pyCodes.pop()#del pyCodes[bStacks[-1][1]-i:]for vPos, vChange in whileVars.items():if vPos == d_pos_l:continuectimes = abs(vChange / cVarChange)ctimesStr = '' if ctimes==1 else '{}*'.format(ctimes)cSign = '+' if vChange > 0 else '-'pyCodes.append('{}data[{}] {}= {}data[{}]'.format(' '*(4*(indentLevel-1)),vPos, cSign, ctimesStr, d_pos_l))pyCodes.append('{}data[{}] = 0'.format(' '*(4*(indentLevel-1)), d_pos_l))del whileVarCache[bStacks[-1][1]]bStacks.pop()elif c == '.':pyCodes.append('{}print(data[{}])'.format(indentStr, d_pos))elif c == ',':pyCodes.append('{}data[{}] = ord(stdin.read(1))'.format(indentStr, d_pos))elif c == '+':opSign = '-=' if d_change < 0 else '+='if pyCodes and pyCodes[-1] == '{}data[{}] = 0'.format(indentStr, d_pos):pyCodes[-1] = '{}data[{}] = {}'.format(indentStr, d_pos, d_change)else:pyCodes.append('{}data[{}] {} {}'.format(indentStr, d_pos, opSign, abs(d_change)))if bStacks:whileVarCache[bStacks[-1][1]].setdefault(d_pos, 0)whileVarCache[bStacks[-1][1]][d_pos] += d_changeelif c == '-':opSign = '+=' if d_change < 0 else '-='if pyCodes and pyCodes[-1] == '{}data[{}] = 0'.format(indentStr, d_pos):pyCodes[-1] = '{}data[{}] = {}'.format(indentStr, d_pos, -d_change)else:pyCodes.append('{}data[{}] {} {}'.format(indentStr, d_pos, opSign, abs(d_change)))if bStacks:whileVarCache[bStacks[-1][1]].setdefault(d_pos, 0)whileVarCache[bStacks[-1][1]][d_pos] -= d_changeelif c == '%':pyCodes.append('{}data[{}] %= data[{}]'.format(indentStr, d_pos, d_pos+1))return '\n'.join(pyCodes)s = '>+++++++++++[<++++++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++++++++[<+++++++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[<++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++[<+++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>+++++++++++++[<++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++++[<++++++++++>-]<[-]>+++++++++++++++++[<+++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>++++++++++++++[<+++++++>-]<[-]>+++++++++++++++++++[<++++++>-]<[-]>+++++++++++++[<++++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++[<++++++>-]<[-]>+++++++[<++++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<[-]>+++++++++++[<+++>-]<[-]>+++++++++++++++++++++++++[<+++++>-]<[-]'shrinkCode, pVars, pChange = shrinkBFCode(s)
res = generatePyCode(shrinkCode, pVars, pChange)# 将结果写入文件,
with open('flag.txt', 'w') as f:f.write(res)print(res)
将输出结果分析一下,就是一直在计算 d[0] 的值,处理一下就好
# 初始化data列表
data = [0, 0]# 存储每次data[0]的值
data_values = []data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 10.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 8
data[0] += 6.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 8
data[0] += 6.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 14
data[0] += 7.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 61
data[0] += 2.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 41
data[0] += 3.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 7
data[0] += 7.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 19
data[0] += 5.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 9.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 13
data[0] += 4.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 10.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 19
data[0] += 5.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 9.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 8
data[0] += 6.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 10
data[0] += 10.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 17
data[0] += 3.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 19
data[0] += 5.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 7
data[0] += 7.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 10.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 19
data[0] += 5.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 14
data[0] += 7.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 19
data[0] += 6.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 13
data[0] += 4.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 7
data[0] += 7.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 10.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 17
data[0] += 6.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 7
data[0] += 6.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 9.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 107
data[0] += data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 11
data[0] += 3.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0
data[1] += 25
data[0] += 5.0*data[1]
data_values.append(data[0])data[1] = 0
data[0] = 0flag = ""
for i in range(len(data_values)):flag += chr(int(data_values[i]))print(flag)
flag: n00bz{1_c4n_c0d3_1n_br41nf*ck!}
Forensics
Plane
题目:
So many plane-related challenges! Why not another one? The flag is the latitude, longitude of the place this picture is taken from, rounded upto two decimal places. Example: n00bz{55.51,-20.27}. Author: NoobMaster Author: NoobMaster
exp:
先下载图片:
curl https://static.n00bzunit3d.xyz/Forensics/Plane/plane.jpg -o plane.jpg
在查看图片信息
exiftool plane.jpg
Wave
题目:
The Wave is not audible, perhaps corrupted? Note: Wrap the flag in n00bz{}. There are no spaces in the flag and it is all lowercase.
学习:【音频处理】WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )_52 49 46 46-CSDN博客
exp:
先下载这个音频
curl https://static.n00bzunit3d.xyz/Forensics/Wave/chall.wav -o wave.wav
我们打开时发现现在被损坏了
010 查看一下 16进制,不难发现,标志位都被换成了 00
修改后,然后播放可以明显听到是摩斯电码,使用在线网站解即可
flag: n00bz{beepbopmorsecode}
Disk Golf
题目:
Let's play some disk golf!
思路:本来想使用 volatility2.6 ,但是无用,想到 fls 工具,就搜索到 flag
fls disk.img | grep "flag"
-r:递归地列出所有文件和目录。
-p:显示文件的路径。
在使用 icat 命令读取数据
flag: n00bz{7h3_l0ng_4w41t3d_d15k_f0r3ns1c5}