De1CTF2020-WriteUp下(Crypto、Reverse)

2020-06-10 13,679

Crypto

ECDH

解题思路

key = secret*(x,y),x,y是你的输入

加密是用key,然后逐bit和明文异或加密,key循环使用

提供一个函数给你的输入加密=>应该是用来获取key的

获取flag的方式是,猜到secret

我们知道这个曲线的参数a, b 然后知道模域q,知道(x,y)和secret*(x,y) => 求secret

然后我们能传90次option 

有没有办法能够找到特定阶的点?

切入点:他没有检查你给的key在不在曲线上

https://www.researchgate.net/publication/301335748_Differential_Fault_Attacks_and_Countermeasures_in_Elliptic_Curve_Cryptography

发送一个低阶点Q去交换,然后利用加密解密函数算出key

根据key可以计算secret的一个剩余, 模数就是这个Q的阶

然后CRT

image.png



NLFSR 

解题思路

非线性反馈移位寄存器,参考

https://wiki.x10sec.org/crypto/streamcipher/fsr/nfsr/

此题与2018 强网杯streamgame3 题目基本相似,不同之处在于:

后者包括三个线性反馈移位寄存器,此题有四个;

后者三个线性反馈移位寄存器中,最终的输出与其中的两个都有高达75%的相同的概率,因此只需要用相关攻击解出其中两个,剩下一个采用爆破即可,而此题最终的输出只和一个有75%的概率,其余三个均为50%,直接对三个都爆破的话需要2^(19+13+6)次循环,不太可行。。。

因此尝试化简:

(ao * bo) ^ (bo * co) ^ (bo * do) ^ co ^ do = (ao * bo) ^ (bo * (co ^ do)) ^ (co ^ do)

(co ^ do)可以合并为一项

将c和d合并成一个线性反馈移位寄存器后,计算其输出与最终输出相同的概率,发现有75%。这样,这道题目就完全转化为强网杯的那道题了~

def lfsr(R, mask):
    output = ((R << 1) & 0xffffff) ^ (bin(R & mask).count('1') % 2)
    lastbit = output & 1
    return (output, lastbit)

def single_round(R1, R1_mask, R2, R2_mask, R3, R3_mask, R4, R4_mask):
    (R1_NEW, x1) = lfsr(R1, R1_mask)
    (R2_NEW, x2) = lfsr(R2, R2_mask)
    (R3_NEW, x3) = lfsr(R3, R3_mask)
    (R4_NEW, x4) = lfsr(R4, R4_mask)
    x5 = x3 ^ x4   
    return (R1_NEW, R2_NEW, R3_NEW, R4_NEW, (x1*x2) ^ (x2*x5) ^ x5)


R1_mask = 0x505a1
R2_mask = 0x40f3f
R3_mask = 0x1f02
R4_mask = 0x31
n4 = 6
n3 = 13
n2 = 19
n1 = 19


def guess(beg, end, num, mask):
    ansn = range(beg, end)
    data = open('./data').read(num)
    # data = ''.join(bin(256 + ord(c))[3:] for c in data)
    now = 0
    res = 0
    for i in ansn:
        r = i
        cnt = 0
        for j in range(num):
            r, lastbit = lfsr(r, mask)
            lastbit = str(lastbit)
            cnt += (lastbit == data[j])
        if cnt/num < 0.7:
            continue
        elif cnt/num <= 0.8:
            print('yes!:', cnt/num, i)
    print('ok')

def guess2(beg1, end1, beg2, end2, num, mask1, mask2):
    ansn1 = range(beg1, end1)
    ansn2 = range(beg2, end2)
    data = open('./data').read(num)
    # data = ''.join(bin(256 + ord(c))[3:] for c in data)
    now = 0
    for i1 in ansn1:
        for i2 in ansn2:
            r1 = i1
            r2 = i2
            cnt = 0
            for j in range(num):
                r1, lastbit1 = lfsr(r1, mask1)
                r2, lastbit2 = lfsr(r2, mask2)
                cnt += (str(lastbit1 ^ lastbit2) == data[j])
            if cnt/num < 0.7:
                continue
            elif cnt/num <= 0.8:
                print('yes!:', cnt/num, i1, i2)
    print('ok')

def bruteforce(x, z, r):
    data = open('./data').read(50)
    # data = ''.join(bin(256 + ord(c))[3:] for c in data)
    for y in range(pow(2, n2 - 1), pow(2, n2)):
        R1, R2, R3, R4 = x, y, z, r
        flag = True
        for i in range(len(data)):
            (R1, R2, R3, R4, 
             out) = single_round(R1, R1_mask, R2, R2_mask, R3, R3_mask, R4, R4_mask)
            if str(out) != data[i]:
                flag = False
                break
        if y % 10000 == 0:
            print('now: ', x, y, z, r)
        if flag:
            print('ans: ', hex(x)[2:], hex(y)[2:], hex(z)[2:], hex(r)[2:])
            break
    print('fail')

