首页
论坛
课程
招聘
KevinsBobo
雪    币: 12138
活跃值: 活跃值 (132)
能力值: (RANK:380 )
在线值:
发帖
24
回帖
207
粉丝
6

[原创]看雪CTF 2019总决赛 第二题 南充茶坊

2019-12-6 22:15 1879

[原创]看雪CTF 2019总决赛 第二题 南充茶坊

2019-12-6 22:15
1879

目录

获取Python源码

首先南充茶坊.exe的图标和PyInstall打包的PE图标一致,将南充茶坊.exe用压缩包打开可以发现里面包含了一个CM.exe,再结合运行后CM.exeAppData\Local\Temp\_MEI?????目录下释放了一堆Python组件,可以判断此程序为打包后的Python程序。

 

使用PyInstallarchive_viewer模块将CM.exe解压,通过x命令提取出主模块CM和依赖包PYZ-00.pyz,再次从PYZ-00.pyz中提取出主模块依赖的2个模块:gerneralCMpub。提取出三个PYC文件后,还需要再提取出struct文件,将struct的前16个字节(版本号)添加到其他三个PYC文件头。接下来就可以使用uncompyle6反编译出源码了。

算法分析

通过分析代码逻辑可发现,使用usernameSHA256值生成了一张索引表,索引表的值为0-9,分别对应10组RSA公钥( ne )。10组公钥中第[0]组将ne分为四段分别使用。

 

验证逻辑为:根据索引表的顺序使用对应的公钥重复解密输入的序列号,若解密后的值为用户名的16进制数据,则验证成功。

 

原来题目的意图是解10组RSA。虽然RSA加密是无法破解的,但是若使用方法或场合错误,则可以爆破或分解出qq,从而计算出密钥d

计算RSA密钥

计算密钥的过程由 @ ccfer 提供

第[0]组

n = 1230179032923966355216193664456989083993912178939747632284136330115404600706909248395341278324517175820853286404743710145952644302282044037365125019184623573863075946389644423629304167773956447181872440665027369039751736977631813405
转16进制拆成4段:
CAD931A5AEDA20EA5E7956D07284DB74832A28D331ADFEB1 
FFFFDB4924156BC1CF0E65FBD9840345985858FCC2F58571 
FFFF43FBA7A3F0E50F38CD120AC5AFB0F6360E79DCF2E935 
FFFF7B8B04F0DC86ABF13C3F79E202726A2ED42564211F1D
e = 516522834974778788822737622050071002228140433403308439492366176194856535110473049678585760137133115927927751389873437178270126066640141239601219481836725664034890696476089482771855782560150644578106217444113872365843767702019835165
转16进制拆成4段:
552BD4790ABF307B7ED1C5997D56639E581CBA65B4762769
9A57D7321E5297B133CB0EBA55FC8AB8D7839772C6490FF1
DE5EEA637EE42461497F3B3286B410FDA678C2EB0662F13D
668594EA4C1BA173614B9860AE8BB1231F60A2BFD36B051D

分别分解,求得d:
n0 = 4973828634074084070222279013150769733596223651485114564273
P29 = 66428487199875098638682243347
P29 = 74874934591065563984140844459
e0 = 2088392012863598836930805392926351714650188437587735488361
d0 = 935387432279493795970516178982877288303534264234974679937

n1 = 6277087998938792861042405062580257456598525084583043892593
P29 = 62221071216704155848060102353
P30 = 100883637587609016545825234081
e1 = 3784482471495320575589048728247975381653380680141800804337
d1 = 5168422726700129702446055556002687483861807983023239862033

n2 = 6277031389885428580574088212602983156224270664268963309877
P30 = 135897650123798146894617474263
P29 = 46189403453019724968918893779
e2 = 5452515267665389664275951067811576469767027838421869719869
d2 = 5595268830569065289149075246423557309146176813871482913465

n3 = 6277052177355867862708971469565390229110991711310599757597
P29 = 50652156588134490618159573691
P30 = 123924677647906847227542543367
e3 = 2513827307676496129699780837261567723809491022362599687453
d3 = 3278088227273880484685188900446423165326324359156241482897

