首页
社区
课程
招聘
[原创] SUSCTF 2022 DigitalCircuits 分析过程及解题脚本
发表于: 2022-3-11 10:19 8224

[原创] SUSCTF 2022 DigitalCircuits 分析过程及解题脚本

2022-3-11 10:19
8224

下载是一个main.exe,根据ico可以知道是python生成的exe文件,python中通过pyinstaller进行py转exe,在默认情况下,并且只有一个exe文件,所以猜测应该是-F进行转换,所以此时可以尝试用pyinstxtractor进行解包:

image-20220302164341202

生成一个_extracted文件夹:

image-20220302164535713

进入文件夹找到同名的pyc文件,对比正常的stuct.pyc文件发现少了16个字节的py头:

image-20220302171504559

将py头复制过去即可反编译,这里无法用在线反编译猜测应该是文件过大,所以采用python进行反编译:

反编译(需要注意python的版本,3.9以上的好像反编译会失败)

根据if可以得知传入的参数非0即1,所以可以知道应该是逻辑指令,f1就是&,f2就是|,f3取非,所以这部分就跟题目名称对上了,数电三大基础逻辑运算:

代入f1-f3得到:(a & ~b) | (~a & b),emm,就是xor,在数电中的基础逻辑语句只有三个,异或虽然在python中是有^这个符号代替的,但实际原理就是题目中的那样进行逻辑操作:

简化:

f5同样代入:

得到,没看懂在干啥:

找到f6调用的位置:

image-20220303120139056

测试一下:

得到res: 10011110001101110111100110111010

可以发现f6其实就是做了个二进制加法,传入的两个参数为二进制字符串,对于二进制字符串,字符串的高位为数据低位,所以传入之后会先对字符串进行翻转:

那么f5的三次异或就可以理解了,最开始z=0,然后传入的x=1,y=1s = x ^ y ^ z = 0,然后第二个c是用来检测是否产生进位,明显0b01 + 0b01 = 0b10,会产生进位,所以c = 1,然后将进位值给到z,代入下一轮循环,最终生成

image-20220303120229954

f7,f8都是传入一个二进制字符串,然后传入一个n,很明显,f7就是左移,f8就是右移,n为位数

f9逐位异或,最终就是整体异或:

首先是限制了flag格式为SUSCTF{xxx}flag正文内容为24字节,进行三次循环,每次循环取8个字节,分成前后4个字节,然后拼接成32位的字符串,bin(ord(flagstr[i]))[2:].zfill(8)字符转二进制字符串

image-20220303160031426

处理完字符串之后通过f10进行处理,这里传入了k0-k3应该是4个key:

转成16进制看看:

image-20220303161759144

将d也转成16进制,发现TEA算法特征

image-20220304103329684

f10代入功能代码进行简化,可以得到f10就是TEA算法的加密过程:

测试:

每次循环的结果是二进制字符串的拼接:

image-20220304105641879

每次循环取flag的8个字节,加密结果互不影响,所以最终拼接会得到192个字节的长度,与res进行比较:

那么只需要将res按64字节分成三份,分别进行解密即可得到真正的flag

得到flag:

考点:

比起以往的XCTF联赛逆向,这次的题目感觉像是入门题了,整体难度不高,该题的难点在于将TEA算法用二进制的形式进行描述,但只要将功能代码分析代入简化,便能轻松秒杀

 
 
 
 
 
 
pip3 install uncompyle6
pip3 install uncompyle6
uncompyle6 -o ./ DigitalCircuits.pyc
uncompyle6 -o ./ DigitalCircuits.pyc
# uncompyle6 version 3.8.0
# Python bytecode 3.7.0 (3394)
# Decompiled from: Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: DigitalCircuits.py
# Compiled at: 1995-09-28 00:18:56
# Size of source mod 2**32: 257 bytes
import time
 
def f1(a, b):
    if a == '1':
        if b == '1':
            return '1'
    return '0'
 
 
def f2(a, b):
    if a == '0':
        if b == '0':
            return '0'
    return '1'
 
 
def f3(a):
    if a == '1':
        return '0'
    if a == '0':
        return '1'
 
 
