kcsc-club / ctfs

repository for kscs-ctfs
8 stars 1 forks source link

One Try - CRYPTO - PragyanCTF2022 #15

Closed BaciHanma closed 2 years ago

BaciHanma commented 2 years ago

One Try

from Crypto.Util.number import long_to_bytes,bytes_to_long
from flag import *
assert k.bit_length() == 40
def hide():
 p=95237125230167487838272944166423714051165223593288401382688685829040590786990768778438234082000903807362777558583037575230881045249425322887376601259055892460702772000162982010970208724929645212521533513649369206757681770172577467721506667626730799406015091008310940052579697065207083389866466950134622798087
 q=124379800279519757231453952571634329234726580565504345524807447690769923505626825913853213968267033307369831541137813374478821479720151365039955869403139958659415082657593784893960018420207872886098820339882222586464425407525431977262528398209506069668083100281117639890041468740215875574081639292225496987247
 return pow(bytes_to_long(flag.encode()),k,p*q)

def pad(a):
    if len(a) % 32 != 0:
        a = ((32-len(a) % 32)*chr(0).encode()) + a
    return a

def encrypt(a, key=k):
    ct = [i for i in (pad(long_to_bytes(a)))]
    keys=long_to_bytes(key)
    for x in range(5):
        for i in range(32):
            ct[i]=ct[i]^keys[0]
            for j in range(len(keys)):
                ct[i] = (ct[i] ^ keys[j] if i & 2**j != 0 else ct[i])
        keys = keys[1:]
    return ct

cipher.txt

#print(hide())
hide=9803360482107840935986732378323704110929708112302712803731012575465683179961905078466611828488789490543493731143558620545390953556032902554822421856356533539501430684361482576102587663520949056746659748698357755897924885992782747151219465028805502494393787119343428804346092071091528754744212809617351149272272380807238804504647510591726329582179077324427249076164587445605982981728078911123292553075494650141966258672901488344682939222675606336207847496023541310374013054536034137315183694024407951884904209160042408478973616348037614424915600220818790089801126821003600059671390406058169258661700548713247796139155
#print(encrypt(69837538996696154134353592503427759134303178119205313290251367614441787869767))
ct =[153, 102, 39, 242, 39, 149, 117, 232, 221, 111, 183, 6, 70, 46, 4, 222, 85, 178, 233, 81, 4, 186, 240, 74, 238, 81, 27, 83, 14, 154, 143, 1]

Nhìn vào code đề cho ta có thể thấy độ dài của key là 40bit = 5 bytes

assert k.bit_length() == 40

Tiếp theo ở hàm encrypt() lần lượt các phần tử ct xor với key. Giờ ta mô phỏng lại từng bước encrypt của đề bài và truy vết chi tiết từng bước.(Phần này mình vẫn chưa refactor lại, bạn có thể tìm cách rút gọn nó lại nhé <3)

def timXor():
    key=[i for i in range(9)]
    keyTest = []
    for x in range(5):
        for i in range(32):
            keyTest.append([])
            keyTest[i].append(key[0])
            for j in range(5):
                if i & 2**j != 0:
                    keyTest[i].append(key[j])
        key = key[1:]
#vì key length = 5 bytes nên ta chỉ lấy các các byte từ (0..4) và bỏ qua các key trùng đã Xor nhau
    for i in range(32):
        t= []
        for j in range(5):
            if keyTest[i].count(j) % 2 != 0:
                t.append(j)
        print(i, t)
timXor()

Kết quả là: image Vậy từ đây chúng ta đã có thể tìm ra từng byte của key. Rồi lấy key lụm lúa thoai.


from Crypto.Util.number import *
def pad(a):
    if len(a) % 32 != 0:
        a = ((32-len(a) % 32)*chr(0).encode()) + a
    return a
def decrypt(a):
    ctOld = [i for i in pad(long_to_bytes(a))]
    keys = []
    for i,j in zip(ctOld,ct):
        keys.append(i^j)
    return keys
key = [decrypt(a)[2],decrypt(a)[7],decrypt(a)[13],decrypt(a)[25],decrypt(a)[17]]
e = bytes_to_long(bytes(key))
d = inverse(e,(p-1)*(q-1))
print(long_to_bytes(pow(hide,d,p*q)).decode())

Flag: p_ctf{0ne_T1m3_Pads_are_1ns3cur5}