2023安洵杯 re复现

ez_cpp

这个题目看了两种办法,受益匪浅

by Arr3stY0u

打开去花得到主函数,反编译后看到单字节判断,可以进行单字节爆破
首先改掉不对就跳到wrong这个逻辑,判断错误后直接跳到exit函数上,然后改掉exit的参数,让它的参数变成ecx,也就是判断正确了几次
111.png
222.png
反编译后就变成了这样
999.png
那么就可以利用这样一个知识点
在main中:
return v; 与 exit(v); 的效果相同。
返回值就是j,可以捕获这个j,来当成单字节爆破的判断依据
师傅的脚本如下

import string
import os
import time

table = string.ascii_letters+string.digits+'!-{}'
# table = string.printable
# 'SYC{Y3S-yE5-y0u-S0Ve-Th3-C9P!!!}'
theflag = ''
while len(theflag) < 32:
    for ch in table:
        flag = (theflag+ch).ljust(32, '#')
        exitcode = os.system(f"echo {flag} | ez_cpp.exe 1>&0")
        if exitcode >= len(theflag) + 1:
            theflag += ch
            print(theflag, exitcode)
            break
            else:
            print('not found')
            time.sleep(0.1)

拼接flag部分并把flag输入到程序里,exitcode就是返回值,也就是ecx的值,如果ecx>=输入的flag的前几位+1,那么这几位就是部分正确的flag,接下来继续拼接即可
SYC{Y3S-yE5-y0u-S0Ve-Th3-C9P!!!}

by Blu3e

这个思路就是直接逆向
依然是去花,然后爆破凯撒加密之后的密文

