首页
社区
课程
招聘
[原创] KCTF 2023 第七题 wp - 98k
发表于: 2023-9-17 10:27 11196

[原创] KCTF 2023 第七题 wp - 98k

2023-9-17 10:27
11196

main 函数挺大,不过没加混淆,其他函数都是加了混淆的。看看混淆模式后写个脚本提取指令去混淆:

得到指令后编译为二进制:

最后在 ida 里新加一个段,起始地址 0x800000 ,将指令放进去

得到的这些函数再手动处理一下多余的指令,逻辑就基本上出来了。

main 前面大部分逻辑都是与用户名相关的,直接跳到最后的判断逻辑:

输入 password 后 16 转成字节数组,传入魔改的 aes 加密,之后又用魔改的 des 加密 22 轮,再用个简单的虚拟机加密,再和最终的目标值比较。密钥和比较的值都应该是固定的或者只与用户名有关,所以调试拿值就行。

aes 实现方式:

多线程但是用一个全局锁控制流程,只有一种执行方式。部分 AES 的实现做了魔改,改一下 aes 板子即可

des 加密(实际上是解密):

与标准的 DES 中的常量相比, S 改了两个值, PC2 改了一个值。抄写出来得到:

最后还有个简单的虚拟机的形式的加密,抄写出来写逆:

将最终结果以及各个密钥动调拿出来,写逆得到密码:

#!/usr/bin/env python3
 
# import ida_bytes
import keystone
import capstone
 
def set_x86():
    global ks, cs
    ks = keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_32)
    cs = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32)
 
set_x86()
 
def asm(code, addr=0):
    return bytes(ks.asm(code, addr)[0])
 
def disasm(code, addr=0):
    for i in cs.disasm(code, addr):
        return ('%s %s' %(i.mnemonic, i.op_str))
 
def ins_len(code):
    return len(next(cs.disasm(code, 0)).bytes)
 
def to_char(x):
    assert 0 <= x < 0x100
    if x >= 0x80: x -= 0x100
    return x
 
def to_int(b):
    assert len(b) == 4
    x = int.from_bytes(b, 'little')
    if x >= 1 << 31: x -= 1 << 32
    return x
 
def make_label(i):
    return '_%x' % (i + ob_start)
 
ob_start = 0x403AC0
ob_end = 0x617DE0
def extract_block(ins, i):
    # print('extract block: 0x%x' % (ob_start + i))
    is_zero = False
    ebx_ebp = False
    push_eax = False
    push_ebx = False
    push_eax_i = None
    push_ebx_i = None
    eax_value = None
    eax_value_i = None
    eax_value_2 = None
    eax_value_2_i = None
    ebx_value = None
    ebx_value_i = None
    test_eax = False
    push_value = None
    last_i = None
 
    while True:
        if i in ins:
            if last_i:
                ins[last_i] += '\njmp %s' % make_label(i)
            return []
        # print(hex(i + ob_start))
        if data[i] == 0x0f and 0x80 <= data[i + 1] < 0x90: # j?? dword
            offset = to_int(data[i + 2: i + 6])
            if data[i + 6] == 0x0f and data[i + 7] == data[i + 1] ^ 1 and\
            offset == 6 + to_int(data[i + 8: i + 12]):
                ins[i] = 'jmp %s' % make_label(i + 6 + offset)
                last_i = None
                i += 6 + offset
            elif data[i + 1] == 0x84 and is_zero: # jz
                ins[i] = 'jmp %s' % make_label(i + 6 + offset)
                last_i = None
                i += 6 + offset
            elif data[i + 1] == 0x85 and test_eax: # jnz
                ins[i] = 'jmp %s' % make_label(i + 6 + offset)
                last_i = None
                i += 6 + offset
            else:
                mnem = disasm(data[i: i + 6]).split(' ')[0]
                ins[i] = '%s %s\njmp %s' % (mnem, make_label(i + 6 + offset), make_label(i + 6))
                return [i + 6, i + 6 + offset]
        elif data[i] == 0x3b and data[i + 1] == 0xc0: # cmp eax, eax
            is_zero = True
            test_eax = False
            ins[i] = 'cmp eax, eax'
            last_i = i
            i += 2
        elif data[i] == 0x3b and data[i + 1] == 0xdb: # cmp ebx, ebx
            is_zero = True
            test_eax = False
            ins[i] = 'cmp ebx, ebx'
            last_i = i
            i += 2
        elif data[i] == 0x50 and eax_value: # push eax
            push_eax_i = i
            push_eax = True
            ins[i] = 'push eax'
            last_i = i
            i += 1
        elif data[i] == 0x53: # push ebx
            push_ebx_i = i
            push_ebx = True
            ins[i] = 'push ebx'
            last_i = i
            i += 1
        elif data[i] == 0x68: # push dword
            value = to_int(data[i + 1: i + 5])
            if data[i + 5] == 0xc3: # ret
                ins[i] = 'jmp %s' % make_label(value - ob_start)
                last_i = None
                i = value - ob_start
            else:
                push_value = value
                push_value_i = i
                ins[i] = 'push 0x%x' % push_value
                last_i = i
                i += 5
        elif 0x70 <= data[i] < 0x80: # j?? short
            offset = to_char(data[i + 1])
            if data[i + 2] == data[i] ^ 1 and offset == 2 + to_char(data[i + 3]):
                ins[i] = 'jmp %s' % make_label(i + 2 + offset)
                last_i = None
                i += 2 + offset
            elif data[i] == 0x74 and is_zero: # jz short
                ins[i] = 'jmp %s' % make_label(i + 2 + offset)
                last_i = None
                i += 2 + offset
            elif data[i] == 0x75 and test_eax: # jnz short
                ins[i] = 'jmp %s' % make_label(i + 2 + offset)
                last_i = None
                i += 2 + offset
            else:
                mnem = disasm(data[i: i + 2]).split(' ')[0]
                ins[i] = '%s %s\njmp %s' % (mnem, make_label(i + 2 + offset), make_label(i + 2))
                return [i + 2, i + 2 + offset]
        elif data[i] == 0x85 and data[i + 1] == 0xc0 and eax_value: # test eax, eax
            if eax_value_2 != None:
                assert eax_value_2 != 0 # call_dst
            else:
                pass
            test_eax = True
            is_zero = False
            ins[i] = 'test eax, eax'
            last_i = i
            i += 2
        elif data[i] == 0x87 and data[i + 1] == 0x1c and data[i + 2] == 0x24 and push_ebx: # xchg ebx, [esp]
            if ebx_value:
                assert not ebx_ebp
                ins[push_ebx_i] = 'nop'
                ins[ebx_value_i] = 'push 0x%x' % ebx_value
                ins[i] = 'nop'
                push_ebx = False
                push_value = ebx_value
                ebx_value = None
                push_value_i = ebx_value_i
            elif ebx_ebp:
                ins[push_ebx_i] = 'push ebp'
                ins[ebx_ebp_i] = 'nop'
                ins[i] = 'nop'
                push_ebx = False
                ebx_ebp = False
            else:
                ins[i] = 'xchg ebx, [esp]'
                push_ebx = False
            last_i = i
            i += 3
        elif data[i] == 0x8b and data[i + 1] == 0xdd and push_ebx: # mov ebx, ebp
            ins[i] = 'mov ebx, ebp'
            last_i = i
            ebx_ebp_i = i
            ebx_ebp = True
            i += 2
        elif data[i] == 0x90: # nop
            ins[i] = 'nop'
            last_i = i
            i += 1
        elif data[i] == 0xb8: # mov eax, dword
            value = to_int(data[i + 1: i + 5])
            ins[i] = 'mov eax, 0x%x' % value
            last_i = i
            if not eax_value:
                eax_value_i = i
                eax_value = value
            else:
                assert push_eax
                eax_value_2_i = i
                eax_value_2 = value
            i += 5
        elif data[i] == 0xbb and push_ebx: # mov ebx, dword
            value = to_int(data[i + 1: i + 5])
            ins[i] = 'mov ebx, 0x%x' % value
            last_i = i
            ebx_value_i = i
            ebx_value = value
            i += 5
        elif data[i] == 0xe9: # jmp
            ins[i] = 'jmp %s' % make_label(i + 5 + to_int(data[i + 1: i + 5]))
            last_i = None
            i += 5 + to_int(data[i + 1: i + 5])
        elif data[i] == 0xeb: # jmp short
            ins[i] = 'jmp %s' % make_label(i + 2 + to_char(data[i + 1]))
            last_i = None
            i += 2 + to_char(data[i + 1])
        elif data[i] == 0xc3: # ret
            if push_value:
                ins[i] = 'ud2'
                i = push_value_i
                j = i + ob_start
                dst = push_value
                offset = dst - j - 5 & 0xffffffff
                ins[i] = 'jmp %s' % make_label(dst - ob_start)
                last_i = None
                push_value = None
                i = dst - ob_start
            else:
                ins[i] = 'ret'
                return []
        elif data[i] == 0xff and data[i + 1] == 0xe0: # jmp eax
            assert push_eax and eax_value and eax_value_2
            ins[i] = 'ud2'
            i = eax_value_2_i
            j = i + ob_start
            dst = eax_value_2
            offset = dst - j - 5 & 0xffffffff
            ins[eax_value_i] = 'nop'
            ins[push_eax_i] = 'nop'
            ins[i] = 'call f%s' % make_label(dst - ob_start)
            funcs_to_handle.append(dst)
            i += 5
            j = i + ob_start
            dst = eax_value
            offset = dst - j - 5 & 0xffffffff
            ins[i] = 'jmp %s' % make_label(dst - ob_start)
            last_i = None
            i = dst - ob_start
            push_eax = False
            eax_value = None
            eax_value_2 = None
        else:
            is_zero = False
            test_eax = False
            push_ebx = False
            ebx_ebp = False
            ebx_value = None
            push_value = None
            push_eax = False
            eax_value = None
            eax_value_2 = None
 
            l = ins_len(data[i: i + 20])
            ins[i] = disasm(data[i: i + l], i + ob_start)
            last_i = i
            i += l
 