猜测R1, R3, R4,用猜到的R1, R3, R4 暴力破解R2:

guess(pow(2, n1 - 1), pow(2, n1), 700, R1_mask)
# 输出:0.7142857142857143 363445
guess2(pow(2, n3 - 1), pow(2, n3), pow(2, n4 - 1), pow(2, n4), 1000, R3_mask, R4_mask)
# 输出:0.758 8136 63
R1 = 363445
R3 = 4406
R4 = 63
bruteforce(R1, R3, R4)
# 输出:ans:  58bb5 78d56 1136 3f
# De1CTF{58bb578d5611363f}



easyRSA

解题思路

感觉利用点在lcm和phi的关系,lcm = (p-1)(q-1)/(gcd(p-1,q-1)),由于是strongPrime gcd(p-1,q-1)很小,尝试了一下,发现一般为2或4.所以lcm*2 = phi 或者lcm*4 = phi

后来发现和D3CTF的一道题很像,直接改脚本,发现得不到p,q,但是可以得到phi,但是算出得phi.解不出明文。于是换了换alpha的值,再试试,,脚本中是正确的alpha值,得到的phi拿去解密可得flag

N=24402191928494981635640497435944050736451453218629774561432653700273120014058697415669445779441226800209154604159648942665855233706977525093135734838825433023506185915211877990448599462290859092875150657461517275171867229282791419867655722945527203477335565212992510088077874648530075739380783193891617730212062455173395228143660241234491822044677453330325054451661281530021397747260054593565182679642519767415355255125571875708238139022404975788807868905750857687120708529622235978672838872361435045431974203089535736573597127746452000608771150171882058819685487644883286497700966396731658307013308396226751130001733
e1=4046316324291866910571514561657995962295158364702933460389468827072872865293920814266515228710438970257021065064390281148950759462687498079736672906875128944198140931482449741147988959788282715310307170986783402655196296704611285447752149956531303574680859541910243014672391229934386132475024308686852032924357952489090295552491467702140263159982675018932692576847952002081478475199969962357685826609238653859264698996411770860260854720047710943051229985596674736079206428312934943752164281391573970043088475625727793169708939179742630253381871307298938827042259481077482527690653141867639100647971209354276568204913
e2=1089598671818931285487024526159841107695197822929259299424340503971498264804485187657064861422396497630013501691517290648230470308986030853450089582165362228856724965735826515693970375662407779866271304787454416740708203748591727184057428330386039766700161610534430469912754092586892162446358263283169799095729696407424696871657157280716343681857661748656695962441400433284766608408307217925949587261052855826382885300521822004968209647136722394587701720895365101311180886403748262958990917684186947245463537312582719347101291391169800490817330947249069884756058179616748856032431769837992142653355261794817345492723
cipher=5089249888618459947548074759524589606478578815336059949176718157024022678024841758856813241335191315643869492784030633661717346809979076682611760035885176766380484743187692409876479000444892361744552075578050587677106211969169204446554196613453202059517114911102484740265052582801216204900709316109336061861758409342194372241877343837978525533125320239702501424169171652846761028157198499078668564324989313965631396082388643288419557330802071756151476264735731881236024649655623821974147680672733406877428067299706347289297950375309050765330625591315867546015398294367460744885903257153104507066970239487158506328863

alpha2 = 727./2048
M1 = N^0.5
M1 = int(M1)
M2 = N^(1+alpha2)
M2 = int(M2)
D = diagonal_matrix(ZZ, [N, M1, M2, 1])
B = Matrix(ZZ, [ [1, -N,   0,  N**2],
                 [0, e1, -e1, -e1*N],
                 [0,  0,  e2, -e2*N],
                 [0,  0,   0, e1*e2] ]) * D

L = B.LLL()
v = Matrix(ZZ, L[0])
x = v * B**(-1)
phi = (x[0,1]/x[0,0]*e1).floor()

print(phi)

#De1CTF{4ef5e5b2-c169-47e2-b90e-9421c56f2f5e}


Homomorphic 

解题思路

由于这个系统,可以构造恶意的密文形成选择密文攻击,导致私钥泄露,于是可以构造c0=1,c1=delta,泄露密钥信息,但是每次交互只能得到一位信息,而私钥长度恰好为1024(交互次数的上限),于是交互1024次的到私钥,用私钥解密初始得到的flag密文(应该是预期解了吧?)

exp如下

from sage.stats.distributions.discrete_gaussian_integer import DiscreteGaussianDistributionIntegerSampler
import os, random, sys, string
from minipwn import *
from itertools import *
from hashlib import sha256
from Crypto.Util.number import bytes_to_long,long_to_bytes
import re
import string
add = "106.52.180.168"
add2 = "106.52.135.150"
#add = "127.0.0.1"
port = 8848

