ACECTF 2025

reverse

Significance of Reversing

通过winhex观察二进制数据,发现elf文件倒过来了,reverse一下(

然后就是解密

1
2
3
4
5
6
7
8
9
10
11
# with open(r"C:\Users\86158\Downloads\Reverseme.png", "rb") as p:
# c = p.read()[::-1]
# with open(r"C:\Users\86158\Downloads\Reverseme__.png", "wb") as f:
# f.write(c)
cipher = r"prtr%uLHb0fc=<0c3_Ff0CbGbCdbN"
# print("".join([chr(((ord(x) - 33) - 14) % 94) for x in cipher]))
for x in cipher:
tmp = ((ord(x) - 33) - 14) % 94
if tmp < 32:
tmp+=94
print(chr(tmp),end='')

The Chemistry Of Code

简单的rust源码逆向。。

1
2
3
4
5
6
7
username = "AdminFeroxide"
passwd = "d3ru571fy1n6"
flag = "4143454354467B34707072336E373163335F3634322C28010D3461302C392E"

tmp = hex(int(flag, 16) ^ (int(passwd.encode('utf-8').hex(), 16) ^ int(username.encode('utf-8').hex(), 16)))[2:]

print(''.join([chr(int(tmp[i:i+2], 16)) for i in range(0, len(tmp), 2)]))

trust item

自定义了一个函数叫strcmp,点进去是注意逻辑。。

1
2
3
4
5
6
7
8
9
10
11
12
cipher = [
6, 17, 29, 114, 96, 31, 24, 124, 62, 15,
109, 120, 51, 53, 64, 94, 62, 37, 95, 48,
120, 20, 55, 74
]
print(len(cipher))
key = "GRX14YcKLzXOlW5iaSlBIrN7"
print(len(key))

for i in range(len(cipher)):
print(chr(ord(key[i]) ^ cipher[i]),end="")

Piped Up

根据输入的数字进行对应的加密操作

对于这几个情况,有writefile和readfile肯定是中间的步骤,只有writefile的是第一个,只有readfile的是最后一个步骤,所以4是第一个,2是最后一个,1,3,5三个加密以某种顺序进行若干次。。

1是流异或,3是与0x56异或,5是与v6进行循环异或,并且flag长度应该为39个字符。

首先是找到加密顺序,我这里使用爆破脚本 ,总共加密次数要手动改:

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
tab1 = [0x7B, 0x2E, 0xF1, 0xEB, 0x8B, 0x76, 0xE7, 0x68, 0x77, 0xA3, 0xEF, 0x52, 0xF6, 0x3C, 0xDA, 0xAA, 0xF6, 0xA7,
0x43, 0xEB, 0x21, 0x24, 0xC3, 0x9C, 0x7D, 0x08, 0x33, 0xB7, 0xF7, 0x2C, 0xB4]

cipher = [0x6C, 0x2C, 0xE0, 0xEF, 0x8D, 0x60, 0xDC, 0x75, 0x0D, 0xFF, 0xD6, 0x59, 0xF4, 0x5D, 0xDE, 0x9B, 0xE3, 0xD7,
0x52, 0x99, 0x5A, 0x7C, 0xA3, 0xC9, 0x4E, 0x1B, 0x45, 0xE5, 0xC0, 0x29, 0x9A]

def dec_1(array):
_ = []
c = 0
for i in range(len(array)):
c = array[i] ^ c
_.append(c)
return _

def dec_2(array):
_ = []
for i in range(len(array)):
c = array[i] ^ 0x56
_.append(c)
return _

def dec_3(array):
_ = []
for i in range(len(array)):
c = array[i] ^ tab1[i]
_.append(c)
return _

func = [dec_1, dec_2, dec_3]

message = "ACECTF{"

message_bytes = [ord(c) for c in message]

def brute_force():
from itertools import permutations

for order in permutations(range(3), 3):
current = message_bytes.copy()
for func_index in order:
current = func[func_index](current)

if current[:len(message_bytes)] == cipher[:len(message_bytes)]:
print(f"Found matching order: {order}")
print(f"Decrypted message: {bytes(current)}")
return

print("No matching order found.")

brute_force()

找到顺序:

然后就是解密:

1
2
3
4
5
6
7
8
tmp1 = [tab1[i] ^ cipher[i] for i in range(len(tab1))]

tmp2 = []
for x in range(len(tmp1)-1, 0, -1):
tmp2.append(tmp1[x] ^ tmp1[x-1])
tmp2.append(tmp1[0])
tmp2 = tmp2[::-1]
print("".join([chr((tmp2[g]) ^ 0x56) for g in range(len(tmp2))]))

DONOTOPEN

一个bash脚本,gzip解压一个py文件,也挺ez的,首先找到gz文件头,1F 8B,然后将之前的字节全删掉,重命名为gz,winrar解压,得到py文件,打开是一个哈希值计算。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import hashlib

import requests

FLAG_PREFIX = "ACE{%s}"
#
# print("It looks like the box is locked with some kind of password, determine the pin to open the box!")
# req = requests.get("http://google.com")
# req.raise_for_status()
#
# pin = input("What is the pin code?")
# if pin == "ACE@SE7EN":
# print("Looks good to me...")
# print("I guess I'll generate a flag")
#
# req = requests.get("http://example.com")
# req.raise_for_status()
#
# print(FLAG_PREFIX % hashlib.blake2b((pin + "Vansh").encode("utf-8")).hexdigest()[:32])
# else:
# print("Bad pin!")
pin = "ACE@SE7EN"
print(FLAG_PREFIX % hashlib.blake2b((pin + "Vansh").encode("utf-8")).hexdigest()[:32])

这道题我一开始拿到的附件有问题,gz部分有大量的 EF BF BD这三个字节,题目描述说是又混淆,还以为这是混淆,但又没有gz文件头,感觉有点懵了,后来重新下了个附件是正常的了。。