2025OpenHarmonyCTF-Crypto-WP

第一届鸿蒙CTF,密码部分都挺简单的

Ea5y_RSA

题目描述

1
这是一个未完全开发的OpenHarmony应用,在hint.txt中泄露了部分日志记录。请根据给定的源码和日志记录得到flag

题目附件

Ea5y_RSA.zip

思路

Ea5y_rsa.ets里面有密文:

1
nlRTOIr7P61VxeNDiPtFd65VCBJWhKlpSMF+g7Fib3VYHZYc/kgNWeFHSMvcgsqWuBCfMkB90SPQDR6hKvaxhYrqLAg/8+rRWqZbL7hXD3s2JA92V8zgx18r9zmekS28UiTUTUZDkkAhhkrWFvdx3gqgxGwj/l+DX82StHiyyOo=

hint.txt里面的gift有部分私钥:

1
00300d06092a864886f70d0101010500048202623082025e02010002818100a2f1fcc64fe2cb96aad3af057fdc9ad7fabe7d032b0fd6ef7a94af14d0adf155a85cb56edca219cd9f6077b41321093422890466a6c38ecc01f78c8db85c0ea27bd0a066709ac282688b8d0a3694a0a464f5d0292767a087636c0fe7dbfff92372836c4690b676fdde73b5479b46878d2449ddcd921f0837b52e6f7fd065b9dd02030100010281802b0d8d2048d33fbf9b7b3aef550d50cc6830148fd5bce5a978d5f83ca3b691e1740eaad193f230a727c931579f06478c42e3b909f65e0d48d1ec3a72e7974b362f59f5d3f871a2bd65bd44a8a503dd17b0b74e38b396c63f7e83dfa5ef203b9ebbcddfd3e4376b1388f1a9ce83225fe1

只能提取出1024bit的n和d的高896bit:

1
2
3
e = 65537
n = 0x00a2f1fcc64fe2cb96aad3af057fdc9ad7fabe7d032b0fd6ef7a94af14d0adf155a85cb56edca219cd9f6077b41321093422890466a6c38ecc01f78c8db85c0ea27bd0a066709ac282688b8d0a3694a0a464f5d0292767a087636c0fe7dbfff92372836c4690b676fdde73b5479b46878d2449ddcd921f0837b52e6f7fd065b9dd
dh = 0x2b0d8d2048d33fbf9b7b3aef550d50cc6830148fd5bce5a978d5f83ca3b691e1740eaad193f230a727c931579f06478c42e3b909f65e0d48d1ec3a72e7974b362f59f5d3f871a2bd65bd44a8a503dd17b0b74e38b396c63f7e83dfa5ef203b9ebbcddfd3e4376b1388f1a9ce83225fe1

exp

d高位泄露攻击:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# exp.sage
from Crypto.Util.number import *
from base64 import b64decode
c = 'nlRTOIr7P61VxeNDiPtFd65VCBJWhKlpSMF+g7Fib3VYHZYc/kgNWeFHSMvcgsqWuBCfMkB90SPQDR6hKvaxhYrqLAg/8+rRWqZbL7hXD3s2JA92V8zgx18r9zmekS28UiTUTUZDkkAhhkrWFvdx3gqgxGwj/l+DX82StHiyyOo='
e = 65537
n = 0x00a2f1fcc64fe2cb96aad3af057fdc9ad7fabe7d032b0fd6ef7a94af14d0adf155a85cb56edca219cd9f6077b41321093422890466a6c38ecc01f78c8db85c0ea27bd0a066709ac282688b8d0a3694a0a464f5d0292767a087636c0fe7dbfff92372836c4690b676fdde73b5479b46878d2449ddcd921f0837b52e6f7fd065b9dd
dh = 0x2b0d8d2048d33fbf9b7b3aef550d50cc6830148fd5bce5a978d5f83ca3b691e1740eaad193f230a727c931579f06478c42e3b909f65e0d48d1ec3a72e7974b362f59f5d3f871a2bd65bd44a8a503dd17b0b74e38b396c63f7e83dfa5ef203b9ebbcddfd3e4376b1388f1a9ce83225fe1
leakbit = 112 * 8
print(leakbit)

k = e * (dh << (1024 - leakbit)) // n + 1
PR.<x> = PolynomialRing(RealField(2048))
f = e * (dh << ((1024 - leakbit))) * x - x - k * (x - 1) * (n- x)
r = f.roots()
ph = int(r[0][0])
PR.<x> = PolynomialRing(Zmod(n))
f = ph + x
pl = int(f.small_roots(X=2**200, beta=0.49, epsilon=0.02)[0])
p = ph + pl
q = n // p
c = bytes_to_long(b64decode(c))
d = pow(e, -1, (p - 1) * (q - 1))
m = pow(c, d, p * q)
print(long_to_bytes(m))
flag{01D_W1Ne_in_4_n3W_80t7lE_HAh4hAH4h4}