def f4(a, b):
    return f2(f1(a, f3(b)), f1(f3(a), b))
 
 
def f5(x, y, z):
    s = f4(f4(x, y), z)
    c = f2(f1(x, y), f1(z, f2(x, y)))
    return (s, c)
 
 
def f6(a, b):
    ans = ''
    z = '0'
    a = a[::-1]
    b = b[::-1]
    for i in range(32):
        ans += f5(a[i], b[i], z)[0]
        z = f5(a[i], b[i], z)[1]
 
    return ans[::-1]
 
 
def f7(a, n):
    return a[n:] + '0' * n
 
 
def f8(a, n):
    return n * '0' + a[:-n]
 
 
def f9(a, b):
    ans = ''
    for i in range(32):
        ans += f4(a[i], b[i])
 
    return ans
 
 
def f10(v0, v1, k0, k1, k2, k3):
    s = '00000000000000000000000000000000'
    d = '10011110001101110111100110111001'
    for i in range(32):
        s = f6(s, d)
        v0 = f6(v0, f9(f9(f6(f7(v1, 4), k0), f6(v1, s)), f6(f8(v1, 5), k1)))
        v1 = f6(v1, f9(f9(f6(f7(v0, 4), k2), f6(v0, s)), f6(f8(v0, 5), k3)))
 
    return v0 + v1
 
 
k0 = '0100010001000101'.zfill(32)
k1 = '0100000101000100'.zfill(32)
k2 = '0100001001000101'.zfill(32)
k3 = '0100010101000110'.zfill(32)
flag = input('please input flag:')
if flag[0:7] != 'SUSCTF{' or flag[(-1)] != '}':
    print('Error!!!The formate of flag is SUSCTF{XXX}')
    time.sleep(5)
    exit(0)
flagstr = flag[7:-1]
if len(flagstr) != 24:
    print('Error!!!The length of flag 24')
    time.sleep(5)
    exit(0)
else:
    res = ''
    for i in range(0, len(flagstr), 8):
        v0 = flagstr[i:i + 4]
        v0 = bin(ord(flagstr[i]))[2:].zfill(8) + bin(ord(flagstr[(i + 1)]))[2:].zfill(8) + bin(ord(flagstr[(i + 2)]))[2:].zfill(8) + bin(ord(flagstr[(i + 3)]))[2:].zfill(8)
        v1 = bin(ord(flagstr[(i + 4)]))[2:].zfill(8) + bin(ord(flagstr[(i + 5)]))[2:].zfill(8) + bin(ord(flagstr[(i + 6)]))[2:].zfill(8) + bin(ord(flagstr[(i + 7)]))[2:].zfill(8)
        res += f10(v0, v1, k0, k1, k2, k3)
 
    if res == '001111101000100101000111110010111100110010010100010001100011100100110001001101011000001110001000001110110000101101101000100100111101101001100010011100110110000100111011001011100110010000100111':
        print('True')
    else:
        print('False')
time.sleep(5)
# uncompyle6 version 3.8.0
# Python bytecode 3.7.0 (3394)
# Decompiled from: Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: DigitalCircuits.py
# Compiled at: 1995-09-28 00:18:56
# Size of source mod 2**32: 257 bytes
import time
 
def f1(a, b):
    if a == '1':
        if b == '1':
            return '1'
    return '0'
 
 
def f2(a, b):
    if a == '0':
        if b == '0':
            return '0'
    return '1'
 
 
def f3(a):
    if a == '1':
        return '0'
    if a == '0':
        return '1'
 
 
def f4(a, b):
    return f2(f1(a, f3(b)), f1(f3(a), b))
 
 
def f5(x, y, z):
    s = f4(f4(x, y), z)
    c = f2(f1(x, y), f1(z, f2(x, y)))
    return (s, c)
 
 
def f6(a, b):
    ans = ''
    z = '0'
    a = a[::-1]
    b = b[::-1]
    for i in range(32):
        ans += f5(a[i], b[i], z)[0]
        z = f5(a[i], b[i], z)[1]
 
    return ans[::-1]
 
 
def f7(a, n):
    return a[n:] + '0' * n
 
 
def f8(a, n):
    return n * '0' + a[:-n]
 
 
