MOECTF 2024

签到

跟着pdf

输入/bind 和个人识别码

MISC

signin

把luo缺勤,别的签到就行

罗小黑战记

gif图直接逐帧分析就行

moectf{y0uu6r3th3m0st3r1nth1sf13ld}

ez_F5

看属性里面

密码就是这个(当时真的无语住了)no_password

ez_Forensics

杂项入门指北

仔细观察,发现摩斯密码加密密文

注意中间要空格

the_secret_of_snowball

发现文件头错了

是ff d8

moectf{Welc0me_t0_the_secret_life_0f_Misc!}

提交发现错了。那应该不是

ret_life_0f_Misc!

find_it

查看西安的桔子水晶酒店,发现北站市政府店附近有相似的建筑

旋转视角

发现两个贴在一起的幼儿园

moectf{ji_di_bao_you_er_yuan}

解不完的压缩包

这里附上爆破脚本(使用时记得修改初始设置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import zipfile
import os

# 初始设置:压缩包存储目录和初始zip文件名称
"""只要修改路径和需要解压的压缩包即可"""
zip_directory = r'D:\网站下载\taowa'
zip_name = '999.zip'

# 循环解压嵌套的压缩包
while True:
# 拼接当前的完整压缩包路径
zip_path = os.path.join(zip_directory, zip_name)

# 打开当前压缩包
with zipfile.ZipFile(zip_path, 'r') as myzip:
# 获取压缩包内文件列表
file_list = myzip.namelist()

# 判断是否有zip文件,提取文件名
if not any('.zip' in f for f in file_list): # 如果文件列表中没有zip文件
print(f"Final unzipped location: {zip_path}")
# 解压到目标目录
myzip.extractall(os.path.join(zip_directory, 'final'))
break # 终止循环
else:
# 如果文件列表中有zip文件,提取其中第一个zip文件
for file_name in file_list:
if file_name.endswith('.zip'):
zip_name = file_name # 更新zip_name为内部的zip文件
break
# 解压当前的zip包到同级目录
myzip.extractall(zip_directory)

拿到1.zip

发现解压要密码

crcexp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from binascii import crc32
import string
import zipfile

dic = string.printable


def CrackCrc(crc):
for i in dic:
# print (i)
for j in dic:
s = i + j
# print (crc32(bytes(s,'ascii')) & 0xffffffff)
if crc == (crc32(bytes(s, 'ascii')) & 0xffffffff):
print(s)
return


def getcrc32(fname):
l = []
file = fname
f = zipfile.ZipFile(file, 'r')
global fileList
fileList = f.namelist()
print(fileList)
# print (type(fileList))
for filename in fileList:
Fileinfo = f.getinfo(filename)
# print(Fileinfo)
crc = Fileinfo.CRC
# print ('crc',crc)
l.append(crc)
return l


def main(filename=None):
l = getcrc32(filename)
# print(l)
for i in range(len(l)):
print(fileList[i], end='的内容是:')
CrackCrc(l[i])


if __name__ == "__main__":
main('cccccccrc.zip')

密码*m:#P7j0

小小套娃

打开png发现文件出错

爆破宽高

拿到kali里面分离一下

改成png文件,扫码得到first key 874jfy37yf37y7

打开txt文件,发现显示长度与所见长度不合,是txt零宽度隐写

放入kali里面

用vi +文件名 命令打开

很明显是零宽度字符隐写,在上面有找到4种零宽度字符,使用在线解密工具进行解密

零宽文本加解密工具 - 翰络云工具 (hanloth.cn)

有feff、200f、200e、200b、200c

拿到密码,解一下佛教

拼图羔手

moejail_lv1

nc 127.0.0.1 63431

import(“os”).system(“ls”)

看一下main函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import re
CONFIG_USE_FORK = True
MOTD = """馃構 Welcome to the ez python jail!"""
def my_safe_eval(code):
if re.match(r"os|system|[\\\+]", code):
return "Hacked By Rx"
return eval(code)
def chall(input, print):
code: str = input("Give me your payload:")
if len(code) > 100:
print("Too long code, Sry!")
return
value = my_safe_eval(code)
print(value)
def handle(input, print):
import random
import string
print(
"HTTP/1.1 302 Found\r\nLocation: https://lug.ustc.edu.cn/planet/2019/09/how-to-use-nc/\r\nContent-Length: 0\r\n\r\n===HTTP REQUEST PREVENT===\x00\033c"
)
try:
print(MOTD)
count = 0
while True:
captcha = "".join(
random.choices(string.ascii_uppercase + string.digits, k=6)
)
captcha2 = "".join(
random.choices(string.ascii_uppercase + string.digits, k=6)
)
if (
input(
f"馃え Are you robot? Please enter '{captcha}'+'{captcha2}'=? to continue: "
)
.strip()
.upper()
!= captcha + captcha2
):
count += 1
print("馃 Robot detected, try again")
if count > 5:
print("馃 Too many tries, blocked")
break
continue
count = 0
try:
chall(input, print)
except Exception as e:
print(f"馃 Error: {e}")
except Exception as e:
print(
f"\033c ========== Unhandled Error! ==========\n馃ズ We cannot recover from error: {e}\nChild process exited. Please reconnect or ask administrators for help if error persist"
)
def daemon_main():
import os
import socket
import subprocess
print("[Info] Server starting")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
pwd = os.path.dirname(__file__)
script = open(__file__, "rb").read()
self_fd = os.memfd_create("main")
os.write(self_fd, script)
os.lseek(self_fd, 0, os.SEEK_SET)
os.chmod(self_fd, 0o444)
try:
sock.bind(("0.0.0.0", 9999))
sock.listen(1)
while True:
try:
conn, addr = sock.accept()
print(f"[Info] Connected with {addr}")
fd = conn.fileno()
subprocess.Popen(
[
"python",
"/proc/self/fd/{}".format(self_fd),
"fork",
],
stdin=fd,
stdout=fd,
stderr=fd,
pass_fds=[self_fd],
cwd=pwd,
env=os.environ,
)
except Exception as e:
print(f"[Error] {e}")
except KeyboardInterrupt:
print("[Info] Server stopped")
finally:
sock.close()
print("[Info] Server closed")
if __name__ == "__main__":
import sys
if len(sys.argv) == 2 and sys.argv[1] == "fork":
del sys
handle(input, print)
else:
daemon_main()

发现在另一个wrapper.sh里面

发现不能超过100个字符

ls /tmp -a 显示所有的文件,包括临时文件

使用通配符*省略后面的字符

moejail_lv2

Web

Web渗透测试与审计入门指北

安装phpstudy

Windows版phpstudy下载 - 小皮面板(phpstudy) (xp.cn)

本地搭建网站

一个视频教会你,如何在本地搭建php网站服务环境_哔哩哔哩_bilibili

创建一个目录,然后将www网站html放入目录中创建本地网站,访问local即可

弗拉格之地的入口

使用dirsearch扫描不出来

访问robots.txt

访问他给的地址拿到flag

ez_http

垫刀之路01: MoeCTF?启动!(env查看环境变量)

查看根目录即可

RE

入门签到

运行代码就行

moectf{r3v3rs3_1s_a_long_long_way_to_explore}

xor

1
2
3
4
5
6
7
8
9
10
11
a=[
0x49, 0x4B, 0x41, 0x47, 0x50, 0x42, 0x5F, 0x41, 0x1C, 0x16,
0x46, 0x10, 0x13, 0x1C, 0x40, 0x09, 0x42, 0x16, 0x46, 0x1C,
0x09, 0x10, 0x10, 0x42, 0x1D, 0x09, 0x46, 0x15, 0x14, 0x14,
0x09, 0x17, 0x16, 0x14, 0x41, 0x40, 0x40, 0x16, 0x14, 0x47,
0x12, 0x40, 0x14, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]
for i in range(45):
a[i]=a[i]^0x24
print(chr(a[i]),end='')

upx

upx-revenge

正常应该是UPX

改回来解壳

dynamic

下个断点,动调一下

点开看一下v7

发现里面存储着flag

shift12提取一下

moectf{18d4c944-947c-4808-9536-c7d34d6b3827}

TEA

单独的xyz在十六进制下都是一位,算半字节,<<16左移两字节

四字节x 四字节y+z

前面是4个密钥

cmp比较最终的密文

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>   //836153A5  8E00  49BD 注意大小写!
#include <stdint.h> //moectf{836153a5-8e00-49bd-9c42-caf30620caaf}

#define DELTA 0x61C88647

void tea_decrypt(uint32_t *v, uint32_t *key) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = 0-DELTA * 32; // 32 轮解密
for (int i = 0; i < 32; i++) {
v1-=(v0+sum)^(16*v0+key[2])^((v0>>5)+key[3]);
v0-=(v1+sum)^(16*v1+key[0])^((v1>>5)+key[1]);
sum += DELTA;
}
v[0] = v0;
v[1] = v1;
}