def extract_function(function):
    print('// function: 0x%x' % function)
    branches_to_handle = [function - ob_start]
    ins = dict()
    while branches_to_handle:
        addr = branches_to_handle.pop(0)
        if addr in ins: continue
        branches_to_handle += extract_block(ins, addr)
 
    code = 'f%s:\n' % make_label(function - ob_start)
    in_pushal = False
    in_pushfd = False
    for i in ins:
        if in_pushal:
            assert ins[i] != 'pushal '
            code += '%s:\n' % make_label(i)
            if ins[i].startswith('popal '):
                in_pushal = False
                for j in ins[i].splitlines()[1: ]:
                    code += j + '\n'
        elif in_pushfd:
            assert ins[i] != 'pushfd '
            code += '%s:\n' % make_label(i)
            if ins[i].startswith('popfd '):
                in_pushfd = False
                for j in ins[i].splitlines()[1: ]:
                    code += j + '\n'
        elif ins[i] == 'pushal ':
            code += '%s:\n' % make_label(i)
            in_pushal = True
        elif ins[i] == 'pushfd ':
            code += '%s:\n' % make_label(i)
            in_pushfd = True
        else:
            code += '%s:\n%s\n' % (make_label(i), ins[i])
    return code
 
offset = 0x400c00
data = open('./KCTF_CrackMe.exe', 'rb').read()[ob_start - offset: ob_end - offset]
 
 
funcs_to_handle = [
    0x611e44, 0x611513, 0x610baf, 0x60f9f2, 0x60f17a, 0x60e8b9, 0x60df9a, 0x60d635,
    0x60cce7, 0x60c3ba, 0x60bac0, 0x60b190, 0x60a819, 0x609f67, 0x609604, 0x608ca6,
    0x608375, 0x607aaa, 0x60714f, 0x6067da, 0x605eba, 0x60557e, 0x604c95, 0x604305,
    0x603a11, 0x603091, 0x60277c, 0x601e0d, 0x601434, 0x600b97, 0x60027e, 0x5ff957,
    0x5fef61, 0x5fe61e, 0x5fdd3d, 0x5fd517, 0x5fcbc4, 0x5fc2cb, 0x5fb9af, 0x5fb07f,
    0x5fa795, 0x5f9e5c, 0x5f94be, 0x5f8bb2, 0x5f822a, 0x5f792b, 0x5f700b, 0x5f673f,
    0x40f9af, 0x5f52e3, 0x409de1, 0x40e62d, 0x403aca, 0x5f50e0
]
 
funcs_to_handle += [
    0x4055C4, 0x404F6B
]
 
funcs_handled = set()
code = ''
while funcs_to_handle:
    f = funcs_to_handle.pop(0)
    if f in funcs_handled: continue
    funcs_handled.add(f)
    if ob_start <= f < ob_end:
        code += extract_function(f)
    else:
        print("// unknown func (maybe library function): f%s" % make_label(f - ob_start))
        code += 'f%s:\njmp 0x%x\n' % (make_label(f - ob_start), f)
    code += '\n\n.string "================"\n\n'
 
# print('\n' + code)
 
with open('out.s', 'w') as f:
    f.write(code)
 
print('OK')
#!/usr/bin/env python3
 
# import ida_bytes
import keystone
import capstone
 
def set_x86():
    global ks, cs
    ks = keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_32)
    cs = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32)
 
set_x86()
 
def asm(code, addr=0):
    return bytes(ks.asm(code, addr)[0])
 
def disasm(code, addr=0):
    for i in cs.disasm(code, addr):
        return ('%s %s' %(i.mnemonic, i.op_str))
 
def ins_len(code):
    return len(next(cs.disasm(code, 0)).bytes)
 
def to_char(x):
    assert 0 <= x < 0x100
    if x >= 0x80: x -= 0x100
    return x
 
def to_int(b):
    assert len(b) == 4
    x = int.from_bytes(b, 'little')
    if x >= 1 << 31: x -= 1 << 32
    return x
 
def make_label(i):
    return '_%x' % (i + ob_start)
 