def login(io):
    rec = io.recvline().decode()
    s = string.ascii_letters + string.digits
    suffix = re.findall(r'\(XXXX\+(.*?)\)', rec)[0]
    digest = re.findall(r'== (.*?)\n', rec)[0]
    print(f"suffix: {suffix} \ndigest: {digest}")
    print('Calculating hash...')
    for i in product(s, repeat=4):
        prefix = ''.join(i)
        guess = prefix + suffix
        if sha256(guess.encode()).hexdigest() == digest:
            print(guess)
            break
    io.sendafter(b'Give me XXXX:', prefix.encode())
    return

def byte2str(m):
    res = ''
    for i in m:
        res += chr(i)
    return res

def toarray(f):
    res = []
    for i in f:
        tt = byte2str(i)[1:-1].split(',')
        tmp = [int(j) for j in tt]
        res.append(tmp)
    return res

def decrypt(io,ind):
    io.recvline()
    io.sendline("Decrypt")
    io.recvline()
    io.sendline("0")
    io.recvline()
    io.sendline('70368744177664')
    io.recvline()
    io.sendline(str(ind))
    io.recvline()
    res = io.recvline().strip()
    return int(res)

io = remote(add2,port)
login(io)
for i in range(5):
    io.recvline()

c1 = []
c2 = []
for i in range(44):
    print("{} time".format(i))
    res = io.recvline().strip()
    c1.append(res)
    res = io.recvline().strip()
    c2.append(res)
# 收集flag信息
C1 = toarray(c1)
C2 = toarray(c2)
# print(io.recvline())
pri = []
for i in range(2^10):
    print(i)
    res = decrypt(io,i)
    pri.append(res)
print(pri)


q = 2 ^ 54
t = 2 ^ 8
d = 2 ^ 10
delta = int(q / t)

PR.<x> = PolynomialRing(ZZ)
DG = DiscreteGaussianDistributionIntegerSampler(sigma=1)
fx = x ^ d + 1
Q.<X> = PR.quotient(fx)


def sample(r):
    return Q([randint(0, r) for _ in range(d)])


def genError():
    return Q([DG() for _ in range(d)])


def Round(a, r):
    A = a.list()
    for i in range(len(A)):
        A[i] = (A[i] % r) - r if (A[i] % r) > r / 2 else A[i] % r
    return Q(A)


def genKeys():
    s = sample(1)
    a = Round(sample(q - 1), q)
    e = Round(genError(), q)
    pk = [Round(-(a * s + e), q), a]
    return s, pk


def encrypt2(m):
    u = sample(1)
    e1 = genError()
    e2 = genError()
    c1 = Round(pk[0] * u + e1 + delta * m, q)
    c2 = Round(pk[1] * u + e2, q)
    return (c1.list(), c2.list())


def decrypt2(c):
    c0 = Q([i for i in c[0]])
    c1 = Q([i for i in c[1]])
    data = (t * Round(c0 + c1 * s, q)).list()
    for i in range(len(data)):
        data[i] = round(data[i] / q)
    data = Round(Q(data), t)
    return data

def recover(C1,C2):
    flag = []
    for i,j in zip(C1,C2):
        cur = (i,j)
        res = decrypt2(cur)
        flag.append(res)
    return flag
s = Q(pri)
flag =recover(C1,C2)
print("".join([chr(i) for i in flag]))

github链接

https://github.com/edwardz246003/danger-of-using-homomorphic-encryption

Reverse

parser

解题思路

程序将输入加上换行符后进行分组,分为"{}_+\n"及头"De1CTF"和被前面符号分隔的数字字母类共7类,接着进行分组检查并加密 。检查分组部分及加密中的有关条件要求有

flag格式:De1CTF{xxxx[_\+]xxxx[_\+]...xxxx}这样的格式。

加密部分的针对的是"{}"内的部分,用到了三种对称加密算法。被符号分隔的每组数字字母类字符R**加密,如果连接符为'_'号,则对连接的前后两部分合并后进行DES加密,如果连接符为'+'号则对连接的前后两部分合并后进行AES加密,优先级是先'_'号后'+'号。三种加密密钥均为De1CTF,后面两个加密需要填充,且分组模式为CBC模式,IV 与KEY相同。最终加密结果与常量比较。

所以直接慢慢地一层层地试三种加密,根据解密结果及padding格式确定加密算法选择是否正确。附上比较乱的乱试脚本:

# -*- coding:utf-8 -*-
from Crypto.Cipher import AR**,DES,AES


def padding(s,n):
  len1 = len(s)
  n1 = len1 % n
  s += chr(n-n1)*(n-n1)
  return s


def de_des_cbc(s,k):
  if len(s) % 8 != 0:
    s = padding(s,8)
  key = padding(k,8)
  iv = key
  out = ''
  for i in range(len(s)/8):
    ci = DES.new(key,DES.MODE_ECB)
    m1 = ci.decrypt(s[8*i:8*i+8])    
    out += xor_str(m1,iv)
    iv = s[8*i:8*i+8]
  return out  


