Ciallo_Encrypt

有意思的题

首先需要根据网站的信息找到项目的github地址

根据网站下方名字可以找到Yu2ul0ver/Ciallo_Encrypt0r: This is a custom-developed encryption tool based on the Ciallo framework.

能找到客户端的源码,同时在commit中,发现了对源码的更改

image-20251026210433569

可以得知账号和密码的来源

在closed的issues中可以找到作者的qq号,

image-20251026205926381

可以尝试使用qq邮箱3517508570@qq.com,密码为md5(Ciallo_Encrypt0r)=f42e16b836b22e83fd3818b603c75dc6,可以成功登录管理端

在管理端的日志中发现之前被加密过的密文,猜测为flag,根据仓库中的app.py所以需要找到加密算法的代码

根据网站中的一段base64可得5qC45b+D5Luj56CB5oiR5bey5bCG5YW25pS+6L+b5LqGZm9ya+eahOengeS6uuS7k+W6k+mHjA== --> 核心代码我已将其放进了fork的私人仓库里

猜测加密算法在私仓里,但是正常情况下我们肯定访问不到私仓,通过下边文章,我们可以以某种手段得到

任何人都可以访问 GitHub 上已删除和私有存储库数据 ◆ Truffle Security Co. — Anyone can Access Deleted and Private Repository Data on GitHub ◆ Truffle Security Co.

使用trufflehog扫描commit,

image-20251026212646559

随机访问某一个commit

image-20251026212721566

得到加密算法,丢给ai,给出解密算法

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
# Retry reverse ciallo_encrypt and decryption.
# This version avoids Crypto by implementing AES via Crypto if available, else tries from Cryptodome.

import hashlib, base64, datetime, zoneinfo, re, sys

# try importing AES
AES = None
try:
from Crypto.Cipher import AES as _AES
from Crypto.Util.Padding import unpad as _unpad
AES = _AES
unpad = _unpad
except Exception as e:
try:
from Cryptodome.Cipher import AES as _AES
from Cryptodome.Util.Padding import unpad as _unpad
AES = _AES
unpad = _unpad
except Exception as e2:
AES = None

ciphertext = """Ciall0~(∠・ω<)⌒★ Ci@110~(2・ω<)⌒★ Cia110一(∠・ω<)⌒★ Cial10一(2・ω<)⌒★ Ciallo一(∠・ω<)⌒★ Cial1o~(∠°ω<)⌒★ Cia1lo一(∠°ω<)⌒★ Cia1l0一(2・ω<)⌒★ Ciallo一(∠°ω<)⌒★ Ciallo~(∠・w<)⌒★ Cia1lo一(∠・w<)⌒★ Cia1lo~(2・ω<)⌒★ Cia1lo一(2・ω<)⌒★ Cia1l0一(∠°ω<)⌒★ Ciall0一(2・ω<)⌒★ Cia1lo~(∠・ω<)⌒★ Ciallo~(∠・ω<)⌒★ Cial1o~(∠・ω<)⌒★ Cia11o~(2・ω<)⌒★ Ci@110~(∠°ω<)⌒★ Cia1lo~(∠・ω<)⌒★ Ciall0~(∠・w<)⌒★ Cia110一(2・ω<)⌒★ Ciallo一(∠・w<)⌒★ Ciallo~(∠・w<)⌒★ Ciall0~(∠・ω<)⌒★ Cia1lo~(2・ω<)⌒★ Cial10~(∠°ω<)⌒★ Ci@110~(∠°ω<)⌒★ Ciall0一(∠・w<)⌒★ Cia1l0一(∠°ω<)⌒★ Ci@11o~(∠・ω<)⌒★ Ci@11o~(∠°ω<)⌒★ Cia1l0~(2・ω<)⌒★ Cial1o~(∠°ω<)⌒★ Cial10~(∠°ω<)⌒★ Ci@110~(∠°ω<)⌒★ Cia110~(∠°ω<)⌒★ Ci@11o~(∠・ω<)⌒★ Cial1o~(2・ω<)⌒★ Cial10一(∠°ω<)⌒★ Cial10~(2・ω<)⌒★ Cia110一(∠・ω<)⌒★ Ciallo一(∠・ω<)⌒★ Cial10~(∠・ω<)⌒★ Ciallo一(∠・w<)⌒★ Ciall0一(∠・w<)⌒★ Cia1l0~(∠・ω<)⌒★ Ciall0一(2・ω<)⌒★ Cia110~(∠・ω<)⌒★ Cia1l0一(∠・ω<)⌒★ Ci@110~(2・ω<)⌒★ Ci@11o~(∠°ω<)⌒★ Ciallo一(2・ω<)⌒★ Ci@110一(2・ω<)⌒★ Cial1o~(2・ω<)⌒★ Ciallo一(∠・ω<)⌒★ Cial10~(∠・w<)⌒★ Cia1l0一(∠°ω<)⌒★ Cia1lo~(2・ω<)⌒★ Ci@110~(∠°ω<)⌒★ Ciallo一(∠°ω<)⌒★ Cia1l0~(∠・w<)⌒★ Cia110一(∠・w<)⌒★"""
tokens = [t.strip() for t in ciphertext.split() if t.strip()]

def char_at(s, idx):
return s[idx] if idx < len(s) else ''

def token_to_bits(tok):
tok_clean = tok.replace('⌒★','')
b = ['0']*8
b[0] = '1' if char_at(tok_clean,1) == '1' else '0'
b[1] = '0' if char_at(tok_clean,2) == '@' else '1'
b[2] = '1' if char_at(tok_clean,3) == '1' else '0'
b[3] = '1' if char_at(tok_clean,4) == '1' else '0'
b[4] = '0' if char_at(tok_clean,5) == '0' else '1'
b[5] = '1' if char_at(tok_clean,6) == '一' else '0'
if char_at(tok_clean,9) == '°':
b[6:8] = list('00')
elif char_at(tok_clean,8) == '2':
b[6:8] = list('10')
elif char_at(tok_clean,10) == 'w':
b[6:8] = list('11')
else:
b[6:8] = list('01')
return ''.join(b)

bits_list = [token_to_bits(t) for t in tokens]
full_bitstr = ''.join(bits_list)
bytes_list = [full_bitstr[i:i+8] for i in range(0, len(full_bitstr), 8)]
if len(bytes_list[-1]) != 8:
bytes_list = bytes_list[:-1]
bts = bytes(int(x,2) for x in bytes_list)
try:
text = bts.decode('utf-8')
except:
text = bts.decode('latin1')

print("Reconstructed base64 text (len={}):\n{}".format(len(text), text))

# base64-decode
try:
cipher_bytes = base64.b64decode(text)
print("Decoded cipher bytes length:", len(cipher_bytes))
except Exception as e:
print("Base64 decode error:", e)
cipher_bytes = None

# compute ts_str from provided datetime in Asia/Shanghai
tz = zoneinfo.ZoneInfo("Asia/Shanghai")
dt = datetime.datetime(2025,10,12,6,4,36, tzinfo=tz)
ts_int = int(dt.timestamp())
ts_str = str(ts_int)
print("Assumed ts_str:", ts_str)

if cipher_bytes and AES is not None:
key = hashlib.md5(ts_str.encode()).digest()
cipher = AES.new(key, AES.MODE_ECB)
try:
pt_padded = cipher.decrypt(cipher_bytes)
pt = unpad(pt_padded, AES.block_size).decode('utf-8', errors='replace')
print("\nDecrypted plaintext:\n", pt)
except Exception as e:
print("AES decrypt/unpad error:", e)
elif cipher_bytes:
print("AES library not available in environment.")

image-20251026213319201