ob_start = 0x403AC0
ob_end = 0x617DE0
def extract_block(ins, i):
    # print('extract block: 0x%x' % (ob_start + i))
    is_zero = False
    ebx_ebp = False
    push_eax = False
    push_ebx = False
    push_eax_i = None
    push_ebx_i = None
    eax_value = None
    eax_value_i = None
    eax_value_2 = None
    eax_value_2_i = None
    ebx_value = None
    ebx_value_i = None
    test_eax = False
    push_value = None
    last_i = None
 
    while True:
        if i in ins:
            if last_i:
                ins[last_i] += '\njmp %s' % make_label(i)
            return []
        # print(hex(i + ob_start))
        if data[i] == 0x0f and 0x80 <= data[i + 1] < 0x90: # j?? dword
            offset = to_int(data[i + 2: i + 6])
            if data[i + 6] == 0x0f and data[i + 7] == data[i + 1] ^ 1 and\
            offset == 6 + to_int(data[i + 8: i + 12]):
                ins[i] = 'jmp %s' % make_label(i + 6 + offset)
                last_i = None
                i += 6 + offset
            elif data[i + 1] == 0x84 and is_zero: # jz
                ins[i] = 'jmp %s' % make_label(i + 6 + offset)
                last_i = None
                i += 6 + offset
            elif data[i + 1] == 0x85 and test_eax: # jnz
                ins[i] = 'jmp %s' % make_label(i + 6 + offset)
                last_i = None
                i += 6 + offset
            else:
                mnem = disasm(data[i: i + 6]).split(' ')[0]
                ins[i] = '%s %s\njmp %s' % (mnem, make_label(i + 6 + offset), make_label(i + 6))
                return [i + 6, i + 6 + offset]
        elif data[i] == 0x3b and data[i + 1] == 0xc0: # cmp eax, eax
            is_zero = True
            test_eax = False
            ins[i] = 'cmp eax, eax'
            last_i = i
            i += 2
        elif data[i] == 0x3b and data[i + 1] == 0xdb: # cmp ebx, ebx
            is_zero = True
            test_eax = False
            ins[i] = 'cmp ebx, ebx'
            last_i = i
            i += 2
        elif data[i] == 0x50 and eax_value: # push eax
            push_eax_i = i
            push_eax = True
            ins[i] = 'push eax'
            last_i = i
            i += 1
        elif data[i] == 0x53: # push ebx
            push_ebx_i = i
            push_ebx = True
            ins[i] = 'push ebx'
            last_i = i
            i += 1
        elif data[i] == 0x68: # push dword
            value = to_int(data[i + 1: i + 5])
            if data[i + 5] == 0xc3: # ret
                ins[i] = 'jmp %s' % make_label(value - ob_start)
                last_i = None
                i = value - ob_start
            else:
                push_value = value
                push_value_i = i
                ins[i] = 'push 0x%x' % push_value
                last_i = i
                i += 5
        elif 0x70 <= data[i] < 0x80: # j?? short
            offset = to_char(data[i + 1])
            if data[i + 2] == data[i] ^ 1 and offset == 2 + to_char(data[i + 3]):
                ins[i] = 'jmp %s' % make_label(i + 2 + offset)
                last_i = None
                i += 2 + offset
            elif data[i] == 0x74 and is_zero: # jz short
                ins[i] = 'jmp %s' % make_label(i + 2 + offset)
                last_i = None
                i += 2 + offset
            elif data[i] == 0x75 and test_eax: # jnz short
                ins[i] = 'jmp %s' % make_label(i + 2 + offset)
                last_i = None
                i += 2 + offset
            else:
                mnem = disasm(data[i: i + 2]).split(' ')[0]
                ins[i] = '%s %s\njmp %s' % (mnem, make_label(i + 2 + offset), make_label(i + 2))
                return [i + 2, i + 2 + offset]
        elif data[i] == 0x85 and data[i + 1] == 0xc0 and eax_value: # test eax, eax
            if eax_value_2 != None:
                assert eax_value_2 != 0 # call_dst
            else:
                pass
            test_eax = True
            is_zero = False
            ins[i] = 'test eax, eax'
            last_i = i
            i += 2
        elif data[i] == 0x87 and data[i + 1] == 0x1c and data[i + 2] == 0x24 and push_ebx: # xchg ebx, [esp]
            if ebx_value:
                assert not ebx_ebp
                ins[push_ebx_i] = 'nop'
                ins[ebx_value_i] = 'push 0x%x' % ebx_value
                ins[i] = 'nop'
                push_ebx = False
                push_value = ebx_value
                ebx_value = None
                push_value_i = ebx_value_i
            elif ebx_ebp:
                ins[push_ebx_i] = 'push ebp'
                ins[ebx_ebp_i] = 'nop'
                ins[i] = 'nop'
                push_ebx = False
                ebx_ebp = False
            else:
                ins[i] = 'xchg ebx, [esp]'
                push_ebx = False
            last_i = i
            i += 3
        elif data[i] == 0x8b and data[i + 1] == 0xdd and push_ebx: # mov ebx, ebp
            ins[i] = 'mov ebx, ebp'
            last_i = i
            ebx_ebp_i = i
            ebx_ebp = True
            i += 2
        elif data[i] == 0x90: # nop
            ins[i] = 'nop'
            last_i = i
            i += 1
        elif data[i] == 0xb8: # mov eax, dword
            value = to_int(data[i + 1: i + 5])
            ins[i] = 'mov eax, 0x%x' % value
            last_i = i
            if not eax_value:
                eax_value_i = i
                eax_value = value
            else:
                assert push_eax
                eax_value_2_i = i
                eax_value_2 = value
            i += 5
        elif data[i] == 0xbb and push_ebx: # mov ebx, dword
            value = to_int(data[i + 1: i + 5])
            ins[i] = 'mov ebx, 0x%x' % value
            last_i = i
            ebx_value_i = i
            ebx_value = value
            i += 5
        elif data[i] == 0xe9: # jmp
            ins[i] = 'jmp %s' % make_label(i + 5 + to_int(data[i + 1: i + 5]))
            last_i = None
            i += 5 + to_int(data[i + 1: i + 5])
        elif data[i] == 0xeb: # jmp short
            ins[i] = 'jmp %s' % make_label(i + 2 + to_char(data[i + 1]))
            last_i = None
            i += 2 + to_char(data[i + 1])
        elif data[i] == 0xc3: # ret
            if push_value:
                ins[i] = 'ud2'
                i = push_value_i
                j = i + ob_start
                dst = push_value
                offset = dst - j - 5 & 0xffffffff
                ins[i] = 'jmp %s' % make_label(dst - ob_start)
                last_i = None
                push_value = None
                i = dst - ob_start
            else:
                ins[i] = 'ret'
                return []
        elif data[i] == 0xff and data[i + 1] == 0xe0: # jmp eax
            assert push_eax and eax_value and eax_value_2
            ins[i] = 'ud2'
            i = eax_value_2_i
            j = i + ob_start
            dst = eax_value_2
            offset = dst - j - 5 & 0xffffffff
            ins[eax_value_i] = 'nop'
            ins[push_eax_i] = 'nop'
            ins[i] = 'call f%s' % make_label(dst - ob_start)
            funcs_to_handle.append(dst)
            i += 5
            j = i + ob_start
            dst = eax_value
            offset = dst - j - 5 & 0xffffffff
            ins[i] = 'jmp %s' % make_label(dst - ob_start)
            last_i = None
            i = dst - ob_start
            push_eax = False
            eax_value = None
            eax_value_2 = None
        else:
            is_zero = False
            test_eax = False
            push_ebx = False
            ebx_ebp = False
            ebx_value = None
            push_value = None
            push_eax = False
            eax_value = None
            eax_value_2 = None
 
            l = ins_len(data[i: i + 20])
            ins[i] = disasm(data[i: i + l], i + ob_start)
            last_i = i
            i += l
 