result=[]
opcode=[0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

cmp=[0x22, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0xFF, 0xFF, 0x72, 0x00, 
  0x00, 0x00, 0xE6, 0xFF, 0xFF, 0xFF, 0x52, 0x00, 0x00, 0x00, 
  0x8C, 0xFF, 0xFF, 0xFF, 0xF2, 0xFF, 0xFF, 0xFF, 0xD4, 0xFF, 
  0xFF, 0xFF, 0xA6, 0xFF, 0xFF, 0xFF, 0x0A, 0x00, 0x00, 0x00, 
  0x3C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0xA6, 0xFF, 
  0xFF, 0xFF, 0x9C, 0xFF, 0xFF, 0xFF, 0x86, 0xFF, 0xFF, 0xFF, 
  0x24, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0xD4, 0xFF, 
  0xFF, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xB6, 0xFF, 0xFF, 0xFF, 
  0x14, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0xCE, 0xFF, 
  0xFF, 0xFF, 0xAC, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x00, 0x00, 
  0x6A, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x7C, 0x00, 
  0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF, 0xE4, 0xFF, 0xFF, 0xFF, 
  0xE4, 0xFF, 0xFF, 0xFF, 0x1E, 0x00, 0x00, 0x00]

for i in range(32):
    for j in range(0x100):
        if i<=16:
            if i>=16:
                a=j^4
            else:
                if opcode[i*4]==1:
                    a=j^9
                else:
                    a=j-2
        else:
            if opcode[i*4]==1:
                a=j^6
            else:
                a=j-5
        v2=0
        v3=0
        v4=7
        a2=8
        while v3<a2:
            v2|=((a>>v3)&1)<<v4
            v3+=1
            v4-=1
        a=1^(v2+1)
        if a==cmp[i*4]:
            result.append(j)

print(bytes(result))

ezr3

by Blu3e

拖进ida,看见函数很少,于是拖进winhex,看见了类似UPX的标志
666.png
全部改成UPX,然后脱壳
777.png
把得到的程序拖进ida,看见了两个可疑函数p和v
888.png
在主函数里面也能找到这两个函数的调用
1010.png1100.png
并且没有其他条件,那么我们直接逆
先逆v
1111.png
做了异或操作,逆一下是这样的

v2 = 0
for i in range(0,len(auth),6):
    for j in range(6):
        auth[i + j] ^= mere[v2+j*12]
    v2 += 2

再逆p,先进行了一次对前四位和后四位的转换,然后进行异或,最后进行验证1686625131683.jpg
逆向脚本如下

v2 = 0
for i in range(0,len(auth),6):
    for j in range(6):
        flag.append(auth[i + j]//mere[(v2+j*6)*2])
    v2 += 1

for i in range(len(flag)):
    flag[len(flag)-1-i] ^= flag[i]
    flag[len(flag)-1-i] = (flag[len(flag)-1-i]>>4|flag[len(flag)-1-i]<<4)&0xff

所以总的脚本如下

auth = [0x0003BC69, 0x000D3FA0, 0x0003A94A, 0x00044AFF, 0x00045254, 0x0000CDD1, 0x00001815, 0x00003B08, 0x00070868, 0x000C6560, 0x00065662, 0x000855C8, 0x0000DCF6, 0x00004CE6, 0x0014EEC2, 0x0002CFD6, 0x00032766, 0x0014F6BA, 0x00025E69, 0x0006A9A3, 0x00121EBD, 0x0005991C, 0x00050016, 0x00004A3D, 0x00097485, 0x0008D0A0, 0x0003B916, 0x00054C58, 0x00096F94, 0x00010334, 0x000DAD22, 0x0004B234, 0x0002FE96, 0x000F33CC, 0x0012C1E8, 0x00148F9E]
mere = [0x00000D21, 0x00000000, 0x0000009D, 0x00000000, 0x0000094B, 0x00000000, 0x000003C9, 0x00000000, 0x00000C3F, 0x00000000, 0x000017E9, 0x00000000, 0x0000130E, 0x00000000, 0x00000088, 0x00000000, 0x00000486, 0x00000000, 0x0000202F, 0x00000000, 0x00002230, 0x00000000, 0x000024B4, 0x00000000, 0x000008B1, 0x00000000, 0x00000A9F, 0x00000000, 0x00001AD2, 0x00000000, 0x000023EB, 0x00000000, 0x00000C7E, 0x00000000, 0x0000042B, 0x00000000, 0x000005BF, 0x00000000, 0x0000113C, 0x00000000, 0x00000449, 0x00000000, 0x00001751, 0x00000000, 0x00000ACE, 0x00000000, 0x00001894, 0x00000000, 0x0000208A, 0x00000000, 0x00000E82, 0x00000000, 0x000006BD, 0x00000000, 0x00000CEE, 0x00000000, 0x00002386, 0x00000000, 0x000013D4, 0x00000000, 0x00000111, 0x00000000, 0x00000D1C, 0x00000000, 0x0000238E, 0x00000000, 0x00001759, 0x00000000, 0x0000012B, 0x00000000, 0x0000214D, 0x00000000, 0x00000040]
v2 = 0
flag = []
for i in range(0,len(auth),6):
    for j in range(6):
        auth[i + j] ^= mere[v2+j*12]
    v2 += 2
v2 = 0
for i in range(0,len(auth),6):
    for j in range(6):
        flag.append(auth[i + j]//mere[(v2+j*6)*2])
    v2 += 1

for i in range(len(flag)):
    flag[len(flag)-1-i] ^= flag[i]
    flag[len(flag)-1-i] = (flag[len(flag)-1-i]>>4|flag[len(flag)-1-i]<<4)&0xff

print(bytes(flag))

111122.png

babythread

by ATC Team

进入main函数,查看,发现是一个RC422222.png
调试不动,查看TLS回调函数里有反调试,去掉
22113.png
然后进行调试,找到RC4的密文Buf2和密钥v12
33221.pngN6W063UAV4)3`%AW2KBXK{H.png
dump下来后写脚本,这个是RC4脚本

def KSA(key):
    key_length = len(key)
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % key_length]) % 256
        S[i], S[j] = S[j], S[i]
    return S


def PRGA(S):
    i = 0
    j = 0
    while True:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        K = S[(S[i] + S[j]) % 256]
        yield K


def RC4(key):
    S = KSA(key)
    keystream = PRGA(S)
    return keystream


# 使用示例
if __name__ == '__main__':
    key = [0x01, 0xE5, 0xD5, 0x40, 0xC3, 0xD5, 0x76, 0x36, 0xFE, 0x66, 0x2D, 0x05, 0xC9, 0xFB, 0x50, 0xE7]
    Buf1 = [0xDE, 0x1C, 0x22, 0x27, 0x1D, 0xAE, 0xAD, 0x65, 0xAD, 0xEF, 0x6E, 0x41, 0x4C, 0x34, 0x75, 0xF1, 0x16, 0x50, 0x50, 0xD4, 0x48, 0x69, 0x6D, 0x93, 0x36, 0x1C, 0x86, 0x3B, 0xBB, 0xD0, 0x4C, 0x91]

    # 解密
    plaintext2 = bytearray()
    keystream = RC4(key)
    for b in Buf1:
        plaintext2.append(b ^ next(keystream))  # 异或操作

    print(plaintext2)
posted @ 2023-06-13 13:46  ㅤ浮虚千年  阅读(198)  评论(2编辑  收藏  举报