def en_des_cbc(s,k):
  s = padding(s,8)
  key = padding(k,8)
  iv = key
  out = ''
  for i in range(len(s)/8):
    ci = DES.new(key,DES.MODE_ECB)
    m1 = xor_str(s[8*i:8*i+8],iv)
    iv = ci.encrypt(m1)    
    out += iv
  return out



def de_aes_cbc(s,k):
  if len(s) % 16 != 0:
    s = padding(s,16)
  key = padding(k,16)
  iv = key
  ci = AES.new(key,AES.MODE_CBC,iv)
  return ci.decrypt(s)

def en_aes_cbc(s,k):
  s = padding(s,16)
  key = padding(k,16)
  iv = key
  ci = AES.new(key,AES.MODE_CBC,iv)
  return ci.encrypt(s)


def de_rc4(s,k):
  ci = AR**.new(k)
  return ci.decrypt(s)

def xor_str(s1,s2):
  return ''.join(map(lambda i:chr(ord(s1[i])^ord(s2[i%len(s2)])),range(len(s1))))

def main():
  data = 'E7A4334CD311E78568569711EED2F8D93E70C94E94A0325A2798001DD5D7111DF48561AC0C802740BDDD1F0BB4971F605B54CBC5A8B71190C9B58165530F7E7F'.decode('hex')
  key = 'De1CTF'
  print de_aes_cbc(data,key).encode('hex')
  print de_aes_cbc('0b827a9e002e076de2d84cacb123bc1eb08ebec1a454e0f550c65d37c58c7daf2d4827342d3b13d9730f25c17689198b'.decode('hex'),key).encode('hex')
  print de_rc4('91983da9b13a31ef0472***2073b68ddbddb3cc17d'.decode('hex')[:5],key) #h3ll0
  print de_des_cbc('91983da9b13a31ef0472***2073b68ddbddb3cc17d'.decode('hex')[5:],key).encode('hex')
  print de_rc4('8e9b23a9e5959829f6f3'.decode('hex')[:5],key) #w0rld
  print de_rc4('8e9b23a9e5959829f6f3'.decode('hex')[5:],key) #l3x3r
  print de_des_cbc('2d4827342d3b13d9730f25c17689198b'.decode('hex'),key).encode('hex')
  print de_rc4('cdc535899f23f0b22e'.decode('hex')[:3],key) #4nd
  print de_rc4('cdc535899f23f0b22e'.decode('hex')[3:],key) #p4r53r
  print 
  print 'end.'


if __name__ == '__main__':
  main()


FLw

解题思路

这是一题VM题 。有些反调试和极少得可以忽略不计的混淆,去掉后的主函数是这样的:

  j_print_banner_41119A(this);
  print_4112BC(std::cout"Please input:");
  v8 = (void *)malloc_41146A(28);
  if ( v8 )
  {
    j_memset_4113A7(v8, 28);
    v7 = (void *)j_vm_init_413DE0(g_code_421048);
  }
  else
  {
    v7 = 0;
  }
  if ( j_vm_handler_415620(v5) )
    print_4112BC(std::cout"Well Done!\n");
  else
    print_4112BC(std::cout"Try again!\n");
  system("pause");
  canary_check_41135C(v3);
  if ( v7 )
    sub_4111F4(v7, 1);
  return canary_check_41135C(v6);

业务流程简单明晰,可做的只有解析VM了。

这个VM挺有个性,解析后也是挺难看的。直接说VM的计算过程吧,明文验证了"De1CTF{}"的格式,其它部分实际上就是一种base58编码,两个字节转成3字节58编码,再进行算术运算,具体看如下反解:

d = '7a194f6e0e56af1f98580e60bd428aa22097b03d87a0229579f941540c6d'.decode('hex')
  table = '0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/='
  out = ''
  for i in range(10):
    l = map(ord,d[3*i:3*i+3])
    l[0] ^= l[2]
    l[2] = (l[2]-l[1])&0xff
    l[1] = (l[1]+l[0])&0xff
    l = map(chr,l)
    n = table.index(l[0])*58**2 + table.index(l[1])*58 + table.index(l[2])
    out += '{:04X}'.format(n)

  print out.decode('hex')
  print out

最终结果为:De1CTF{Innocence_Eye&Daisy*}。


小精灵/little elves 

解题思路

此题有混淆,实际上并不怎么影响,无需去除,直接静态看即可。除了输入外,只有44段如下 代码:

seg000:00888065 8A 0C 3C                                mov     cl, [esp+edi]
seg000:00888068 8A 97 A9 80 88 00                       mov     dl, ds:byte_8880A9[edi]
seg000:0088806E 31 F6                                   xor     esi, esi
seg000:00888070
seg000:00888070                         loc_888070:                             ; CODE XREF: seg000:00888091↓j
seg000:00888070 F7 C2 01 00 00 00                       test    edx, 1
seg000:00888076 74 02                                   jz      short loc_88807A
seg000:00888078 31 CB                                   xor     ebx, ecx
seg000:0088807A
seg000:0088807A                         loc_88807A:                             ; CODE XREF: seg000:00888076↑j
seg000:0088807A F7 C1 80 00 00 00                       test    ecx, 80h
seg000:00888080 74 07                                   jz      short loc_888089
seg000:00888082 D0 E1                                   shl     cl, 1
seg000:00888084 80 F1 39                                xor     cl, 39h
seg000:00888087 EB 02                                   jmp     short loc_88808B
seg000:00888089                         ; ---------------------------------------------------------------------------
seg000:00888089
seg000:00888089                         loc_888089:                             ; CODE XREF: seg000:00888080↑j
seg000:00888089 D0 E1                                   shl     cl, 1
seg000:0088808B
seg000:0088808B                         loc_88808B:                             ; CODE XREF: seg000:00888087↑j
seg000:0088808B D0 EA                                   shr     dl, 1
seg000:0088808D 46                                      inc     esi
seg000:0088808E 83 FE 08                                cmp     esi, 8
seg000:00888091 75 DD                                   jnz     short loc_888070
seg000:00888093 47                                      inc     edi
seg000:00888094 83 FF 2C                                cmp     edi, 2Ch ; ','
seg000:00888097 75 CC                                   jnz     short loc_888065
seg000:00888099 81 FB C8 00 00 00                       cmp     ebx, 0C8h
seg000:0088809F 0F 95 C3                                setnz   bl
seg000:008880A2 09 D8                                   or      eax, ebx
seg000:008880A4 E8 2C 00 00 00                          call    loc_8880D5

校验算法用python表示 如下:

  for i in range(44):
    ch3 
0  
    for j in range(44):
      ch1 
= input[j]
      ch2 = t1[i][j]     
      for k in range(8):
        if ch2 & 1:
          ch3 ^
= ch1
        flag = ch1 & 0x80
        ch1 = (ch1 << 1)&0xff
        if flag:
          ch1 ^= 0x39
        ch2 >>= 1
#    print i
    assert(ch3 == t2[i])

sage反解如下:

 F.<x> = GF(2^8,modulus=[1,0,0,1,1,1,0,0,1])