d0,d1,d2,d3合并后:
2625E684EE3FA1A2BE936C4144D5BFBFF44B7A9646389381D2C8D9DEEA4C03DDE63DABCE64349FB0AE79CDCA3EF61711E4315512E61E47D432F7D738193F3DFB0795ED14D441C2B985B0D687CA04D21912CFD52100255A3E646CD9B0FCE34491
转10进制得到
d = 231349749158583579949039718606348832345605133393805777133420928094319680216601822460127654993430958078940461462422406257359280556871448350189878998731668936956281838863906877563919765029383962761070215049843547656169497792123978897

第[1]组

n = 1230197346433601576871359147146318345794660644587556813317361121112259736906064757424819981626600536503633922734399282271582600808051530362336101942259823441839299355603967188517947938968081105138847731565260537550727639211683197879
用msieve153_win64直接跑出来了:
p = 3012613441
q = 408348887278831461892610983390456945715612189153595698014201723503582993177671598068402822885301113712860820610804438839912419021850712894809826330539771179969086301239790288951959814006579380835620367785931463468740342519
e = 763019398230639020385095590111745749325105506404934257293148841704076883985487416392986296273940405033341623636375465706381388882972769884442281412068657916633528090146878551371406807944205178239005601520958614234641039656871416589
d = 1229061379053482744823152709690434888605435342198642793057361495153090878523561729157374272032362247153476832905266577597936263875922635915871109425948662301015976854125739243408750974498511602088546684816889116185016023460221241669

第[2]组

n = 1230175103148238074642625667635930176506433011031372989302833308622794392947506662903737049730958209740476679577696669046125817578949235076594181707520951908118478466754559490593457625240572006099913042624607335165510041897534435209
用ecm的P-1可以跑出来:
p = 33432251606513919330224622231317366537583494828490610118526091564149071313914670507018535045422242143860852944567717
q = 36796059015915981995743432427927902530578158826788662547913509800095517347118062478922356654842254755916234587213077
e = 758988267473789691400810521950661631157749425185051374867090671651749645717430551141709267885532654476900928589359256799354189000242807872593092025777838259738748452497031844208902096380110211365512236965688511597330444132995706089
d = 777757116197429014363243483536399809327489478672765799132008796613164652485176625704586327714092043960999487185568710834915265226900792279774759093092549483626423808502139519027474793822444064402879491357824424416255246538629615833

第[3]组

n = 1230195419889872144876656964938566328205499234259210834822623032535100815525647028091967713768075507813160118981470260555950945392043292242406398016007295386079663975352275199434079009613722639414793342879897781273997830701207001839
用ecm的P+1可以跑出来:
e = 1160624249765899561934599801255171381291816170997589163041066264243942985094428544791715385847964978883555709070528078257993944356365754193784103706700609561770247555832359683008614876192584738534198649251915489100192910235497240729
p = 34508357350889186927005771176009938286558270433215942821530479444470024241863567490529149148811494601012847563892119
q = 35649202521608097930406469243867007880953508969230221480710213863570107942900924156757677983779306674419762868555881
d = 823517544270505260875748293850542665969704501523967290816451493771583601768953397655610971102989198539746963950912153425409736040224095605717482218948794082459357645210952999432155985335398508720958815348576453854403675948095665769

第[4]组

n = 1230174827420484335136670743465041112031290639257519417607166302989196920558878232997045073571925815302061150702941267642751824310540753494973942944709182841639107639574372312103384805313053886702823094137071927771880443876497834223
最后在factordb查到了:
e = 969584864618350548573879514405798110739020997255786147754353418263140741786718203172013471748696400657712445258494301947449205093259143099235572291402265831321039275001497928579686310419303799571460516007736804962510266314260484877
p = 35073848198058968264749790689745197012385911613318747771531468291963621262770461817935405298684967674641247961569207
q = 35073848198058968264749790689745197012385911613318747864444430571453140176920442860760331340059929469925220710756489
d = 201419093613711761798540120588879041236840801068737686325195769604622639638393093247553615834885873886104026065263583851481439063609372020322699902282368593094548575688163522138303256348801329176798576662806247524508598547117027909