int main() {
uint32_t v[2] = {0x284C2234, 0x3910C558}; // 加密后数据
uint32_t key[4] = {0x65736162, 0x6F783436, 0x61657472, 0x61657478}; // 密钥

printf("Encrypted: %08X %08X\n", v[0], v[1]);
tea_decrypt(v, key);
printf("Decrypted: %08X %08X\n", v[0], v[1]);

return 0;
}

moectf{xxxxxxxx-yyyy-zzzz-9c42-caf30620caaf}

moectf{836153A5-8E00-49BD-9c42-caf30620caaf}

moectf{836153a5-8e00-49bd-9c42-caf30620caaf}(改成小写就对了)

xtea

moectf{your key}

d0tN3t

用ilspy打开

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = [173, 146, 161, 174, 132, 179, 187, 234, 231, 244,
177, 161, 65, 13, 18, 12, 166, 247, 229, 207,
125, 109, 67, 180, 230, 156, 125, 127, 182, 236,
105, 21, 215, 148, 92, 18, 199, 137, 124, 38,
228, 55, 62, 164]
x = len(a)
b = []

for i in range(x):
b.append((((a[i] ^ (i * i)) ^ 0x72) - 114)%128)
"要使得ascll在0-127内,所以要取余128,否则会输出乱码"