def extract_function(function):
    print('// function: 0x%x' % function)
    branches_to_handle = [function - ob_start]
    ins = dict()
    while branches_to_handle:
        addr = branches_to_handle.pop(0)
        if addr in ins: continue
        branches_to_handle += extract_block(ins, addr)
 
    code = 'f%s:\n' % make_label(function - ob_start)
    in_pushal = False
    in_pushfd = False
    for i in ins:
        if in_pushal:
            assert ins[i] != 'pushal '
            code += '%s:\n' % make_label(i)
            if ins[i].startswith('popal '):
                in_pushal = False
                for j in ins[i].splitlines()[1: ]:
                    code += j + '\n'
        elif in_pushfd:
            assert ins[i] != 'pushfd '
            code += '%s:\n' % make_label(i)
            if ins[i].startswith('popfd '):
                in_pushfd = False
                for j in ins[i].splitlines()[1: ]:
                    code += j + '\n'
        elif ins[i] == 'pushal ':
            code += '%s:\n' % make_label(i)
            in_pushal = True
        elif ins[i] == 'pushfd ':
            code += '%s:\n' % make_label(i)
            in_pushfd = True
        else:
            code += '%s:\n%s\n' % (make_label(i), ins[i])
    return code
 
offset = 0x400c00
data = open('./KCTF_CrackMe.exe', 'rb').read()[ob_start - offset: ob_end - offset]
 
 
funcs_to_handle = [
    0x611e44, 0x611513, 0x610baf, 0x60f9f2, 0x60f17a, 0x60e8b9, 0x60df9a, 0x60d635,
    0x60cce7, 0x60c3ba, 0x60bac0, 0x60b190, 0x60a819, 0x609f67, 0x609604, 0x608ca6,
    0x608375, 0x607aaa, 0x60714f, 0x6067da, 0x605eba, 0x60557e, 0x604c95, 0x604305,
    0x603a11, 0x603091, 0x60277c, 0x601e0d, 0x601434, 0x600b97, 0x60027e, 0x5ff957,
    0x5fef61, 0x5fe61e, 0x5fdd3d, 0x5fd517, 0x5fcbc4, 0x5fc2cb, 0x5fb9af, 0x5fb07f,
    0x5fa795, 0x5f9e5c, 0x5f94be, 0x5f8bb2, 0x5f822a, 0x5f792b, 0x5f700b, 0x5f673f,
    0x40f9af, 0x5f52e3, 0x409de1, 0x40e62d, 0x403aca, 0x5f50e0
]
 
funcs_to_handle += [
    0x4055C4, 0x404F6B
]
 
funcs_handled = set()
code = ''
while funcs_to_handle:
    f = funcs_to_handle.pop(0)
    if f in funcs_handled: continue
    funcs_handled.add(f)
    if ob_start <= f < ob_end:
        code += extract_function(f)
    else:
        print("// unknown func (maybe library function): f%s" % make_label(f - ob_start))
        code += 'f%s:\njmp 0x%x\n' % (make_label(f - ob_start), f)
    code += '\n\n.string "================"\n\n'
 
# print('\n' + code)
 
with open('out.s', 'w') as f:
    f.write(code)
 
print('OK')
import pwn
# pwn.context.os = 'windows' # not needed
pwn.context.arch = 'i386'
 
code = open('out.s', 'r').read()
 
with open('out', 'wb') as f:
    f.write(pwn.asm(code, vma=0x800000))
 
print('OK')
import pwn
# pwn.context.os = 'windows' # not needed
pwn.context.arch = 'i386'
 
code = open('out.s', 'r').read()
 
with open('out', 'wb') as f:
    f.write(pwn.asm(code, vma=0x800000))
 
print('OK')
import ida_bytes
with open('out', 'rb') as f:
    data = f.read()
 
ida_bytes.patch_bytes(0x800000, data)
import ida_bytes
with open('out', 'rb') as f:
    data = f.read()
 
ida_bytes.patch_bytes(0x800000, data)
  printf(v597);                                 // 输入序列号:
  gets_s(password, 0x100u);
  if ( strlen(password) >= 0x21 )
    goto LABEL_20;
  for ( k = 0; ; ++k )
  {
    v5 = strlen(password);
    if ( k >= v5 )
      break;
    if ( password[k] >= 97 && password[k] <= 122 )
      goto LABEL_20;
  }
  v525 = (char *)((int (__cdecl *)(char *, int))loc_40E62D)(password, 32);  // hex to bytes
  memset(input, 0, 0x100u);
  j_AES_encrypt(v525, v609, input);
 
  // ...
 
  j_decrypt1(&Source[189], output, input);
  memcpy(&output[8], v573, 8u);
  j_decrypt1(&Source[180], v602, output);
  memcpy(&v602[8], v594, 8u);
  j_decrypt1(&Source[171], output, v602);
  memcpy(&output[8], v593, 8u);
  j_decrypt1(&Source[162], v602, output);
  memcpy(&v602[8], v592, 8u);
  j_decrypt1(&Source[153], output, v602);
  memcpy(&output[8], v591, 8u);
  j_decrypt1(&Source[144], v602, output);
  memcpy(&v602[8], v590, 8u);
  j_decrypt1(&Source[135], output, v602);
  memcpy(&output[8], v589, 8u);
  j_decrypt1(&Source[126], v602, output);
  memcpy(&v602[8], v588, 8u);
  j_decrypt1(&Source[117], output, v602);
  memcpy(&output[8], v587, 8u);
  j_decrypt1(&Source[108], v602, output);
  memcpy(&v602[8], v586, 8u);
  j_decrypt1(&Source[99], output, v602);
  memcpy(&output[8], v585, 8u);
  j_decrypt1(&Source[90], v602, output);
  memcpy(&v602[8], v584, 8u);
  j_decrypt1(&Source[81], output, v602);
  memcpy(&output[8], v583, 8u);
  j_decrypt1(&Source[72], v602, output);
  memcpy(&v602[8], v582, 8u);
  j_decrypt1(&Source[63], output, v602);
  memcpy(&output[8], v581, 8u);
  j_decrypt1(&Source[54], v602, output);
  memcpy(&v602[8], v580, 8u);
  j_decrypt1(&Source[45], output, v602);
  memcpy(&output[8], v579, 8u);
  j_decrypt1(&Source[36], v602, output);
  memcpy(&v602[8], v578, 8u);
  j_decrypt1(&Source[27], output, v602);
  memcpy(&output[8], v577, 8u);
  j_decrypt1(&Source[18], v602, output);
  memcpy(&v602[8], v575, 8u);
  j_decrypt1(&Source[9], output, v602);
  memcpy(&output[8], v576, 8u);
  j_decrypt1(Source, v602, output);
  Str2[8] = 0;
  memcpy(Str2, v602, 8u);
  memset(Destination, 0, 0x1F4u);
  for ( l = 0; l < 50; strcat_s(Destination, 0x400u, &Source[9 * l++]) )
    ;
  memmove(vm_key, Destination, 500u);
  j_vm_encrypt(vm_key, Str2, 1);
  if ( !strcmp(Str1, Str2) )
    MessageBoxA(0, "success", "success", 0);
  else