第[5]组

n = 1230185988420782350445684618408731075592594374149632568516959143947765502111474165779039038375448460747737995123102271976521803891348006321134167925739699715318653372703575221067707929872597815216923462345784043188962130180912008349
KevinsBobo同学发现迭代几百次会循环,所以不用求d
    #p = 31503816680213636132912806593832467127701905358069068741861031758425557411621894830115937323069127836741631806806413
    #q = 39048792116461747945360620417583820898846483722528412615831165805123652201251081469267423776974114973544133333275473
    #e = 977635869919691501956476862485989771461480520535754082824505449124021204549179419508424215127475063873127952064971338143136691515421466871627243381628988777601672460858098249144471775030169367579800220246847826510445608881346258241
    #d = 1117009106464734780030135903971376007649834288754022581938053795622284810882686627104126219248876731365945251933106270030770558470980321270557768251797621710130641017642655840899260118345619011299266192192635438821749949055206265985

第[6]组

n = 1230182067416272799574586563163545941454653137377618375202713428977357995541722463977983142958255155175313052685136009571171283284447072364958073918526788611457558644331357136872625495927467161960356807765452292242153097362794537297
RSA-and-LLL-attacks得到结果:
p = 26153324138194530872309557862464074525306735281010877795840958405693838446634362256045094682633541743845611502925341
q = 47037312003475104493787837223043052957997925611039410248119470723357078273788416725476266555402464778755414193496517
e = 78547544255936347746865903259860321812178052069796003154571672431430356709336862994676369608681727972743046653319757142976388460246409300441314120923213061705641045744824531268088986356203751782848608006264879618324460588039470689
d = 4043296382360454915279470869953391352707507302270983672749

第[7]组和第[8]组

发现两个n有公因子gcd(?,?) = 31550999035553713541658090861648847436644679578302163888858659624252927748982782365539915958668921514993162014394013
所以就容易了:
n = 1230175667673121302771605367336364266247327534138626737357715728447532125946735363769285915448580252805827932111511713836998047583507066247536863749820566853793525683889378074234787827092004094825431802398656705570322640700888234457
p = 31550999035553713541658090861648847436644679578302163888858659624252927748982782365539915958668921514993162014394013
q = 38990070212574870147996976234485159783294770114760127229326637585796111190341078784636949590143174262955343019982189
e = 917852167599983949701460374746950168138446186550074700858636881546192542929330983597633909534315139846805451671216776221152853388795036676315895948093016056124384137235869660229554239964598066970045657946753074761366723500887474273
d = 627567627354326605515830278366021138159090868181225778581524414114680017539982571880336309158282300554534438008003322761037932916796881232969829716072515736525821134512405811777096389132413642826921797756179543381108933388795804769

n = 1230196215847264556140155304337951587143228841840811940425256504477922246092127337047231112435502675187836322205816125340569108923142351137471846665258392302281836567949024626839375922984390501852966755563575130612920367863203222919
p = 31550999035553713541658090861648847436644679578302163888858659624252927748982782365539915958668921514993162014394013
q = 38990721481148651230245403302870059427845712033679000902896256935166030973974325392836914596772977488693063112507763
e = 512767915836808239407587704603826045022417741229198687031456060058182528147222248648359114235863620155721720617193551963387219761946115199232261616095015003006138489919312964841684835736418589367746436759162173805823822810793395319
d = 87763698610259057934268676955169084425464093902524300758830437447338976666426976224860384022223934601405128988601223084334832120115000652985202766336425151725676233383146800117094745887838499800523801384784235875984207816521259103

第[9]组