mt =    [[16681161874879491438819427131587525119519218569608424124332112511401241619442082042837591477923257161284],
        [73, 252, 81, 126, 50, 87, 184, 130, 196, 114, 29, 107, 153, 91, 63, 217, 31, 191, 74, 176, 208, 252, 97, 253, 55, 231, 82, 169, 185, 236, 171, 86, 208, 154, 192, 109, 255, 62, 35, 140, 91, 49, 139, 255],
        [57, 18, 43, 102, 96, 26, 50, 187, 129, 161, 7, 55, 11, 29, 151, 219, 203, 139, 56, 12, 176, 160, 250, 237, 1, 238, 239, 211, 241, 254, 18, 13, 75, 47, 215, 168, 149, 154, 33, 222, 77, 138, 240, 42],
        [96, 198, 230, 11, 49, 62, 42, 10, 169, 77, 7, 164, 198, 241, 131, 157, 75, 147, 201, 103, 120, 133, 161, 14, 214, 157, 28, 220, 165, 232, 20, 132, 16, 79, 9, 1, 33, 194, 192, 55, 109, 166, 101, 110],
        [108, 159, 167, 183, 165, 180, 74, 194, 149, 63, 211, 153, 174, 97, 102, 123, 157, 142, 47, 30, 185, 209, 57, 108, 170, 161, 126, 248, 206, 238, 140, 105, 192, 231, 237, 36, 46, 185, 123, 161, 97, 192, 168, 129],
        [72, 18, 132, 37, 37, 42, 224, 99, 92, 159, 95, 27, 18, 172, 43, 251, 97, 44, 238, 106, 42, 86, 124, 1, 231, 63, 99, 147, 239, 180, 217, 195, 203, 106, 21, 4, 238, 229, 43, 232, 193, 31, 116, 213],
        [17, 133, 116, 7, 57, 79, 20, 19, 197, 146, 5, 40, 103, 56, 135, 185, 168, 73, 3, 113, 118, 102, 210, 99, 29, 12, 34, 249, 237, 132, 57, 71, 44, 41, 1, 65, 136, 112, 20, 142, 162, 232, 225, 15],
        [224, 192, 5, 102, 220, 42, 18, 221, 124, 173, 85, 87, 112, 175, 157, 72, 160, 207, 229, 35, 136, 157, 229, 10, 96, 186, 112, 156, 69, 195, 89, 86, 238, 167, 169, 154, 137, 47, 205, 238, 22, 49, 177, 83],
        [234, 233, 189, 191, 209, 106, 254, 220, 45, 12, 242, 132, 93, 12, 226, 51, 209, 114, 131, 4, 51, 119, 117, 247, 19, 219, 231, 136, 251, 143, 203, 145, 203, 212, 71, 210, 12, 255, 43, 189, 148, 233, 199, 224],
        [5, 62, 126, 209, 242, 136, 95, 189, 79, 203, 244, 196, 2, 251, 150, 35, 182, 115, 205, 78, 215, 183, 88, 246, 208, 211, 161, 35, 39, 198, 171, 152, 231, 57, 44, 91, 81, 58, 163, 230, 179, 149, 114, 105],
        [72, 169, 107, 116, 56, 205, 187, 117, 2, 157, 39, 28, 149, 94, 127, 255, 60, 45, 59, 254, 30, 144, 182, 156, 159, 26, 39, 44, 129, 34, 111, 174, 176, 230, 253, 24, 139, 178, 200, 87, 44, 71, 67, 67],
        [5, 98, 151, 83, 43, 8, 109, 58, 204, 250, 125, 152, 246, 203, 135, 195, 8, 164, 195, 69, 148, 14, 71, 94, 81, 37, 187, 64, 48, 50, 230, 165, 20, 167, 254, 153, 249, 73, 201, 40, 106, 3, 93, 178],
        [104, 212, 183, 194, 181, 196, 225, 130, 208, 159, 255, 32, 91, 59, 170, 44, 71, 34, 99, 157, 194, 182, 86, 167, 148, 206, 237, 196, 250, 113, 22, 244, 100, 185, 47, 250, 33, 253, 204, 44, 191, 50, 146, 181],
        [143, 5, 236, 210, 136, 80, 252, 104, 156, 100, 209, 109, 103, 134, 125, 138, 115, 215, 108, 155, 191, 160, 228, 183, 21, 157, 225, 61, 89, 198, 250, 57, 189, 89, 205, 152, 184, 86, 207, 72, 65, 20, 209, 155],
        [103, 51, 118, 167, 111, 152, 184, 97, 213, 190, 175, 93, 237, 141, 92, 30, 82, 136, 16, 212, 99, 21, 105, 166, 161, 214, 103, 21, 116, 161, 148, 132, 95, 54, 60, 161, 207, 183, 250, 45, 156, 81, 208, 15],
        [150, 65, 4, 37, 202, 4, 54, 106, 113, 55, 51, 181, 225, 120, 173, 61, 251, 42, 153, 149, 88, 160, 79, 197, 204, 20, 65, 79, 165, 85, 203, 193, 203, 97, 9, 142, 53, 50, 127, 193, 225, 11, 121, 148],
        [99, 27, 20, 52, 248, 197, 117, 210, 216, 249, 122, 48, 225, 117, 211, 2, 33, 172, 60, 140, 84, 44, 71, 187, 160, 198, 26, 100, 162, 92, 89, 181, 82, 55, 184, 152, 112, 51, 248, 255, 205, 145, 31, 137],
        [209, 78, 219, 94, 189, 146, 92, 172, 214, 106, 122, 121, 90, 60, 174, 6, 82, 28, 166, 206, 248, 86, 28, 113, 159, 183, 196, 12, 183, 146, 225, 107, 169, 128, 67, 221, 228, 244, 212, 66, 118, 136, 162, 218],
        [163, 143, 112, 123, 98, 87, 0, 143, 198, 176, 196, 246, 231, 201, 157, 169, 244, 123, 106, 210, 50, 159, 47, 55, 28, 203, 235, 91, 74, 16, 175, 125, 53, 54, 82, 2, 112, 159, 122, 251, 118, 138, 120, 184],
        [187, 81, 128, 55, 221, 223, 44, 37, 166, 168, 32, 169, 22, 255, 169, 251, 101, 158, 161, 153, 89, 1, 244, 87, 246, 237, 157, 232, 180, 3, 248, 23, 58, 162, 144, 159, 173, 28, 117, 196, 186, 225, 81, 83],
        [169, 45, 229, 173, 17, 248, 83, 201, 242, 38, 116, 201, 12, 87, 3, 231, 200, 143, 166, 63, 146, 86, 240, 197, 26, 198, 21, 34, 202, 192, 26, 188, 203, 3, 13, 238, 109, 179, 214, 146, 193, 255, 226, 189],
        [16, 63, 38, 178, 184, 25, 51, 81, 142, 189, 2, 37, 163, 244, 157, 193, 149, 21, 6, 215, 185, 13, 205, 56, 158, 45, 48, 243, 98, 248, 129, 223, 68, 111, 88, 62, 119, 28, 255, 243, 132, 238, 149, 75],
        [185, 141, 49, 173, 86, 9, 150, 99, 183, 114, 226, 133, 170, 2, 65, 124, 2, 164, 2, 155, 153, 89, 109, 220, 138, 127, 150, 213, 114, 6, 151, 227, 248, 172, 28, 0, 92, 63, 41, 229, 214, 120, 49, 164],
        [242, 48, 147, 252, 204, 89, 111, 168, 251, 136, 160, 106, 5, 155, 137, 198, 250, 250, 57, 180, 252, 118, 165, 21, 254, 155, 154, 247, 242, 217, 131, 65, 35, 207, 112, 77, 209, 176, 122, 192, 147, 107, 80, 37],
        [52, 183, 251, 29, 226, 175, 39, 75, 34, 254, 233, 96, 155, 144, 9, 254, 189, 41, 169, 184, 91, 97, 87, 88, 251, 138, 114, 118, 91, 156, 198, 75, 222, 19, 183, 52, 81, 194, 144, 13, 249, 111, 3, 73],
        [21, 107, 222, 106, 222, 98, 190, 4, 244, 225, 112, 133, 120, 253, 141, 48, 52, 154, 63, 235, 190, 78, 33, 209, 4, 172, 158, 187, 219, 151, 17, 233, 214, 32, 120, 38, 26, 0, 250, 129, 251, 40, 89, 39],
        [25, 66, 117, 107, 200, 80, 88, 90, 24, 176, 247, 95, 59, 121, 118, 67, 56, 133, 145, 167, 24, 46, 180, 145, 128, 220, 200, 29, 172, 157, 100, 9, 97, 253, 8, 200, 52, 229, 147, 218, 254, 255, 182, 170],
        [172, 79, 214, 26, 85, 230, 228, 223, 32, 227, 84, 74, 109, 209, 222, 45, 48, 66, 23, 197, 52, 212, 179, 184, 90, 149, 199, 128, 153, 70, 3, 73, 160, 39, 49, 165, 88, 252, 135, 9, 157, 140, 32, 33],
        [72, 233, 196, 173, 35, 166, 146, 186, 61, 86, 64, 42, 25, 86, 66, 93, 12, 255, 63, 83, 95, 219, 108, 152, 205, 31, 238, 77, 74, 156, 149, 228, 68, 244, 178, 78, 181, 173, 251, 248, 185, 99, 181, 205],
        [106, 86, 224, 51, 91, 194, 158, 83, 144, 77, 217, 95, 125, 119, 144, 47, 85, 220, 24, 40, 59, 77, 70, 190, 188, 20, 105, 150, 79, 85, 194, 168, 64, 215, 234, 226, 4, 99, 157, 0, 186, 74, 18, 94],
        [36, 23, 51, 78, 191, 254, 1, 166, 174, 62, 222, 243, 131, 207, 37, 4, 199, 35, 169, 7, 216, 42, 190, 241, 120, 11, 166, 129, 117, 93, 184, 50, 237, 84, 122, 67, 250, 248, 60, 96, 117, 91, 187, 79],
        [248, 17, 173, 127, 98, 184, 11, 20, 50, 140, 249, 248, 24, 222, 34, 86, 71, 0, 237, 138, 148, 107, 115, 104, 62, 191, 39, 221, 123, 115, 131, 229, 127, 56, 64, 177, 106, 239, 26, 255, 100, 88, 1, 75],
        [144, 18, 85, 103, 3, 31, 157, 44, 67, 24, 228, 226, 82, 208, 69, 17, 189, 216, 205, 140, 6, 1, 33, 11, 61, 223, 12, 116, 123, 167, 151, 58, 167, 79, 96, 189, 151, 233, 92, 94, 22, 60, 254, 254],
        [216, 167, 82, 244, 143, 231, 192, 63, 79, 49, 131, 176, 212, 46, 141, 107, 125, 207, 201, 5, 103, 155, 107, 166, 210, 49, 182, 60, 34, 26, 220, 198, 225, 160, 57, 52, 138, 27, 247, 181, 0, 67, 1, 205],
        [19, 243, 215, 203, 156, 157, 71, 187, 142, 198, 244, 52, 100, 195, 129, 134, 38, 227, 155, 241, 122, 192, 145, 179, 195, 16, 180, 70, 86, 219, 250, 67, 127, 47, 178, 249, 19, 36, 183, 50, 154, 186, 239, 15],
        [163, 224, 95, 10, 171, 106, 49, 57, 28, 178, 119, 6, 40, 228, 92, 163, 93, 225, 23, 37, 24, 211, 72, 105, 209, 70, 0, 165, 70, 226, 43, 187, 167, 60, 143, 233, 207, 209, 12, 207, 64, 246, 222, 16],
        [245, 140, 237, 250, 89, 99, 215, 112, 85, 182, 51, 26, 62, 220, 116, 17, 196, 247, 172, 121, 22, 106, 91, 200, 115, 240, 31, 78, 47, 126, 50, 114, 109, 88, 83, 120, 17, 95, 198, 206, 71, 112, 172, 49],
        [254, 198, 189, 175, 121, 123, 248, 38, 163, 170, 91, 171, 125, 66, 94, 37, 181, 207, 13, 60, 210, 178, 252, 39, 175, 18, 106, 94, 171, 196, 182, 129, 101, 165, 103, 164, 234, 110, 146, 69, 36, 75, 58, 98],
        [184, 162, 160, 24, 71, 214, 24, 14, 196, 222, 67, 178, 163, 150, 206, 104, 38, 176, 245, 98, 180, 213, 93, 134, 25, 198, 166, 10, 183, 99, 207, 127, 163, 10, 141, 105, 52, 68, 18, 121, 217, 209, 124, 127],
        [142, 153, 245, 130, 182, 55, 211, 250, 217, 10, 172, 119, 212, 171, 244, 99, 99, 41, 223, 221, 128, 66, 31, 129, 195, 145, 241, 50, 77, 139, 29, 232, 60, 167, 110, 139, 124, 135, 18, 197, 200, 85, 15, 159],
        [225, 159, 86, 55, 158, 137, 229, 250, 129, 194, 200, 31, 147, 30, 219, 233, 147, 28, 6, 219, 81, 172, 132, 162, 212, 115, 232, 60, 152, 105, 146, 77, 187, 9, 20, 191, 157, 96, 131, 190, 125, 175, 141, 4],
        [110, 75, 232, 58, 102, 13, 222, 137, 137, 14, 191, 155, 48, 100, 169, 184, 49, 249, 49, 39, 138, 124, 63, 73, 237, 150, 244, 126, 127, 206, 91, 252, 110, 45, 189, 116, 188, 42, 18, 68, 194, 244, 53, 2],
        [109, 116, 87, 241, 128, 121, 227, 188, 2, 6, 81, 194, 4, 225, 176, 48, 8, 59, 243, 50, 234, 228, 192, 176, 168, 187, 248, 244, 27, 188, 107, 204, 222, 202, 73, 141, 160, 139, 151, 206, 1, 227, 152, 81],
        [13, 149, 85, 158, 164, 119, 149, 36, 138, 84, 173, 132, 39, 230, 96, 229, 84, 218, 14, 153, 184, 98, 160, 129, 2, 161, 99, 41, 17, 114, 55, 67, 192, 102, 241, 168, 149, 191, 216, 18, 229, 153, 94, 171]]
