2022第五届"强网"拟态

2022QW拟态

题目大多是调试+汇编,考点涉及ollvm、go、veh、call、vm。

"夫唯不争,故天下莫能与之争。"忙里偷闲摸的比赛,索性成绩还不错,就是最后平台那边出了点意外。专业课要临近结课了,任务还是比较多的,准备🔥🔥🔥起来,好好冲刺一下课内成绩。

Crypto

WeakRandom

一元随机数生成,输出的随机数会泄露16bit的x的信息,并且高16bit也与x有关,因为限制时限比较长,借助高16bit直接爆破即可。

1
2
3
4
5
6
7
def next(self):
x = int((self.x ** 2) // (10 ** (self.s // 2))) % self.n
self.x = x
high = (int(hashlib.sha256(str(x).encode()).hexdigest(),16) >> 16) & (2 ** 16 - 1)
low = x & (2 ** 16 - 1)
result = high << 16 | low
return result

可见输出随机数中的低16bit即x中的低16bit,而其高16bit是对x进行hash等运算,那么直接爆破高16bit,做同样的hash运算再与随机数中的高16bit进行比对即可恢复x,之后就可以正常预测。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from pwn import *
from time import time
from hashlib import sha256
from mycrypto.retool import pfw
guess=0
myx=0
def getx(xx:int):
global guess,myx
low=xx&0xffff
for i in range(0xffff):
tt=i<<16|low
ans=(int(hashlib.sha256(str(tt).encode()).hexdigest(), 16) >> 16) & (2 ** 16 - 1)
if ans==xx>>16:
guess=1
myx=tt
print('get get x')
return
def get_num():
global myx
x = int((myx ** 2) // (10 ** 2)) % 10000000000
myx = x
high = (int(sha256(str(myx).encode()).hexdigest(), 16) >> 16) & (2 ** 16 - 1)
low = x & (2 ** 16 - 1)
result = high << 16 | low
return result

r=remote('172.51.60.200',9998)
p=r.recvline().strip()
p=p.split(b' == ')
m=p[0][12:-1].decode()
t=p[1].decode()
ans=pfw(m,4,t).encode()
r.recvuntil(b'Give me XXXX:')
r.sendline(ans)
r.recvuntil(b'predict game!')
cnt=0
for i in range(100):
r.recvuntil(b'Please your guess :')
if guess==0:
r.sendline(b'0')
else:
r.sendline(str(get_num()).encode())
p=r.recvline().strip()
if b'Success!' not in p:
num=int(p.split(b'is ')[-1])
if guess==0:
getx(num)
else:
print('=.=')
else:
cnt+=1
print(cnt)
r.interactive()
r.close()
# 限制的时间太长了,直接爆破2字节即可恢复状态

Misc

babymisc

经典二分,银行卡密6位数,在lost前能猜13/14次也就2^13内的数据可以找,直接转为概率问题,多次交互限定在小范围内二分即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from pwn import *
e=0

while e==0:
min = 480000
num = 0
max = min+2**12
r = remote('172.51.60.153', 9999)
r.recvuntil(b'>')
r.sendline(b'Y')
while 1:
r.recvuntil(b'Please enter a number:')
r.sendline(str(num).encode())
p=r.recvline().strip()
if b'low' in p:
min=num
num=(max+num)//2
print(p)
print("min:%d max:%d num:%d"%(min,max,num))

elif b'up' in p:
print(p)
max=num
num=(min+num)//2
print("min:%d max:%d num:%d"%(min, max, num))
else :
print(p)
if b'You lost' in p:
r.close()
break
else:
print(r.recvline())
print(r.recvline())
print(r.recvline())
e=1
print('********************************************************')
break
if e==1:
r.interactive()
break

"""
b'Bingo'
b'Time use:1.13second\n'
b"To thank you, I'll give you the flag\n"
b'flag{NTbkIYgC4ZxeAZJohoeP0Xi2ubrgQUKH}\n'
"""

image-20221106175215920

Re

comeongo

go语言逆向,将username和passwd切片组合进行加密,在mian_check1、main_check2中进行check,设计加密base58、base64、移位和方程组。

要求输入的username和passwd均为16字节,main_check1是正常的base58加密

image-20221106162733131

cyberchef解出GoM0bi13G3tItEzF,通过切片的逻辑得知该部分为username和passwd的前8个字节。

image-20221106163659228

maincheck2将username和passwd的后8个字节再分成4字节一组,每次加密一组(4字节name、4字节passwd),第一段最后会有base64加密,对X051YmNmRnE=解密后得_NubcfFq,在base64前还有一部分移位加密。测试输入为bxs时会输出nlg满足12移位。

1
2
3
4
5
6
7
8
9
k=b'nlg'
s=b'bxs'
for i in range(3):
if s[i]>96 and s[i]<123:
if s[i]-97+12<26:
print(chr(((s[i]-97+12)%26)+97),end='')
else:
print(chr(((s[i] - 97 -12 +26) % 26) + 97),end='')
print()

所以对_NubcfFq进行移位解密得到_BinorRe,之后使用main_encryptBytes函数加密最后一组。

image-20221106165122015

把两部分的值逐字节相加起来,并且会把密码那部分的前两个字节改为vG,这样能保证前两个字节是可以确定的。之后在main_runtime_other中会限制后两个字节的差值分别为0x3f和0x1f,解方程即可恢复。

image-20221106165831028

go的反编译这块还是有所欠缺,关键是紧跟输入的变化来求解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from hashlib import md5
n='GoM0bi13ABabef12'
s='G3tItEzF_bxs2345'

k=b'nlg'
s=b'bxs'
for i in range(3):
if s[i]>96 and s[i]<123:
if s[i]-97+12<26:
print(chr(((s[i]-97+12)%26)+97),end='')
else:
print(chr(((s[i] - 97 -12 +26) % 26) + 97),end='')
print()
s=b'ubcf'
for i in range(len(s)):
if s[i]>96 and s[i]<123:
if s[i]-97>=12:
print(chr(((s[i]-97-12)%26)+97),end='')
else:
print(chr(((s[i] - 97 +12 +26) % 26) + 97),end='')
print()
C='_NubcfFq'
# _BinorRe

n='GoM0bi13_BingGo@'
s='G3tItEzForRevG0!'

a=b'gG@!'
b=b'vG_@'
cc=[0xDD, 0x8F, 0xA1, 0x64]

print(chr((0xa1+0x3f-2)//2))
print(chr((0xa1+0x3f-2)//2-0x3f))
print(chr((0x64+0x1f-3)//2))
print(chr((0x64+0x1f-3)//2 - 0x1f))
n='GoM0bi13_BingGo@'
s='G3tItEzForRevG0!'
print(md5(('flag{'+n+s+'}').encode()).hexdigest())

mcmc

主要是控制流平坦化和虚假控制流混淆,用D810插件可以还原大部分逻辑,并且部分加密的基本块都比较大且明显,直接看汇编还原逻辑即可。

加密的主要逻辑如下

image-20221105212557046

输入32字节,异或了部分,并每次4个dword类型进行线性运算,sub_405480函数反混淆不是太好,但是其加密的基本块很大,直接调试跟汇编即可还原逻辑。

image-20221105212933137

还原的加密算法如下,对4块进行线性运算。

1
2
3
4
5
6
7
8
9
def encry(s:list):
c=[0]*4
c[0]=2*s[0]+s[1]-s[2]+s[3]
c[1]=s[0]+s[1]+s[2]-s[3]
c[2]=s[0]-s[1]+s[2]-s[3]
c[3]=s[0]+2*s[1]-s[2]+2*s[3]
for i in range(4):
c[i]&=0xffffffff
return c

之后的 sub_4011A0函数是salsa20加密的秘钥初始化,根据findcrypt识别出的expand 32-byte k可判断,而秘钥和随机数都是在init_array系列函数中获取的,因位salsa20为流密码,所以主要定位到加密的异或,在sub_401820函数。

image-20221105213538149

v7仅与流秘钥相关,之后根据i的奇偶情况生成不同的v4,之后是将明文与v4+v7进行异或,v7可以通过调试获取,比对的密文可以查看.data段的数据,发现有32字节的数组,并且对其交叉引用出现在了与s比对的代码附近,并且在salsa20加密之后密文s没有再变化。

image-20221105214203909

解密脚本和测试数据如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def encry(s:list):
c=[0]*4 #硬看汇编
c[0]=2*s[0]+s[1]-s[2]+s[3]
c[1]=s[0]+s[1]+s[2]-s[3]
c[2]=s[0]-s[1]+s[2]-s[3]
c[3]=s[0]+2*s[1]-s[2]+2*s[3]
for i in range(4):
c[i]&=0xffffffff
return c

cc=encry([0x61616161,0x3A616161,0x61616161,0x3B616161])

#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
t1=[0x23, 0x24, 0x24, 0xC9, 0xC2, 0xC2, 0xC2, 0xA5, 0x00, 0x00, 0x00, 0x5B, 0x84, 0x85, 0x85, 0xCF, 0x23, 0x24, 0x24, 0xD7, 0xC2, 0xC2, 0xC2, 0xC1, 0x00, 0x00, 0x00, 0x4D, 0x84, 0x85, 0x85, 0xEB]
c1=[0xD4, 0xCB, 0xB1, 0xE7, 0x73, 0xEE, 0x70, 0x93, 0xA0, 0x7B, 0x3D, 0x1F, 0x04, 0x96, 0x03, 0xDE, 0xCC, 0x1B, 0x35, 0x68, 0x45, 0x51, 0x3D, 0xE8, 0x0C, 0xFC, 0xEF, 0x7A, 0x9D, 0x88, 0x97, 0x59]

kstr=[ t1[i]^c1[i] for i in range(32)]
for i in range(32):
if i&1:
kstr[i]-=c1[(i-1+32)%32]
else:
kstr[i]-=t1[(i+1)%32]
kstr=[(i+256)%256 for i in kstr]

#bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
t2=[0x26, 0x27, 0x27, 0xCA, 0xC4, 0xC4, 0xC4, 0xA9, 0x00, 0x00, 0x00, 0x5D, 0x88, 0x89, 0x89, 0xCF, 0x26, 0x27, 0x27, 0xD4, 0xC4, 0xC4, 0xC4, 0xC5, 0x00, 0x00, 0x00, 0x53, 0x88, 0x89, 0x89, 0xE3]
c2=[0xDC, 0xD0, 0xB1, 0xE4, 0x77, 0xF4, 0x72, 0x91, 0xA0, 0x7B, 0x3F, 0x1B, 0x0C, 0x92, 0x0F, 0xD2, 0xD4, 0x60, 0x29, 0x67, 0x4D, 0x5F, 0xC7, 0x76, 0x0C, 0xFC, 0xF5, 0x6E, 0x95, 0x8C, 0x83, 0x7D]
kstr1=[ t2[i]^c2[i] for i in range(32)]
for i in range(32):
if i&1:
kstr1[i]-=c2[(i-1+32)%32]
else:
kstr1[i]-=t2[(i+1)%32]
kstr1=[(i+256)%256 for i in kstr1]

assert kstr==kstr1
v7=kstr1

def hexdump(s:list):
for i in s:
print(hex(i)[2:].zfill(2),end=' ')
print()
enc=[0x06, 0x08, 0x65, 0x04, 0x60, 0x03, 0x08, 0x01, 0x4A, 0x10, 0x32, 0x58, 0xEE, 0x97, 0x65, 0x84, 0x44, 0xF2, 0x10, 0x6B, 0xE8, 0x50, 0x24, 0x99, 0xF6, 0xE3, 0x21, 0x51, 0xC2, 0x5D, 0xBF, 0x32]

c=[]
from z3 import *
a2=[BitVec('a2%d'%i,8) for i in range(32)]
sol=Solver()
for i in range(32):
if i&1:
v4=c[i-1]
else:
v4=a2[i+1]
c.append((a2[i]^(v4+v7[i]))&0xff)
sol.append(c[i]==enc[i])
print(sol.check())
m=sol.model()
encry_c=[m[a2[i]].as_long() for i in range(32)]
print(encry_c)
hexdump(encry_c)
# assert encry_c==t2

print('sol salsal20 success!')
tc=[]
for i in range(0,32,4):
tmp=0
for j in range(4):
tmp|=(encry_c[i+j]<<(8*j))
tc.append(tmp)

from claripy import *
fm=[BVS('fm%d'%i,32) for i in range(4)]
sol0=Solver()
fc1=encry(fm)
for i in range(4):
sol0.add(fc1[i]==tc[i+4]) #分两组解即可
print(sol0.check_satisfiability())
for i in range(4):
print(int.to_bytes(sol0.eval(fm[i],4)[0],4,'little').decode(),end='')
print()
#3ummer170ver_C0Gingcn0t(T0p0hhh2
# m0=sol0.model()
# print(int.to_bytes(m0[fm[0]].as_long(),4,'little'))
s=list(b'3ummer170ver_C0Gingcn0t(T0p0hhh2')
s[7] ^= 0x44
s[15] ^= 0x23
s[23] ^= 0x5B
s[31] ^= 0x5A
print(bytes(s))

windows_call

题目隐藏了大部分的windows函数,并且数据通过偏移来寻址,结合调试和算法特征还原程序逻辑。

首先是check输入格式为flag{},并且限制内容长度为40字节的16进制数据。

image-20221106170559796

期间会将输入内容小写转大写,并保存转化前后的字符。调试中可知c函数中包含md5的模数,故该部分线对转换前和转换后的输入进行md5校检,要求相同即输入的内容为大写,之后会将输入2个一组转为字节数据,存在0x400偏移处。

image-20221106170752644

转换后的输入20字节,取出前4个字节,分为2个word数据x和y来生成后续加密所使用的key和iv。

image-20221106171110451

因为在密文的比对处有对x和y值的约束,可以通过该约束爆破x和y共4个字节。

image-20221106171207819

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def get_key(x,y):
c=x^y
d=c&0xff
h=c>>8
sum=0
out=[]
out0=[]
for i in range(16):
out.append((h+i)^(d+i))
for i in range(16):
out0.append(out[i]^((i-64+0x100)%0x100))
sum+=out0[i]
#print(hex(sum))
return sum,out0,out

get_key(0x2301,0xbc4a)

for x in range(0xff):
v7=x<<8 | 0xa0
for y in range(0xffff):
if (v7-y)&0xffff==0x2B8 and (v7+0x3500)&0xffff <=0x800 and (y+0x3800)&0xffff<=0x800:
if get_key(v7,y)[0]==0x8A8:

print(hex(v7),hex(y))
#0xcca0 0xc9e8
#0xcea0 0xcbe8
#满足条件的为 x=0xcca0 y=0xc9e8,故前8个字符为E8C9A0CC

image-20221106171506809

首先经过秘钥扩展,0x80(128),之后传入key和iv到sub_402613进行加密。

image-20221106171621293

可见先异或iv,再ECB即典型的CBC模式。在尝试使用finger恢复符号时,其识别出了Camellia算法让人误解,观察后续算法和特征并没有找到其特征运算,=.=被坑了好久,以为是魔改。之后在调试秘钥扩展(sub_40234A)详细步骤时发现了AES的特征Sbox,在v4的280偏移处。

image-20221106172014100

使用AES解密密文,check成功。干扰finger的识别技术比较帅,杀伤力蛮大的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def get_key(x,y):
c=x^y
d=c&0xff
h=c>>8
sum=0
out=[]
out0=[]
for i in range(16):
out.append((h+i)^(d+i))
for i in range(16):
out0.append(out[i]^((i-64+0x100)%0x100))
sum+=out0[i]
return sum,out0,out


# for x in range(0xff):
# v7=x<<8 | 0xa0
# for y in range(0xffff):
# if (v7-y)&0xffff==0x2B8 and (v7+0x3500)&0xffff <=0x800 and (y+0x3800)&0xffff<=0x800:
# if get_key(v7,y)[0]==0x8A8:
#
# print(hex(v7),hex(y))
#0xcca0 0xc9e8
#0xcea0 0xcbe8
#前8个字节正确后即可调试提取iv和k
k=[0x8D, 0x8E, 0x8F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x95, 0x96, 0x97, 0x88, 0x89, 0x8A, 0x8B, 0x8C]
iv=[0x4D, 0x4F, 0x4D, 0x43, 0x45, 0x47, 0x45, 0x43, 0x5D, 0x5F, 0x5D, 0x43, 0x45, 0x47, 0x45, 0x43]
assert len(iv)==len(k)

enc=[0xF3A03784, 0xFC3436EC,0x6F38A294,0x7C7E343F]
mc=[]
for i in enc:
mc.append(int.to_bytes(i,4,'little'))

s='flag{E8C9A0CC8437A0F3EC3634FC94A2386F3F347E7C}'

from Crypto.Cipher import AES
aes=AES.new(bytes(k),AES.MODE_CBC,bytes(iv))
print(aes.decrypt(b''.join(mc)).hex().upper())
flag='flag{E8C9A0CC8B9854CDD0AC321B790FC74EFA520FBC}'

babyre

tls中触发异,借助veh修改AES的sbox,程序存在反调试不过不影响正常执行,把修改后的sbox在加密前patch能达到同一个效果。

tls回调函数,完成注册veh->反调试->触发/0异常->修改sbox。

image-20221106173214891

修改sbox的操作与程序输入获反调试步骤无关,直接在handle函数下断点,改跳转绕过反调试让程序触发异常断下即可get sbox。

image-20221106173709006

运行时通过idapython进行patch即可模拟触发异常的情况。

1
2
3
4
5
6
7
import idautils
sbox=[0x00000077, 0x00000068, 0x00000063, 0x0000006F, 0x000000E6, 0x0000007F, 0x0000007B, 0x000000D1, ...]

adr=0xCD4000
for i in range(256):
patch_dword(adr+4*i,sbox[i])
print('ok')

因为秘钥扩展中出现了密文的踪迹,但是初始的key是写死在秘钥中的,所以可以直接调试获取轮秘钥以避免出错。

image-20221106174010265

并且分成两组进行加密,前一组的密文会用于第二组的初始化。

对于AES的加密部分就有一点阴间了,结构很经典但是其在矩阵的排布上与以往不同,该程序中为连续4个字节为一行而并非一列,并且轮秘钥异或时的下标索引也进行了变动。

image-20221106174111858

大部分脚本都用列来写的,手上没有好用的板子来改,直接现场手撸AES,顺便复习密码学; ), 跟一轮与调试加密相同即可get flag(累啊。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def hexdump(s):
for i in range(len(s)):
print(hex(s[i])[2:].zfill(2),end=' ')
print()
def get_invs(sb:list):
out=[0]*256
for i in range(256):
out[sb[i]]=i
return out
sbox=[0x00000077, 0x00000068, 0x00000063, 0x0000006F, 0x000000E6, 0x0000007F, 0x0000007B, 0x000000D1, 0x00000024, 0x00000015, 0x00000073, 0x0000003F, 0x000000EA, 0x000000C3, 0x000000BF, 0x00000062, 0x000000DE, 0x00000096, 0x000000DD, 0x00000069, 0x000000EE, 0x0000004D, 0x00000053, 0x000000E4, 0x000000B9, 0x000000C0, 0x000000B6, 0x000000BB, 0x00000088, 0x000000B0, 0x00000066, 0x000000D4, 0x000000A3, 0x000000E9, 0x00000087, 0x00000032, 0x00000022, 0x0000002B, 0x000000E3, 0x000000D8, 0x00000020, 0x000000B1, 0x000000F1, 0x000000E5, 0x00000065, 0x000000CC, 0x00000025, 0x00000001, 0x00000010, 0x000000D3, 0x00000037, 0x000000D7, 0x0000000C, 0x00000082, 0x00000011, 0x0000008E, 0x00000013, 0x00000006, 0x00000094, 0x000000F6, 0x000000FF, 0x00000033, 0x000000A6, 0x00000061, 0x0000001D, 0x00000097, 0x00000038, 0x0000000E, 0x0000000F, 0x0000007A, 0x0000004E, 0x000000B4, 0x00000046, 0x0000002F, 0x000000C2, 0x000000A7, 0x0000003D, 0x000000F7, 0x0000003B, 0x00000090, 0x00000047, 0x000000C5, 0x00000014, 0x000000F9, 0x00000034, 0x000000E8, 0x000000A5, 0x0000004F, 0x0000007E, 0x000000DF, 0x000000AA, 0x0000002D, 0x0000005E, 0x00000058, 0x0000004C, 0x000000DB, 0x000000C4, 0x000000FB, 0x000000BE, 0x000000EF, 0x00000057, 0x00000059, 0x00000027, 0x00000091, 0x00000051, 0x000000ED, 0x00000016, 0x0000006B, 0x00000044, 0x00000028, 0x0000008B, 0x000000BC, 0x00000045, 0x000000B7, 0x00000054, 0x0000009B, 0x00000086, 0x00000089, 0x0000002C, 0x000000E1, 0x000000A8, 0x000000A2, 0x000000CE, 0x00000035, 0x00000004, 0x000000EB, 0x000000E7, 0x000000C6, 0x000000D9, 0x00000018, 0x00000007, 0x000000F8, 0x0000004B, 0x00000083, 0x00000050, 0x00000003, 0x000000D0, 0x000000B3, 0x0000006A, 0x00000029, 0x00000070, 0x00000049, 0x0000000D, 0x00000067, 0x00000074, 0x00000095, 0x0000005B, 0x000000C8, 0x00000036, 0x0000003E, 0x00000084, 0x0000009C, 0x00000052, 0x000000FA, 0x000000AC, 0x00000000, 0x000000CA, 0x0000004A, 0x0000001F, 0x000000CF, 0x000000F4, 0x00000026, 0x0000002E, 0x0000001E, 0x0000005D, 0x00000012, 0x00000030, 0x00000048, 0x000000D6, 0x000000C7, 0x000000B8, 0x00000076, 0x00000085, 0x00000081, 0x000000F0, 0x0000006D, 0x000000F3, 0x000000DC, 0x00000023, 0x00000079, 0x00000099, 0x000000C1, 0x0000005A, 0x000000BD, 0x00000078, 0x00000042, 0x000000E0, 0x000000FE, 0x00000071, 0x0000006E, 0x000000BA, 0x0000001C, 0x000000AE, 0x0000006C, 0x00000031, 0x0000003A, 0x00000008, 0x000000B2, 0x000000A0, 0x000000D2, 0x000000FC, 0x000000C9, 0x00000060, 0x0000000B, 0x0000005F, 0x000000A9, 0x0000009F, 0x0000009E, 0x00000064, 0x0000002A, 0x000000A1, 0x00000072, 0x0000005C, 0x00000017, 0x000000E2, 0x0000001A, 0x00000075, 0x00000021, 0x00000043, 0x000000AD, 0x00000092, 0x000000D5, 0x00000009, 0x0000008A, 0x000000F5, 0x000000EC, 0x0000008C, 0x00000005, 0x0000007D, 0x000000CD, 0x0000009A, 0x00000080, 0x0000008F, 0x0000000A, 0x00000093, 0x000000FD, 0x000000DA, 0x00000041, 0x0000003C, 0x000000CB, 0x00000098, 0x000000B5, 0x0000009D, 0x00000019, 0x000000AB, 0x000000F2, 0x00000056, 0x0000007C, 0x00000055, 0x0000008D, 0x00000039, 0x0000001B, 0x000000A4, 0x00000040, 0x000000AF, 0x00000002]
invsbox = get_invs(sbox)
def round_key(m:list,rk:list):
for i in range(4):
for j in range(4):
m[4 * i + j] ^= rk[(3 - i) + 4 * j]
def inv_sub(m:list):
for i in range(len(m)):
m[i]=invsbox[m[i]]
def byte_sub(m:list):
for i in range(len(m)):
m[i]=sbox[m[i]]

def shift_row(s:list):
out=s[:4]
out.extend(s[5:8])
out.append(s[4])
out.extend(s[10:12])
out.extend(s[8:10])
out.append(s[15])
out.extend(s[12:15])
return out

def inv_shift_row(s:list):
out=s[:4]
out.append(s[7])
out.extend(s[4:7])
out.extend(s[10:12])
out.extend(s[8:10])
out.extend(s[13:16])
out.append(s[12])
return out


xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
def mix_single_column(a):
t = a[0] ^ a[1] ^ a[2] ^ a[3]
u = a[0]
a[0] ^= t ^ xtime(a[0] ^ a[1])
a[1] ^= t ^ xtime(a[1] ^ a[2])
a[2] ^= t ^ xtime(a[2] ^ a[3])
a[3] ^= t ^ xtime(a[3] ^ u)

def mix_column(c:list):
a = []
for i in range(4):
tmp = []
for j in range(4):
tmp.append(c[4 * j + i])
a.append(tmp)

for i in range(4):
mix_single_column(a[i])
cc = [0] * 16
for i in range(4):
for j in range(4):
cc[4 * j + i] = a[i][j]
return cc

def GFMul(a:int,b:int):
sig=0
ans=0
while a:
if(a&1): ans^=b
a>>=1
if a:
sig=(b>>7)&1
b=(b<<1)&0xff
if(sig) :b^=0x1b
return ans
def inv_mix_col(c:list):
tmp=[]
for i in range(4):
for j in range(4):
tmp.append(c[4*j+i])
m=[0]*16
for i in range(0,16,4):
m[i] = GFMul(0xe, tmp[i]) ^ GFMul(0xb, tmp[i + 1]) ^ GFMul(0xd, tmp[i + 2]) ^ GFMul(0x9, tmp[i + 3]);
m[i + 1] = GFMul(0x9, tmp[i]) ^ GFMul(0xe, tmp[i + 1]) ^ GFMul(0xb, tmp[i + 2]) ^ GFMul(0xd, tmp[i + 3]);
m[i + 2] = GFMul(0xd, tmp[i]) ^ GFMul(0x9, tmp[i + 1]) ^ GFMul(0xe, tmp[i + 2]) ^ GFMul(0xb, tmp[i + 3]);
m[i + 3] = GFMul(0xb, tmp[i]) ^ GFMul(0xd, tmp[i + 1]) ^ GFMul(0x9, tmp[i + 2]) ^ GFMul(0xe, tmp[i + 3]);

for i in range(4):
for j in range(4):
tmp[4*i+j]=m[i+4*j]
return tmp


# kk=[0x0C, 0x38, 0x93, 0x17, 0x54, 0xF7, 0xA7, 0x11, 0x20, 0xC8, 0x89, 0xF7, 0x25, 0xFA, 0x1A, 0xD4]
# m=[0x61]*16
# c=[0x00000076, 0x00000070, 0x00000096, 0x000000B5, 0x000000F2, 0x000000C6, 0x000000E8, 0x0000007B, 0x00000059, 0x00000096, 0x000000A9, 0x0000009B, 0x0000006D, 0x00000035, 0x00000041, 0x00000044]
# round_key(m,kk)
# hexdump(m)
#
# print('--- byte_sub ---')
# c=m
# byte_sub(c)
# hexdump(c)
#
#
# x=[0x0000007F, 0x0000003C, 0x00000005, 0x00000022, 0x0000003E, 0x0000007C, 0x00000002, 0x000000F4, 0x0000001C, 0x000000A6, 0x0000009D, 0x000000F9, 0x00000019, 0x00000004, 0x00000076, 0x00000060]
#
# print('--- shift_row ---')
# c=shift_row(c)
# hexdump(c)
#
# print('--- mix_column ---')
# cc=mix_column(c)
# print(cc)
# hexdump(cc)
# inv_mix_col(cc)
#
# rkk=[0x44, 0x07, 0xBE, 0xB4, 0x10, 0xF0, 0x19, 0xA5, 0x30, 0x38, 0x90, 0x52, 0x15, 0xC2, 0x8A, 0x86]
# print('--- round_key ---')
# round_key(cc,rkk)
#
#
# ee=[0x000000CB, 0x00000099, 0x00000057, 0x000000A4, 0x00000080, 0x00000065, 0x00000092, 0x0000007E, 0x0000001B, 0x00000056, 0x000000A5, 0x0000003B, 0x0000005D, 0x00000014, 0x00000046, 0x00000075]
# hexdump(cc)

def encry(t:list,exkey:list):
m=t[:]
round_key(m,exkey[:16])
for i in range(1,10):
byte_sub(m)
m=shift_row(m)
m=mix_column(m)
round_key(m,exkey[16*i:16*i+16])
byte_sub(m)
m=shift_row(m)
round_key(m,exkey[160:176])
return m[:]

def decry(t:list,exkey:list):
c=t[:]
round_key(c,exkey[160:176])
c=inv_shift_row(c)
inv_sub(c)
for i in range(9,0,-1):
round_key(c, exkey[16 * i:16 * i + 16])
c=inv_mix_col(c)
c=inv_shift_row(c)
inv_sub(c)
round_key(c,exkey[:16])
hexdump(c)
return c


print('--- encry ---')
rk=[0x0C, 0x38, 0x93, 0x17, 0x54, 0xF7, 0xA7, 0x11, 0x20, 0xC8, 0x89, 0xF7, 0x25, 0xFA, 0x1A, 0xD4, 0x44, 0x07, 0xBE, 0xB4, 0x10, 0xF0, 0x19, 0xA5, 0x30, 0x38, 0x90, 0x52, 0x15, 0xC2, 0x8A, 0x86, 0x00, 0x5E, 0x9B, 0xC8, 0x10, 0xAE, 0x82, 0x6D, 0x20, 0x96, 0x12, 0x3F, 0x35, 0x54, 0x98, 0xB9, 0x56, 0xC8, 0xBB, 0x8A, 0x46, 0x66, 0x39, 0xE7, 0x66, 0xF0, 0x2B, 0xD8, 0x53, 0xA4, 0xB3, 0x61, 0xB9, 0x25, 0xF2, 0xEF, 0xFF, 0x43, 0xCB, 0x08, 0x99, 0xB3, 0xE0, 0xD0, 0xCA, 0x17, 0x53, 0xB1, 0x71, 0x51, 0x02, 0x12, 0x8E, 0x12, 0xC9, 0x1A, 0x17, 0xA1, 0x29, 0xCA, 0xDD, 0xB6, 0x7A, 0x7B, 0x50, 0x90, 0x4C, 0xE8, 0xDE, 0x82, 0x85, 0xF2, 0xC9, 0x23, 0xAC, 0x38, 0x14, 0x95, 0xD6, 0x43, 0x4A, 0x6A, 0x66, 0x5E, 0x94, 0xE8, 0xE3, 0xAC, 0x5D, 0xCB, 0x4F, 0x94, 0x49, 0x5E, 0x99, 0xD7, 0x44, 0x51, 0x3E, 0x30, 0xD0, 0xB9, 0xDD, 0x9C, 0x8D, 0x72, 0x92, 0x08, 0xC4, 0x2C, 0x0B, 0xDF, 0xDA, 0x4D, 0x4F, 0x00, 0x0A, 0xF4, 0x92, 0x9C, 0x87, 0x86, 0x00, 0x94, 0x43, 0xAA, 0x0B, 0x4B, 0x69, 0x57, 0xE3, 0x1D, 0x63, 0xA3, 0x71, 0x81, 0xE4, 0x25, 0x71, 0x15, 0xA7, 0x8F, 0x7A, 0x5E]
rdk=[0x0C, 0x38, 0x93, 0x17, 0x54, 0xF7, 0xA7, 0x11, 0x20, 0xC8, 0x89, 0xF7, 0x25, 0xFA, 0x1A, 0xD4, 0x50, 0x13, 0xAA, 0xA0, 0x04, 0xE4, 0x0D, 0xB1, 0x24, 0x2C, 0x84, 0x46, 0x01, 0xD6, 0x9E, 0x92, 0x0B, 0x7B, 0x48, 0xBD, 0x0F, 0x9F, 0x45, 0x0C, 0x2B, 0xB3, 0xC1, 0x4A, 0x2A, 0x65, 0x5F, 0xD8, 0x7E, 0x8A, 0x11, 0x62, 0x71, 0x15, 0x54, 0x6E, 0x5A, 0xA6, 0x95, 0x24, 0x70, 0xC3, 0xCA, 0xFC, 0xDA, 0xCF, 0x2B, 0x0A, 0xAB, 0xDA, 0x7F, 0x64, 0xF1, 0x7C, 0xEA, 0x40, 0x81, 0xBF, 0x20, 0xBC, 0xAB, 0xD7, 0x37, 0xB9, 0x00, 0x0D, 0x48, 0xDD, 0xF1, 0x71, 0xA2, 0x9D, 0x70, 0xCE, 0x82, 0x21, 0x42, 0x92, 0xA8, 0x9E, 0x42, 0x9F, 0xE0, 0x43, 0xB3, 0xEE, 0x42, 0xDE, 0xC3, 0x20, 0xC0, 0xFF, 0x40, 0xA8, 0x0B, 0x70, 0x02, 0x37, 0xEB, 0x33, 0xB1, 0xD9, 0xA9, 0xED, 0x72, 0xF9, 0x69, 0x12, 0x9D, 0xFC, 0x86, 0x1D, 0x9F, 0xCB, 0x6D, 0x2E, 0x2E, 0x12, 0xC4, 0xC3, 0x5C, 0xEB, 0xAD, 0xD1, 0xB7, 0xA2, 0x7B, 0x87, 0x28, 0x69, 0x16, 0xA9, 0x06, 0x7B, 0xD2, 0x6A, 0x5A, 0x90, 0x7F, 0xBB, 0x49, 0x08, 0x0F, 0x77, 0x61, 0x61, 0x19, 0xDE, 0x67, 0x1A, 0xCB, 0xB4, 0x3D, 0x8A, 0xB4, 0x0F]
enc=[0x0000004E, 0x00000054, 0x000000D6, 0x00000026, 0x000000C7, 0x00000097, 0x00000097, 0x0000008B, 0x00000006, 0x000000E5, 0x00000009, 0x0000009E, 0x000000BE, 0x00000057, 0x00000008, 0x0000004E, 0x00000028, 0x0000002A, 0x0000008A, 0x0000007F, 0x00000088, 0x000000C9, 0x000000F7, 0x000000EB, 0x000000E2, 0x000000BA, 0x000000F4, 0x0000005E, 0x000000E1, 0x00000040, 0x000000C0, 0x0000005A]
rdk2=[0x2A, 0xEE, 0xC7, 0x59, 0xDF, 0x60, 0x30, 0xD6, 0xBE, 0xC1, 0x6C, 0xF1, 0x6B, 0xF2, 0x4D, 0x6A, 0x3C, 0x85, 0x5A, 0xAF, 0xE3, 0xE5, 0x6A, 0x79, 0x5D, 0x24, 0x06, 0x88, 0x36, 0xD6, 0x4B, 0xE2, 0xB0, 0x94, 0xB8, 0x0A, 0x53, 0x71, 0xD2, 0x73, 0x0E, 0x55, 0xD4, 0xFB, 0x38, 0x83, 0x9F, 0x19, 0x70, 0x87, 0x40, 0xC1, 0x23, 0xF6, 0x92, 0xB2, 0x2D, 0xA3, 0x46, 0x49, 0x15, 0x20, 0xD9, 0x50, 0x37, 0xCA, 0xE3, 0xE8, 0x14, 0x3C, 0x71, 0x5A, 0x39, 0x9F, 0x37, 0x13, 0x2C, 0xBF, 0xEE, 0x43, 0x39, 0xAF, 0xFF, 0xC4, 0x2D, 0x93, 0x8E, 0x9E, 0x14, 0x0C, 0xB9, 0x8D, 0x38, 0xB3, 0x57, 0xCE, 0xA6, 0xBC, 0x86, 0xAB, 0x8B, 0x2F, 0x08, 0x35, 0x9F, 0x23, 0xB1, 0xB8, 0xA7, 0x90, 0xE6, 0x76, 0x8A, 0xF4, 0xF2, 0x71, 0x01, 0xDB, 0xFA, 0x44, 0x9E, 0xF8, 0x4B, 0xFC, 0x39, 0x68, 0xAD, 0x8A, 0xE0, 0xF2, 0xA3, 0x70, 0xE1, 0x29, 0x59, 0x34, 0x7F, 0xD1, 0x12, 0xC8, 0x46, 0xB9, 0xBF, 0x42, 0xD8, 0xBC, 0xE1, 0x77, 0x39, 0x95, 0xB8, 0x43, 0x46, 0x44, 0xAA, 0x8B, 0x00, 0xFD, 0x15, 0xC9, 0x11, 0xCB, 0xA1, 0x0C, 0x28, 0x5E, 0x19, 0x4F, 0x6E, 0x1A, 0xB3, 0xC4, 0x6E, 0xE7, 0xA6, 0x0D]
p1=enc[:16]
p2=enc[16:]
m1=decry(p1,rdk)
print(bytes(m1))
s='jRphhACRh8TquLAKaaaaaaaaaaaaaaaa'
m2=decry(p2,rdk2)
print(bytes(m2))
print('flag{jRphhACRh8TquLAKHJuppYiK0gaC4MME}')

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!