Small Message For (SM4) Encryption

题目描述

1
2
3
SM4 is a block cipher, standardised for commercial cryptography in China. It is used in the Chinese National Standard for Wireless LAN WAPI (WLAN Authentication and Privacy Infrastructure), and with Transport Layer Security.

It seems to be very secure... But what if someone implement it insecurely?

题目附件

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
from gmssl import sm4, func
from os import urandom
from flag import FLAG, secret_message

def xor(a, b):
return bytes(x ^ y for x, y in zip(a, b))

def encrypt(key, plaintext, iv):
cipher = sm4.CryptSM4(sm4.SM4_ENCRYPT, 0)
cipher.set_key(key, sm4.SM4_ENCRYPT)
ciphertext = cipher.crypt_cbc(iv,plaintext)
return ciphertext


def main():
key = secret_message
while len(key) < 16:
key += secret_message
key = key[:16]
iv = urandom(16)

plaintext = b"My FLAG? If you want it, I'll let you have it... search for it! I left all of it at that place: " + FLAG
assert len(plaintext) % 16 == 0, "The message must be a multiple of 16 bytes."
ciphertext = encrypt(key, plaintext, iv)
print(f"Ciphertext: {ciphertext.hex()}")
print(f"What is this: {xor(key, iv).hex()}")

if __name__ == "__main__":
main()

exp

让ai写一个爆破secret_message的脚本

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
from gmssl import sm4, func
import itertools
import string

# 已知数据
ciphertext_hex = "d9ea43b0d208aa168e4a275a69df3bc86051e756f9ca7959b68c6b23c9e1b69c19e08b75938375a6be830d1844d8a6e368faf1ddffecea69b5abe00ac0d6e10d6696be33d40e83a272072fbe131f98c82587011f61f2d58a020c8c54cf9b651abd740a3d55d36daa9c88cfc10a520ce4211fba4365ce98b82355b17c64dd2de4800fc68df36cfa8a3fd05baac6970dcd"
xor_key_iv_hex = "ee278c4e526ff15b8d308b6b18f83221"

# 转换为字节
ciphertext = bytes.fromhex(ciphertext_hex)
xor_key_iv = bytes.fromhex(xor_key_iv_hex)

# 可能的字符集 (可打印ASCII)
charset = string.printable.strip()

def decrypt(key, ciphertext, iv):
cipher = sm4.CryptSM4(sm4.SM4_DECRYPT, 0)
cipher.set_key(key, sm4.SM4_DECRYPT)
plaintext = cipher.crypt_cbc(iv, ciphertext)
return plaintext

