这次比赛因为有事外出,只做了前两题,最近有空才把另外3题也做出来,总体来说比以往的VNCTF逆向题目要难一些。当然也有可能是我水平退步了,就算有时间参加比赛,应该也做不完这5题。VN的小伙伴越来越厉害了,出的题质量还不错哦。
RE1:TBXO
全部代码都采用了栈地址修改的方法进行跳转
静态分析不方便,只好动态调试,好在加密算法这个函数没有怎么混淆
分析得到是魔改的TEA算法,key是cdbgnamie_dyilik
写脚本计算出flag:
import struct
def decrypt(v, k):
v0 = v[0]
v1 = v[1]
delta = 0x9E3779B9
x = delta*32&0xffffffff
k0 = k[0]
k1 = k[1]
k2 = k[2]
k3 = k[3]
for i in range(32):
v1 -= ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3) ^ 0x33
v1 = v1 & 0xFFFFFFFF
v0 -= ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1) ^ 0x33
v0 = v0 & 0xFFFFFFFF
x -= delta
x = x & 0xFFFFFFFF
v[0] = v0
v[1] = v1
return v
if __name__ == '__main__':
encrypted=[0x31363010, 0xAD938623, 0x8492D4C5, 0x7567E366, 0xC786696B, 0xA0092E31, 0xDB695733, 0xDD13A893, 0x88D8A53E, 0x7E845437]
key = [0x67626463, 0x696D616E, 0x79645F65, 0x6B696C69]
for i in range(len(encrypted)//2):
decrypted = decrypt(encrypted[i*2:i*2+2], key)
x=struct.pack('<2I',decrypted[0],decrypted[1]).decode()
print(x,end='')
# VNCTF{Box_obfuscation_and_you_ar_socool}
RE2:baby_c2
流量包中能看到flag.txt文件和加密的内容:
再看另一个powershell脚本,用base64逐层解码如下:
$b64EncodedData = "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABe9JNiGpX9MRqV/TEalf0xE+1uMRaV/TEcFPwwGJX9MRwU+DAJlf0xHBT5MBaV/TEcFP4wGJX9MVHt/DARlf0xGpX8MVGV/TFwFPQwG5X9MXAUAjEblf0xcBT/MBuV/TFSaWNoGpX9MQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" //内容过长,省去部分内容
$PEBytes = [System.Convert]::FromBase64String($b64EncodedData)
$filePath = Join-Path -Path $env:TEMP -ChildPath "169sdaf1c56a4s5da4.bin"
$PEBytes | Set-Content -Path $filePath -Encoding byte -Force
Start-Process -FilePath "cmd.exe" -ArgumentList "/c start %temp%\169sdaf1c56a4s5da4.bin"
$actionParams = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c start %temp%\169sdaf1c56a4s5da4.bin"
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5)
$taskName = "Firef0x update services"
Register-ScheduledTask -TaskName $taskName -Trigger $trigger -Action $actionParams -Description "This scheduled task is implemented to check firefox upgrade."
Start-ScheduledTask -TaskName $taskName
前面的b64EncodedData解码后得到一个exe文件,其中s参数处理中有两个函数是动态加密生成的代码,加密部分是在sub_401220:
显然根据比赛的日期,判断出v3=217,对数据异或得到2个关键函数代码
明显是RC4加密,key根据主函数中的代码是由PathFindFileNameA调用得到的
该方法就是返回文件名,这个文件名在抓包的报文中就是flag.txt,因此可以解密文件得到flag.txt的内容
RE3:yun
这个app我的华为手机都装不了,需要android 11,更别说虚机和模拟器了,不能进行调试,只能靠静态分析。
解压出来so库文件,然后发现JNI_Onload里什么都没有,比较奇怪,然后看汇编发现有问题
最后ret到了sub_1fb44去执行了
真正注册的函数在这里:
再看下这个主函数
sub_20004就是好像变量复制,sub_1F17C是获取输入字符串内容,而sub_1EAE0是加密数据的核心代码
根据VNVN数据生成加密数据(这里VNVN在启动后会被改成“s0ry”)
最后再进行base64编码,然后判断是否和bjJydXY4LXB6cnIyZjJxam0ydGNvM3RqOGQ0eTBpdHpoMXUt相等
因此用z3写出爆破求解脚本,不需要什么计算,直接出结果:
from z3 import *
s = Solver()
flag = [BitVec('x%d' % i, 16) for i in range(36)]
tmp=[0]*4
b='s0ry'
a='abcdefghijklmnopqrstuvwxyz1234567890-'
res='n2ruv8-pzrr2f2qjm2tco3tj8d4y0itzh1u-'
for i in range(2):
for j in range(2):
tmp[2*i+j]=a.index(b[2*i+j])
ret=[0]*36
for i in range(len(flag)//2):
for j in range(2):
for k in range(2):
ret[i*2+j]+=flag[i*2+k]*tmp[k*2+j]
for i in range(36):
s.add(And(flag[i]>=0,flag[i]<37))
s.add(ret[i]%37==a.index(res[i]))
if s.check() != sat:
print ("error!")
count=0
while s.check() == sat:
m = s.model()
count+=1
print(count,''.join(a[m[flag[i]].as_long()%37] for i in range(36)))
#flag:75531c14-8825-44ed-a9ec-74d47d5cb76b
RE4:obfuse
题目给的是个.o的文件,除非找到正确的gcc版本,否则不能编译成可执行的程序,因此也不能调试,只能静态分析
代码混淆有两种跳转,第一种是2个条件跳转,第二种是一个jmp $+5
第一种混淆可以看出来两个跳转后有4个乱字节,可以写脚本patch掉,一个块带跳转共替换成16个nop;
第二种比较简单,就直接把jmp $+5这句替换成5个nop就行。
除去跳转混淆以后,可以用F5看伪代码了,不过还是有扁平化混淆,不知道这时候D810插件为啥报错了
只好肉眼手工慢慢看
这里unnamed_3和4都是16字节的数据,unamed_5则是加密后比较的数据
还给了提示,应该是魔改了4处的加密算法:
首先根据加密过程,判断出来应该是个AES算法:
第一处魔改是与IV异或的地方,就是sub_406790:
相当于明文和IV异或的时候也同时和i+22进行异或,这个i就是0-15的字符串下标索引
第二处魔改是AddRoundkey函数,在sub_403610:
实现类似如下的逻辑:
for i in range(4):
for j in range(4):
data[i*4+j]^=roundkey[i*4+j]^i^j
第三处魔改是MixColumns函数,在sub_404160:
有4次异或0x64的操作
实现这样的代码:
static void MixColumns(state_t* state)
{
uint8_t i;
uint8_t Tmp, Tm, t;
for (i = 0; i < 4; ++i)
{
t = (*state)[i][0];
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ^0x64;
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ^0x64;
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ^0x64;
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ^0x64;
}
}
最后一处是PlainSubBytes函数,在sub_403b60:
对查表结果进行了异或0xC8
找对4处魔改,写AES解密脚本即可完成解密:
import re
import binascii
class Aes:
#字节替换s盒,未修改
sbox = [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]
s_box = {}
ns_box = { # 逆字节替换s盒
}
Rcon = { # Rcon生成密钥的表
1: ['0x01', '0x00', '0x00', '0x00'],
2: ['0x02', '0x00', '0x00', '0x00'],
3: ['0x04', '0x00', '0x00', '0x00'],
4: ['0x08', '0x00', '0x00', '0x00'],
5: ['0x10', '0x00', '0x00', '0x00'],
6: ['0x20', '0x00', '0x00', '0x00'],
7: ['0x40', '0x00', '0x00', '0x00'],
8: ['0x80', '0x00', '0x00', '0x00'],
9: ['0x1B', '0x00', '0x00', '0x00'],
10: ['0x36', '0x00', '0x00', '0x00']
}
Matrix = [ # 列混淆
['0x02', '0x03', '0x01', '0x01'],
['0x01', '0x02', '0x03', '0x01'],
['0x01', '0x01', '0x02', '0x03'],
['0x03', '0x01', '0x01', '0x02']
]
ReMatrix = [ # 逆列混淆
['0x0e', '0x0b', '0x0d', '0x09'],
['0x09', '0x0e', '0x0b', '0x0d'],
['0x0d', '0x09', '0x0e', '0x0b'],
['0x0b', '0x0d', '0x09', '0x0e']
]
plaintext = [[], [], [], []] # 存放明文
plaintext1 = [[], [], [], []] # 最后输出的密文
subkey = [[], [], [], []] # 存放密钥
def __init__(self, key): # 构造函数,同时生成密钥
self.s_box = dict(zip(["0x%02x"%i for i in range(256)], ["0x%02x"%i for i in self.sbox]))
self.ns_box = dict(zip(self.s_box.values(), self.s_box.keys())) # s盒键值互换,变为逆S盒
for i in range(4):
for j in range(0, 8, 2):
self.subkey[i].append("0x" + key[i * 8 + j:i * 8 + j + 2]) # 将密钥变成二维矩阵
# print(self.subkey)
for i in range(4, 44): # 生成密钥
if i % 4 != 0: # 如果不是4的倍数,那么直接异或
tmp = xor_32(self.subkey[i - 1], self.subkey[i - 4])
self.subkey.append(tmp)
else: # 4的倍数的时候执行
tmp1 = self.subkey[i - 1][1:]
tmp1.append(self.subkey[i - 1][0])
# print(tmp1)
for m in range(4):
tmp1[m] = self.s_box[tmp1[m]]
# tmp1 = self.s_box['cf'] # 字节代替
tmp1 = xor_32(tmp1, self.Rcon[i / 4]) # 和Rcon异或
self.subkey.append(xor_32(tmp1, self.subkey[i - 4]))
# print(self.subkey)
def AddRoundKey(self, round): # 轮密钥加
for i in range(4):
temp=[]
for j in range(4):
temp.append("0x%02x"%(int(self.plaintext[i][j],16)^int(self.subkey[round * 4 + i][j],16)^i^j))
self.plaintext[i]=temp
#self.plaintext[i] = xor_32(self.plaintext[i], self.subkey[round * 4 + i])
# print('AddRoundKey',self.plaintext)
def RePlainSubBytes(self): # 逆字节代替
for i in range(4):
for j in range(4):
self.plaintext[i][j] = self.ns_box["0x%02x"%(int(self.plaintext[i][j],16)^0xc8)]
def ReShiftRows(self): # 逆行移位
p1, p2, p3, p4 = self.plaintext[0][1], self.plaintext[1][1], self.plaintext[2][1], self.plaintext[3][1]
self.plaintext[3][1] = p3
self.plaintext[2][1] = p2
self.plaintext[0][1] = p4
self.plaintext[1][1] = p1
p1, p2, p3, p4 = self.plaintext[0][2], self.plaintext[1][2], self.plaintext[2][2], self.plaintext[3][2]
self.plaintext[0][2] = p3
self.plaintext[1][2] = p4
self.plaintext[2][2] = p1
self.plaintext[3][2] = p2
p1, p2, p3, p4 = self.plaintext[0][3], self.plaintext[1][3], self.plaintext[2][3], self.plaintext[3][3]
self.plaintext[0][3] = p2
self.plaintext[1][3] = p3
self.plaintext[2][3] = p4
self.plaintext[3][3] = p1
def ReMixColumns(self): # 逆列混淆
for i in range(4):
self.plaintext[i] = xor_32(self.plaintext[i], ['0x64']*4)
for j in range(4):
self.plaintext1[i].append(MatrixMulti(self.ReMatrix[j],self.plaintext[i]))
def AES_ECB_Dec(self, cipher): # AES单组解密函数
self.plaintext = [[], [], [], []]
for i in range(4):
for j in range(0, 8, 2):
self.plaintext[i].append('0x' + cipher[i * 8 + j:i * 8 + j + 2]) # 16进制转成2进制
# print(self.ns_box)
self.AddRoundKey(10)
for i in range(9):
self.ReShiftRows()
self.RePlainSubBytes()
self.AddRoundKey(9-i)
self.ReMixColumns()
self.plaintext = self.plaintext1
self.plaintext1 = [[], [], [], []]
self.ReShiftRows()
self.RePlainSubBytes()
self.AddRoundKey(0)
return Matrixtostr(self.plaintext)
def AES_CBC_Dec(self, cipher ,iv): #bytes cipher,iv
plain=b''
for i in range(len(cipher)//16-1,-1,-1):
plain16 = self.AES_ECB_Dec(cipher[i*16:(i+1)*16].hex())
if i>0:
plain=xor(bytes.fromhex(plain16),xor(cipher[i*16-16:i*16],iv0))+plain
else:
plain=xor(bytes.fromhex(plain16),xor(iv,iv0))+plain
return plain
def Encryption(self, text): # 加密函数
group = PlaintextGroup(TextToByte(text), 32, 1)
# print(group)
cipher = ""
for i in range(len(group)):
cipher = cipher + self.AESEncryption(group[i])
return cipher
def Decryption(self, cipher): # 解密函数
group = PlaintextGroup(cipher, 32, 0)
# print(group)
text = ''
for i in range(len(group)):
text = text + self.AESDecryption(group[i])
text = ByteToText(text)
return text
def xor_32(start, end): # 32位进行异或
a = []
for i in range(0, 4):
xor_tmp = ""
b = hextobin(start[i])
c = hextobin(end[i])
for j in range(8):
xor_tmp += str(int(b[j], 10) ^ int(c[j], 10))
a.append(bintohex(xor_tmp))
return a
def xor_8(begin, end): # 二进制字符串8位异或
xor_8_tmp = ""
for i in range(8):
xor_8_tmp += str(int(begin[i]) ^ int(end[i]))
return xor_8_tmp
def hextobin(word): # 把十六进制转换成二进制
word = bin(int(word, 16))[2:] # 去除掉最前面的0b
for i in range(0, 8-len(word)): # 补全八位
word = '0'+word
return word
def bintohex(word): # 把二进制转换十六进制
word = hex(int(word, 2))
if len(word) == 4:
return word
elif len(word) < 4:
return word.replace('x', 'x0')
def MatrixMulti(s1, s2): # 列混淆中的矩阵乘法
result = []
s3 = []
for i in range(4):
s3.append(hextobin(s2[i])) # s3保存原始矩阵一行的四个二进制值
for i in range(4):
result.append(MultiProcess(int(s1[i], 16), s3[i]))
for i in range(3):
result[0] = xor_8(result[0], result[i+1])
return bintohex(result[0])
def MultiProcess(a, b): # 列混淆中的乘法运算的具体过程
if a == 1:
return b
elif a == 2:
if b[0] == '0':
b = b[1:] + '0'
else:
b = b[1:] + '0'
b = xor_8(b, '00011011')
return b
elif a == 3:
tmp_b = b
if b[0] == '0':
b = b[1:] + '0'
else:
b = b[1:] + '0'
b = xor_8(b, '00011011')
return xor_8(b, tmp_b)
elif a == 9:
tmp_b = b
return xor_8(tmp_b, MultiProcess(2, MultiProcess(2, MultiProcess(2, b))))
elif a == 11:
tmp_b = b
return xor_8(tmp_b, xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, b)))
elif a == 13:
tmp_b = b
return xor_8(tmp_b, xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, MultiProcess(2, b))))
elif a == 14:
return xor_8(MultiProcess(2, b), xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, MultiProcess(2, b))))
def Matrixtostr(matrix): # 矩阵转成字符串
result = ""
for i in range(4):
for j in range(4):
result += matrix[i][j][2:]
return result
def PlaintextGroup(plaintext, length, flag): # 明文分组和填充
group = re.findall('.{'+str(length)+'}', plaintext)
group.append(plaintext[len(group)*length:])
if group[-1] == '' and flag:
group[-1] = '16161616161616161616161616161616'
elif len(group[-1]) < length and flag:
tmp = int((length-len(group[-1])) / 2)
if tmp < 10:
for i in range(tmp):
group[-1] = group[-1] + '0'+str(tmp)
else:
for i in range(tmp):
group[-1] = group[-1] + str(tmp)
elif not flag:
del group[-1]
return group
def TextToByte(words): # 明文转成十六进制字节流
text = words.encode('utf-8').hex()
return text
def ByteToText(encode): # 十六进制字节流转成明文
tmp = int(encode[-2:])
word = ''
for i in range(len(encode)-tmp*2):
word = word + encode[i]
# print(word)
word = bytes.decode(binascii.a2b_hex(word))
return word
def xor(a,b):
return bytes([i^j for i,j in zip(a,b)])
from Crypto.Util.number import *
#下面是手工CBCd
iv='000102030405060708090A0B0C0D0E0F'
ciphertext='B5962103B6D50DE30CD75B887CEB297E1414EA8802FEBA923994D2F6472BE26F'
key='2B7E151628AED2A6ABF7158809CF4F3C'.lower()
iv0=bytes.fromhex('161718191a1b1c1d1e1f202122232425')
A1 = Aes(key)
print(A1.AES_CBC_Dec(bytes.fromhex(ciphertext),bytes.fromhex(iv)))
# VNCTF{th1s_t@stes_go0d_r1ght~~?}
RE5:ko
感觉这题比较坑,有点像MISC,一直找不到RC4的key,谁会知道用户代码会怎么写?!
后来发现内核日志信息里居然有提示,才明白为啥代码中要写这么多printk,好吧,是我肤浅了。
首先,代码中所有的数据都经过了加密
在初始化函数中调用_register_chrdev,_class_create,device_create进行驱动的注册
注意off_CE0这里,对几个回调函数都进行了注册
其中核心的逻辑在ioctl回调函数中
根据调用函数的参数顺序分别有如下代码:
第一部分主要是调用了rc4_init函数
第二部分主要是调用了rc4_encrypt函数
第三部分主要是调用了check_flag函数
下面在分别说下这3个函数
rc4_init函数:这个函数没啥问题,里面就多了一个srand(),后面细说。
rc4_encrypt函数:这里有魔改的地方,有个随机数加入了加密流程
而check_flag函数就是一个比较字符串长度和内容是否正确的
看看mt19937gen函数:
就是一个标准的梅森旋转数伪随机算法。
再看下srand函数:
这里设置了种子是0xfa11010d
其实流程还是满简单的,关键是rc4的key在哪里,最后在init函数里找到一个日志信息
这里表示1D00这里存放的就是key了,写出解密脚本如下:
def _int32(x):
return int(0xFFFFFFFF & x)
class MT19937:
def __init__(self, seed):
self.mt = [0] * 624
self.mt[0] = seed
self.mti = 0
for i in range(1, 624):
self.mt[i] = _int32(1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i)
def extract_number(self):
if self.mti == 0:
self.twist()
y = self.mt[self.mti]
y = y ^ y >> 11
y = y ^ y << 7 & 2636928640
y = y ^ y << 15 & 4022730752
y = y ^ y >> 18
self.mti = (self.mti + 1) % 624
return _int32(y)
def twist(self):
for i in range(0, 624):
y = _int32((self.mt[i] & 0x80000000) + (self.mt[(i + 1) % 624] & 0x7fffffff))
self.mt[i] = (y >> 1) ^ self.mt[(i + 397) % 624]
if y % 2 != 0:
self.mt[i] = self.mt[i] ^ 0x9908b0df
rand=MT19937(0xFA11010D)
def rc4_init_sbox(key):
s_box = list(range(256))
j = 0
for i in range(256):
j = (j + s_box[i] + (key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
return s_box
def rc4_encrypt(plain, box):
res = []
i = j = 0
for s in plain:
i = (i + 1) % 256
j = (j + box[i]) % 256
box[i], box[j] = box[j], box[i]
t = (box[i] + box[j] + rand.extract_number()) % 256
k = box[t]
res.append(((s) ^ k)&0xff)
# print("res用于加密字符串,加密后是:%res" %res)
cipher = bytes(res)
print("加密后的字符串是:%s" %cipher)
# print(str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
res=bytes.fromhex('1fd1f1913e5aad6c0425e1c49a5aa0771d6be717ab10e7ac294913fbc487d5be60d7d79692ece1618ab0')
key=b"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcnNhAAAAAwEAAQAAAYEAwl1xDcAhbdm49z9MEJuVkyw2jFjAAIVYtYIZ2D3bK0YpKLuOY7uqtFOsjCO1I47ZLc2nGWfrvaxtCo28N56Ie5BlvDhjkqlqNZjLwhAVCNLWntCsXJn8xt3vhCEf9ccEiNKgJQzIvXsf96Uh2k76cXLi6yqzvjzmNnkuqiPv"
s_box = rc4_init_sbox(key)
rc4_encrypt(res, s_box)
# VNCTF{Welcome_To_Kernel_World@RETraveler}