长城杯2023

# PREFACE:RE 比较容易
# ps. 初赛猛猛做最后是第一,决赛线下直接不会了,赛后仨小时出了 re1 一小时出的 re2,只能说离开网络和 gpt 的 moyaoxue 一事无成

初赛:

# vvm

简单的 vm,opcode 很少直接可以看出来逻辑

image-20230913214608382

n
enc = [  126,  120,  117,  127,  107,  82,  117,  114,  109,  119,  78,  121,  121,  121,  119,  68,  98,  36,  96,  113,  115,  96,  53,  105]
for i in enc:
    i ^= 0x16
    i -= 2
    print(chr(i),end = "")

# ezSocket

字节码逆向,通信过程的 sm4 和 rsa 都不需要管,只是信道加解密内容,只需要爆破六位 key 对比 sha256 即可

n
from Crypto.Cipher import DES
import string
import itertools
import base64
import hashlib
# import owiener
if __name__ == "__main__":
    charset = string.digits + ""
    for i in itertools.product(charset, repeat=6):
        key = ''.join(i)
        key += 'ffffffffff'
        key = key.encode()
        a = hashlib.sha256(key).hexdigest().encode()
        if (a == b'fdce9fbba473a2e47c14c72a78dcf62a28f0259847d7910ecb18a0af80983693'):
            print(key)

决赛

# RE

# file

一个类 lz77 压缩的压缩算法,改变的地方在于滑块长度固定二

具体规则是:建立缓存

image-20230916212036353

每次出现新的双字节(两个 ascii,即滑块长),则在该字节前面加一 bit 的’1’,并存入缓冲区,如果在缓存找到已有,则在前面加 8bit 的’0’,然后下面 8bit 做填充和寻址(在缓存内找到相应的双字节)

(脚本不全,解压部分是手动试的,因为真正压缩的地方只有两处):

n
a='1011001101011011001011000011011001111011110111001101001011001001011001101001101101001110001001100111011001001001100101001011011001101111011000111001100111001100011001011011001100111001100001001110001011000111001011011011000111001100101001100011001101111001011011001100011011001001001101111011001000000000000110000000000001001000010011010010011010010011001110110001110111110100'
i = 0
flag = ''
j = 0
while(i< len(a)):
    if a[i] == '0':
        i += 1
        i += 12
    else :
        i += 1
        flag += chr(int(a[i:i+8], 2))
        i += 8
print(flag)
#   flag{4df683d2-7c31-308c-c217-1d7d0817443c}
# your_emb

一点一点硬看汇编,发现 check 前面有 xor 操作,这里的 xor 应该是 getkey 访问失败返回得到的,即: connection refused

image-20230916212956794

n
enc = [  0x05, 0x03, 0x0F, 0x09, 0x1E, 0x5B, 0x12, 0x5C, 0x09, 0x0F,
  0x10, 0x43, 0x56, 0x4B, 0x17, 0x40, 0x56, 0x55, 0x4E, 0x5B,
  0x08, 0x5C, 0x57, 0x4E, 0x15, 0x0D, 0x5C, 0x0D, 0x0D, 0x16,
  0x5C, 0x05, 0x43, 0x41, 0x57, 0x5D, 0x02, 0x59, 0x5D, 0x5C,
  0x50, 0x1E]
key = 'connection refused'
for i in range(len(enc)):
    print(chr(enc[i] ^ ord(key[i % len(key)])),end='')
    
# flag{8f5fa013-b331-4f22-ad3c-d9c6229a6325}