for i in range(x):
print(chr(b[i]), end='')

取余前:

取余后

rc4

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from Crypto.Cipher import ARC4
import binascii

# 十六进制字符串
hex_data = "A71A68ECD82711CC8C9B16155CD2673E82ADCE75D4BC5756C28A52B86BD6CCF8A4BA722FE05715B92411"

# 将十六进制字符串转换为字节
ciphertext = binascii.unhexlify(hex_data)

# RC4 密钥(假设你知道密钥)
key = b'RC4_1s_4w3s0m3' # 替换为你的RC4密钥

# 创建 RC4 解密对象
cipher = ARC4.new(key)

# 解密数据
plaintext = cipher.decrypt(ciphertext)

# 输出解密后的内容
print(plaintext.decode('utf-8', errors='ignore'))

babe-ze3(不会)

先脱壳

网站Hint最后一个if有问题,狗屁通说v4和 !(_DWORD)v4无法同时成立

之前Z3解密用的都是Ints类型,这次运算有变,变成BitVec()位向量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from libnum import n2s
from z3 import *
from Crypto.Util.number import *

# 定义变量
s = BitVec('s', 64)
v6 = BitVec('v6', 64)
v7 = BitVec('v7', 64)
v8 = BitVec('v8', 64)
solver = Solver()

# 添加条件
solver.add((v7 & s & v8 | (~(v6 | s) | v6 & v7) & v6 & s) == 0x2024243035302131)
solver.add((v6 ^ (v7 & (s + v7) | v8 & ~(v7 & s) | v6 & (v6 + v8) & ~s)) == 0x7071001344417B54)
solver.add(((v7 - v8) ^ (s - v6)) == 0x3FE01013130FFD3)
solver.add((s + v7 - v8 + v6) * (v8 + s + v6 - v7) == 0x1989A41A9049C5C9)
solver.add((v7 + v6 + s + v8) % 0x1BF52 == 21761)
solver.add(v8 * v7 * v6 * s % 0x1D4B42 == 827118)

# 检查是否有解
if solver.check() == sat:
model = solver.model()

