FSCTF2023 WP (Re&Crypto)

第一次做出题人,共出题10道(4道re,6道密码),现将wp补充在下面,做个记录。。。

FSCTF2023 re WP ------出题人:Tanggerr

ezbroke

  • DIE查壳

  • 拖进010查看:

  • 发现PE头被修改了,先把开头标识改为4D 5A

  • 再看3C处,指向70处,而80处才是50 45,故修改为80

  • 保存后发现有UPX壳,但是不能直接去除,再用010看

  • 发现UPX特征码被改掉了,故把所有的TUT改为UPX

  • 此时再去查壳

  • 经典3.96壳,直接工具脱壳即可

  • 32位无壳程序

  • 拖入IDA,看main函数

  • 其实是一个很简单的vm,我们恢复一下opcode即可

  • 根据提示,我们找到opcode与一些handler即可

  • void __noreturn main()
    {
      int v0; // [esp+1Ch] [ebp-4h] BYREF
    
      __main();
      v0 = 0;
      puts("We1c0me t0 FSCTF");
      puts("---------------------");
      puts("please input the flag:");
      vm_init((vm_cpu *)&v0);
      vm_start((vm_cpu *)&v0);
      check();
    }
    
  • 找到vm_init:

  • void __cdecl vm_init(vm_cpu *cpu)
    {
      cpu->r1 = 0;
      cpu->r2 = 0;
      cpu->r3 = 0;
      cpu->eip = vm_code;
      cpu->op_list[0].opcode = -15;
      cpu->op_list[0].handle = (void (*)(void *))mov;
      cpu->op_list[1].opcode = -14;
      cpu->op_list[1].handle = (void (*)(void *))xor;
      cpu->op_list[2].opcode = -11;
      cpu->op_list[2].handle = (void (*)(void *))read_;
      vm_stack = (char *)malloc(0x512u);
      memset(vm_stack, 0, 0x512u);
    }
    
  • void __cdecl xor(vm_cpu *cpu)
    {
      cpu->r1 ^= cpu->r2 ^ 0x17;
      ++cpu->eip;
    }
    
  • check函数:

  • void __noreturn check()
    {
      int i; // [esp+1Ch] [ebp-Ch]
    
      for ( i = 0; i <= 11; ++i )
      {
        if ( vm_stack[i + 32] != enc_flag[i] )
        {
          puts("think please");
          exit(0);
        }
      }
      puts("Success!");
      exit(0);
    }
    
  • 看完函数,我们把opcode提取出来对应handler进行翻译

  • 0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 
    0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00, 
    0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02, 
    0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00, 
    0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23, 
    0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2, 
    0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 
    0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1, 
    0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00, 
    0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1, 
    0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00, 
    0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1, 
    0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00, 
    0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 
    0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00, 
    0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C, 
    0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00, 
    0xF4
    
  • 只有一个异或操作,直接写脚本:

  • c=''
    x=[0x51, 0x44, 0x54, 0x43, 0x51, 0x6C, 0x4E, 0x27, 0x62, 0x37, 0x64, 0x62, 0x74, 0x74, 0x72, 0x64, 0x64, 0x71, 0x62, 0x26, 0x26, 0x6E, 0x37, 0x75, 0x65, 0x27, 0x7C, 0x24, 0x37, 0x7A, 0x6E, 0x37, 0x67, 0x65, 0x27, 0x63, 0x24, 0x74, 0x63, 0x26, 0x27, 0x79, 0x36, 0x36, 0x36, 0x6A]
    for i in range(len(x)):
        c+=chr(x[i]^0x17)
    print(c)
    
  • 得到flag

  • FSCTF{Y0u successfu11y br0k3 my pr0t3ct10n!!!}

ezcode

  • 手撕python字节码

  • 分析可得是魔改RC4及base64换表加密

  • 直接上脚本

  • def func1(key, message):
        s_box = func2(key)
        crypt = str(func3(message, s_box))
        return crypt
    
    def func2(key):
        s_box = list(range(256))
        j = 0
        for i in range(256):
            j = (j + s_box[i] + ord(key[i % len(key)])) % 256
            s_box[i], s_box[j] = s_box[j], s_box[i]
        return s_box
    
    def func3(plain, box):
        res = []
        y='FSCTF'
        i = j = 0
        for s in plain:
            i = (i + 1) % 256
            j = (j + box[i]) % 256
            box[i], box[j] = box[j], box[i]
            t = (box[i] + box[j]) % 256
            k = box[t]
            res.append(chr(ord(s) ^ k ^ ord(y[i % len(y)])))
            cipher = "".join(res)
        return cipher
    
    def rc4_decrypt(key, cipher):
        s_box = func2(key)
        plain = []
        y = 'FSCTF'
        i = j = 0
        for c in cipher:
            i = (i + 1) % 256
            j = (j + s_box[i]) % 256
            s_box[i], s_box[j] = s_box[j], s_box[i]
            t = (s_box[i] + s_box[j]) % 256
            k = s_box[t]
            plain.append(chr(ord(c) ^ k ^ ord(y[i % len(y)])))
            message = "".join(plain)
        return message
    
    key = "XFFTnT"
    cipher = "=.#MØQïòtÂЭv|·"
    message = rc4_decrypt(key, cipher)
    print(message)
    
  • 解得FSCTF{G00d_j0b!!!}

