2022DASCTF X SU 三月春季挑戰賽-Crypto-FlowerCipher


2022DASCTF X SU 三月春季挑戰賽

Crypto

0x01 FlowerCipher

源碼

題目源碼
# python3

from secret import flag
import random

# flag = b'flag{%s}' % md5(something).hexdigest()
# note that md5 only have characters 'abcdef' and digits

def Flower(x, key):
    flower = random.randint(0, 4096)
    return x * (key ** 3 + flower)

flag = flag[5:-1]
rounds = len(flag)

L, R = 1, 0
for i in range(rounds):
    L, R = R + Flower(L, flag[i]), L

print(L, R)
'''
15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899 139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
'''

解析

縱觀整個文件,邏輯結構比較簡單,接下來就逐步分析代碼;

  1. # flag = b'flag{%s}' % md5(something).hexdigest()
    # note that md5 only have characters 'abcdef' and digits
    

    ​ 給了一段注釋,說 \(flag\) 的內容是由花括號內的部分轉為字解以后與某個字符串的 md5 值進行取模運算,后面的 hexdigest() 函數的作用,根據函數名大致可以猜出是把字符串轉為十六進制,具體作用查找資料以后證實與猜測符合。

    ​ 第二段的注釋說 something 的內容是'abcdef'和數字,簡而言之就是16進制,由於md5大部分是32位,這里又沒有給出具體的值,若在這一步進行了運算,是得不出 \(flag\) 的,所以這里的 \(flag\) 就是我們最終解出的字樣。

  2. def Flower(x, key):
        flower = random.randint(0, 4096)
        return x * (key ** 3 + flower)
    

    ​ 該函數的作用暫時還不清楚,就是一個簡單的運算,只不過中間有一個 \(0-4095\) 的隨機數,后續應該是爆破這個隨機數,量也不大,也沒有其他方法。

  3. flag = flag[5:-1]
    rounds = len(flag)
    
    L, R = 1, 0
    

    ​ 進行基本的賦值操作,第一步是取出 \(flag\) 字符串中花括號里的內容,第二步是計算 \(flag\) 的長度, \(L\)\(R\) 往下看就知道是循環計算的值。

  4. for i in range(rounds):
        L, R = R + Flower(L, flag[i]), L
    

    ​ 一個簡單的 for 循環,看到 \(flag[i]\) 可以知道遍歷了 \(flag\) 中的每一個字符進行運算,每一次運算將 \(L\)\(R\) 交換位置賦值,可能是為了改變二者的值,若不改變位置賦值,那么 \(R\) 就是無用的,另一方面是為了將每一次運算結果嵌入到下一次運算,使得每一次運算都是息息相關的。

  5. print(L, R)
    '''
    15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899 139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
    '''
    

    ​ 輸出 \(L\)\(R\) 的值,題目也給了對應的值。

  6. 至此為止,程序分析完了,就是簡單的循環計算,只需要逆推整個過程每一次計算的返回值我們就都一目了然,模仿數學歸納法那樣舉幾個例子更好理解。

    L R
    image image
    image image
    image image

decode

​ 為了解決整個題目我們有幾個需要解決的問題:

  1. 上面提到的隨機數,怎么去確定,暫時的解決辦法就是遍歷所有的值,因為這種計算式子哪怕幾萬個結果對於計算機來說也是一瞬間的,時間代價很低,可以嘗試。
  2. 每一次計算都會交換 \(L\)\(R\) 的值,要去分離所有的 \(L\)\(R\) ,分離了 \(L\)\(R\) 才能去嘗試分離出每一次的函數返回值。
  3. 函數返回值的表達式是一定要逆推拿到 \(L\) 的輸入值,因為本次函數的輸出值關乎到 \(L\) 的值是多少,上一次 \(L\) 的值關乎到上上次的計算...

​ 我們可以通過逆推去還原代碼的執行過程。發現imageimage什么意思呢,就是說同一次得出的 \(L\) 減去 \(R\) 就可以得到函數的返回值。

​ 但是問題又來了,盡管這樣我們只能推算一步而已,怎么拿到除了最后一步之外的值呢,這里有個小細節,就是每一次賦值語句后的 \(L_n\)\(R_n\) 的值,始終成立 \(L_n>R_n\) ,為什么呢,因為,imageimage,並且其中函數返回值一定大於1。知道這些有什么用呢,已知函數返回值是 \(L_n\) 的整數倍,且 \(L_n>R_n\) 恆成立,怎么得到image,此時此刻想到的是模運算,image,拿到了image之后就可以拿到image,以此類推,就拿到了所有的 \(L\)\(R\)

listL = []
listR = []
n = 0
while L > 1:
    listL.append(L)
    listR.append(R)
    L, R = R, L % R
    n += 1
listL.append(L)
listR.append(R)
listL = listL[::-1]#逆序
listR = listR[::-1]

​ 這里的 \(n\) 的作用是看他循環了多少次,因為我們知道循環到最初的時候 \(L=1\) ,這就是循環結束的條件,但是結束的時候 \(L=1\) 並沒有寫入列表中,所以需要額外在添加一次,但我們是逆序反推的,為了后面運算方便,將他們逆序過來。