n = 1230186684530117755130494958384962720772853569595334792197322452151726400507263657518745202199786469389956474942774063845925192557326303453731548268507917026122142913461670429214311602221240479274737794080665351419597459856902143413
最早就在factordb查到了:
p = 33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489
q = 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917
e = 1528664914065178933673821962753205462549978186396819666317790993639228285768444490202530533489915241541000489357324333513953018274712260336841857865516134868397620862505815431605074038377372062941322744934135683316080403207986149067
d = 476133969086427941368462698171675198835788633664060460402567958612344234273279077792246479357026462298849835811290909092037603283477920353500979549470973082158764663458247740861805650589884280458476962517272738918503674157481390819

第[5]组无需密钥

在@ccfer解的剩下[4]、[5]的时候,我提出是不是存在不需要d的情况,然后就找资料,尝试后无果。后来就把代码删的只剩下重复加密放到那里跑,没想到把[5]的明文跑出来了。并且发现无论明文是什么,都可以在第972次跑出来!第973次就回到了最初的密文!

 

题目结束后在群里和大佬们沟通时,@readyu 给出了公式 e^973 = mod (p-1)(q-1),引来大伙一阵膜拜。(除此之外@readyu大佬还在群里普及了很多相关的知识和公式,十分佩服!)

 

以下是爆破代码:

import math

def without_d(n, e, data, enc):
    current = enc
    i = 0
    while True:
        current = pow(current, e, n)
        if current == enc:
            print('get enc : %d' % i)
            print(enc)
            break
        if current == data:
            print('get data : %d' % i)
            print(current)
        i+=1

if __name__ == '__main__':
    n = 1230185988420782350445684618408731075592594374149632568516959143947765502111474165779039038375448460747737995123102271976521803891348006321134167925739699715318653372703575221067707929872597815216923462345784043188962130180912008349
    e = 977635869919691501956476862485989771461480520535754082824505449124021204549179419508424215127475063873127952064971338143136691515421466871627243381628988777601672460858098249144471775030169367579800220246847826510445608881346258241

    data = 147258369369258147147258369
    enc = pow(data, e, n)
    # without_d(n, e, data, enc)
    without_d(n, e, enc)

    data = 123456789987654321123456789
    enc = pow(data, e, n)
    # without_d(n, e, data, enc)
    without_d(n, e, enc)

图片描述

逆推(注册机)算法

import math
from Crypto.Util.number import bytes_to_long
from general import get_enc_seq, enc0
from CMpub import pub_n_list, pub_e_list

d_list = [ ... ] # 节省篇幅,这里省略,完整代码在附件中

def without_d(n, e, enc):
    current = enc
    i = 0
    while True:
        dec = current
        current = pow(current, e, n)
        if current == enc:
            # print('get dec data : %d' % i)
            # print(dec)
            return dec
        i+=1

def dec(name):
        print('dec for ' + name)
        username = name.encode('utf-8')
        seq = get_enc_seq(username)
        print('seq:')
        print(seq)
        username = bytes_to_long(username)
        print('username hex data: ' + hex(username))
        now = username
        seq.reverse()
        for i in seq:
            n = pub_n_list[i]
            e = pub_e_list[i]
            d = d_list[i]
            if i == 0:
                new_now = enc0(now, d, n)
            elif d == 0:
                new_now = without_d(n, e, now)
            else:
                new_now = pow(now, d, n)
            now = new_now

        serial = now
        serial = hex(serial)[2:].upper()
        print(name + ' Serial : ' + serial)

if __name__ == '__main__':
    dec('KCTF')
    print()
    dec('89F3A5FD45E2A383')

图片描述

最后于 2019-12-9 09:41 被KevinsBobo编辑 ,原因:
上传的附件:
最新回复 (1)
yimingqpa
雪    币: 6850
活跃值: 活跃值 (34)
能力值: ( LV7,RANK:110 )
在线值:
发帖
33
回帖
410
粉丝
5
yimingqpa 活跃值 1 2019-12-10 17:04
2
0
666,原来在pyz里,前些天没找到那两个模块没弄了。
游客
登录 | 注册 方可回帖
返回