LABEL_20:
    MessageBoxA(0, "fail", "fail", 0);
  return 0;
}
  printf(v597);                                 // 输入序列号:
  gets_s(password, 0x100u);
  if ( strlen(password) >= 0x21 )
    goto LABEL_20;
  for ( k = 0; ; ++k )
  {
    v5 = strlen(password);
    if ( k >= v5 )
      break;
    if ( password[k] >= 97 && password[k] <= 122 )
      goto LABEL_20;
  }
  v525 = (char *)((int (__cdecl *)(char *, int))loc_40E62D)(password, 32);  // hex to bytes
  memset(input, 0, 0x100u);
  j_AES_encrypt(v525, v609, input);
 
  // ...
 
  j_decrypt1(&Source[189], output, input);
  memcpy(&output[8], v573, 8u);
  j_decrypt1(&Source[180], v602, output);
  memcpy(&v602[8], v594, 8u);
  j_decrypt1(&Source[171], output, v602);
  memcpy(&output[8], v593, 8u);
  j_decrypt1(&Source[162], v602, output);
  memcpy(&v602[8], v592, 8u);
  j_decrypt1(&Source[153], output, v602);
  memcpy(&output[8], v591, 8u);
  j_decrypt1(&Source[144], v602, output);
  memcpy(&v602[8], v590, 8u);
  j_decrypt1(&Source[135], output, v602);
  memcpy(&output[8], v589, 8u);
  j_decrypt1(&Source[126], v602, output);
  memcpy(&v602[8], v588, 8u);
  j_decrypt1(&Source[117], output, v602);
  memcpy(&output[8], v587, 8u);
  j_decrypt1(&Source[108], v602, output);
  memcpy(&v602[8], v586, 8u);
  j_decrypt1(&Source[99], output, v602);
  memcpy(&output[8], v585, 8u);
  j_decrypt1(&Source[90], v602, output);
  memcpy(&v602[8], v584, 8u);
  j_decrypt1(&Source[81], output, v602);
  memcpy(&output[8], v583, 8u);
  j_decrypt1(&Source[72], v602, output);
  memcpy(&v602[8], v582, 8u);
  j_decrypt1(&Source[63], output, v602);
  memcpy(&output[8], v581, 8u);
  j_decrypt1(&Source[54], v602, output);
  memcpy(&v602[8], v580, 8u);
  j_decrypt1(&Source[45], output, v602);
  memcpy(&output[8], v579, 8u);
  j_decrypt1(&Source[36], v602, output);
  memcpy(&v602[8], v578, 8u);
  j_decrypt1(&Source[27], output, v602);
  memcpy(&output[8], v577, 8u);
  j_decrypt1(&Source[18], v602, output);
  memcpy(&v602[8], v575, 8u);
  j_decrypt1(&Source[9], output, v602);
  memcpy(&output[8], v576, 8u);
  j_decrypt1(Source, v602, output);
  Str2[8] = 0;
  memcpy(Str2, v602, 8u);
  memset(Destination, 0, 0x1F4u);
  for ( l = 0; l < 50; strcat_s(Destination, 0x400u, &Source[9 * l++]) )
    ;
  memmove(vm_key, Destination, 500u);
  j_vm_encrypt(vm_key, Str2, 1);
  if ( !strcmp(Str1, Str2) )
    MessageBoxA(0, "success", "success", 0);
  else
LABEL_20:
    MessageBoxA(0, "fail", "fail", 0);
  return 0;
}
void __cdecl AES_encrypt(char *input, char *key, char *output)
{
  char v3[176]; // [esp+1Ch] [ebp-ECh] BYREF
  char v4[16]; // [esp+CCh] [ebp-3Ch] BYREF
  int v5; // [esp+DCh] [ebp-2Ch]
  char state[16]; // [esp+E0h] [ebp-28h] BYREF
  DWORD v7; // [esp+F0h] [ebp-18h] BYREF
  Params *v8; // [esp+F4h] [ebp-14h]
  int j; // [esp+F8h] [ebp-10h]
  Params *v10; // [esp+FCh] [ebp-Ch]
  int i; // [esp+100h] [ebp-8h]
 
  v5 = 0;
  j_memset_0(state, 0, sizeof(state));
  j_memset_0(v4, 0, sizeof(v4));
  j_memset_0(v3, 0, sizeof(v3));
  j_AES_set_state(input, state);
  j_AES_set_state(key, v4);
  j_AES_KeyExpansion(v4, v3);
  j_AES_AddRoundKey(state, v3, 4 * aes_lock_index);
  aes_lock_index += 2;
  j_AES_ShiftRows(state);
  j_AES_SubBytes(state);
  v7 = 1;
  for ( i = 8; i <= 20; i += 4 )
  {
    v10 = (Params *)j_calloc_0(0xCu, 1u);
    v10->index = i;
    v10->state = state;
    v10->exkey = v3;
    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_1, v10, 0, &v7);
  }
  for ( j = 18; j > 0; j -= 4 )
  {
    v8 = (Params *)j_calloc_0(0xCu, 1u);
    v8->index = j;
    v8->state = state;
    v8->exkey = v3;
    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_2, v8, 0, &v7);
  }
  while ( aes_lock_index != -1 )
    ;
  j_AES_AddRoundKey(state, v3, 0);
  AES_get_state(state, output);
}
 
void __cdecl thread_1(Params *p)
{
  while ( aes_lock_index != p->index / 2 )
    ;
  j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
  AES_MixColumns(p->state);
  j_AES_ShiftRows(p->state);
  j_AES_SubBytes(p->state);
  if ( aes_lock_index == 10 )
    --aes_lock_index;
  else
    aes_lock_index += 2;
  j_free(p);
}
 
