n00bzCTF 2024

Crypto

Vinegar

题目:

Encrypted flag: nmivrxbiaatjvvbcjsf
Key: secretkey

exp:

维吉尼亚密码

image-20240803213429-3gxhu0y

flag:n00bz{vigenerecipherisfun}

RSA

题目:

e = 3
n = 135112325288715136727832177735512070625083219670480717841817583343851445454356579794543601926517886432778754079508684454122465776544049537510760149616899986522216930847357907483054348419798542025184280105958211364798924985051999921354369017984140216806642244876998054533895072842602131552047667500910960834243
c = 13037717184940851534440408074902031173938827302834506159512256813794613267487160058287930781080450199371859916605839773796744179698270340378901298046506802163106509143441799583051647999737073025726173300915916758770511497524353491642840238968166849681827669150543335788616727518429916536945395813

思路:

低加密指数攻击

exp :

from Crypto.Util.number import *
import gmpy2

e = 3
n = 135112325288715136727832177735512070625083219670480717841817583343851445454356579794543601926517886432778754079508684454122465776544049537510760149616899986522216930847357907483054348419798542025184280105958211364798924985051999921354369017984140216806642244876998054533895072842602131552047667500910960834243
c = 13037717184940851534440408074902031173938827302834506159512256813794613267487160058287930781080450199371859916605839773796744179698270340378901298046506802163106509143441799583051647999737073025726173300915916758770511497524353491642840238968166849681827669150543335788616727518429916536945395813

m = 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 += 1
    
    flag=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 random

questions = 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 打印出来

image-20240805235532-qzmqkzx

exp: 错误的

import pwn
import re
import time

p = 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 leet

app = Flask(__name__)
flag = open('/flag.txt').read()
leet=uuid.UUID('13371337-1337-1337-1337-133713371337')

@app.route('/',methods=['GET','POST'])
def main():
    global username
    if 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 flag

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=1337)

思路:

看路由  /<uid>  ,当 uid = uuid.uuid5(leet,'admin123') 时可以 return flag,

学习: 探索 Python 中的 uuid 模块:生成唯一标识符

exp:

所以我们本地可以生成这个 uid
import uuid

leet=uuid.UUID('13371337-1337-1337-1337-133713371337')
uid = uuid.uuid5(leet,"admin123")
print(uid)

image-20240805234610-o4a24xu

Rev

Brain

题目:

+++++++++++[<++++++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++++++++[<+++++++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[<++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++[<+++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>+++++++++++++[<++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>++++++++[<++++++>-]<[-]>++++++++++[<++++++++++>-]<[-]>+++++++++++++++++[<+++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++++[<+++++>-]<[-]>++++++++++++++[<+++++++>-]<[-]>+++++++++++++++++++[<++++++>-]<[-]>+++++++++++++[<++++>-]<[-]>+++++++[<+++++++>-]<[-]>+++++++++++[<++++++++++>-]<[-]>+++++++++++++++++[<++++++>-]<[-]>+++++++[<++++++>-]<[-]>+++++++++++[<+++++++++>-]<[-]>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<[-]>+++++++++++[<+++>-]<[-]>+++++++++++++++++++++++++[<+++++>-]<[-]

思路:

Brainfuck 解密,解密失败,说明需要将给的BF转成python代码,

**学习:**​记一次brainfuck的解密思路 - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

exp:

def shrinkBFCode(code):
    cPos2Vars = {}   #位置对应的变量
    cPos2Change = {}  #位置中 + 号 增加的值
    varPos = 0
    nCode = []
    incVal = 0
    lc = None
    dataChangeOp = set(['+', '-'])
    dataShiftOp = set(['>', '<'])
    for i in range(len(code)):
        c = code[i]
        if c not in dataChangeOp and lc in dataChangeOp:
            cPos2Change[len(nCode)] = incVal
            cPos2Vars[len(nCode)] = varPos
            nCode.append('+')
            incVal = 0
        if c == '>':
            varPos += 1
        elif c == '<':
            varPos -= 1
        else:
            if c in dataChangeOp:
                incVal += 1 if c == '+' else -1
            else:
                #if lc == '>' or lc == '<':
                #    cPos2Vars[len(nCode)] = varPos
                cPos2Vars[len(nCode)] = varPos
                nCode.append(c)
        lc = c
    return ''.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 skip
                loopCondvar = 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 indent
                while 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:
                        continue
                    ctimes = 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_change
        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_change
        elif 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] = 0

flag = ""
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

image-20240806004346-55ar9na

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

我们打开时发现现在被损坏了

image-20240806004937-62ujmug

010 查看一下 16进制,不难发现,标志位都被换成了 00

image-20240806161816-n8zfbva

修改后,然后播放可以明显听到是摩斯电码,使用在线网站解即可

image-20240806162436-5ec1aj5

image-20240806163319-2og40bd

flag: n00bz{beepbopmorsecode}

Disk Golf

题目:

Let’s play some disk golf!

思路:本来想使用 volatility2.6 ,但是无用,想到 fls 工具,就搜索到 flag

fls disk.img | grep "flag"

-r:递归地列出所有文件和目录。

-p:显示文件的路径。

image-20240807023220-f9uz68x

在使用 icat 命令读取数据

image-20240807023612-uodhfgu

image-20240807024431-k2n9sjh

flag: n00bz{7h3_l0ng_4w41t3d_d15k_f0r3ns1c5}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值