MINE SWEEPER

  • 签到题,IDA打开,搜索字符串即有flag

rrrrust!!!

  • 查壳,ELF64位

  • rust逆向

  • 找到主函数中的关键函数

  • 注意到:

  • qmemcpy(v63, ">*'3", 4);
    v63[4] = 21;
    v63[5] = 3;
    v63[6] = 61;
    v63[7] = 119;
    v63[8] = 37;
    v63[9] = 100;
    v63[10] = 3;
    v63[11] = 103;
    v63[12] = 7;
    v63[13] = 50;
    v63[14] = 118;
    v63[15] = 11;
    v63[16] = 28;
    v63[17] = 33;
    v63[18] = 43;
    v63[19] = 50;
    v63[20] = 25;
    
  • 明显的关键字符串

  • 在程序输入处下断点,直接动调,观察输入的字符串的变化

  • 发现只是在进行一个循环异或

  • 我们动调出来异或密钥为XFFTnT

  • 直接上脚本解密就行

  • x=[0x3E, 0x2A, 0x27, 0x33, 0x15, 0x03, 0x3D, 0x77, 0x25, 0x64,
      0x03, 0x67, 0x07, 0x32, 0x76, 0x0B, 0x1C, 0x21, 0x2B, 0x32,
      0x19, 0x23, 0x5E, 0x26, 0x69, 0x22, 0x3B]
    y='XFFTnT'
    c=''
    for i in range(len(x)):
        c+=chr(x[i]^ord(y[i%len(y)]))
    print(c)
    
  • flag{We1c0m3_t0_rust_w0r1d}

FSCTF2023 Crypto WP---出题人:Tanggerr

Do you know gcd

  • 发现两个模数有公因子

  • 直接gcd破解

  • from Crypto.Util.number import *
    e=65537
    n1= 18680935400842120133090782991548100098299141114788036098274292600814484762178879421175852824971602717084073867867453382415307589970440719890918576225495401632854107018246844209327118177917122236073227158593514362850629722223228335334773008682775987859295083444638923726449899310854161394586430943134469559429878238769266114132469166535509030877235272476877484918308883799496627699789051809542538091061550107526246728583019140703765888157806778516567048103700384849598143249322109207879381251223776896702362630437178664824125387477797876186939235800859102380783259361745143574493440078787931593394188675093506492640857
    n2= 16308523133405725830120564525574438512803584148781960516042054284309437381876822602134185065101371986717984978566359252072738078020261823966208153922611063201149105749778596739692554295573408850719208215646167050188830459343054219856901871953140988948482577813730729085764541988120049026971705499798003225755018687242522370406495429425494022876627543617474873929054728724093702291448754458748923218635900061398716191201846139296921753782690468189409101899415028480878296408735247604084627019116374444335509072590669239349212479592499426230525792270750612371117196200786891891430446212938482959351978202358044864822577
    c1= 534518909595318304521410713148076850830155521838755402438490325620155197496935820831936109252194297244161393310730073882257949954815312409974998733265641354273665213856408848764503848122264972023143474923678585167025591255034150826271791019266426616987355463111138963331008761826310757292765842789380409826387579098421126952331558360737102888876551724241978020305977032047901621477384392409864427091911872691182528938458750707982564581322551517287491916691010743390992018974168703956622998928457142606354825714033609199676987795174032254878017883605565760275857658822315970522114838062469258676628619381342357632179
    c2= 10248394002302905069278122013496854496130190499518622376819239887579692634750808499513497018453473232140518824608976734237637842228035017757831938865937098325684711995382081489403971465596662585196007547659143066184546400992333479193424580690897692586491475768279754939199148642035267049092880715299621206567123356521609120801306358100326600900326310677054810032471472266402660807205675696110133573150125117412696328434523507708110949743705536889950671778501402435457354251761692098671783596194430798692942013503015764266392551048702428063161786512924608239609802040937400619384828550050291094616346317726139970219621
    p=gcd(n1,n2)
    q1=n1//p
    q2=n2//p
    phi1=(p-1)*(q1-1)
    phi2=(p-1)*(q2-1)
    d1=inverse(e,phi1)
    d2=inverse(e,phi2)
    print(long_to_bytes(pow(c1,d1,n1))+long_to_bytes(pow(c2,d2,n2)))
    
    
  • FSCTF{0hN0_Y0u_f1nd_th3_gcd!}