void __cdecl thread_2(Params *p)
{
  while ( aes_lock_index != p->index / 2 )
    ;
  j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
  AES_MixColumns(p->state);
  j_AES_ShiftRows(p->state);
  j_AES_SubBytes(p->state);
  aes_lock_index -= 2;
  j_free(p);
}
void __cdecl AES_encrypt(char *input, char *key, char *output)
{
  char v3[176]; // [esp+1Ch] [ebp-ECh] BYREF
  char v4[16]; // [esp+CCh] [ebp-3Ch] BYREF
  int v5; // [esp+DCh] [ebp-2Ch]
  char state[16]; // [esp+E0h] [ebp-28h] BYREF
  DWORD v7; // [esp+F0h] [ebp-18h] BYREF
  Params *v8; // [esp+F4h] [ebp-14h]
  int j; // [esp+F8h] [ebp-10h]
  Params *v10; // [esp+FCh] [ebp-Ch]
  int i; // [esp+100h] [ebp-8h]
 
  v5 = 0;
  j_memset_0(state, 0, sizeof(state));
  j_memset_0(v4, 0, sizeof(v4));
  j_memset_0(v3, 0, sizeof(v3));
  j_AES_set_state(input, state);
  j_AES_set_state(key, v4);
  j_AES_KeyExpansion(v4, v3);
  j_AES_AddRoundKey(state, v3, 4 * aes_lock_index);
  aes_lock_index += 2;
  j_AES_ShiftRows(state);
  j_AES_SubBytes(state);
  v7 = 1;
  for ( i = 8; i <= 20; i += 4 )
  {
    v10 = (Params *)j_calloc_0(0xCu, 1u);
    v10->index = i;
    v10->state = state;
    v10->exkey = v3;
    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_1, v10, 0, &v7);
  }
  for ( j = 18; j > 0; j -= 4 )
  {
    v8 = (Params *)j_calloc_0(0xCu, 1u);
    v8->index = j;
    v8->state = state;
    v8->exkey = v3;
    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_2, v8, 0, &v7);
  }
  while ( aes_lock_index != -1 )
    ;
  j_AES_AddRoundKey(state, v3, 0);
  AES_get_state(state, output);
}
 
void __cdecl thread_1(Params *p)
{
  while ( aes_lock_index != p->index / 2 )
    ;
  j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
  AES_MixColumns(p->state);
  j_AES_ShiftRows(p->state);
  j_AES_SubBytes(p->state);
  if ( aes_lock_index == 10 )
    --aes_lock_index;
  else
    aes_lock_index += 2;
  j_free(p);
}
 
void __cdecl thread_2(Params *p)
{
  while ( aes_lock_index != p->index / 2 )
    ;
  j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
  AES_MixColumns(p->state);
  j_AES_ShiftRows(p->state);
  j_AES_SubBytes(p->state);
  aes_lock_index -= 2;
  j_free(p);
}
#include <stdio.h>
#include <string.h>
#include <assert.h>
// AES
typedef struct {
    unsigned char rk[4][11][4]; // round key
    unsigned char iv[16];
} AES_CONTEXT;
 
const unsigned char Sbox[256] = {
    0x28, 0xC2, 0xE8, 0x57, 0x48, 0x24, 0x97, 0xC5, 0x18, 0x8C, 0x9B, 0x72, 0xF7, 0x99, 0xDE, 0xD3,
    0x85, 0x58, 0x7A, 0x0B, 0x44, 0xD1, 0xB0, 0x47, 0xC7, 0xAE, 0xF0, 0x6D, 0x53, 0xE1, 0x60, 0xB4,
    0x4B, 0x5C, 0x10, 0x52, 0x01, 0x39, 0xB9, 0x90, 0xAB, 0x00, 0xD4, 0x73, 0x64, 0x32, 0x9F, 0xA1,
    0x6A, 0x1C, 0x6B, 0x21, 0xF1, 0xEF, 0x3F, 0x67, 0x95, 0xF2, 0x79, 0xE0, 0x0C, 0xD0, 0x66, 0x7F,
    0x2C, 0xC3, 0x12, 0x5A, 0x34, 0xEB, 0x15, 0xA6, 0xBC, 0x7D, 0xA0, 0xB8, 0x55, 0x49, 0xC1, 0xFB,
    0xE9, 0x08, 0x3C, 0xE2, 0x56, 0x2F, 0x30, 0x9E, 0x0E, 0xCB, 0x25, 0xE3, 0x46, 0x5D, 0xEC, 0x4C,
    0x09, 0xBE, 0x87, 0x04, 0x89, 0xD8, 0x19, 0x3D, 0x71, 0x40, 0x7E, 0x5F, 0x16, 0x7B, 0x3A, 0x27,
    0x43, 0x76, 0x45, 0x8A, 0x35, 0x96, 0xF9, 0x07, 0x8F, 0x0F, 0x54, 0xCF, 0xBA, 0x38, 0x83, 0xCE,
    0x2A, 0xAC, 0x68, 0xF4, 0x80, 0x31, 0xA4, 0xFE, 0x93, 0xB3, 0x7C, 0xCA, 0xB6, 0x75, 0xDA, 0xA8,
    0xD7, 0xB1, 0x37, 0xC4, 0x6C, 0x6F, 0xD5, 0x4F, 0x23, 0x14, 0x98, 0xAA, 0xDC, 0x65, 0x74, 0x42,
    0xC8, 0x41, 0x8D, 0xA5, 0x22, 0xEA, 0x4D, 0xB5, 0x17, 0x02, 0x1E, 0x88, 0x91, 0x33, 0xC6, 0x78,
    0x3B, 0x2D, 0xD9, 0xFC, 0x1B, 0x9A, 0xCD, 0xE6, 0x1F, 0xED, 0x92, 0x29, 0x4A, 0xFA, 0x1A, 0xEE,
    0x0D, 0xE7, 0x63, 0x8E, 0xFF, 0x06, 0x3E, 0x1D, 0xF8, 0xAD, 0xE5, 0x36, 0x05, 0x70, 0xA2, 0x69,
    0x84, 0xBF, 0xA9, 0x8B, 0x03, 0xD6, 0x26, 0x2E, 0x82, 0x62, 0x81, 0xE4, 0x94, 0xA7, 0xAF, 0x5E,
    0x9D, 0xD2, 0xB2, 0x86, 0x2B, 0x51, 0xCC, 0xDD, 0x13, 0xF5, 0x77, 0x50, 0xC0, 0xB7, 0x0A, 0x59,
    0x4E, 0xC9, 0xBB, 0x11, 0xA3, 0x6E, 0xDB, 0xF6, 0x61, 0x9C, 0x20, 0xDF, 0xFD, 0xBD, 0x5B, 0xF3
};
 
unsigned char InvSbox[256] = {
 
};
 
void KeyExpansion(AES_CONTEXT *ctx, const unsigned char* key) {
    int i, j, r, c;
    unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4; c++) {
            ctx->rk[r][0][c] = key[r + c * 4];
        }
    }
    for(i = 1; i <= 10; i++) {
        for(j = 0; j < 4; j++) {
            unsigned char t[4];
            for(r = 0; r < 4; r++) {
                t[r] = j ? ctx->rk[r][i][j - 1] : ctx->rk[r][i - 1][3];
            }
            if(j == 0) {
                unsigned char temp = t[0];
                for(r = 0; r < 3; r++) {
                    t[r] = Sbox[t[(r + 1) % 4]];
                }
                t[3] = Sbox[temp];
                t[0] ^= rc[i - 1];
            }
            for(r = 0; r < 4; r++) {
                ctx->rk[r][i][j] = ctx->rk[r][i - 1][j] ^ t[r];
            }
        }
    }
}
 
