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
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}
解题思路
感觉利用点在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
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()
解题思路
这是一题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*}。
解题思路
此题有混淆,实际上并不怎么影响,无需去除,直接静态看即可。除了输入外,只有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 = [[166, 8, 116, 187, 48, 79, 49, 143, 88, 194, 27, 131, 58, 75, 251, 195, 192, 185, 69, 60, 84, 24, 124, 33, 211, 251, 140, 124, 161, 9, 44, 208, 20, 42, 8, 37, 59, 147, 79, 232, 57, 16, 12, 84],
[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 = [200, 201, 204, 116, 124, 94, 129, 127, 211, 85, 61, 154, 50, 51, 27, 28, 19, 134, 121, 70, 100, 219, 1, 132, 93, 252, 152, 87, 32, 171, 228, 156, 43, 98, 203, 2, 24, 63, 215, 186, 201, 128, 103, 52]
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