RSA签到

  • 注意到:assert m.bit_length()<150 ,e=3

  • 考虑直接开方

  • from Crypto.Util.number import *
    c = 42336544435252811021843650684098817755849747192874682997240960601474927692351510022965782272751339319782351146077580929125
    print(long_to_bytes(iroot(c,3)[0]))
    
  • flag{sign_1n_RSA}

Big_e

  • 简单的低解密指数攻击

  • def rational_to_contfrac(x, y):
        # Converts a rational x/y fraction into a list of partial quotients [a0, ..., an]
        a = x // y
        pquotients = [a]
        while a * y != x:
            x, y = y, x - a * y
            a = x // y
            pquotients.append(a)
        return pquotients
    
    
    def convergents_from_contfrac(frac):
        # computes the list of convergents using the list of partial quotients
        convs = [];
        for i in range(len(frac)): convs.append(contfrac_to_rational(frac[0: i]))
        return convs
    
    
    def contfrac_to_rational(frac):
        # Converts a finite continued fraction [a0, ..., an] to an x/y rational.
        if len(frac) == 0: return (0, 1)
        num = frac[-1]
        denom = 1
        for _ in range(-2, -len(frac) - 1, -1): num, denom = frac[_] * num + denom, num
        return (num, denom)
    n = 12238605063252292170613110607692779326628090745751955692266649177882959231822580682548279800443278979485092243645806337103841086023159482786712759291169541633901936290854044069486201989034158882661270017305064348254800318759062921744741432214818915527537124001063995865927527037625277330117588414586505635959411443039463168463608235165929831344586283875119363703480280602514451713723663297066810128769907278246434745483846869482536367912810637275405943566734099622063142293421936734750356828712268385319217225803602442033960930413469179550331907541244416573641309943913383658451409219852933526106735587605884499707827
    
    e= 11850552481503020257392808424743510851763548184936536180317707155841959788151862976445957810691568475609821000653594584717037528429828330763571556164988619635320288125983463358648887090031957900011546300841211712664477474767941406651977784177969001025954167441377912326806132232375497798238928464025466905201977180541053129691501120197010080001677260814313906843670652972019631997467352264392296894192998971542816081534808106792758008676039929763345402657578681818891775091140555977382868531202964486261123748663752490909455324860302967636149379567988941803701512680099398021640317868259975961261408500449965277690517
    c=4218884541887711839568615416673923480889604461874475071333225389075770098726337046768413570546617180777109293884545400260353306419150066928226964662256930702466709992997796154415790565112167663547017839870351167884417142819504498662037048412313768450136617389372395690363188005647619061128497371121168347810294424378348301835826084732747005110258557662466626720961279087145559906371505117097599774430970980355531235913439823966628008554872896820907555353892843539526041019103819804854883231421963308265517622470779089941078841902464033685762524196275032288319744157255628189204988632871276637699312750636348750883054
    
    
    
    def egcd(a, b):
        if a == 0: return (b, 0, 1)
        g, x, y = egcd(b % a, a)
        return (g, y - (b // a) * x, x)
    
    
    def mod_inv(a, m):
        g, x, _ = egcd(a, m)
        return (x + m) % m
    
    
    def isqrt(n):
        x = n
        y = (x + 1) // 2
        while y < x:
            x = y
            y = (x + n // x) // 2
        return x
    
    
    def crack_rsa(e, n):
        frac = rational_to_contfrac(e, n)
        convergents = convergents_from_contfrac(frac)
    
        for (k, d) in convergents:
            if k != 0 and (e * d - 1) % k == 0:
                phi = (e * d - 1) // k
                s = n - phi + 1
                # check if x*x - s*x + n = 0 has integer roots
                D = s * s - 4 * n
                if D >= 0:
                    sq = isqrt(D)
                    if sq * sq == D and (s + sq) % 2 == 0: return d
    
    
    d = crack_rsa(e, n)
    m = hex(pow(c, d, n))[2:]
    print(bytes.fromhex(m))
    
  • FSCTF{Y0u_ar3_s0_C001}

babyhint

  • 通过两个hint进行推理,再gcd得到p或q

  • 得到关键kq = pow(2023,1919*9191,n)*pow(h2,1919,n) - pow(2022,1919*9191,n)*pow(h1,9191,n)
    
  • 上脚本解密

  • import libnum
    h1= 83535799515204730191288403119559179388147974968301357768644756769205396635068662150926873512812305514469213626273460486537390422570056287512841114712846420160416446291128064734960979586229744062965998582728378025151822479630618024804808407804317029367335421715125562402059266983021662398390585435529976586654
    h2= 14402204438484882372730843813561914135941866642278909172674395293274736617425618184831446215507756031454895377588951726822765439585979555636320832177929472057402274116190878688601329765374509467243968967279090492272317903230101551317377700802837187081510381677262879617929177970455244249498674083943925477229
    n= 94120719816617297967197808458007462810449143149204454740678593087096770130918870563878599847276923902207042790106345400843990455347835029220453217996810995363105274873857381469314548191574754245357568090646094043040797653858225598519876785530143007788084656262253002478643994943076851585839631209338814367691
    c= 84244594789418833202484965138308516535996015903654462304986953156471594657993252593373963514364258027091543394305491354187806441313428473670956684437253991594327692679733432489342255718685303997647293213324463025120804679847465190496542879161344985402542539184706559207299026102682674060562738496314731555616
    e=65537
    kq = pow(2023,1919*9191,n)*pow(h2,1919,n) - pow(2022,1919*9191,n)*pow(h1,9191,n)
    q = libnum.gcd(kq,n)
    phi = (q-1)*(n//q - 1)
    d = libnum.invmod(e,phi)
    print(libnum.n2s(pow(c,d,n)))
    
    
    
    • flag{ezsy_e3sy_ea4y_so_easy!!!}

ezmath

  • 同样找到公因子是p的两个式子即可

  • import libnum
    from Crypto.Util.number import *
    n=16099847254382387482323197733210572595987701766995679577427964142162383113660616883997429365200200943640950821711084123429306946305893862414506257284441114840863787499898478803568113348661314216300658606282276936902117099898776435948501831796770856505782683585268617613575681655903107683069260253287994894440427511440504754827820494060133773435262418256886443037510658584541624614692050308222516337333585823733360631982795323752298740497235142977602602205292595197618229629610834651923388269194546316023246525302500676142502931303976146680655368617094100097945625676103639154884247373003120937959132698199043562660573
    c=7980021929208497878634194663038470941705554065040985666635317762877799614984808729636911256912639929083920319066806111423231500122646366713245534616522235309310234767331344216892929739448126523171652425415458999098138841038319673380331281114806318366697490343176758140150118761408250366783210772381316729932361601257318131085116265135718477224618689710966570938280408341402386000281564650565256635313406111364916715660419153433573586809503564050585204002594864254089288672391014804368427324162776953191520483774116807593366091685560902424782104761523067998300887293902330501335485075609216897135678017158187880996872
    hint=14005608544369156893681352040163362072608754453657200460825561123439158535855236943525558717120672888372079069187756549797113560863313618058077150885401191613229507892570378437310964624470055767463556516869604496669085622244233154871165554916349033197798790982409986216498996673603605465039336316170130644317728786516639634775709400754328137266154981484016505702738584209800158047120647468364899692021253904198509376650238372552486792709682170146695759196408908825447960637667502907929061819408441663880712891979320089482801220225451560809151067631824526463122992973388740015878474372614751149918455457191739542980396
    
    e = 65537
    p = libnum.gcd(hint-pow(2023,n,n), n)
    phi = (p-1)*(n//p -1)
    d = libnum.invmod(e,phi)
    print(libnum.n2s(pow(c,d,n)))
    
    
  • flag{ju3t_a_s1mpl3_ta3k}

ezRSA

  • 构造方程求解就行

  • from sympy import *
    from Crypto.Util.number import *
    
    n = 1901485114700245088118015176838411045645808657633721129158322425051110390237801115516544893309422501851747092251796770953642000579931231478667887589988786560834446696408732292786254192492281586457284980263740183
    enc = 1199361436656854951826843585559905358018072076349745598865984504434921942249797269971584270541920348511243191511578321283455075109027873358983934024677982086699270397304699932717071144314481599892879445599516848
    
    e = 31337
    
    k = symbols('k')
    p = k**6 + 7*k**4 - 40*k**3 + 12*k**2 - 114*k + 31377
    q = k**5 - 8*k**4 + 19*k**3 - 313*k**2 - 14*k + 14011
    ans = solve(p * q - n, k)
    k = int(ans[0])
    p = k**6 + 7*k**4 - 40*k**3 + 12*k**2 - 114*k + 31377
    q = k**5 - 8*k**4 + 19*k**3 - 313*k**2 - 14*k + 14011
    assert p * q == n
    
    phi = (p - 1) * (q - 1)
    d = inverse(e, phi)
    m = pow(enc, d, n)
    flag = long_to_bytes(m).decode()
    print(flag)
    
  • 注:这个脚本有点小慢,大家可以去用sage求解

  • flag{y0u_kn0w_th3_P0lyn0mialRing_w1th_RSA!!!}