unsigned char FFmul(unsigned char a, unsigned char b) {
    unsigned char bw[4];
    unsigned char res = 0;
    int i;
    bw[0] = b;
    for(i = 1; i < 4; i++) {
        bw[i] = bw[i-1] << 1;
        if(bw[i - 1] & 0x80) {
            bw[i] ^= 0x1b;
        }
    }
    for(i=0; i<4; i++) {
        if((a >> i) & 0x01) {
            res ^= bw[i];
        }
    }
    return res;
}
 
void SubBytes(AES_CONTEXT *ctx, unsigned char state[][4]) {
    int r, c;
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4; c++) {
            state[r][c] = Sbox[state[r][c]];
        }
    }
}
 
unsigned int ror4(unsigned int x, int n) {
    return (x >> n) | (x << (32 - n));
}
 
unsigned int rol4(unsigned int x, int n) {
    return ror4(x, 32 - n);
}
 
void ShiftRows(AES_CONTEXT *ctx, unsigned char state[][4]) {
    unsigned int* _s = (unsigned int*) state;
    _s[0] = ror4(_s[0], 0);
    _s[1] = ror4(_s[1], 8);
    _s[2] = ror4(_s[2], 24);
    _s[3] = ror4(_s[3], 16);
}
 
void MixColumns(AES_CONTEXT *ctx, unsigned char state[][4]) {
    unsigned char t[4];
    int r, c;
    for(c = 0; c < 4; c++) {
        for(r = 0; r < 4; r++) {
            t[r] = state[r][c];
        }
        for(r=0; r<4; r++) {
            state[r][c] = FFmul(0x0e, t[r]) ^ FFmul(0x0b, t[(r + 1) % 4]) ^ FFmul(0x0d, t[(r + 2) % 4]) ^ FFmul(0x09, t[(r + 3) % 4]);
        }
    }
}
 
void AddRoundKey(AES_CONTEXT *ctx, unsigned char state[][4], unsigned char k[][11][4], int index) {
    int r, c;
    for(c = 0; c < 4; c++) {
        for(r = 0; r < 4; r++) {
            state[c][r] ^= k[c][index][r];
        }
    }
}
 
void InvSubBytes(AES_CONTEXT *ctx, unsigned char state[][4]) {
    int r, c;
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4; c++) {
            state[r][c] = InvSbox[state[r][c]];
        }
    }
}
 
void InvShiftRows(AES_CONTEXT *ctx, unsigned char state[][4]) {
    unsigned int* _s = (unsigned int*) state;
    _s[0] = rol4(_s[0], 0);
    _s[1] = rol4(_s[1], 8);
    _s[2] = rol4(_s[2], 24);
    _s[3] = rol4(_s[3], 16);
}
 
void InvMixColumns(AES_CONTEXT *ctx, unsigned char state[][4]) {
    unsigned char t[4];
    int r, c;
    for(c = 0; c < 4; c++) {
        for(r = 0; r < 4; r++) {
            t[r] = state[r][c];
        }
        for(r = 0; r < 4; r++) {
            state[r][c] = FFmul(0x02, t[r]) ^ FFmul(0x03, t[(r + 1) % 4]) ^ FFmul(0x01, t[(r + 2) % 4]) ^ FFmul(0x01, t[(r + 3) % 4]);
        }
    }
}
 
void aes_init(AES_CONTEXT *ctx, const unsigned char* key, const void* iv) {
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 16; j++) {
            InvSbox[Sbox[16 * i + j]] = 16 * i + j;
        }
    }
    KeyExpansion(ctx, key);
    if (iv) memcpy(ctx->iv, iv, 16);
}
 
unsigned char* aes_encrypt_block(AES_CONTEXT* ctx, unsigned char* input) {
    unsigned char state[4][4];
    int i, r, c;
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4 ;c++) {
            state[r][c] = input[c * 4 + r];
        }
    }
 
    AddRoundKey(ctx, state, ctx->rk, 2);
    ShiftRows(ctx, state);
    SubBytes(ctx, state);
 
    for(i = 8; i <= 20; i += 4) {
        AddRoundKey(ctx, state, ctx->rk, i / 2);
        MixColumns(ctx, state);
        ShiftRows(ctx, state);
        SubBytes(ctx, state);
    }
 
    for(i = 18; i > 0; i -= 4) {
        AddRoundKey(ctx, state, ctx->rk, i / 2);
        MixColumns(ctx, state);
        ShiftRows(ctx, state);
        SubBytes(ctx, state);
    }
    AddRoundKey(ctx, state, ctx->rk, 0);
     
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4 ;c++) {
            input[c * 4 + r] = state[r][c];
        }
    }
 
    return input;
}
 
unsigned char* aes_decrypt_block(AES_CONTEXT *ctx, unsigned char* input) {
    unsigned char state[4][4];
    int i, r, c;
 
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4; c++) {
            state[r][c] = input[c * 4 + r];
        }
    }
 
    AddRoundKey(ctx, state, ctx->rk, 0);
    for (int i = 2; i <= 18; i += 4) {
        InvSubBytes(ctx, state);
        InvShiftRows(ctx, state);
        InvMixColumns(ctx, state);
        AddRoundKey(ctx, state, ctx->rk, i / 2);
    }
    for(i = 20; i >= 8; i -= 4) {
        InvSubBytes(ctx, state);
        InvShiftRows(ctx, state);
        InvMixColumns(ctx, state);
        AddRoundKey(ctx, state, ctx->rk, i / 2);
    }
 
    InvSubBytes(ctx, state);
    InvShiftRows(ctx, state);
    AddRoundKey(ctx, state, ctx->rk, 2);
 
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4 ;c++) {
            input[c * 4 + r] = state[r][c];
        }
    }
 
    return input;
}
 
void aes_encrypt_ecb(const void* key, void* data, int data_len) {
    assert(data_len % 16 == 0);
    AES_CONTEXT ctx;
    aes_init(&ctx, (const unsigned char*) key, NULL);
    unsigned char* _data = (unsigned char*) data;
    for (int i = 0; i < data_len / 16; i++) {
        aes_encrypt_block(&ctx, _data);
        _data += 16;
    }
}
 
void aes_decrypt_ecb(const void* key, void* data, int data_len) {
    assert(data_len % 16 == 0);
    AES_CONTEXT ctx;
    aes_init(&ctx, (const unsigned char*) key, NULL);
    unsigned char* _data = (unsigned char*) data;
    for (int i = 0; i < data_len / 16; i++) {
        aes_decrypt_block(&ctx, _data);
        _data += 16;
    }
}
#include <stdio.h>
#include <string.h>
#include <assert.h>
// AES
typedef struct {
    unsigned char rk[4][11][4]; // round key
    unsigned char iv[16];
} AES_CONTEXT;
 