# 输出变量的解
s_val = model[s].as_long()
v6_val = model[v6].as_long()
v7_val = model[v7].as_long()
v8_val = model[v8].as_long()

# 将解转换为字符串
print("s:", n2s(s_val))
print("v6:", n2s(v6_val))
print("v7:", n2s(v7_val))
print("v8:", n2s(v8_val))
else:
print("No solution found")

# 处理字符串翻转
s = 'cd5250c9dbc4fdab1760517947e35495'
s1 = ''
for i in range(0, 32, 8):
a = s[i:i+8]
a = a[::-1] # 翻转每个8字符的子串
s1 += a

print("Processed string:", s1)
# 结果应为: 9c0525dcba4fdfbd9715067159453e74

moectf{9c0525dcbadf4cbd9715067159453e74}

xor(大嘘)

ez_maze

脱壳

Crypto

入门指北

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import gmpy2
from Crypto.Util.number import long_to_bytes


e = 0x10001
# n=8518969207529636389484032230886536704406768047371377256638626913642749445259329340941109791553519452501892180150380956873522604338824472473236167891564393

# print(n)
n = 40600296529065757616876034307502386207424439675894291036278463517602256790833
p = 197380555956482914197022424175976066223
q = 205695522197318297682903544013139543071
c = 36450632910287169149899281952743051320560762944710752155402435752196566406306
d = gmpy2.invert(e, (p - 1) * (q - 1))
print("d=", d)
m = pow(c, d, n)
print(m)
print(long_to_bytes(m))

signin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from Crypto.Util.number import inverse, long_to_bytes
from sympy import symbols, solve

# 已知值
c = 5654386228732582062836480859915557858019553457231956237167652323191768422394980061906028416785155458721240012614551996577092521454960121688179565370052222983096211611352630963027300416387011219744891121506834201808533675072141450111382372702075488292867077512403293072053681315714857246273046785264966933854754543533442866929316042885151966997466549713023923528666038905359773392516627983694351534177829247262148749867874156066768643169675380054673701641774814655290118723774060082161615682005335103074445205806731112430609256580951996554318845128022415956933291151825345962528562570998777860222407032989708801549746
pq = 18047017539289114275195019384090026530425758236625347121394903879980914618669633902668100353788910470141976640337675700570573127020693081175961988571621759711122062452192526924744760561788625702044632350319245961013430665853071569777307047934247268954386678746085438134169871118814865536503043639618655569687154230787854196153067547938936776488741864214499155892870610823979739278296501074632962069426593691194105670021035337609896886690049677222778251559566664735419100459953672218523709852732976706321086266274840999100037702428847290063111455101343033924136386513077951516363739936487970952511422443500922412450462
qp = 18047017539289114275195019384090026530425758236625347121394903879980914618669633902668100353788910470141976640337675700570573127020693081175961988571621759711122062452192526924744760561788625702044632350319245961013430665853071569777307047934247268954386678746085438134169871118814865536503043639618655569687077087914198877794354459669808240133383828356379423767736753506794441545506312066344576298453957064590180141648690226266236642320508613544047037110363523129966437840660693885863331837516125853621802358973786440314619135781324447765480391038912783714312479080029167695447650048419230865326299964671353746764860
n = 18047017539289114275195019384090026530425758236625347121394903879980914618669633902668100353788910470141976640337675700570573127020693081175961988571621759711122062452192526924744760561788625702044632350319245961013430665853071569777307047934247268954386678746085438134169871118814865536503043639618655569687534959910892789661065614807265825078942931717855566686073463382398417205648946713373617006449901977718981043020664616841303517708207413215548110294271101267236070252015782044263961319221848136717220979435486850254298686692230935985442120369913666939804135884857831857184001072678312992442792825575636200505903
p_q = 279533706577501791569740668595544511920056954944184570513187478007551195831693428589898548339751066551225424790534556602157835468618845221423643972870671556362200734472399328046960316064864571163851111207448753697980178391430044714097464866523838747053135392202848167518870720149808055682621080992998747265496
e = 65537

# 恢复 p 和 q
p, q = symbols('p q', integer=True)
solutions = solve([
p * q - n,
p + q - p_q,
(p-1)*(q-2) - pq,
(q-1)*(p-2) - qp,
], [p, q])