def brute_force_secret_message():
# 尝试1-16字节长度的secret_message
for length in range(1, 17):
print(f"Trying length: {length}")
# 生成所有可能的组合
for candidate in itertools.product(charset, repeat=length):
secret = ''.join(candidate)
# 扩展key到16字节
key = (secret * (16 // len(secret) + 1))[:16].encode()
# 计算iv
iv = bytes(x ^ y for x, y in zip(key, xor_key_iv))

try:
plaintext = decrypt(key, ciphertext, iv)
# 检查解密结果是否符合预期格式
if b"My FLAG? If you want it" in plaintext:
print(f"Found secret_message: {secret}")
print(f"Decrypted plaintext: {plaintext}")
# 提取FLAG
flag_start = plaintext.find(b"flag{")
if flag_start != -1:
flag_end = plaintext.find(b"}", flag_start) + 1
flag = plaintext[flag_start:flag_end].decode()
print(f"FLAG found: {flag}")
return secret, flag
except:
continue

return None, None

if __name__ == "__main__":
secret_message, flag = brute_force_secret_message()
if secret_message:
print(f"Success! secret_message: '{secret_message}', FLAG: '{flag}'")
else:
print("Failed to find the secret_message and FLAG.")
flag{tHe_m3s5ag3_1s_2_sMa11!11!}

Weak_random

题目描述

1
一道弱伪随机数生成器题目,密钥的生成过程存在严重漏洞。

题目附件

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
from secret import flag
import time
import os
import random
from Crypto.Util.number import *
from Crypto.Cipher import AES
import os
import hashlib

assert(len(flag)==32)

def padding(message):
padding_len = 16 - len(message)%16
ret = hex(padding_len)[2:].zfill(2)
return bytes.fromhex(ret*padding_len)+message

def get_weak_entropy():
time_now=time.time()%10000

entropy_part1 = int(time_now) & 0xFFFF

entropy_part2 = os.getpid() & 0xFF

final_seed = entropy_part1 + (entropy_part2 << 8)
random.seed(final_seed)

key = random.getrandbits(128)

return key
entropy_key=get_weak_entropy()
iv = os.urandom(16)
key_bytes = entropy_key.to_bytes(16, byteorder='big')
msg=padding(flag.encode())
aes = AES.new(key_bytes,AES.MODE_CBC,iv=iv)
enc = aes.encrypt(msg)
print(enc.hex())
check=hashlib.sha256(flag.encode('utf-8')).hexdigest()
print(check)
#enc=e88b2eb25b22929b2eb84898bc2c620c8798637ab64b892c218c83a0e523580f6c5772c84461f09045b6bce48c102a5f
#check=83d92dc441e420587b2eb46f46ca424597af97a88f0da1b64243e287c69aa645

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import os
import random
from Crypto.Util.number import *
from Crypto.Cipher import AES
import hashlib
from tqdm import trange

enc = bytes.fromhex("e88b2eb25b22929b2eb84898bc2c620c8798637ab64b892c218c83a0e523580f6c5772c84461f09045b6bce48c102a5f")
check = "83d92dc441e420587b2eb46f46ca424597af97a88f0da1b64243e287c69aa645"

iv = os.urandom(16)
for seed in trange(0, 256*256 + 10000):
random.seed(seed)
key = random.getrandbits(128).to_bytes(16, byteorder='big')
aes = AES.new(key,AES.MODE_CBC,iv=iv)
msg = aes.decrypt(enc)[16:]
if hashlib.sha256(msg).hexdigest() == check:
print(b"flag{" + msg + b"}")
break

flag{9848ca46c1c1cc9db4246566b275d3c8}

Simple LLL

题目描述

1
simple lattice but openharmony

题目附件

Simple_LLL.zip

思路

解压后发现是个鸿蒙逆向,拿https://github.com/ohos-decompiler/abc-decompiler/releases工具反编译。

核心加密如下:

即我们可以得到50组如下形式的\(c_i\)\[ c_i = r_i*q + (g^{m_i}s_i \mod p) \] 其中\(r_i\)\(q\)相对\(p\)较小,所以直接用正交格加离散对数就解掉了

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
from Crypto.Util.number import *
from random import getrandbits

a = [45596599146517595769213567008027354990530152281109573038863246709378806226257335310766479851680188494182323525530530505256, 62432374431437591826734273911812391207656242897401885268127107607214388994256327721530322212234111642476641341569615655775, 66640867270680683651105915351782232550272910743762721024149499622223272317021218813086665442488154134536635091168151679262, 76568791607439426429890581080326982594324744169701114653618996191036247280167861065425161127891911640115719874949519513409, 80505764860782440798434567134832555598469365799962186558947545820389077349592175372099995788813126347559362498096484561087, 49886762049415620162731028873582943421775694364410242029122769830561241631714493053920164993309711714828904752810911376673, 63764608791300251401000140557122880801227171628942028982810331285921668215965127876492165610922306217924951340692885034445, 75150749592297738434833716596208117968146378967070896331493267301751508105379281839545556616649489492862396168011336629860, 64640885967491510460161437267821813741190981731057014520820089056784197782061031601387968993783090906716081424349788858131, 64437291571761719605154322068355171624572928894219031137168295198426051411772641573978100287013420825453909253049882111608, 66504977482535802726769039193408744223638783830651957559642117606942253995141503865661025618554702478031262816698525032136, 76002568717709562873915527551148914168997623756300359592451412016772230012774064201866937923034345062382027041394993181454, 63266985974944409749869963721110410312519236858231888474633226073550935799575298125269866699330196788217453515960042308014, 41378678610694150590920910285112607982977816143559599698344863434208418190795670372530100158282880873585095139346542182207, 47095714976926850579359360089815975293364468242683704814212607488560707212600108415692525003584392669639960496824687225871, 81712279014270911594566324410970967065420131442219991825217142864252526122573901396406765443368883802863522142841038531059, 46899315688285826493888208674882803737623349293461166939548270777452716728288162058211757343071983713080383903753175566525, 77001953210338837057924001273567386417735976768153786434377740557131463743054441573962638411859255662145059533392768151159, 61344092790836117616593559739714992543552126735084182427898958666452402020794852886254745796680655750124380725951855048010, 41798537018707926245084694076262041173943033079080146970126525132704066495699601424087894987780276017360809502522616125394, 63387993920920122367999624086483629563252946113412688583890185139461926238435833641040933872789534901371558025032872075509, 73308599701131409464380487348189364538310423897958233779818170276256490392349086950293706361381652255418906670559849023338, 79656592431138093729170996132259461695478861668300598583789836126987243595249158493470453092373692862598725554307228872775, 66686609349363352414174552287289340779849453906905378709020779878225151601984410724395496186873990929643813847426883168892, 73629238580972114305567044343530088917932511220527756471428594467552523423255130084899098302915123830683981111535738601638, 49498906417357835892520675114611644052169603417532472178901453472582291336119172842035513537774428033797593014512677351435, 52174217475092237597936231689235487926615205995485347429534522208443240578238018451973609326577546098568499813741462015539, 80047762077509250355763047192733755477123946490832613760007651778991838965572319380438868001156427212461586278039816493826, 65093211867471012814356995410138867637862719476444799545940055034242517927221160325208221269710241764401111566664350993658, 46011244750481202278149073625755585684260386245667515244622055779661135900620865355790231322990781098608449420272236827649, 53117509020129498861968904973153083766481628602843082575566170552766982459112237988922328578653333150309738552227954392141, 55459188663102328389961593038479425938901985433225942468392445820718629229313178400426180281496533959937344423076984430674, 78444745613219318304755274100121829802982955598779086342705126567561388206659867698016883565928585796097381260797922655519, 43958732315072668909629997482365926883011682959499021501879834969759552915014043651906394862009078183350949233959094932805, 61305435387549084308484680178646146929431427882044457046211844779552509450815730509488874603808230047212187842781103455153, 70637259106230458373333494078168198926256656499333956870221228138617427598610924695021659385808327535049122557717095889661, 65488728024961307175054135997812474419797386013099712092129340958152238442655356597216364171923967429155549425314004976747, 41625960760631805176266652837586144901306841022437321127731795763904181671613462308134640764955282404049919880515527122098, 71963979924766202542689152185192891354279089665062029590009513136963032846334363384099417013523272240110934926309168051428, 80251778335603398358629896861168846340221689717009306678229176648582836983027616322956600208242209788987847059377353910549, 70284032408930923412572260535342969184801973281722349552207656726600064883190098349426312634152674923127303108515857786319, 42017603985852991154545640679246147284482910315115721206206452863103006355613789016611463239370863506027749335463578575305, 69877399809833254387653649392946328765278216825706254792870473350054372563698919553742183921227432721214640597147524631246, 53857121890842582862177371083826128456199075709482866213895717527182513045934317770490721788186406883690528462156380898247, 64001232528214466569851169431725495993460092493119013330479471106567913343082607991839399906226146294179112946412714353633, 68794934824127239944040431762674854475686621190929074032646726399953434603694936833899174892998387998834509107900100986371, 68966508075486889501108784849699866656588246221931458138799356947047368779859934967665457687684069221994712578788436679754, 76000714031230558195498090452755463892015002095887478759556871466937829860283192442760605574465753606694091015079927493429, 65889577129438227733404759215735188782970893752143620491220200742094265192946367814381845991305876972823427075367837470223, 78057186896723223998512735748769800421682091882992425661700127016657965666059373278973633235161094736796529787276595121298]
M = column_matrix(a)
M *= getPrime(1024)
M = M.augment(identity_matrix(M.nrows()))
ML = M.LLL()

K = []
for i in range(48):
assert ML[i][0] == 0
K.append(ML[i][1:])
K = matrix(K)
KK = K.right_kernel_matrix().LLL()
m_ = KK[0]
if m_[0] < 0:
m_ *= -1

s = "Lattice-based cryptography is the generic term for constructions of cryptographic primitives that involve "[:50]
P = 910927656194791222517913045809166069831899969390111
G = 181486661693304272005374759243600368243
flag = ""
for i in range(49, -1, -1):
gm = m_[i] * pow(ord(s[i]), -1, P)
m = discrete_log_lambda(Mod(gm, P), Mod(G, P), bounds=(2**16, 2**24))
flag = long_to_bytes(m).decode() + flag
print(flag)
# b8fdba363c31f3a4cadaf5289e0bf4fb578f2a5e28dcdb8fdba363c31f3a4cadaf5289e0bf4fb578f2a5e28dcdb8fdba363c31f3a4cadaf5289e0bf4fb578f2a5e28dcdb8fdba363c31f3a

最后解出来这一串不是flag,flag是子串b8fdba363c31f3a4cadaf5289e0bf4fb578f2a5e28dcd。。。