ezCsky

ezCsky固件逆向,使用ida arm架构打开可以看到rc4_int rc4_crypto 等字符串,猜测为rc4加密,testkey为rc4的key,有一组数据猜测为enc,进行rc4解密后,得到0a0d061c1f545653575100031d14585603191c0054034b14580702494c020701510c0800010003004f7d,尝试发现第一位异或"f",之后相邻异或可得flag

dump

提供了一个re.exe和一个加密后的flag二进制文件。
我们可以注意到re.exe会读取程序参数,所以我们输入:

C:\Users\Administrator\Desktop\bin>re.exe ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
02030405060708090a0b0c0d0e0f101112131415161718191a1b1e1f202122232425262728292a2b2c2d2e2f3031323334353637001c1d00000000000000000001
C:\Users\Administrator\Desktop\bin>re.exe `1234567890-=[]\';,./~!@#$%^&*()_+{}:"?
001c1d00000000000000000001000000000000000000000000000000000000000038390000

我们就可以得到字符表和输出的对应关系,发现是hex,而且是一一对应,除了3~9这几个数字和+/号,还有{},我们容易验证flag二进制文件的前几个就是flag{,最后一个是},所以人工进行一一对照就行。
2024-12-15T08:28:34.png

23 29 1E 24 38 0E 15 20 37 0E 05 20 00 0E 37 12 1D 0F 24 01 01 39
f  l  a  g  {  M  T  c  z  M  D  c  0  M  z  Q   2  N  g  1  1  }

但是问题是,这个flag交上去是错的,原因是因为数字的对应关系, 0是00,3~9也都是00,所以我们手动尝试一下3~9的数字,发现4是对的。所以这个程序的编码是有缺陷的,还好只有一个位置需要猜。
所以flag如下。中间那串是base64,解出来是一个时间戳,应该是出题人出题的时候的时间。

flag{MTczMDc4MzQ2Ng==}

Rand0m

Cython 逆向,pyd里面
x64dbg Hook
由于Python虚拟机的Number都是30bit,所以我经过了如下的处理来还原。
2024-12-15T08:29:03.png

PyNumber_And
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) & ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} & 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Add
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) + ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} + 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Xor
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) ^ ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} ^ 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_LShift
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) << ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} << 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_RShift
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) >> ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} >> 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Reminder
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) % ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} % 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Power
0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} ** 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyObject_RichCompare
0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} ?= 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}

输入如下:

rand0m.check('11223344aabbccddeeffeeffaaccddee')

我们可以拿到Log Trace

0x124AC252FFCF = 0x3FFFFFFFFFFFFFFF % 0x1FFE26F569F0
.....此处省略几十行
0x8F154AFD = 0x11223344 ^ 0x9E3779B9
0x12223440 = 0x112233440 & 0xFA3AFFFF
0x12223441 = 0x12223440 + 0x1
0x2268011E2A9 ** 0x40010001
0x13C501CC = 0xEF90A60E6D9E2A9 % 0xFFFFFFFD
0x12223441 ?= 0x52287F38

INT3 breakpoint at python312.00007FF826A9A862!
0x27FE60B7 ?= 0x98D24B3A


INT3 breakpoint at python312.00007FF826A9A862!
0x348CB564 = 0xAABBCCDD ^ 0x9E3779B9
0xAA38CDD0 = 0xAABBCCDD0 & 0xFA3AFFFF
0xAA38CDDA = 0xAA38CDD0 + 0xA
0x100069196 ** 0x40010001
0x0 = 0x0 % 0xFFFFFFFD
0xAA38CDDA ?= 0x4A30F74D

INT3 breakpoint at python312.00007FF826A9A862!
0x2B356987 ?= 0xE0F1DB77


INT3 breakpoint at python312.00007FF826A9A862!
0x70C89746 = 0xEEFFEEFF ^ 0x9E3779B9
0xEA3AEFF0 = 0xEEFFEEFF0 & 0xFA3AFFFF
0xEA3AEFFE = 0xEA3AEFF0 + 0xE
0x1000E1912 ** 0x40010001
0x0 = 0x0 % 0xFFFFFFFD
0xEA3AEFFE ?= 0x423A1268

INT3 breakpoint at python312.00007FF826A9A862!
0x81AC0CF0 ?= 0xADF38403


INT3 breakpoint at python312.00007FF826A9A862!
0x34FBA457 = 0xAACCDDEE ^ 0x9E3779B9
0xA808DEE0 = 0xAACCDDEE0 & 0xFA3AFFFF
0xA808DEEA = 0xA808DEE0 + 0xA
0xC0069F74 ** 0x40010001
0x0 = 0x0 % 0xFFFFFFFD
0xA808DEEA ?= 0x88108807
INT3 breakpoint at python312.00007FF826A9A862!
0x61FF12D1 ?= 0xD8499BB6
INT3 breakpoint at python312.00007FF826A9A862!
...后面没用了,不看了

我们显然可以观察到,对于每个加密后的数据有两组判断,log中具有断点的原因是,如果第一组判断不成立,那么第二组判断不会发生,所以我断下来,手动把PyFalseObject改为了PyTrueObject,让程序以为是正确的。
接下来就是分析,可见一组数据拆成了两部分进行加密,而这两部分都会破坏数据完整性。比如说第一部分异或了一个TEA常量,来让别人感觉是TEA,然后AND了一个 0xFA3AFFFF,显然丢失了很多比特的信息。
第二部分是一个** 0x10001 然后对0xfffffffd取余,很容易让我们想到RSA加密算法,然后我们就可以对N进行分解:
2024-12-15T08:30:26.png

随后就可以写出RSA加密解密函数,把这些参量都算出来。

def rsa_decrypt(x):
    N = 0xfffffffd
    p = 9241
    q = 464773
    assert p * q == N
    phi = (p-1) * (q-1)
    e = 0x10001
    # c = (m ** e) % N
    d = pow(e, -1, phi)
    return pow(x, d, N)

def rsa_encrypt(x):
    N = 0xfffffffd
    e = 0x10001
    return pow(x, e, N)

我们可以注意另一个加密,他对于我们的输入进行一同操作,获取到的结果,如0x*123,我们发现123是原先的低32位,最低4位其实是ROL的结果,这个我们不需要关心,因为RSA那边可以让我们获取到原先数字的高22位,而123可以让我们获取到原先数字的低12位,而我们只需要低11位,所以我们就有思路了:

((rsa_decrypt(enc2) << 11) ^ 0x9E3779B9) & 0xfffff800 来获取高22位
(a >> 4) & 0x7ff 来获取低11位
然后把上面两部分进行拼接,就是整个结果。

所以我们的EXP就是:

def rsa_decrypt(x):
    N = 0xfffffffd
    p = 9241
    q = 464773
    assert p * q == N
    phi = (p-1) * (q-1)
    e = 0x10001
    # c = (m ** e) % N
    d = pow(e, -1, phi)
    return pow(x, d, N)

def rsa_encrypt(x):
    N = 0xfffffffd
    e = 0x10001
    return pow(x, e, N)

enc_list = [(0x52287F38, 0x98D24B3A), 
            (0x4A30F74D, 0xE0F1DB77), 
            (0x423A1268, 0xADF38403), 
            (0x88108807, 0xD8499BB6)]
flag = ''
for i in enc_list:
    a, b = i
    b = rsa_decrypt(b) << 11
    b ^= 0x9E3779B9
    b &= 0xfffff800
    a = (a >> 4) & 0x7ff
    s = a | b
    flag += hex(s)[2:]

print(f"flag{{{flag}}}")
# flag{813a97f3d4b34f74802ba12678950880}

Cython

拿到exe文件,我们先使用 pyinstextractor 来解包,解包出来之后,有一个test1.pyc,一个ez.xx.pyd
显然pyc是程序IO逻辑部分,ez是加密算法部分。
我们反编译pyc可以得到如下结果:

# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: test1.py
# Bytecode version: 3.11a7e (3495)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)

import ez
flag = input('请输入flag:')
flag1 = list(flag)
value = []
b = 0
ck = 0
if len(flag1) == 24:
    for i in range(0, len(flag1), 4):
        b = ord(flag1[i]) 3 * (ord(flag1[i]) 3 * 24, ord(flag1, i[1]) 3) + ord(flag1, i[2]) 3 * 8 + ord(flag1, i[3])
        value.append(b)
    key = [102, 108, 97, 103]
    flag_encrypt = []
    for i in range(0, 6, 2):
        res = ez.encrypt(value[i], value[i 0], key)
        flag_encrypt.append(res)
    ck = ez.check(flag_encrypt)
    if ck == 3:
        print('yes!!!,you get right flag')
    else:  # inserted
        print('wrong!!!')

可以观察到flag长度24,然后转成了大端序的整数,之后进行了2个一组的加密,我们大概可以猜出来是TEA家族的加密算法,随后程序进行了check。
我们手动import一下这个pyd
help(ez)的内容

Help on module ez:

NAME
    ez

FUNCTIONS
    FormatError(...)
        FormatError([integer]) -> string

        Convert a win32 error code into a string. If the error code is not
        given, the return value of a call to GetLastError() is used.

    POINTER(...)

    addressof(...)
        addressof(C instance) -> integer
        Return the address of the C instance internal buffer

    alignment(...)
        alignment(C type) -> integer
        alignment(C instance) -> integer
        Return the alignment requirements of a C instance

    byref(...)
        byref(C instance[, offset=0]) -> byref-object
        Return a pointer lookalike to a C instance, only usable
        as function argument

    check(flag_encrypt)

    encrypt(V0, V1, key)

    get_errno(...)

    get_last_error(...)

    pointer(...)

    resize(...)
        Resize the memory buffer of a ctypes instance

    set_errno(...)

    set_last_error(...)

    sizeof(...)
        sizeof(C type) -> integer
        sizeof(C instance) -> integer
        Return the size in bytes of a C instance

DATA
    DEFAULT_MODE = 0
    GetLastError = <_FuncPtr object>
    RTLD_GLOBAL = 0
    RTLD_LOCAL = 0
    __test__ = {}
    cdll = <ctypes.LibraryLoader object>
    data = [(3914733448, 1983234354), (342009100, 2529626303), (2587440738...
    #[(3914733448, 1983234354), (342009100, 2529626303), (2587440738, 819204946)]
#(2396885758, 685625361)
    memmove = <CFunctionType object>
    memset = <CFunctionType object>
    oledll = <ctypes.LibraryLoader object>
    pydll = <ctypes.LibraryLoader object>
    pythonapi = <PyDLL 'python dll', handle 7ffde60d0000>
    windll = <ctypes.LibraryLoader object>

FILE
    e:\ctf\ez.pyd

可以看到有个

data = [(3914733448, 1983234354), (342009100, 2529626303), (2587440738, 819204946)] (2396885758, 685625361)]

这应该是我们需要找的加密后的值,所以现在我们的分析点只需要在encrypt中就可以了。
Cython 逆向,pyd里面
x64dbg Hook
由于Python虚拟机的Number都是30bit,所以我经过了如下的处理来还原。

2024-12-15T08:33:10.png

PyNumber_And
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) & ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} & 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Add
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) + ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} + 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Xor
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) ^ ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} ^ 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_LShift
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) << ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} << 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_RShift
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) >> ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} >> 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Reminder
0x{([rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)) % ([rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e))} = 0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} % 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyNumber_Power
0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} ** 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}
PyObject_RichCompare
0x{[rcx+0x18] & 0xffffffff | (([rcx+0x18] >> 0x20) << 0x1e)} ?= 0x{[rdx+0x18] & 0xffffffff | (([rdx+0x18] >> 0x20) << 0x1e)}

输入

ez.encrypt(0xdead, 0xc0de, [0x1122, 0x3344, 0x5566, 0x7788])

然后可以得到trace

0x606F0 = 0xC0DE << 0x3
0x7FF8000303 = 0x1FFE0000C0DE >> 0x6
0x605F3 = 0x3000606F0 ^ 0x300000303
0x20010006C6D1 = 0x1FFE000605F3 + 0x30000C0DE
0x80001122 = 0x0 + 0x80001122
0x6D7F3 = 0x30006C6D1 ^ 0x300001122
0x3DB500 = 0x7B6A0 << 0x3
0x7FF8001EDA = 0x1FFE0007B6A0 >> 0x6
0x26B803DABDA = 0x268803DB500 ^ 0x300001EDA
0x20010045627A = 0x1FFE003DABDA + 0x30007B6A0
0xA8C8C = 0x54646454 >> 0xB
0xD4647576 = 0x54646454 + 0x80001122
0x268D421170C = 0x2688045627A ^ 0x54647576
0xA10EBF50 = 0x5421D7EA << 0x3
0x150875F = 0x5421D7EA >> 0x6
0x2E05E380F = 0x2A10EBF50 ^ 0x4150875F
0x2F4800FF9 = 0x2A05E380F + 0x5421D7EA
0xD4647576 = 0x54646454 + 0x80001122
0x2A0E47A8F = 0x2F4800FF9 ^ 0x54647576
0x7618978 = 0xA0EC312F << 0x3
0x283B0C4 = 0xA0EC312F >> 0x6
0x785E239BC = 0x507618978 ^ 0x28283B0C4
0x5A6CE6AEB = 0x505E239BC + 0xA0EC312F
....此处省略很多行

我们从头开始分析。

l = 0xdead
r = 0xc0de
k = [0x1122, 0x3344, 0x5566, 0x7788]

使用这几个值是因为可以在log中清晰看见。
然后跟着分析

v0 = r << 0x3
v1 = r >> 0x6
v2 = v0 ^ v1
v3 = v2 + r
v4 = v3 ^ k[0]
....

整合一下

v4 = (((r << 0x3) ^ (r >> 0x6)) + r) ^ k[0]
....

看得出来,这是XTEA,完整还原如下

l = 0xdead
r = 0xc0de
l += (((r << 3) ^ (r >> 6)) + r) ^ k[0]
l = 0x7B6A0
r += (((l << 3) ^ (l >> 6)) + l) ^ k[0]

后面的>>0xb,也可以说明问题,就是XTEA的左移右移数被改掉了,delta也被改掉了。
由于是第一轮加密,所以DELTA = SUM = 0x54646454,这一点可以很好从Trace里面看出来,然后我们加密对应一下,但是发现结果并不对,意识到可能是round的问题,我们写一个程序Fuzz一下,拿到round是64,也就是说他把XTEA的轮数魔改成了64,知道了上面的信息,我们就可以解出flag。
EXP

from regadgets.bits import byte2dword, dword2byte, pack_dword, bswap32
from typing import List, Tuple, Union
from ctypes import c_uint32
from struct import unpack
def xtea_decrypt(
    src: Union[Tuple[int, int], bytes, List[int]], key: Union[List[int], bytes], delta: int = 0x9E3779B9, rounds: int = 32
) -> Union[Tuple[int, int], bytes, List[int]]:
    # For bytes src
    if type(src) == bytes:
        result = b''
        for i in pack_dword(byte2dword(src)):
            result += dword2byte(xtea_decrypt(i, key, delta, rounds))
        return result
    # For list src
    elif type(src) == list:
        result = b''
        for i in pack_dword(src):
            result += dword2byte(xtea_decrypt(i, key, delta, rounds))
        return result
    elif type(src) != tuple:
        raise "wrong src type"
    # For bytes key
    if type(key) == bytes:
        key = byte2dword(key)
    elif type(key) != list:
        raise "wrong key type"

    l, r = c_uint32(src[0]), c_uint32(src[1])
    sum = c_uint32(delta * rounds)
    k = [c_uint32(key[0]), c_uint32(key[1]), c_uint32(key[2]), c_uint32(key[3])]
    for _ in range(rounds):
        # modified
        r.value -= (((l.value << 3) ^ (l.value >> 6)) + l.value) ^ (
            sum.value + k[(sum.value >> 11) & 3].value
        )
        sum.value -= delta
        # modified
        l.value -= (((r.value << 3) ^ (r.value >> 6)) + r.value) ^ (
            sum.value + k[sum.value & 3].value
        )
    return (l.value, r.value)

k = [102, 108, 97, 103]
enc = [3914733448, 1983234354, 342009100, 2529626303, 2587440738, 819204946]
dec = dword2byte(byte2dword(xtea_decrypt(enc, key=k, delta=0x54646454, rounds=64), endian='big'))
print(dec)
# b'flag{wYemsWPHCGC0ZRPqds}'

vt (赛后解出)

通过参数传递数据,然后程序会GetCommandline然后检测参数有几个,如果只有一个(用户传入的值),就CreateProcess并附加一个父进程的PID,随后子进程会DebugActiveProcess,通过参数的PID来调试父进程。在此同时,父进程会启动一个线程,循环检测IsDebuggerPresent,如果挂载了上去,则开始WaitDebugEvent。与此同时,子进程开始检测用户输入,正确后会解密flag并且输出(注意,输出的函数是GetProcAddress动态加载,所以直接x-ref不过去)。
载入IDA,很多花指令,关闭IDA。
启动x64dbg动态调试,指定参数,第二个PID随便输。断DebugActiveProcess
2024-12-16T17:46:04.png
修改返回值0->1,让进程以为Debug附加成功。此时子进程才会进入验证输入阶段。
程序有GetThreadContext,会检测当前线程的寄存器,反硬件断点。而且在调试的时候,由于多线程会乱跳线程,所以我们先把其他线程多暂停一次,保证我们调试的线程唯一。
程序通过CreateThread创建新线程,进入输入验证子函数。
2024-12-16T17:48:27.png
经过手动分析可以确定这两个函数分别是strlen和byte2hex。后面有一堆的mov都是局部数组变量的初始化,是一个固定的table,记作table0。我们直接对byte2hex的结果(rax)进行硬件断点,经过测试这边没有检测。可以跟踪到一个地方。
2024-12-16T17:50:17.png
这个地方由于我第一次输入的是1111222233334444,所以它表现为(table0[i] - 8) ^ 0x11,之后通过更改输入到1122才发现是XOR input[i % 2],并且只有这两个字节,后面的程序不读,所以输入是????(4个16进制数,而且由于byte2hex函数只支持将A-F大写字母转换,如果写a-f将被识别成0)。
X64dbg Trace
2024-12-16T17:52:33.png
经过第一步后,程序进入下一阶段,我们硬件断点第一步的结果来追踪。我们发现两个点,一个是>>1,一个是>>1 后 xor 一个常数,显然是类似CRC32的东西。
X64dbg Trace
2024-12-16T17:53:33.png

FFFFFFBC = FFFFFFFF^43
7FFFFFDE = FFFFFFBC >> 1
3FFFFFEF = 7FFFFFDE >> 1
F2477CD7 = (3FFFFFEF >> 1) ^ 0xedb88320
949B3D4B = (F2477CD7 >> 1) ^ 0xedb88320
A7F51D85 = (949B3D4B >> 1) ^ 0xedb88320
BE420DE2 = (A7F51D85 >> 1) ^ 0xedb88320
5F2106F1 = BE420DE2 >> 1
C2280058 = (5F2106F1 >> 1) ^ 0xedb88320
C228009B = C2280058^C3
8CAC836D = (C228009B >> 1) ^ 0xedb88320
ABEEC296 = (8CAC836D >> 1) ^ 0xedb88320
55F7614B = ABEEC296 >> 1
C7433385 = (55F7614B >> 1) ^ 0xedb88320
8E191AE2 = (C7433385 >> 1) ^ 0xedb88320
470C8D71 = 8E191AE2 >> 1
CE3EC598 = (470C8D71 >> 1) ^ 0xedb88320
671F62CC = CE3EC598 >> 1
671F6299 = 671F62CC^55
DE37326C = (671F6299 >> 1) ^ 0xedb88320
6F1B9936 = DE37326C >> 1
378DCC9B = 6F1B9936 >> 1
F67E656D = (378DCC9B >> 1) ^ 0xedb88320
9687B196 = (F67E656D >> 1) ^ 0xedb88320
4B43D8CB = 9687B196 >> 1
C8196F45 = (4B43D8CB >> 1) ^ 0xedb88320
89B43482 = (C8196F45 >> 1) ^ 0xedb88320
89B43442 = 89B43482^C0
44DA1A21 = 89B43442 >> 1
CFD58E30 = (44DA1A21 >> 1) ^ 0xedb88320
67EAC718 = CFD58E30 >> 1
33F5638C = 67EAC718 >> 1
19FAB1C6 = 33F5638C >> 1
CFD58E3 = 19FAB1C6 >> 1
EBC62F51 = (CFD58E3 >> 1) ^ 0xedb88320
985B9488 = (EBC62F51 >> 1) ^ 0xedb88320
985B94A0 = 985B9488^28
4C2DCA50 = 985B94A0 >> 1
2616E528 = 4C2DCA50 >> 1
130B7294 = 2616E528 >> 1
985B94A = 130B7294 >> 1
4C2DCA5 = 985B94A >> 1
EFD9ED72 = (4C2DCA5 >> 1) ^ 0xedb88320
77ECF6B9 = EFD9ED72 >> 1
D64EF87C = (77ECF6B9 >> 1) ^ 0xedb88320
D64EF8BF = D64EF87C^C3
869FFF7F = (D64EF8BF >> 1) ^ 0xedb88320
AEF77C9F = (869FFF7F >> 1) ^ 0xedb88320
BAC33D6F = (AEF77C9F >> 1) ^ 0xedb88320
B0D91D97 = (BAC33D6F >> 1) ^ 0xedb88320
B5D40DEB = (B0D91D97 >> 1) ^ 0xedb88320
B75285D5 = (B5D40DEB >> 1) ^ 0xedb88320
B611C1CA = (B75285D5 >> 1) ^ 0xedb88320
5B08E0E5 = B611C1CA >> 1
5B08E0AA = 5B08E0E5^4F
2D847055 = 5B08E0AA >> 1
FB7ABB0A = (2D847055 >> 1) ^ 0xedb88320
7DBD5D85 = FB7ABB0A >> 1
D3662DE2 = (7DBD5D85 >> 1) ^ 0xedb88320
69B316F1 = D3662DE2 >> 1
D9610858 = (69B316F1 >> 1) ^ 0xedb88320
6CB0842C = D9610858 >> 1
36584216 = 6CB0842C >> 1
365842AF = 36584216^B9
F694A277 = (365842AF >> 1) ^ 0xedb88320
96F2D21B = (F694A277 >> 1) ^ 0xedb88320
A6C1EA2D = (96F2D21B >> 1) ^ 0xedb88320
BED87636 = (A6C1EA2D >> 1) ^ 0xedb88320
5F6C3B1B = BED87636 >> 1
C20E9EAD = (5F6C3B1B >> 1) ^ 0xedb88320
8CBFCC76 = (C20E9EAD >> 1) ^ 0xedb88320
465FE63B = 8CBFCC76 >> 1
465FE67B = 465FE63B^40
CE97701D = (465FE67B >> 1) ^ 0xedb88320
8AF33B2E = (CE97701D >> 1) ^ 0xedb88320
45799D97 = 8AF33B2E >> 1
CF044DEB = (45799D97 >> 1) ^ 0xedb88320
8A3AA5D5 = (CF044DEB >> 1) ^ 0xedb88320
A8A5D1CA = (8A3AA5D5 >> 1) ^ 0xedb88320
5452E8E5 = A8A5D1CA >> 1
C791F752 = (5452E8E5 >> 1) ^ 0xedb88320
C791F7AC = C791F752^FE
63C8FBD6 = C791F7AC >> 1
31E47DEB = 63C8FBD6 >> 1
F54ABDD5 = (31E47DEB >> 1) ^ 0xedb88320
971DDDCA = (F54ABDD5 >> 1) ^ 0xedb88320
4B8EEEE5 = 971DDDCA >> 1
C87FF452 = (4B8EEEE5 >> 1) ^ 0xedb88320
643FFA29 = C87FF452 >> 1
DFA77E34 = (643FFA29 >> 1) ^ 0xedb88320
DFA77E3C = DFA77E34^8
6FD3BF1E = DFA77E3C >> 1
37E9DF8F = 6FD3BF1E >> 1
F64C6CE7 = (37E9DF8F >> 1) ^ 0xedb88320
969EB553 = (F64C6CE7 >> 1) ^ 0xedb88320
A6F7D989 = (969EB553 >> 1) ^ 0xedb88320
BEC36FE4 = (A6F7D989 >> 1) ^ 0xedb88320
5F61B7F2 = BEC36FE4 >> 1
2FB0DBF9 = 5F61B7F2 >> 1
2FB0DB43 = 2FB0DBF9^BA
FA60EE81 = (2FB0DB43 >> 1) ^ 0xedb88320
9088F460 = (FA60EE81 >> 1) ^ 0xedb88320
48447A30 = 9088F460 >> 1
24223D18 = 48447A30 >> 1
12111E8C = 24223D18 >> 1
9088F46 = 12111E8C >> 1
48447A3 = 9088F46 >> 1
EFFAA0F1 = (48447A3 >> 1) ^ 0xedb88320
EFFAA0B0 = EFFAA0F1^41
77FD5058 = EFFAA0B0 >> 1
3BFEA82C = 77FD5058 >> 1
1DFF5416 = 3BFEA82C >> 1
EFFAA0B = 1DFF5416 >> 1
EAC75625 = (EFFAA0B >> 1) ^ 0xedb88320
98DB2832 = (EAC75625 >> 1) ^ 0xedb88320
4C6D9419 = 98DB2832 >> 1
CB8E492C = (4C6D9419 >> 1) ^ 0xedb88320
CB8E499C = CB8E492C^B0
65C724CE = CB8E499C >> 1
32E39267 = 65C724CE >> 1
F4C94A13 = (32E39267 >> 1) ^ 0xedb88320
97DC2629 = (F4C94A13 >> 1) ^ 0xedb88320
A6569034 = (97DC2629 >> 1) ^ 0xedb88320
532B481A = A6569034 >> 1
2995A40D = 532B481A >> 1
F9725126 = (2995A40D >> 1) ^ 0xedb88320
F972510E = F9725126^28
7CB92887 = F972510E >> 1
D3E41763 = (7CB92887 >> 1) ^ 0xedb88320
844A8891 = (D3E41763 >> 1) ^ 0xedb88320
AF9DC768 = (844A8891 >> 1) ^ 0xedb88320
57CEE3B4 = AF9DC768 >> 1
2BE771DA = 57CEE3B4 >> 1
15F3B8ED = 2BE771DA >> 1
E7415F56 = (15F3B8ED >> 1) ^ 0xedb88320
E7415FB5 = E7415F56^E3
9E182CFA = (E7415FB5 >> 1) ^ 0xedb88320
4F0C167D = 9E182CFA >> 1
CA3E881E = (4F0C167D >> 1) ^ 0xedb88320
651F440F = CA3E881E >> 1
DF372127 = (651F440F >> 1) ^ 0xedb88320
822313B3 = (DF372127 >> 1) ^ 0xedb88320
ACA90AF9 = (822313B3 >> 1) ^ 0xedb88320
BBEC065C = (ACA90AF9 >> 1) ^ 0xedb88320
BBEC061D = BBEC065C^41
B04E802E = (BBEC061D >> 1) ^ 0xedb88320
58274017 = B04E802E >> 1
C1AB232B = (58274017 >> 1) ^ 0xedb88320
8D6D12B5 = (C1AB232B >> 1) ^ 0xedb88320
AB0E0A7A = (8D6D12B5 >> 1) ^ 0xedb88320
5587053D = AB0E0A7A >> 1
C77B01BE = (5587053D >> 1) ^ 0xedb88320
63BD80DF = C77B01BE >> 1
63BD8063 = 63BD80DF^BC
DC664311 = (63BD8063 >> 1) ^ 0xedb88320
838BA2A8 = (DC664311 >> 1) ^ 0xedb88320
41C5D154 = 838BA2A8 >> 1
20E2E8AA = 41C5D154 >> 1
10717455 = 20E2E8AA >> 1
E580390A = (10717455 >> 1) ^ 0xedb88320
72C01C85 = E580390A >> 1
D4D88D62 = (72C01C85 >> 1) ^ 0xedb88320
D4D88D21 = D4D88D62^43
87D4C5B0 = (D4D88D21 >> 1) ^ 0xedb88320
43EA62D8 = 87D4C5B0 >> 1
21F5316C = 43EA62D8 >> 1
10FA98B6 = 21F5316C >> 1
87D4C5B = 10FA98B6 >> 1
E986250D = (87D4C5B >> 1) ^ 0xedb88320
997B91A6 = (E986250D >> 1) ^ 0xedb88320
4CBDC8D3 = 997B91A6 >> 1
4CBDC873 = 4CBDC8D3^A0
CBE66719 = (4CBDC873 >> 1) ^ 0xedb88320
884BB0AC = (CBE66719 >> 1) ^ 0xedb88320
4425D856 = 884BB0AC >> 1
2212EC2B = 4425D856 >> 1
FCB1F535 = (2212EC2B >> 1) ^ 0xedb88320
93E079BA = (FCB1F535 >> 1) ^ 0xedb88320
49F03CDD = 93E079BA >> 1
C9409D4E = (49F03CDD >> 1) ^ 0xedb88320
C9409D78 = C9409D4E^36
64A04EBC = C9409D78 >> 1
3250275E = 64A04EBC >> 1
192813AF = 3250275E >> 1
E12C8AF7 = (192813AF >> 1) ^ 0xedb88320
9D2EC65B = (E12C8AF7 >> 1) ^ 0xedb88320
A32FE00D = (9D2EC65B >> 1) ^ 0xedb88320
BC2F7326 = (A32FE00D >> 1) ^ 0xedb88320
5E17B993 = BC2F7326 >> 1
5E17B933 = 5E17B993^A0
C2B35FB9 = (5E17B933 >> 1) ^ 0xedb88320
8CE12CFC = (C2B35FB9 >> 1) ^ 0xedb88320
4670967E = 8CE12CFC >> 1
23384B3F = 4670967E >> 1
FC24A6BF = (23384B3F >> 1) ^ 0xedb88320
93AAD07F = (FC24A6BF >> 1) ^ 0xedb88320
A46DEB1F = (93AAD07F >> 1) ^ 0xedb88320
BF8E76AF = (A46DEB1F >> 1) ^ 0xedb88320
BF8E7698 = BF8E76AF^37
5FC73B4C = BF8E7698 >> 1
2FE39DA6 = 5FC73B4C >> 1
17F1CED3 = 2FE39DA6 >> 1
E6406449 = (17F1CED3 >> 1) ^ 0xedb88320
9E98B104 = (E6406449 >> 1) ^ 0xedb88320
4F4C5882 = 9E98B104 >> 1
27A62C41 = 4F4C5882 >> 1
FE6B9500 = (27A62C41 >> 1) ^ 0xedb88320
FE6B95C5 = FE6B9500^C5
928D49C2 = (FE6B95C5 >> 1) ^ 0xedb88320
4946A4E1 = 928D49C2 >> 1
C91BD150 = (4946A4E1 >> 1) ^ 0xedb88320
648DE8A8 = C91BD150 >> 1
3246F454 = 648DE8A8 >> 1
19237A2A = 3246F454 >> 1
C91BD15 = 19237A2A >> 1
EBF05DAA = (C91BD15 >> 1) ^ 0xedb88320
EBF05DE8 = EBF05DAA^42
75F82EF4 = EBF05DE8 >> 1
3AFC177A = 75F82EF4 >> 1
1D7E0BBD = 3AFC177A >> 1
E30786FE = (1D7E0BBD >> 1) ^ 0xedb88320
7183C37F = E30786FE >> 1
D579629F = (7183C37F >> 1) ^ 0xedb88320
8704326F = (D579629F >> 1) ^ 0xedb88320
AE3A9A17 = (8704326F >> 1) ^ 0xedb88320
AE3A9AB5 = AE3A9A17^A2
BAA5CE7A = (AE3A9AB5 >> 1) ^ 0xedb88320
5D52E73D = BAA5CE7A >> 1
C311F0BE = (5D52E73D >> 1) ^ 0xedb88320
6188F85F = C311F0BE >> 1
DD7CFF0F = (6188F85F >> 1) ^ 0xedb88320
8306FCA7 = (DD7CFF0F >> 1) ^ 0xedb88320
AC3BFD73 = (8306FCA7 >> 1) ^ 0xedb88320
BBA57D99 = (AC3BFD73 >> 1) ^ 0xedb88320
BBA57DAC = BBA57D99^35
5DD2BED6 = BBA57DAC >> 1
2EE95F6B = 5DD2BED6 >> 1
FACC2C95 = (2EE95F6B >> 1) ^ 0xedb88320
90DE956A = (FACC2C95 >> 1) ^ 0xedb88320
486F4AB5 = 90DE956A >> 1
C98F267A = (486F4AB5 >> 1) ^ 0xedb88320
64C7933D = C98F267A >> 1
DFDB4ABE = (64C7933D >> 1) ^ 0xedb88320
DFDB4A1C = DFDB4ABE^A2
6FEDA50E = DFDB4A1C >> 1
37F6D287 = 6FEDA50E >> 1
F643EA63 = (37F6D287 >> 1) ^ 0xedb88320
96997611 = (F643EA63 >> 1) ^ 0xedb88320
A6F43828 = (96997611 >> 1) ^ 0xedb88320
537A1C14 = A6F43828 >> 1
29BD0E0A = 537A1C14 >> 1
14DE8705 = 29BD0E0A >> 1
14DE8756 = 14DE8705^53
A6F43AB = 14DE8756 >> 1
E88F22F5 = (A6F43AB >> 1) ^ 0xedb88320
99FF125A = (E88F22F5 >> 1) ^ 0xedb88320
4CFF892D = 99FF125A >> 1
CBC747B6 = (4CFF892D >> 1) ^ 0xedb88320
65E3A3DB = CBC747B6 >> 1
DF4952CD = (65E3A3DB >> 1) ^ 0xedb88320
821C2A46 = (DF4952CD >> 1) ^ 0xedb88320
821C2AB8 = 821C2A46^FE
410E155C = 821C2AB8 >> 1
20870AAE = 410E155C >> 1
10438557 = 20870AAE >> 1
E599418B = (10438557 >> 1) ^ 0xedb88320
9F7423E5 = (E599418B >> 1) ^ 0xedb88320
A20292D2 = (9F7423E5 >> 1) ^ 0xedb88320
51014969 = A20292D2 >> 1
C5382794 = (51014969 >> 1) ^ 0xedb88320
C53827BC = C5382794^28
629C13DE = C53827BC >> 1
314E09EF = 629C13DE >> 1
F51F87D7 = (314E09EF >> 1) ^ 0xedb88320
973740CB = (F51F87D7 >> 1) ^ 0xedb88320
A6232345 = (973740CB >> 1) ^ 0xedb88320
BEA91282 = (A6232345 >> 1) ^ 0xedb88320
5F548941 = BEA91282 >> 1
C212C780 = (5F548941 >> 1) ^ 0xedb88320
C212C73C = C212C780^BC
6109639E = C212C73C >> 1
3084B1CF = 6109639E >> 1
F5FADBC7 = (3084B1CF >> 1) ^ 0xedb88320
9745EEC3 = (F5FADBC7 >> 1) ^ 0xedb88320
A61A7441 = (9745EEC3 >> 1) ^ 0xedb88320
BEB5B900 = (A61A7441 >> 1) ^ 0xedb88320
5F5ADC80 = BEB5B900 >> 1
2FAD6E40 = 5F5ADC80 >> 1
2FAD6E53 = 2FAD6E40^13
FA6E3409 = (2FAD6E53 >> 1) ^ 0xedb88320
908F9924 = (FA6E3409 >> 1) ^ 0xedb88320
4847CC92 = 908F9924 >> 1
2423E649 = 4847CC92 >> 1
FFA97004 = (2423E649 >> 1) ^ 0xedb88320
7FD4B802 = FFA97004 >> 1
3FEA5C01 = 7FD4B802 >> 1
F24DAD20 = (3FEA5C01 >> 1) ^ 0xedb88320
F24DAD96 = F24DAD20^B6
7926D6CB = F24DAD96 >> 1
D12BE845 = (7926D6CB >> 1) ^ 0xedb88320
852D7702 = (D12BE845 >> 1) ^ 0xedb88320
4296BB81 = 852D7702 >> 1
CCF3DEE0 = (4296BB81 >> 1) ^ 0xedb88320
6679EF70 = CCF3DEE0 >> 1
333CF7B8 = 6679EF70 >> 1
199E7BDC = 333CF7B8 >> 1
199E7BEA = 199E7BDC^36
CCF3DF5 = 199E7BEA >> 1
EBDF1DDA = (CCF3DF5 >> 1) ^ 0xedb88320
75EF8EED = EBDF1DDA >> 1
D74F4456 = (75EF8EED >> 1) ^ 0xedb88320
6BA7A22B = D74F4456 >> 1
D86B5235 = (6BA7A22B >> 1) ^ 0xedb88320
818D2A3A = (D86B5235 >> 1) ^ 0xedb88320
40C6951D = 818D2A3A >> 1
40C695BE = 40C6951D^A3
20634ADF = 40C695BE >> 1
FD89264F = (20634ADF >> 1) ^ 0xedb88320
937C1007 = (FD89264F >> 1) ^ 0xedb88320
A4068B23 = (937C1007 >> 1) ^ 0xedb88320
BFBBC6B1 = (A4068B23 >> 1) ^ 0xedb88320
B2656078 = (BFBBC6B1 >> 1) ^ 0xedb88320
5932B03C = B2656078 >> 1
2C99581E = 5932B03C >> 1
2C99584A = 2C99581E^54
164CAC25 = 2C99584A >> 1
E69ED532 = (164CAC25 >> 1) ^ 0xedb88320
734F6A99 = E69ED532 >> 1
D41F366C = (734F6A99 >> 1) ^ 0xedb88320
6A0F9B36 = D41F366C >> 1
3507CD9B = 6A0F9B36 >> 1
F73B65ED = (3507CD9B >> 1) ^ 0xedb88320
962531D6 = (F73B65ED >> 1) ^ 0xedb88320
96253177 = 962531D6^A1
A6AA1B9B = (96253177 >> 1) ^ 0xedb88320
BEED8EED = (A6AA1B9B >> 1) ^ 0xedb88320
B2CE4456 = (BEED8EED >> 1) ^ 0xedb88320
5967222B = B2CE4456 >> 1
C10B1235 = (5967222B >> 1) ^ 0xedb88320
8D3D0A3A = (C10B1235 >> 1) ^ 0xedb88320
469E851D = 8D3D0A3A >> 1
CEF7C1AE = (469E851D >> 1) ^ 0xedb88320
CEF7C1EE = CEF7C1AE^40
677BE0F7 = CEF7C1EE >> 1
DE05735B = (677BE0F7 >> 1) ^ 0xedb88320
82BA3A8D = (DE05735B >> 1) ^ 0xedb88320
ACE59E66 = (82BA3A8D >> 1) ^ 0xedb88320
5672CF33 = ACE59E66 >> 1
C681E4B9 = (5672CF33 >> 1) ^ 0xedb88320
8EF8717C = (C681E4B9 >> 1) ^ 0xedb88320
477C38BE = 8EF8717C >> 1
477C380F = 477C38BE^B1
CE069F27 = (477C380F >> 1) ^ 0xedb88320
8ABBCCB3 = (CE069F27 >> 1) ^ 0xedb88320
A8E56579 = (8ABBCCB3 >> 1) ^ 0xedb88320
B9CA319C = (A8E56579 >> 1) ^ 0xedb88320
5CE518CE = B9CA319C >> 1
2E728C67 = 5CE518CE >> 1
FA81C513 = (2E728C67 >> 1) ^ 0xedb88320
90F861A9 = (FA81C513 >> 1) ^ 0xedb88320
90F861BA = 90F861A9^13
487C30DD = 90F861BA >> 1
C9869B4E = (487C30DD >> 1) ^ 0xedb88320
64C34DA7 = C9869B4E >> 1
DFD925F3 = (64C34DA7 >> 1) ^ 0xedb88320
825411D9 = (DFD925F3 >> 1) ^ 0xedb88320
AC928BCC = (825411D9 >> 1) ^ 0xedb88320
564945E6 = AC928BCC >> 1
2B24A2F3 = 564945E6 >> 1
2B24A251 = 2B24A2F3^A2
F82AD208 = (2B24A251 >> 1) ^ 0xedb88320
7C156904 = F82AD208 >> 1
3E0AB482 = 7C156904 >> 1
1F055A41 = 3E0AB482 >> 1
E23A2E00 = (1F055A41 >> 1) ^ 0xedb88320
711D1700 = E23A2E00 >> 1
388E8B80 = 711D1700 >> 1
1C4745C0 = 388E8B80 >> 1
1C474595 = 1C4745C0^55
E39B21EA = (1C474595 >> 1) ^ 0xedb88320
71CD90F5 = E39B21EA >> 1
D55E4B5A = (71CD90F5 >> 1) ^ 0xedb88320
6AAF25AD = D55E4B5A >> 1
D8EF11F6 = (6AAF25AD >> 1) ^ 0xedb88320
6C7788FB = D8EF11F6 >> 1
DB83475D = (6C7788FB >> 1) ^ 0xedb88320
8079208E = (DB83475D >> 1) ^ 0xedb88320
8079202D = 8079208E^A3
AD841336 = (8079202D >> 1) ^ 0xedb88320
56C2099B = AD841336 >> 1
C6D987ED = (56C2099B >> 1) ^ 0xedb88320
8ED440D6 = (C6D987ED >> 1) ^ 0xedb88320
476A206B = 8ED440D6 >> 1
CE0D9315 = (476A206B >> 1) ^ 0xedb88320
8ABE4AAA = (CE0D9315 >> 1) ^ 0xedb88320
455F2555 = 8ABE4AAA >> 1
455F2500 = 455F2555^55
22AF9280 = 455F2500 >> 1
1157C940 = 22AF9280 >> 1
8ABE4A0 = 1157C940 >> 1
455F250 = 8ABE4A0 >> 1
22AF928 = 455F250 >> 1
1157C94 = 22AF928 >> 1
8ABE4A = 1157C94 >> 1
455F25 = 8ABE4A >> 1
455F86 = 455F25^A3
22AFC3 = 455F86 >> 1
EDA9D4C1 = (22AFC3 >> 1) ^ 0xedb88320
9B6C6940 = (EDA9D4C1 >> 1) ^ 0xedb88320
4DB634A0 = 9B6C6940 >> 1
26DB1A50 = 4DB634A0 >> 1
136D8D28 = 26DB1A50 >> 1
9B6C694 = 136D8D28 >> 1
4DB634A = 9B6C694 >> 1
4DB631F = 4DB634A^55
EFD532AF = (4DB631F >> 1) ^ 0xedb88320
9A521A77 = (EFD532AF >> 1) ^ 0xedb88320
A0918E1B = (9A521A77 >> 1) ^ 0xedb88320
BDF0442D = (A0918E1B >> 1) ^ 0xedb88320
B340A136 = (BDF0442D >> 1) ^ 0xedb88320
59A0509B = B340A136 >> 1
C168AB6D = (59A0509B >> 1) ^ 0xedb88320
8D0CD696 = (C168AB6D >> 1) ^ 0xedb88320
8D0CD635 = 8D0CD696^A3
AB3EE83A = (8D0CD635 >> 1) ^ 0xedb88320
559F741D = AB3EE83A >> 1
C777392E = (559F741D >> 1) ^ 0xedb88320
63BB9C97 = C777392E >> 1
DC654D6B = (63BB9C97 >> 1) ^ 0xedb88320
838A2595 = (DC654D6B >> 1) ^ 0xedb88320
AC7D91EA = (838A2595 >> 1) ^ 0xedb88320
563EC8F5 = AC7D91EA >> 1

算法抄出来

def crc(n):
    for _ in range(8):
        if n % 2 != 0:
            # print(f"{hex((n >> 1) ^ 0xedb88320)} = ({hex(n)} >> 1) ^ 0xedb88320")
            n = (n >> 1) ^ 0xedb88320
            n &= 0xffffffff
        else:
            # print(f"{hex(n >> 1)} = {hex(n)} >> 1")
            n = n >> 1
            n &= 0xffffffff
    return n

def enc1(a):
    table = bytes.fromhex('5A E9 4C EA 41 E9 66 A3 59 E4 21 A0 58 9A 41 C9 58 A6 5A 8A 2F 8A 2E EF 5B 88 2C 88 4A E4 41 A6 0A 9C 2F 89 4D 8B 59 9B 0A 88 4C 89 4C 89 4C 89')
    enc = [a[i % 2] ^ ((table[i] - 8) & 0xff) for i in range(len(table))]
    # print([hex(i) for i in enc])
    r = 0xffffffff
    for i in enc:
        r ^= i
        r = crc(r)
    r ^= 0xffffffff
    return r

最后我们使用X64dbg条件断点来断最后的数据,然后进行追踪,我们可以跳到一个CMP。
2024-12-16T17:55:35.png
原理是我们的输入减去常数和0比较,然后通过setne设置al,之后是一个混淆后的比较,最后的结果体现在下面的ecx。
2024-12-16T17:56:22.png
这个je,不跳转是EXIT,跳转是正确,解密flag。
第一次到这直接改标志位了,但是flag没输出,应该是用输入来进行解密的。
我们可以看到刚刚的cmp,只要结果是CRC的结果就可以,我们选择BruteForce

for i in range(256):
    for j in range(256):
        if enc1([i, j]) == 0xF703DF16:
            print(hex(i), hex(j))
            break

所以EXP是

def crc(n):
    for _ in range(8):
        if n % 2 != 0:
            # print(f"{hex((n >> 1) ^ 0xedb88320)} = ({hex(n)} >> 1) ^ 0xedb88320")
            n = (n >> 1) ^ 0xedb88320
            n &= 0xffffffff
        else:
            # print(f"{hex(n >> 1)} = {hex(n)} >> 1")
            n = n >> 1
            n &= 0xffffffff
    return n

def enc1(a):
    table = bytes.fromhex('5A E9 4C EA 41 E9 66 A3 59 E4 21 A0 58 9A 41 C9 58 A6 5A 8A 2F 8A 2E EF 5B 88 2C 88 4A E4 41 A6 0A 9C 2F 89 4D 8B 59 9B 0A 88 4C 89 4C 89 4C 89')
    enc = [a[i % 2] ^ ((table[i] - 8) & 0xff) for i in range(len(table))]
    # print([hex(i) for i in enc])
    r = 0xffffffff
    for i in enc:
        r ^= i
        r = crc(r)
    r ^= 0xffffffff
    return r

for i in range(256):
    for j in range(256):
        if enc1([i, j]) == 0xF703DF16:
            print(hex(i), hex(j))
            break
0x79 0xbc

输入79BC就可以解出flag。

顺便分析一下解密flag的地方,先malloc,再memset,然后
解密前:
2024-12-16T17:58:06.png
解密后:
2024-12-16T17:58:22.png
2024-12-16T17:59:00.png
flag{MjExNTY3MzE3NTQzMjI=}

vm

Windows下的VM
二血。
拖入IDA,可以直接观察到一个SIMD优化的RC4_init,直接看下面的单字节部分就行了,上面的优化只是对于整16字节进行的快速处理,而下面就是对余16字节后的进行的处理。
2024-12-06T06:14:38.png

然后sub_140001970里面是RC4的优化展开。
2024-12-06T06:14:48.png
最后程序直接输出了这个。我们发现rc4的key传入了这个函数,并且这个函数会校验这个key是否正确
2024-12-06T06:15:00.png
该函数就是一个标准的栈VM了。
2024-12-06T06:15:11.png
于是我们直接开始调试,找到下面几个关键点:
2024-12-06T06:15:21.png
2024-12-06T06:15:25.png
2024-12-06T06:15:30.png
VM_sub, VM_div 没调用,所以就不管了,调用的是VM_Add
然后去Xdbg中打断点输出
输入一组测试数据

abcdefghijklmnopqrstuvwxyzABCDEF

我们可以trace出以下结果

INT3 breakpoint at secret_box.00007FF77B1820E3!
1 = (61 >> 0) & 1
2 = 1 * 2
0 = (61 >> 1) & 1
0 = 0 * 3
0 = (61 >> 2) & 1
0 = 0 * 43
0 = (61 >> 3) & 1
0 = 0 * 25
0 = (61 >> 4) & 1
0 = 0 * 29
1 = (61 >> 5) & 1
B = 1 * B
1 = (61 >> 6) & 1
D = 1 * D
0 = (61 >> 7) & 1
0 = 0 * 59
D = D + 0
18 = B + D
18 = 0 + 18
18 = 0 + 18
18 = 0 + 18
18 = 0 + 18
1A = 2 + 18
5C = 1A ^ 46
0 = (62 >> 0) & 1
0 = 0 * 2
1 = (62 >> 1) & 1
3 = 1 * 3
0 = (62 >> 2) & 1
0 = 0 * 43
0 = (62 >> 3) & 1
0 = 0 * 5
0 = (62 >> 4) & 1
0 = 0 * 7
1 = (62 >> 5) & 1
2F = 1 * 2F
1 = (62 >> 6) & 1
3D = 1 * 3D
0 = (62 >> 7) & 1
0 = 0 * 1D
3D = 3D + 0
6C = 2F + 3D
6C = 0 + 6C
6C = 0 + 6C
6C = 0 + 6C
6F = 3 + 6C
6F = 0 + 6F
57 = 6F ^ 38
1 = (63 >> 0) & 1
2 = 1 * 2
1 = (63 >> 1) & 1
43 = 1 * 43
0 = (63 >> 2) & 1
0 = 0 * 25
0 = (63 >> 3) & 1
0 = 0 * 7
0 = (63 >> 4) & 1
0 = 0 * 2B
1 = (63 >> 5) & 1
B = 1 * B
1 = (63 >> 6) & 1
D = 1 * D
0 = (63 >> 7) & 1
0 = 0 * 1F
D = D + 0
18 = B + D
18 = 0 + 18
18 = 0 + 18
18 = 0 + 18
5B = 43 + 18
5D = 2 + 5B
1B = 5D ^ 46
0 = (64 >> 0) & 1
0 = 0 * 61
0 = (64 >> 1) & 1
0 = 0 * 3
1 = (64 >> 2) & 1
29 = 1 * 29
0 = (64 >> 3) & 1
0 = 0 * 49
0 = (64 >> 4) & 1
0 = 0 * B
1 = (64 >> 5) & 1
D = 1 * D
1 = (64 >> 6) & 1
35 = 1 * 35
0 = (64 >> 7) & 1
0 = 0 * 1D
35 = 35 + 0
42 = D + 35
42 = 0 + 42
42 = 0 + 42
6B = 29 + 42
6B = 0 + 6B
6B = 0 + 6B
26 = 6B ^ 4D
1 = (65 >> 0) & 1
61 = 1 * 61
0 = (65 >> 1) & 1
0 = 0 * 43
1 = (65 >> 2) & 1
3 = 1 * 3
0 = (65 >> 3) & 1
0 = 0 * B
0 = (65 >> 4) & 1
0 = 0 * 2B
1 = (65 >> 5) & 1
D = 1 * D
1 = (65 >> 6) & 1
2F = 1 * 2F
0 = (65 >> 7) & 1
0 = 0 * 53
2F = 2F + 0
3C = D + 2F
3C = 0 + 3C
3C = 0 + 3C
3F = 3 + 3C
3F = 0 + 3F
A0 = 61 + 3F
EA = A0 ^ 4A
0 = (66 >> 0) & 1
0 = 0 * 43
1 = (66 >> 1) & 1
5 = 1 * 5
1 = (66 >> 2) & 1
25 = 1 * 25
0 = (66 >> 3) & 1
0 = 0 * 47
0 = (66 >> 4) & 1
0 = 0 * 7
1 = (66 >> 5) & 1
B = 1 * B
1 = (66 >> 6) & 1
59 = 1 * 59
0 = (66 >> 7) & 1
0 = 0 * 1D
59 = 59 + 0
64 = B + 59
64 = 0 + 64
64 = 0 + 64
89 = 25 + 64
8E = 5 + 89
8E = 0 + 8E
D4 = 8E ^ 5A
1 = (67 >> 0) & 1
2 = 1 * 2
1 = (67 >> 1) & 1
3 = 1 * 3
1 = (67 >> 2) & 1
5 = 1 * 5
0 = (67 >> 3) & 1
0 = 0 * B
0 = (67 >> 4) & 1
0 = 0 * D
1 = (67 >> 5) & 1
53 = 1 * 53
1 = (67 >> 6) & 1
35 = 1 * 35
0 = (67 >> 7) & 1
0 = 0 * 3D
35 = 35 + 0
88 = 53 + 35
88 = 0 + 88
88 = 0 + 88
8D = 5 + 88
90 = 3 + 8D
92 = 2 + 90
C5 = 92 ^ 57
0 = (68 >> 0) & 1
0 = 0 * 2
0 = (68 >> 1) & 1
0 = 0 * 3
0 = (68 >> 2) & 1
0 = 0 * 7
1 = (68 >> 3) & 1
47 = 1 * 47
0 = (68 >> 4) & 1
0 = 0 * 2B
1 = (68 >> 5) & 1
53 = 1 * 53
1 = (68 >> 6) & 1
1D = 1 * 1D
0 = (68 >> 7) & 1
0 = 0 * 1F
1D = 1D + 0
70 = 53 + 1D
70 = 0 + 70
B7 = 47 + 70
B7 = 0 + B7
B7 = 0 + B7
B7 = 0 + B7
E5 = B7 ^ 52
1 = (69 >> 0) & 1
7 = 1 * 7
0 = (69 >> 1) & 1
0 = 0 * 49
0 = (69 >> 2) & 1
0 = 0 * B
1 = (69 >> 3) & 1
D = 1 * D
0 = (69 >> 4) & 1
0 = 0 * 35
1 = (69 >> 5) & 1
59 = 1 * 59
1 = (69 >> 6) & 1
1D = 1 * 1D
0 = (69 >> 7) & 1
0 = 0 * 1F
1D = 1D + 0
76 = 59 + 1D
76 = 0 + 76
83 = D + 76
83 = 0 + 83
83 = 0 + 83
8A = 7 + 83
B6 = 8A ^ 3C
0 = (6A >> 0) & 1
0 = 0 * 2
1 = (6A >> 1) & 1
3 = 1 * 3
0 = (6A >> 2) & 1
0 = 0 * 5
1 = (6A >> 3) & 1
25 = 1 * 25
0 = (6A >> 4) & 1
0 = 0 * 7
1 = (6A >> 5) & 1
2B = 1 * 2B
1 = (6A >> 6) & 1
D = 1 * D
0 = (6A >> 7) & 1
0 = 0 * 3D
D = D + 0
38 = 2B + D
38 = 0 + 38
5D = 25 + 38
5D = 0 + 5D
60 = 3 + 5D
60 = 0 + 60
23 = 60 ^ 43
1 = (6B >> 0) & 1
2 = 1 * 2
1 = (6B >> 1) & 1
5 = 1 * 5
0 = (6B >> 2) & 1
0 = 0 * 7
1 = (6B >> 3) & 1
2B = 1 * 2B
0 = (6B >> 4) & 1
0 = 0 * B
1 = (6B >> 5) & 1
D = 1 * D
1 = (6B >> 6) & 1
35 = 1 * 35
0 = (6B >> 7) & 1
0 = 0 * 59
35 = 35 + 0
42 = D + 35
42 = 0 + 42
6D = 2B + 42
6D = 0 + 6D
72 = 5 + 6D
74 = 2 + 72
22 = 74 ^ 56
0 = (6C >> 0) & 1
0 = 0 * 5
0 = (6C >> 1) & 1
0 = 0 * 7
1 = (6C >> 2) & 1
49 = 1 * 49
1 = (6C >> 3) & 1
2B = 1 * 2B
0 = (6C >> 4) & 1
0 = 0 * B
1 = (6C >> 5) & 1
D = 1 * D
1 = (6C >> 6) & 1
3B = 1 * 3B
0 = (6C >> 7) & 1
0 = 0 * 1F
3B = 3B + 0
48 = D + 3B
48 = 0 + 48
73 = 2B + 48
BC = 49 + 73
BC = 0 + BC
BC = 0 + BC
E3 = BC ^ 5F
1 = (6D >> 0) & 1
3 = 1 * 3
0 = (6D >> 1) & 1
0 = 0 * 5
1 = (6D >> 2) & 1
49 = 1 * 49
1 = (6D >> 3) & 1
29 = 1 * 29
0 = (6D >> 4) & 1
0 = 0 * 2B
1 = (6D >> 5) & 1
D = 1 * D
1 = (6D >> 6) & 1
53 = 1 * 53
0 = (6D >> 7) & 1
0 = 0 * 59
53 = 53 + 0
60 = D + 53
60 = 0 + 60
89 = 29 + 60
D2 = 49 + 89
D2 = 0 + D2
D5 = 3 + D2
95 = D5 ^ 40
0 = (6E >> 0) & 1
0 = 0 * 2
1 = (6E >> 1) & 1
7 = 1 * 7
1 = (6E >> 2) & 1
47 = 1 * 47
1 = (6E >> 3) & 1
B = 1 * B
0 = (6E >> 4) & 1
0 = 0 * 2B
1 = (6E >> 5) & 1
D = 1 * D
1 = (6E >> 6) & 1
1D = 1 * 1D
0 = (6E >> 7) & 1
0 = 0 * 3D
1D = 1D + 0
2A = D + 1D
2A = 0 + 2A
35 = B + 2A
7C = 47 + 35
83 = 7 + 7C
83 = 0 + 83
DD = 83 ^ 5E
1 = (6F >> 0) & 1
2 = 1 * 2
1 = (6F >> 1) & 1
5 = 1 * 5
1 = (6F >> 2) & 1
7 = 1 * 7
1 = (6F >> 3) & 1
B = 1 * B
0 = (6F >> 4) & 1
0 = 0 * D
1 = (6F >> 5) & 1
4F = 1 * 4F
1 = (6F >> 6) & 1
2F = 1 * 2F
0 = (6F >> 7) & 1
0 = 0 * 53
2F = 2F + 0
7E = 4F + 2F
7E = 0 + 7E
89 = B + 7E
90 = 7 + 89
95 = 5 + 90
97 = 2 + 95
C2 = 97 ^ 55
0 = (70 >> 0) & 1
0 = 0 * 3
0 = (70 >> 1) & 1
0 = 0 * 43
0 = (70 >> 2) & 1
0 = 0 * 25
0 = (70 >> 3) & 1
0 = 0 * 5
1 = (70 >> 4) & 1
49 = 1 * 49
1 = (70 >> 5) & 1
B = 1 * B
1 = (70 >> 6) & 1
D = 1 * D
0 = (70 >> 7) & 1
0 = 0 * 3D
D = D + 0
18 = B + D
61 = 49 + 18
61 = 0 + 61
61 = 0 + 61
61 = 0 + 61
61 = 0 + 61
23 = 61 ^ 42
1 = (71 >> 0) & 1
2 = 1 * 2
0 = (71 >> 1) & 1
0 = 0 * 43
0 = (71 >> 2) & 1
0 = 0 * 5
0 = (71 >> 3) & 1
0 = 0 * 7
1 = (71 >> 4) & 1
47 = 1 * 47
1 = (71 >> 5) & 1
B = 1 * B
1 = (71 >> 6) & 1
D = 1 * D
0 = (71 >> 7) & 1
0 = 0 * 3D
D = D + 0
18 = B + D
5F = 47 + 18
5F = 0 + 5F
5F = 0 + 5F
5F = 0 + 5F
61 = 2 + 5F
40 = 61 ^ 21
0 = (72 >> 0) & 1
0 = 0 * 43
1 = (72 >> 1) & 1
3 = 1 * 3
0 = (72 >> 2) & 1
0 = 0 * 5
0 = (72 >> 3) & 1
0 = 0 * 25
1 = (72 >> 4) & 1
2B = 1 * 2B
1 = (72 >> 5) & 1
B = 1 * B
1 = (72 >> 6) & 1
D = 1 * D
0 = (72 >> 7) & 1
0 = 0 * 3D
D = D + 0
18 = B + D
43 = 2B + 18
43 = 0 + 43
43 = 0 + 43
46 = 3 + 43
46 = 0 + 46
3 = 46 ^ 45
1 = (73 >> 0) & 1
2 = 1 * 2
1 = (73 >> 1) & 1
3 = 1 * 3
0 = (73 >> 2) & 1
0 = 0 * 25
0 = (73 >> 3) & 1
0 = 0 * 7
1 = (73 >> 4) & 1
47 = 1 * 47
1 = (73 >> 5) & 1
29 = 1 * 29
1 = (73 >> 6) & 1
B = 1 * B
0 = (73 >> 7) & 1
0 = 0 * 1D
B = B + 0
34 = 29 + B
7B = 47 + 34
7B = 0 + 7B
7B = 0 + 7B
7E = 3 + 7B
80 = 2 + 7E
C0 = 80 ^ 40
0 = (74 >> 0) & 1
0 = 0 * 3
0 = (74 >> 1) & 1
0 = 0 * 5
1 = (74 >> 2) & 1
29 = 1 * 29
0 = (74 >> 3) & 1
0 = 0 * B
1 = (74 >> 4) & 1
2B = 1 * 2B
1 = (74 >> 5) & 1
2F = 1 * 2F
1 = (74 >> 6) & 1
35 = 1 * 35
0 = (74 >> 7) & 1
0 = 0 * 1D
35 = 35 + 0
64 = 2F + 35
8F = 2B + 64
8F = 0 + 8F
B8 = 29 + 8F
B8 = 0 + B8
B8 = 0 + B8
DA = B8 ^ 62
1 = (75 >> 0) & 1
2 = 1 * 2
0 = (75 >> 1) & 1
0 = 0 * 3
1 = (75 >> 2) & 1
7 = 1 * 7
0 = (75 >> 3) & 1
0 = 0 * 47
1 = (75 >> 4) & 1
2B = 1 * 2B
1 = (75 >> 5) & 1
D = 1 * D
1 = (75 >> 6) & 1
2F = 1 * 2F
0 = (75 >> 7) & 1
0 = 0 * 4F
2F = 2F + 0
3C = D + 2F
67 = 2B + 3C
67 = 0 + 67
6E = 7 + 67
6E = 0 + 6E
70 = 2 + 6E
33 = 70 ^ 43
0 = (76 >> 0) & 1
0 = 0 * 2
1 = (76 >> 1) & 1
3 = 1 * 3
1 = (76 >> 2) & 1
5 = 1 * 5
0 = (76 >> 3) & 1
0 = 0 * 25
1 = (76 >> 4) & 1
B = 1 * B
1 = (76 >> 5) & 1
2B = 1 * 2B
1 = (76 >> 6) & 1
D = 1 * D
0 = (76 >> 7) & 1
0 = 0 * 4F
D = D + 0
38 = 2B + D
43 = B + 38
43 = 0 + 43
48 = 5 + 43
4B = 3 + 48
4B = 0 + 4B
C = 4B ^ 47
1 = (77 >> 0) & 1
61 = 1 * 61
1 = (77 >> 1) & 1
43 = 1 * 43
1 = (77 >> 2) & 1
5 = 1 * 5
0 = (77 >> 3) & 1
0 = 0 * 25
1 = (77 >> 4) & 1
7 = 1 * 7
1 = (77 >> 5) & 1
29 = 1 * 29
1 = (77 >> 6) & 1
B = 1 * B
0 = (77 >> 7) & 1
0 = 0 * 3D
B = B + 0
34 = 29 + B
3B = 7 + 34
3B = 0 + 3B
40 = 5 + 3B
83 = 43 + 40
E4 = 61 + 83
BA = E4 ^ 5E
0 = (78 >> 0) & 1
0 = 0 * 3
0 = (78 >> 1) & 1
0 = 0 * 47
0 = (78 >> 2) & 1
0 = 0 * 7
1 = (78 >> 3) & 1
2B = 1 * 2B
1 = (78 >> 4) & 1
B = 1 * B
1 = (78 >> 5) & 1
4F = 1 * 4F
1 = (78 >> 6) & 1
35 = 1 * 35
0 = (78 >> 7) & 1
0 = 0 * 3D
35 = 35 + 0
84 = 4F + 35
8F = B + 84
BA = 2B + 8F
BA = 0 + BA
BA = 0 + BA
BA = 0 + BA
E7 = BA ^ 5D
1 = (79 >> 0) & 1
2 = 1 * 2
0 = (79 >> 1) & 1
0 = 0 * 3
0 = (79 >> 2) & 1
0 = 0 * 47
1 = (79 >> 3) & 1
49 = 1 * 49
1 = (79 >> 4) & 1
B = 1 * B
1 = (79 >> 5) & 1
D = 1 * D
1 = (79 >> 6) & 1
3D = 1 * 3D
0 = (79 >> 7) & 1
0 = 0 * 1F
3D = 3D + 0
4A = D + 3D
55 = B + 4A
9E = 49 + 55
9E = 0 + 9E
9E = 0 + 9E
A0 = 2 + 9E
FA = A0 ^ 5A
0 = (7A >> 0) & 1
0 = 0 * 61
1 = (7A >> 1) & 1
2 = 1 * 2
0 = (7A >> 2) & 1
0 = 0 * 3
1 = (7A >> 3) & 1
43 = 1 * 43
1 = (7A >> 4) & 1
5 = 1 * 5
1 = (7A >> 5) & 1
B = 1 * B
1 = (7A >> 6) & 1
D = 1 * D
0 = (7A >> 7) & 1
0 = 0 * 53
D = D + 0
18 = B + D
1D = 5 + 18
60 = 43 + 1D
60 = 0 + 60
62 = 2 + 60
62 = 0 + 62
42 = 62 ^ 20
1 = (41 >> 0) & 1
2 = 1 * 2
0 = (41 >> 1) & 1
0 = 0 * 3
0 = (41 >> 2) & 1
0 = 0 * 5
0 = (41 >> 3) & 1
0 = 0 * 25
0 = (41 >> 4) & 1
0 = 0 * 7
0 = (41 >> 5) & 1
0 = 0 * 29
1 = (41 >> 6) & 1
B = 1 * B
0 = (41 >> 7) & 1
0 = 0 * 35
B = B + 0
B = 0 + B
B = 0 + B
B = 0 + B
B = 0 + B
B = 0 + B
D = 2 + B
4C = D ^ 41
0 = (42 >> 0) & 1
0 = 0 * 2
1 = (42 >> 1) & 1
3 = 1 * 3
0 = (42 >> 2) & 1
0 = 0 * 49
0 = (42 >> 3) & 1
0 = 0 * 2B
0 = (42 >> 4) & 1
0 = 0 * B
0 = (42 >> 5) & 1
0 = 0 * D
1 = (42 >> 6) & 1
35 = 1 * 35
0 = (42 >> 7) & 1
0 = 0 * 3D
35 = 35 + 0
35 = 0 + 35
35 = 0 + 35
35 = 0 + 35
35 = 0 + 35
38 = 3 + 35
38 = 0 + 38
6A = 38 ^ 52
1 = (43 >> 0) & 1
2 = 1 * 2
1 = (43 >> 1) & 1
43 = 1 * 43
0 = (43 >> 2) & 1
0 = 0 * 3
0 = (43 >> 3) & 1
0 = 0 * 25
0 = (43 >> 4) & 1
0 = 0 * 7
0 = (43 >> 5) & 1
0 = 0 * B
1 = (43 >> 6) & 1
2F = 1 * 2F
0 = (43 >> 7) & 1
0 = 0 * 3B
2F = 2F + 0
2F = 0 + 2F
2F = 0 + 2F
2F = 0 + 2F
2F = 0 + 2F
72 = 43 + 2F
74 = 2 + 72
30 = 74 ^ 44
0 = (44 >> 0) & 1
0 = 0 * 2
0 = (44 >> 1) & 1
0 = 0 * 25
1 = (44 >> 2) & 1
5 = 1 * 5
0 = (44 >> 3) & 1
0 = 0 * 49
0 = (44 >> 4) & 1
0 = 0 * D
0 = (44 >> 5) & 1
0 = 0 * 2F
1 = (44 >> 6) & 1
35 = 1 * 35
0 = (44 >> 7) & 1
0 = 0 * 3B
35 = 35 + 0
35 = 0 + 35
35 = 0 + 35
35 = 0 + 35
3A = 5 + 35
3A = 0 + 3A
3A = 0 + 3A
7B = 3A ^ 41
1 = (45 >> 0) & 1
2 = 1 * 2
0 = (45 >> 1) & 1
0 = 0 * 43
1 = (45 >> 2) & 1
47 = 1 * 47
0 = (45 >> 3) & 1
0 = 0 * 49
0 = (45 >> 4) & 1
0 = 0 * 29
0 = (45 >> 5) & 1
0 = 0 * B
1 = (45 >> 6) & 1
D = 1 * D
0 = (45 >> 7) & 1
0 = 0 * 59
D = D + 0
D = 0 + D
D = 0 + D
D = 0 + D
54 = 47 + D
54 = 0 + 54
56 = 2 + 54
B = 56 ^ 5D
0 = (46 >> 0) & 1
0 = 0 * 2
1 = (46 >> 1) & 1
3 = 1 * 3
1 = (46 >> 2) & 1
43 = 1 * 43
0 = (46 >> 3) & 1
0 = 0 * 25
0 = (46 >> 4) & 1
0 = 0 * 49
0 = (46 >> 5) & 1
0 = 0 * B
1 = (46 >> 6) & 1
2B = 1 * 2B
0 = (46 >> 7) & 1
0 = 0 * 3B
2B = 2B + 0
2B = 0 + 2B
2B = 0 + 2B
2B = 0 + 2B
6E = 43 + 2B
71 = 3 + 6E
71 = 0 + 71
11 = 71 ^ 60
1C = B + 11
97 = 7B + 1C
C7 = 30 + 97
131 = 6A + C7
17D = 4C + 131
1BF = 42 + 17D
2B9 = FA + 1BF
3A0 = E7 + 2B9
45A = BA + 3A0
466 = C + 45A
499 = 33 + 466
573 = DA + 499
633 = C0 + 573
636 = 3 + 633
676 = 40 + 636
699 = 23 + 676
75B = C2 + 699
838 = DD + 75B
8CD = 95 + 838
9B0 = E3 + 8CD
9D2 = 22 + 9B0
9F5 = 23 + 9D2
AAB = B6 + 9F5
B90 = E5 + AAB
C55 = C5 + B90
D29 = D4 + C55
E13 = EA + D29
E39 = 26 + E13
E54 = 1B + E39
EAB = 57 + E54
F07 = 5C + EAB
INT3 breakpoint at secret_box.00007FF77B182055!

显然是对于每一个输入的东西,由于是8位的,按照位拆开,每个位分别是0或者1,然后乘以一个const,得到的结果是本位的加密后结果,然后这个结果会异或一个东西得到enc[i],然后程序将计算他们的和,从而得到最后的结果

0 = S = \sum{(bits[i]_0 * c_0 + bits[i]_1 * c_1 + bits[i]_2 * c_2 + bits[i]_3 * c_3 + bits[i]_4 * c_4 + bits[i]_5 * c_5 + bits[i]_6 * c_6 + bits[i]_7 * c_7) \oplus CONST[i] }

由于程序约束S == 0,则
Exp:

enc = [0x46, 0x38, 0x46, 0x4D, 0x4A, 0x5A, 0x57, 0x52, 0x3C, 0x43, 0x56, 0x5F, 0x40, 0x5E, 0x55, 0x42, 0x21, 0x45, 0x40, 0x62, 0x43, 0x47, 0x5E, 0x5D, 0x5A, 0x20, 0x41, 0x52, 0x44, 0x41, 0x5D, 0x60]
muls = []
muls.append([0x2,0x3,0x43,0x25,0x29,0xB,0xD,0x59]   )
muls.append([0x2,0x3,0x43,0x5,0x7,0x2F,0x3D,0x1D]   )
muls.append([0x2,0x43,0x25,0x7,0x2B,0xB,0xD,0x1F]   )
muls.append([0x61,0x3,0x29,0x49,0xB,0xD,0x35,0x1D]  )
muls.append([0x61,0x43,0x3,0xB,0x2B,0xD,0x2F,0x53]  )
muls.append([0x43,0x5,0x25,0x47,0x7,0xB,0x59,0x1D]  )
muls.append([0x2,0x3,0x5,0xB,0xD,0x53,0x35,0x3D]    )
muls.append([0x2,0x3,0x7,0x47,0x2B,0x53,0x1D,0x1F]  )
muls.append([0x7,0x49,0xB,0xD,0x35,0x59,0x1D,0x1F]  )
muls.append([0x2,0x3,0x5,0x25,0x7,0x2B,0xD,0x3D]    )
muls.append([0x2,0x5,0x7,0x2B,0xB,0xD,0x35,0x59]    )
muls.append([0x5,0x7,0x49,0x2B,0xB,0xD,0x3B,0x1F]   )
muls.append([0x3,0x5,0x49,0x29,0x2B,0xD,0x53,0x59]  )
muls.append([0x2,0x7,0x47,0xB,0x2B,0xD,0x1D,0x3D]   )
muls.append([0x2,0x5,0x7,0xB,0xD,0x4F,0x2F,0x53]    )
muls.append([0x3,0x43,0x25,0x5,0x49,0xB,0xD,0x3D]   )
muls.append([0x2,0x43,0x5,0x7,0x47,0xB,0xD,0x3D]    )
muls.append([0x43,0x3,0x5,0x25,0x2B,0xB,0xD,0x3D]   )
muls.append([0x2,0x3,0x25,0x7,0x47,0x29,0xB,0x1D]   )
muls.append([0x3,0x5,0x29,0xB,0x2B,0x2F,0x35,0x1D]  )
muls.append([0x2,0x3,0x7,0x47,0x2B,0xD,0x2F,0x4F]   )
muls.append([0x2,0x3,0x5,0x25,0xB,0x2B,0xD,0x4F]    )
muls.append([0x61,0x43,0x5,0x25,0x7,0x29,0xB,0x3D]  )
muls.append([0x3,0x47,0x7,0x2B,0xB,0x4F,0x35,0x3D]  )
muls.append([0x2,0x3,0x47,0x49,0xB,0xD,0x3D,0x1F]   )
muls.append([0x61,0x2,0x3,0x43,0x5,0xB,0xD,0x53]    )
muls.append([0x2,0x3,0x5,0x25,0x7,0x29,0xB,0x35]    )
muls.append([0x2,0x3,0x49,0x2B,0xB,0xD,0x35,0x3D]   )
muls.append([0x2,0x43,0x3,0x25,0x7,0xB,0x2F,0x3B]   )
muls.append([0x2,0x25,0x5,0x49,0xD,0x2F,0x35,0x3B]  )
muls.append([0x2,0x43,0x47,0x49,0x29,0xB,0xD,0x59]  )
muls.append([0x2,0x3,0x43,0x25,0x49,0xB,0x2B,0x3B]  )
ans = bytearray()
for rin range(32):
    # BruteForce Ascii
    for i in range(0x20, 0x7f):
        a0 = ((i >> 0) & 1) * muls[r][0]
        a1 = ((i >> 1) & 1) * muls[r][8]
        a2 = ((i >> 2) & 1) * muls[r][9]
        a3 = ((i >> 3) & 1) * muls[r][10]
        a4 = ((i >> 4) & 1) * muls[r][11]
        a5 = ((i >> 5) & 1) * muls[r][12]
        a6 = ((i >> 6) & 1) * muls[r][13]
        a7 = ((i >> 7) & 1) * muls[r][14] 
        s1 = a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7
        if s1 == enc[r]:
            ans.append(i)
            break
print(ans)
# bytearray(b's1mpl3_VM_us3s_link3d_l1st_st4ck')

然后把这个输入程序就能解出真flag了

C:\Users\Administrator\Desktop\S1mpLeVM_6d429db3ceeba8f95131c477020ee899>secret_box.exe quest
Enter ur passcode: s1mpl3_VM_us3s_link3d_l1st_st4ck115
Thank for providing passcode, my ultimate secret box is checking...
Cracked...
flag{s1mpl3_VM_us1ng_st4ck_th4t_1mpl3m3nt_by_l1nk3d_l1st_^3^_!!}

unsafeFile

小Y玩游戏很菜,于是他找了个神秘人要了一个修改器文件,在开启功能后,发现他的一个重要文件居然被加密了,你能想办法帮他恢复吗
请不要在物理机上运行题目中的任何文件,主办方对由此造成的任何损失不承担任何责任,如有需要请在虚拟机内进行运行和调试,解压密码2024qwbfinal

Cheat Engine 脚本,用于注入PlantsVsZombies.exe实现修改
ce的库函数 decodefuction()解码成函数
使用Github上的这个工具来提取encodeFunction的内容。
2024-12-06T06:16:44.png

下面是反编译后的重要内容。

// 远程代码注入
L2_1 = "injectDLL"
L2_1 = _ENV[L2_1]
L3_1 = "C:\\system.dll"
L2_1(L3_1)
L2_1 = "sleep"
L2_1 = _ENV[L2_1]
L3_1 = 5
L2_1(L3_1)
L2_1 = [[
alloc(newmem,256)
label(returnhere)
label(originalcode)
label(exit)
// 远程代码注入
newmem:

originalcode:
xor eax,5A

mov ecx, eax
shr eax, 4
shl ecx, 4
or eax, ecx

mov ecx,[ebp-1C]

exit:
jmp returnhere

"system.dll"+25C6:
jmp newmem
nop
returnhere:

]]
L3_1 = "autoAssemble"
L3_1 = _ENV[L3_1]
L4_1 = L2_1
L3_1(L4_1)
L3_1 = "writeByte"
L3_1 = _ENV[L3_1]
L4_1 = "system.dll+C6DC"
L5_1 = 1
L3_1(L4_1, L5_1)
L3_1 = "activateProtection"
L3_1 = _ENV[L3_1]
L3_1()
L3_1 = "enableDRM"
L3_1 = _ENV[L3_1]
L3_1()

可以看出是导出了一个system.dll
我们直接在ce里面运行这个脚本,由于经过我们分析,只要没有pvz.exe的运行,这个dll就不会被注入,但是无论如何这个dll都会被释放到C盘根目录,这样我们就可以导出system.dll。
分析System.dll,发现AES

2024-12-06T06:17:11.png

AES-CBC
2024-12-06T06:17:20.png
文件遍历
2024-12-06T06:17:29.png
加密,然后弄成.yr结尾的
2024-12-06T06:17:37.png
加密文件
2024-12-06T06:17:44.png
xdbg动态调试,在DeleteFile上下断点防止程序把本机的正常文件删掉。随后断KEY_Expansion,发现是随机的key,然后断这里,就可以拿到iv(v39)。
2024-12-06T06:17:51.png
发现Iv也是随机的,由于题目肯定能解,所以猜测key和iv都写进了文件
分析手动加密的.yr,发现多了32字节,对应key和iv,key被xor了0x5a,iv直接放进去的。

newmem:

originalcode:
xor eax,5A

mov ecx, eax
shr eax, 4
shl ecx, 4
or eax, ecx

mov ecx,[ebp-1C]

exit:
jmp returnhere

"system.dll"+25C6:
jmp newmem
nop
returnhere:

注意到上面,把xor eax, 5a后面加上了ror 4
所以我们有EXP

from regadgets import *
enc = open('secret.pdf.yr', 'rb').read()
iv = enc[-16:]
key = enc[-32:-16]
key = bytes([ror8(i, 4) for i in key])
key = bxor_cycle(key, 0x5a)
print("iv", iv.hex())
print("key", key.hex())
enc = enc[:-32]
dec = AES_cbc_decrypt(enc, key, iv)
open('secret.pdf', 'wb').write(dec)

2024-12-06T06:18:17.png
flag{7he_Che47_En9INe_74BLE_I5_N07_54fE#cf17565a3d91fdbf}

没报名,赛后问朋友要的题,看了看。

loser (Nononono!.exe)

赛中2解
该程序实现了一个类似Base64的算法和一个标准TEA解密算法,用来对输入数据进行编码和加密,并与加密后的结果进行比较,由于程序使用C++,结构体众多,逆向难度中等偏上。

首先是一个类似Base64的编码算法,开始做的时候测试了几个数据,看着很像base64但是其实并不是,算法是以3个字节为一组,每一个字节分别按位与 0x3f 用以获取低6位,然后第2个和第三个and后的数据是要换位置的,第四个字节是前面三个字节的高2位,所以没有加密只是编码,在下面Exp可以看如何解码。

其次是一个TEA解密,拿到key后我们只需要写一个TEA加密,就可以“解密”了。值得注意的是在我们加密前,需要对l和r两个参数进行xor ord('S')即可。
最后是enc了,我们搜索字符串常量right
2024-11-17T12:43:52.png
可以看出 unk_140031520 大概率就是enc了,我们双击进去进行X-Ref,发现它在下面的函数进行了初始化。
2024-11-17T12:44:33.png
copy下来,就可以写exp了。
一个特别小的注意点就是,enc是DWORD big-endian。

Exp:

from regadgets import *
from z3 import *
def decrypt(enc):
    assert len(enc) % 4 == 0
    table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    result = []
    for i in range(0, len(enc), 4):
        a1 = table.index(enc[i + 0])
        a2 = table.index(enc[i + 2])
        a3 = table.index(enc[i + 1])
        a4 = table.index(enc[i + 3])
        result.append(a1 | ((a4 & 0b110000) << 2))
        result.append(a2 | ((a4 & 0b001100) << 4))
        result.append(a3 | ((a4 & 0b000011) << 6))
    return bytes(result)

v4 = [0] * 48
v4[0] = 165
v4[1] = 100
v4[2] = 159
v4[3] = 4
v4[4] = 57
v4[5] = 183
v4[6] = 166
v4[7] = 23
v4[8] = 34
v4[9] = 205
v4[10] = 38
v4[11] = 77
v4[12] = 125
v4[13] = 16
v4[14] = 130
v4[15] = 219
v4[16] = 133
v4[17] = 219
v4[18] = 39
v4[19] = 57
v4[20] = 66
v4[21] = 60
v4[22] = 30
v4[23] = 165
v4[24] = 34
v4[25] = 205
v4[26] = 38
v4[27] = 77
v4[28] = 125
v4[29] = 16
v4[30] = 130
v4[31] = 219
v4[32] = 214
v4[33] = 55
v4[34] = 104
v4[35] = 128
v4[36] = 177
v4[37] = 249
v4[38] = 21
v4[39] = 25
v4[40] = 68
v4[41] = 24
v4[42] = 66
v4[43] = 36
v4[44] = 143
v4[45] = 120
v4[46] = 162
v4[47] = 44
print(len(v4))
v4 = byte2dword(v4, endian='big')
v4 = [i ^ ord('S') for i in v4]

dec = tea_encrypt(v4, key=[ord('L'), ord('Z'), ord('S'), ord('D')])
print(decrypt(dec.decode()))
# 48
# b'LZSDS{how_how_how_how_how_ow_ow_ow!}'