p, q = solutions[0]

# 转换为标准的 Python int 类型
p = int(p)
q = int(q)

print(f"Recovered p: {p}")
print(f"Recovered q: {q}")

# 计算 φ(n)
phi_n = (p - 1) * (q - 1)

# 计算 d (私钥指数)
d = inverse(e, phi_n)

# 解密消息
m = pow(c, d, n)
flag = long_to_bytes(m)
print(f"Decrypted flag: {flag.decode()}")

ez_hash

1
2
3
4
5
6
7
8
from hashlib import sha256
from secret import flag, secrets

assert flag == b'moectf{' + secrets + b'}'
assert secrets[:4] == b'2100' and len(secrets) == 10
hash_value = sha256(secrets).hexdigest()
print(f"{hash_value = }")
# hash_value = '3a5137149f705e4da1bf6742e62c018e3f7a1784ceebcb0030656a2b42f50b6a'

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import itertools
import hashlib
from concurrent.futures import ThreadPoolExecutor

# 已知条件
known_prefix = b'2100'
target_hash = '3a5137149f705e4da1bf6742e62c018e3f7a1784ceebcb0030656a2b42f50b6a'
total_length = 10

# 计算剩余字节的长度
remaining_length = total_length - len(known_prefix)

# 定义可能的字符集(限制为数字)
charset = '0123456789'

# 定义多线程的工作函数
def hash_crack(candidate_suffix):
potential_secret = known_prefix + candidate_suffix.encode()
hash_value = hashlib.sha256(potential_secret).hexdigest()
if hash_value == target_hash:
return potential_secret
return None

# 使用多线程进行暴力破解
def main():
with ThreadPoolExecutor(max_workers=8) as executor: # 使用 8 个线程
for candidate in itertools.product(charset, repeat=remaining_length):
candidate_suffix = ''.join(candidate)
future = executor.submit(hash_crack, candidate_suffix)
result = future.result()
if result:
print(f"Found matching secret: {result}")
return # 找到结果后终止

if __name__ == "__main__":
main()

moectf{2100360168}

Big and small(e很小)

1
2
3
4
5
6
7
8
9
10
11
12
13
from secret import flag
from Crypto.Util.number import*
m = long_to_bytes(flag)
p = getPrime(1024)
q = getPrime(1024)
n = p*q
e = 3
c = pow(m,e,n)
'''
c = 150409620528288093947185249913242033500530715593845912018225648212915478065982806112747164334970339684262757
e = 3
n = 20279309983698966932589436610174513524888616098014944133902125993694471293062261713076591251054086174169670848598415548609375570643330808663804049384020949389856831520202461767497906977295453545771698220639545101966866003886108320987081153619862170206953817850993602202650467676163476075276351519648193219850062278314841385459627485588891326899019745457679891867632849975694274064320723175687748633644074614068978098629566677125696150343248924059801632081514235975357906763251498042129457546586971828204136347260818828746304688911632041538714834683709493303900837361850396599138626509382069186433843547745480160634787
'''

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import gmpy2
from Crypto.Util.number import *


def de(c, e, n):
k = 0
while True:
m = c + n * k
result, flag = gmpy2.iroot(m, e)
if True == flag:
return result
k += 1


e = 3
n = 20279309983698966932589436610174513524888616098014944133902125993694471293062261713076591251054086174169670848598415548609375570643330808663804049384020949389856831520202461767497906977295453545771698220639545101966866003886108320987081153619862170206953817850993602202650467676163476075276351519648193219850062278314841385459627485588891326899019745457679891867632849975694274064320723175687748633644074614068978098629566677125696150343248924059801632081514235975357906763251498042129457546586971828204136347260818828746304688911632041538714834683709493303900837361850396599138626509382069186433843547745480160634787
c = 150409620528288093947185249913242033500530715593845912018225648212915478065982806112747164334970339684262757
m = de(c, e, n)
print(m)
print(long_to_bytes(m))


MOECTF 2024
http://example.com/2024/10/29/MOE CTF/
Author
chaye
Posted on
October 29, 2024
Licensed under