const unsigned char Sbox[256] = {
    0x28, 0xC2, 0xE8, 0x57, 0x48, 0x24, 0x97, 0xC5, 0x18, 0x8C, 0x9B, 0x72, 0xF7, 0x99, 0xDE, 0xD3,
    0x85, 0x58, 0x7A, 0x0B, 0x44, 0xD1, 0xB0, 0x47, 0xC7, 0xAE, 0xF0, 0x6D, 0x53, 0xE1, 0x60, 0xB4,
    0x4B, 0x5C, 0x10, 0x52, 0x01, 0x39, 0xB9, 0x90, 0xAB, 0x00, 0xD4, 0x73, 0x64, 0x32, 0x9F, 0xA1,
    0x6A, 0x1C, 0x6B, 0x21, 0xF1, 0xEF, 0x3F, 0x67, 0x95, 0xF2, 0x79, 0xE0, 0x0C, 0xD0, 0x66, 0x7F,
    0x2C, 0xC3, 0x12, 0x5A, 0x34, 0xEB, 0x15, 0xA6, 0xBC, 0x7D, 0xA0, 0xB8, 0x55, 0x49, 0xC1, 0xFB,
    0xE9, 0x08, 0x3C, 0xE2, 0x56, 0x2F, 0x30, 0x9E, 0x0E, 0xCB, 0x25, 0xE3, 0x46, 0x5D, 0xEC, 0x4C,
    0x09, 0xBE, 0x87, 0x04, 0x89, 0xD8, 0x19, 0x3D, 0x71, 0x40, 0x7E, 0x5F, 0x16, 0x7B, 0x3A, 0x27,
    0x43, 0x76, 0x45, 0x8A, 0x35, 0x96, 0xF9, 0x07, 0x8F, 0x0F, 0x54, 0xCF, 0xBA, 0x38, 0x83, 0xCE,
    0x2A, 0xAC, 0x68, 0xF4, 0x80, 0x31, 0xA4, 0xFE, 0x93, 0xB3, 0x7C, 0xCA, 0xB6, 0x75, 0xDA, 0xA8,
    0xD7, 0xB1, 0x37, 0xC4, 0x6C, 0x6F, 0xD5, 0x4F, 0x23, 0x14, 0x98, 0xAA, 0xDC, 0x65, 0x74, 0x42,
    0xC8, 0x41, 0x8D, 0xA5, 0x22, 0xEA, 0x4D, 0xB5, 0x17, 0x02, 0x1E, 0x88, 0x91, 0x33, 0xC6, 0x78,
    0x3B, 0x2D, 0xD9, 0xFC, 0x1B, 0x9A, 0xCD, 0xE6, 0x1F, 0xED, 0x92, 0x29, 0x4A, 0xFA, 0x1A, 0xEE,
    0x0D, 0xE7, 0x63, 0x8E, 0xFF, 0x06, 0x3E, 0x1D, 0xF8, 0xAD, 0xE5, 0x36, 0x05, 0x70, 0xA2, 0x69,
    0x84, 0xBF, 0xA9, 0x8B, 0x03, 0xD6, 0x26, 0x2E, 0x82, 0x62, 0x81, 0xE4, 0x94, 0xA7, 0xAF, 0x5E,
    0x9D, 0xD2, 0xB2, 0x86, 0x2B, 0x51, 0xCC, 0xDD, 0x13, 0xF5, 0x77, 0x50, 0xC0, 0xB7, 0x0A, 0x59,
    0x4E, 0xC9, 0xBB, 0x11, 0xA3, 0x6E, 0xDB, 0xF6, 0x61, 0x9C, 0x20, 0xDF, 0xFD, 0xBD, 0x5B, 0xF3
};
 
unsigned char InvSbox[256] = {
 
};
 
void KeyExpansion(AES_CONTEXT *ctx, const unsigned char* key) {
    int i, j, r, c;
    unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4; c++) {
            ctx->rk[r][0][c] = key[r + c * 4];
        }
    }
    for(i = 1; i <= 10; i++) {
        for(j = 0; j < 4; j++) {
            unsigned char t[4];
            for(r = 0; r < 4; r++) {
                t[r] = j ? ctx->rk[r][i][j - 1] : ctx->rk[r][i - 1][3];
            }
            if(j == 0) {
                unsigned char temp = t[0];
                for(r = 0; r < 3; r++) {
                    t[r] = Sbox[t[(r + 1) % 4]];
                }
                t[3] = Sbox[temp];
                t[0] ^= rc[i - 1];
            }
            for(r = 0; r < 4; r++) {
                ctx->rk[r][i][j] = ctx->rk[r][i - 1][j] ^ t[r];
            }
        }
    }
}
 
unsigned char FFmul(unsigned char a, unsigned char b) {
    unsigned char bw[4];
    unsigned char res = 0;
    int i;
    bw[0] = b;
    for(i = 1; i < 4; i++) {
        bw[i] = bw[i-1] << 1;
        if(bw[i - 1] & 0x80) {
            bw[i] ^= 0x1b;
        }
    }
    for(i=0; i<4; i++) {
        if((a >> i) & 0x01) {
            res ^= bw[i];
        }
    }
    return res;
}
 
void SubBytes(AES_CONTEXT *ctx, unsigned char state[][4]) {
    int r, c;
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4; c++) {
            state[r][c] = Sbox[state[r][c]];
        }
    }
}
 
unsigned int ror4(unsigned int x, int n) {
    return (x >> n) | (x << (32 - n));
}
 
unsigned int rol4(unsigned int x, int n) {
    return ror4(x, 32 - n);
}
 
void ShiftRows(AES_CONTEXT *ctx, unsigned char state[][4]) {
    unsigned int* _s = (unsigned int*) state;
    _s[0] = ror4(_s[0], 0);
    _s[1] = ror4(_s[1], 8);
    _s[2] = ror4(_s[2], 24);
    _s[3] = ror4(_s[3], 16);
}
 
void MixColumns(AES_CONTEXT *ctx, unsigned char state[][4]) {
    unsigned char t[4];
    int r, c;
    for(c = 0; c < 4; c++) {
        for(r = 0; r < 4; r++) {
            t[r] = state[r][c];
        }
        for(r=0; r<4; r++) {
            state[r][c] = FFmul(0x0e, t[r]) ^ FFmul(0x0b, t[(r + 1) % 4]) ^ FFmul(0x0d, t[(r + 2) % 4]) ^ FFmul(0x09, t[(r + 3) % 4]);
        }
    }
}
 
void AddRoundKey(AES_CONTEXT *ctx, unsigned char state[][4], unsigned char k[][11][4], int index) {
    int r, c;
    for(c = 0; c < 4; c++) {
        for(r = 0; r < 4; r++) {
            state[c][r] ^= k[c][index][r];
        }
    }
}
 
void InvSubBytes(AES_CONTEXT *ctx, unsigned char state[][4]) {
    int r, c;
    for(r = 0; r < 4; r++) {
        for(c = 0; c < 4; c++) {
            state[r][c] = InvSbox[state[r][c]];
        }
    }

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 5
支持
分享
最新回复 (1)
雪    币: 3114
活跃值: (30886)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-9-18 08:47
1
游客
登录 | 注册 方可回帖
返回
//