def f9(a, b):
    ans = ''
    for i in range(32):
        ans += f4(a[i], b[i])
 
    return ans
 
 
def f10(v0, v1, k0, k1, k2, k3):
    s = '00000000000000000000000000000000'
    d = '10011110001101110111100110111001'
    for i in range(32):
        s = f6(s, d)
        v0 = f6(v0, f9(f9(f6(f7(v1, 4), k0), f6(v1, s)), f6(f8(v1, 5), k1)))
        v1 = f6(v1, f9(f9(f6(f7(v0, 4), k2), f6(v0, s)), f6(f8(v0, 5), k3)))
 
    return v0 + v1
 
 
k0 = '0100010001000101'.zfill(32)
k1 = '0100000101000100'.zfill(32)
k2 = '0100001001000101'.zfill(32)
k3 = '0100010101000110'.zfill(32)
flag = input('please input flag:')
if flag[0:7] != 'SUSCTF{' or flag[(-1)] != '}':
    print('Error!!!The formate of flag is SUSCTF{XXX}')
    time.sleep(5)
    exit(0)
flagstr = flag[7:-1]
if len(flagstr) != 24:
    print('Error!!!The length of flag 24')
    time.sleep(5)
    exit(0)
else:
    res = ''
    for i in range(0, len(flagstr), 8):
        v0 = flagstr[i:i + 4]
        v0 = bin(ord(flagstr[i]))[2:].zfill(8) + bin(ord(flagstr[(i + 1)]))[2:].zfill(8) + bin(ord(flagstr[(i + 2)]))[2:].zfill(8) + bin(ord(flagstr[(i + 3)]))[2:].zfill(8)
        v1 = bin(ord(flagstr[(i + 4)]))[2:].zfill(8) + bin(ord(flagstr[(i + 5)]))[2:].zfill(8) + bin(ord(flagstr[(i + 6)]))[2:].zfill(8) + bin(ord(flagstr[(i + 7)]))[2:].zfill(8)
        res += f10(v0, v1, k0, k1, k2, k3)
 
    if res == '001111101000100101000111110010111100110010010100010001100011100100110001001101011000001110001000001110110000101101101000100100111101101001100010011100110110000100111011001011100110010000100111':
        print('True')
    else:
        print('False')
time.sleep(5)
def f1(a, b):
    if a == '1':
        if b == '1':
            return '1'
    return '0'
 
 
def f2(a, b):
    if a == '0':
        if b == '0':
            return '0'
    return '1'
 
def f3(a):
    if a == '1':
        return '0'
    if a == '0':
        return '1'
def f1(a, b):
    if a == '1':
        if b == '1':
            return '1'
    return '0'
 
 
def f2(a, b):
    if a == '0':
        if b == '0':
            return '0'
    return '1'
 
def f3(a):
    if a == '1':
        return '0'
    if a == '0':
        return '1'
def f4(a, b):
    return f2(f1(a, f3(b)), f1(f3(a), b))
def f4(a, b):
    return f2(f1(a, f3(b)), f1(f3(a), b))
def f4(a, b):
    return a ^ b
def f4(a, b):
    return a ^ b
def f5(x, y, z):
    s = f4(f4(x, y), z)
    c = f2(f1(x, y), f1(z, f2(x, y)))
    return (s, c)
def f5(x, y, z):
    s = f4(f4(x, y), z)
    c = f2(f1(x, y), f1(z, f2(x, y)))
    return (s, c)
def f5(x, y, z):
    s = x ^ y ^ z
    c = (x & y) | (z & (x | y))
    return (s, c)
def f5(x, y, z):
    s = x ^ y ^ z
    c = (x & y) | (z & (x | y))
    return (s, c)
def f6(a, b):
    ans = ''
    z = '0'
    a = a[::-1]
    b = b[::-1]
    for i in range(32):
        ans += f5(a[i], b[i], z)[0]
        z = f5(a[i], b[i], z)[1]
 
    return ans[::-1]
def f6(a, b):
    ans = ''
    z = '0'
    a = a[::-1]
    b = b[::-1]
    for i in range(32):
        ans += f5(a[i], b[i], z)[0]
        z = f5(a[i], b[i], z)[1]

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//