t = [200201204116124941291272118561154505127281913412170100219113293252152873217122815643982032246321518620112810352]
for i in range(44):
    for j in range(44):
        mt[i][j] 
= F(mt[i][j].bits())
for i in range(44):
    t[i] 
= F(t[i].bits())
MT = matrix(F, mt)
TT = matrix(F, t).T
#print(T)
inp = MT.inverse() * TT
inp = inp.T[0].list()
x = [i.integer_representation() for i in inp]
print (x)
flag=""
for i in x:
    flag+=chr(i)
print(flag)

最终结果为:De1CTF{01ab211f-589b-40b7-9ee4-4243f541fc40}。



mc_ticktock

解题思路

加了UPX的golang程序。启动了80端口的web server和8080端口的proxy server。一开始比较蒙,不知道此题意图。

细看后,注意到在0x691B24注册了"/ticktock"路由,其handler函数为main_muxRegister_func2。此函数加密了GET请求中的text参数内容,并返回结果的base64编码内容。在此函数最后还有加密结果与常量的校验,正确则调用runtime.newproc,于是想试试这个部分是不是可以解出flag。

使用的加密算法为feistel结构的分组对称加密,CFB模式,KEY和IV为常量的sha256的hash值,其实这些都不重要,重要的是crypto_cipher_newCFB参数中有控制加解密模式的参数。将0x693743处的

mov     byte ptr [rsp+90h+var_68], 0
patch为
mov     byte ptr [rsp+90h+var_68], 1

正常运行程序,在浏览器中请求如下:

ticktock?text=%A4%A3%04%B9%1E%F1%96%C6%0A%26%4D%E9%AF%FD%B1%FF%06%EE%E5%CF%6B%2E%0C%02%17%6A%97%B7%95%AC%B8%11%1A%8F%13%83%E5%AF%67%C9%6A%26%99%2B%1C%AD%3F%41%DF%AA%36%36%08%A2%04%9D

得到返回

TickTock: SGVyZSBpcyBhIEZMQUc6IERlMUNURnt0MUNrLXQwY2tfVGxjay0xb2NLX01DMk8yMF86KVNNNH0=

解base64,得到Here is a FLAG: De1CTF{t1Ck-t0ck_Tlck-1ocK_MC2O20_:)SM4}。

原来是SM4算法。


本文作者:ChaMd5安全团队

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/133089.html

Tags:
评论  (0)
快来写下你的想法吧!

ChaMd5安全团队

文章数:85 积分: 181

www.chamd5.org 专注解密MD5、Mysql5、SHA1等

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号