L:

L的值
1
133317
137492755075
24316418691677517
2694478038943586736328
449366186013055209469307061
424678007756192434300006917804988
67952303343509961405922862120527631953
10722465754210488857842384539746544074196670
11050144307727113700681557772687121323224647867153
11731219952144596819377276074864534430521345582519171825
1501209023627137765492979001172871435243212151481455508796928
240324048977128823416619126180138745528644638124733113619292984561
241267801518963217329803327254141129383508497053892152707957403620167975
32759342090485149698017824597983901673872922475506121132811189377165700630061
5830376668137452804173383567980586211563348379884185911787096393298400138955904511
6028609474886885541605763758989943967354486126474121155263363791803356933057570965004061
973825402922208545745882895848854992390620148165434035074196392656950555217820068399921894085
163194634853135239779527687110852732238802459017066087158243026833107794785760861815584881897662446
19287157921091613716265688246942013055491723611322575658962386161345041119412098008892719335475158074595
19304497076225869711849746340455541612339463403087957113496859433662333338211557279788474751973335123601723351
19346619488865481717482094100686681292384530125288986759529832156605546935716879938892385301891033660176897469426477
18822751726365286700612339826340137082689797360168751039458371318582478795225200597245268849966216725478600774872948579145
17728566345779292838907909381612640668036643431117165902908905722221490552536570008262521006387722966311695266888986102760148482
16713517279670522179142602316669021266414545548551242366498025076135157482269671171234675566764239156725485371108735804221489129242235
3121683903445470016877317983137081025437455800044243487676152297523129079630621593231064333666220053742946978640516933836161839706107832842
3038050870004975946934828279229998090001629942971672705946371743686684953534372767609080560274203027849883925292484330032865963662762987021572213
363542281260527120641507826394376579427002124891256726811704925452455933892306777570036028677323021255266880206017499363363356743613369155668503557061
41491807647864532203061547188977816042392604608090542687445179257686072390683442091157724792609311622180322599523073162631870961894947012137520634996058265
7402968320895532116930768370098929764678065093602516751185225609968053961398195671796668035067389408306736179462173593882795916384659802649189800851665219198361
935298420671754230833014738849730432588169238033228173469583131476419084794695511761146278309606770027490667271610796624269392034586175088396235641537756093736185366
139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003
15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899

R:

R的值
0
1
133317
137492755075
24316418691677517
2694478038943586736328
449366186013055209469307061
424678007756192434300006917804988
67952303343509961405922862120527631953
10722465754210488857842384539746544074196670
11050144307727113700681557772687121323224647867153
11731219952144596819377276074864534430521345582519171825
1501209023627137765492979001172871435243212151481455508796928
240324048977128823416619126180138745528644638124733113619292984561
241267801518963217329803327254141129383508497053892152707957403620167975
32759342090485149698017824597983901673872922475506121132811189377165700630061
5830376668137452804173383567980586211563348379884185911787096393298400138955904511
6028609474886885541605763758989943967354486126474121155263363791803356933057570965004061
973825402922208545745882895848854992390620148165434035074196392656950555217820068399921894085
163194634853135239779527687110852732238802459017066087158243026833107794785760861815584881897662446
19287157921091613716265688246942013055491723611322575658962386161345041119412098008892719335475158074595
19304497076225869711849746340455541612339463403087957113496859433662333338211557279788474751973335123601723351
19346619488865481717482094100686681292384530125288986759529832156605546935716879938892385301891033660176897469426477
18822751726365286700612339826340137082689797360168751039458371318582478795225200597245268849966216725478600774872948579145
17728566345779292838907909381612640668036643431117165902908905722221490552536570008262521006387722966311695266888986102760148482
16713517279670522179142602316669021266414545548551242366498025076135157482269671171234675566764239156725485371108735804221489129242235
3121683903445470016877317983137081025437455800044243487676152297523129079630621593231064333666220053742946978640516933836161839706107832842
3038050870004975946934828279229998090001629942971672705946371743686684953534372767609080560274203027849883925292484330032865963662762987021572213
363542281260527120641507826394376579427002124891256726811704925452455933892306777570036028677323021255266880206017499363363356743613369155668503557061
41491807647864532203061547188977816042392604608090542687445179257686072390683442091157724792609311622180322599523073162631870961894947012137520634996058265
7402968320895532116930768370098929764678065093602516751185225609968053961398195671796668035067389408306736179462173593882795916384659802649189800851665219198361
935298420671754230833014738849730432588169238033228173469583131476419084794695511761146278309606770027490667271610796624269392034586175088396235641537756093736185366
139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003

​ 既然都獲取到了所有的 \(L\)\(R\) ,那我們就把所有的函數值返回值拿到。

for i in range (len(listL) - 1):
    num = int((listL[i+1] - listR[i]))
    flowers.append(num)

flowers:

flowers的值
133317
137492755074
24316418691544200
2694478038806093981253
449366185988738790777629544
424678007753497956261063331068660
67952303343060595219909806911058324892
10722465753785810850086192105446537156391682
11050144307659161397338047811281198461104120235200
11731219952133874353623065586006692045981599038444975155
1501209023616087621185251887472189877470525030158230860929775
240324048965397603464474529360761469453780103694211768036773812736
241267801517462008306176189488648150382335625618648940556475948111371047
32759342090244825649040695774567282547692783729977476494686456263546407645500
5830376667896185002654420350650782884309207250500677414733204240590442735335736536
6028609474854126199515278609291926142756502224800248232787857670670545743680405264374000
973825402916378169077745443044681608822639561953870686694312206745163458824521668260965989574
163194634847106630304640801569246968479812515049711601031768905677844430993957504882527310932658385
19287157920117788313343479701196130159642868618931955510796952126270844726755147453674899267075236180510
19304497076062675076996611100676013925228610670849154654479793346504090311378449485002713890157750241704060905
19346619488846194559561002486970415604137588112233495035918509580946584549555534897772973203882140940841422311351882
18822751726345982203536113956628287336349341818556411576055283361468981935791538263907057292686428250726627439749346855794
17728566345759946219419043899895158573935956749824781372783616735461960720379964461326804126448830581009804233228809205290722005
16713517279651699427416237029968408926588205411468552569137856325095699110951088692439450366166993887875519154383257203446616180663090
3121683903427741450531538690298173116055843159376206844245035131620220173908400102678527763657957532736559255674205238569272853603347684360
3038050869988262429655157757050855487684960921705258160397820501320186928458237610126810889102968352283119686135758844661757227858541497892329978
363542281257405436738062356377499261443865043865819271011660681964779781594783648490405407084091956921600660152274552384722839809777207315962395724219
41491807644826481333056571242042987763162606518088912744473506551739700646996757137623352025000231061906119571673189237339386631862081048474757647974486052
7402968320531989835670241249457421938283688514175514626293968883156349035945739737904361257497353379629413158206906713676778417021296445905576431695996715641300
935298420630262423185150206646668885399191421990835568861492588788973905537009439370462836218449045234881355649430474024746318871954304126501288629400235458740127101
139721425168891349281451572792544680133048837962069857150100615261867817820225178415462359077837226554096748311704122075309731667870724937930248453782400769574967523270642
15720197268010049967757675120469992186537658494704135479561283085920610969374470767952957875436059114121446299016141673102641832905150384839824642839374686669270876487929996533

​ 拿到之后在仔細分析以下函數的返回值。

def Flower(x, key):
    flower = random.randint(0, 4096)
    return x * (key ** 3 + flower)

image,所以我們直接在上一步處理一下 \(L\) 就可以得到一個更為簡潔的式子 \(key^3+flower\)\(flower\) 是隨機數,不好處理,但是有一個很關鍵的點, \(key^3\) ,這一項可以通過 \(gmpy2\) 庫的 \(iroot()\) 函數來開方,正確的值開方返回值第二項應該是 \(True\) ,對於數字字母的ASCII碼來說,相鄰數的三次方差距已經超過了4096了,即便是最小的 '0' 和 '1' 的差值都達到了7057,所以可以放心的遍歷所有 \(0-4095\) 之間的值。

for i in flowers:
    for j in range(4096):
        if iroot(i - j, 3)[1] == False:
            continue
        print(iroot(i - j, 3)[0], end=' ')
51 101 56 48 55 98 54 54 101 102 50 54 100 51 56 101 54 55 49 100 100 99 98 98 57 99 49 48 56 50 53 48
```![image](https://img2022.cnblogs.com/blog/2553489/202203/2553489-20220326213855426-1985494792.png)


​		到這一步就很簡單了,一看就是ASCII碼,直接在輸出上加一個ASCII碼即可。

```python
for i in flowers:
    for j in range(4096):
        if iroot(i - j, 3)[1] == False:
            continue
        print(chr(iroot(i - j, 3)[0]), end='')
3e807b66ef26d38e671ddcbb9c108250

​ 這就是flag了,提交即可。

整個解密代碼:

解密源碼
import random

L = 15720197268945348388429429351303006925387388927292304717594511259390194100850889852747653387197205392431053069043632340374252629529419776874410817927770922310808632581666181899

R = 139721425176294317602347104909475448503147767726747922243703132013053043430193232376860554749633894589164137720010858254771905261753520854314908256431590570426632742469003

listL = []
listR = []
flowers = []

n = 0
while L > 1:
    listL.append(L)
    listR.append(R)
    L, R = R, L % R
    n += 1

listL.append(L)
listR.append(R)
listL = listL[::-1]
listR = listR[::-1]

print("n=:", n)
for i in range (len(listL) - 1):
    num = int((listL[i+1] - listR[i]) / listL[i])
    flowers.append(num)
for i in flowers:
    for j in range(4096):
        if iroot(i - j, 3)[1] == False:
            continue
        print(chr(iroot(i - j, 3)[0]), end='')


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM