网鼎杯 第四场: rev

pwn学艺不精,确认过名字,是我没学过的类型。就搞了一个babyvm,java是后来看的,还有个babyperf,最近rev做得少,没见过,还没搞出来,学一波先。

java

题目分析

挺简单的,就不详细写了,就是xor + AES_ECB + base64。

script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from Crypto.Cipher import AES 
from base64 import b64decode as bd

val = [214, 144, 233, 254, 204, 225, 61, 183, 22, 182, 43, 103, 20, 194, 40, 251, 44, 5, 43, 103, 154, 118, 42, 190, 4, 195, 43, 103, 170, 68, 19, 38, 73, 134, 43, 103, 153, 156, 66, 80, 244, 145, 80, 103, 239, 152, 122, 98, 50, 214]

string = bd('VsBDJCvuhD65/+sL+Hlf587nWuIa2MPcqZaq7GMVWI0Vx8l9R42PXWbhCRftoFB3')
print(string)

res = []
for i in range(len(string)):
res.append(ord(string[i]) ^ val[i] ^ 22)

cipher = ''.join([chr(item) for item in res])
print(len(cipher))

key = "aos_chock_koy!@#"
aes = AES.new(key, AES.MODE_ECB)

print(aes.decrypt(cipher))

babyvm

题目分析

  1. 输入形如 “flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}” 的flag,其中”x“为[0-9a-f]
  2. 判断flag长度为42,判断flag特征,顺序提取出的16进制字符串的长度为32
  3. 将16进制字符串encode(‘hex’),得到长度16的字符串
  4. 计算字符串的md5,以及通过算法扩展至100长度的字符串的md5
  5. 以上明文字符串,md5,扩展md5分为4组,分组输入虚拟机计算

  6. 虚拟机执行,结果通过第一个寄存器返回,指令集:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    0x0: "mov", # from stack
    0x1: "push", # imm
    0x2: "pop",
    0x3: "call",
    0x4: "ret",
    0x5: "jmp",
    0x6: "je",
    0x7: "neg rflag",
    0x8: "add",
    0x9: "sub",
    0xA: "mul",
    0xB: "div",
    0xC: "xor",
    0xD: "push", # reg
    0xE: "cmp",
    0xF: "and",
    0x10: "or",
    0x11: "ror",
    0x12: "rol",
    0x13: "neg",
    0x14: "mod",
    0xD0: "push",
    0xE0: "mov", # to stack
    0xF0: "mov", # to stack (imm)
    0xFF: "halt"
  7. 将计算结果进行比较

script

  1. 提取指令:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    ins = \
    [
    0xD0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0D, 0x01, 0x02, 0x04, 0x01, 0x10, 0x00, 0x00, 0x00,
    0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02,
    0x09, 0x01, 0x02, 0x0D, 0x01, 0x02, 0x05, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x06, 0x14, 0x05,
    0x06, 0x11, 0x04, 0x05, 0x01, 0xB9, 0x79, 0x37, 0x9E, 0x02, 0x05, 0x0C, 0x04, 0x05, 0x0D, 0x04,
    0x03, 0xAD, 0x00, 0x00, 0x00, 0x0C, 0x04, 0x01, 0x02, 0x04, 0x0E, 0x01, 0x03, 0x07, 0x06, 0x19,
    0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,
    0x03, 0x0D, 0x04, 0x02, 0x05, 0x10, 0x05, 0x02, 0x10, 0x05, 0x03, 0x0D, 0x05, 0x0D, 0x04, 0x02,
    0x05, 0x0F, 0x05, 0x02, 0x0F, 0x05, 0x03, 0x0D, 0x05, 0x0D, 0x04, 0x02, 0x05, 0x0F, 0x05, 0x02,
    0x0D, 0x05, 0x0D, 0x04, 0x02, 0x05, 0x0F, 0x05, 0x03, 0x0D, 0x05, 0x0D, 0x02, 0x02, 0x05, 0x0F,
    0x05, 0x03, 0x02, 0x06, 0x0C, 0x05, 0x06, 0x02, 0x06, 0x0C, 0x05, 0x06, 0x02, 0x06, 0x0C, 0x05,
    0x06, 0x02, 0x06, 0x0C, 0x05, 0x06, 0x0D, 0x05, 0x02, 0x01, 0x13, 0x01, 0xFF, 0x00, 0x08, 0x00,
    0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x01, 0x02, 0xE0, 0x08, 0x00,
    0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x02, 0x03,
    0x12, 0x02, 0x03, 0xE0, 0x09, 0x00, 0x00, 0x00, 0x02, 0x04
    ]

    opcode = \
    {
    0x0: "mov", # from stack
    0x1: "push", # imm
    0x2: "pop",
    0x3: "call",
    0x4: "ret",
    0x5: "jmp",
    0x6: "je",
    0x7: "neg rflag",
    0x8: "add",
    0x9: "sub",
    0xA: "mul",
    0xB: "div",
    0xC: "xor",
    0xD: "push", # reg
    0xE: "cmp",
    0xF: "and",
    0x10: "or",
    0x11: "ror",
    0x12: "rol",
    0x13: "neg",
    0x14: "mod",
    0xD0: "push",
    0xE0: "mov", # to stack
    0xF0: "mov", # to stack (imm)
    0xFF: "halt"
    }

    index = 0
    pc = 0
    while pc < len(ins):
    print(hex(pc) + ": "),

    res = ""
    op = ins[pc]
    if op == 0x0:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 5]) + " "
    res += "[$sp + 4 * " + str((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1]) + "]"
    pc += 6
    elif op == 0x1:
    res += opcode[op] + " "
    res += hex((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1])
    pc += 5
    elif op == 0x2:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    pc += 2
    elif op == 0x3:
    res += opcode[op] + " "
    res += hex((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1])
    pc += 5
    elif op == 0x4:
    res += opcode[op] + " "
    pc += 1
    elif op == 0x5:
    res += opcode[op] + " "
    res += hex((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1])
    pc += 5
    elif op == 0x6:
    res += opcode[op] + " "
    res += hex((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1])
    pc += 5
    elif op == 0x7:
    res += opcode[op] + " "
    pc += 1
    elif op == 0x8:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0x9:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0xA:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0xB:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0xC:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0xD:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    pc += 2
    elif op == 0xE:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0xF:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0x10:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0x11:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0x12:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0x13:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    pc += 2
    elif op == 0x14:
    res += opcode[op] + " "
    res += "r" + str(ins[pc + 1]) + " "
    res += "r" + str(ins[pc + 2]) + " "
    pc += 3
    elif op == 0xD0:
    res += opcode[op] + " "
    res += "[$data + 4 * " + str((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1]) + "]" + " "
    pc += 5
    elif op == 0xE0:
    res += opcode[op] + " "
    res += "[$sp + 4 * " + str((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1]) + "]" + " "
    res += "r" + str(ins[pc + 5]) + " "
    pc += 6
    elif op == 0xF0:
    res += opcode[op] + " "
    res += "[$sp + 4 * " + str((ins[pc + 4] << 24) + (ins[pc + 3] << 16) + (ins[pc + 2] << 8) + ins[pc + 1]) + "]" + " "
    res += hex((ins[pc + 8] << 24) + (ins[pc + 7] << 16) + (ins[pc + 6] << 8) + ins[pc + 5])
    pc += 9
    elif op == 0xFF:
    res += opcode[op] + " "
    pc += 1
    else:
    break

    print(res)
    index += 1
    提取结果:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    0x0:  push [$data + 4 * 0] 
    0x5: pop r1
    0x7: push r1
    0x9: pop r4
    0xb: push 0x10
    0x10: pop r1
    0x12: push 0x0
    0x17: pop r3
    0x19: push 0x1
    0x1e: pop r2
    0x20: sub r1 r2
    0x23: push r1
    0x25: pop r5
    0x27: push 0x8
    0x2c: pop r6
    0x2e: mod r5 r6
    0x31: ror r4 r5
    0x34: push 0x9e3779b9
    0x39: pop r5
    0x3b: xor r4 r5 # r4 = ror(input, i % 0x10) ^ 0x9e3779b9
    0x3e: push r4
    0x40: call 0xad
    0x45: xor r4 r1
    0x48: pop r4 # return here r4 = rol(r4, 6) # input[0] = r4
    0x4a: cmp r1 r3
    0x4d: neg rflag # loop 0x10 times
    0x4e: je 0x19
    0x53: push [$data + 4 * 1]
    0x58: push [$data + 4 * 2]
    0x5d: pop r2
    0x5f: pop r3
    0x61: push r4
    0x63: pop r5
    0x65: or r5 r2
    0x68: or r5 r3 # input[0] | input[1] | input[2]
    0x6b: push r5
    0x6d: push r4
    0x6f: pop r5
    0x71: and r5 r2
    0x74: and r5 r3 # input[0] & input[1] & input[2]
    0x77: push r5
    0x79: push r4
    0x7b: pop r5
    0x7d: and r5 r2 # input[0] & input[2]
    0x80: push r5
    0x82: push r4
    0x84: pop r5
    0x86: and r5 r3 # input[0] & input[1]
    0x89: push r5
    0x8b: push r2
    0x8d: pop r5
    0x8f: and r5 r3 # input[2] & input[1]
    0x92: pop r6
    0x94: xor r5 r6
    0x97: pop r6
    0x99: xor r5 r6
    0x9c: pop r6
    0x9e: xor r5 r6
    0xa1: pop r6
    0xa3: xor r5 r6
    0xa6: push r5 # xor and neg
    0xa8: pop r1
    0xaa: neg r1
    0xac: halt
    0xad: mov r1 [$sp + 4 * 8]
    0xb3: push 0x3
    0xb8: pop r2
    0xba: add r1 r2 # ret_addr += 3 ==> 0x48
    0xbd: mov [$sp + 4 * 8] r1
    0xc3: mov r2 [$sp + 4 * 9]
    0xc9: push 0x6
    0xce: pop r3
    0xd0: rol r2 r3
    0xd3: mov [$sp + 4 * 9] r2
    0xd9: ret
  2. z3约束求解:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    #coding:utf-8
    from z3 import *
    from hashlib import md5
    from Crypto.Util.number import long_to_bytes, bytes_to_long

    def foo(v8):
    v13 = []
    for k in range(100):
    v10 = 0
    v8 ^= 0xC3
    v13.append(v8&0xff)
    for l in range(8):
    v10 ^= (v8 >> l) & 1
    v8 = (v10 | 2 * v8)&0xff
    return v13

    def decrypt(cipher):
    for i in range(0x10):
    cipher = ((cipher & 0x3F) << 26) | (cipher >> 6)
    cipher ^= 0x9e3779b9
    cipher = ((cipher << (i % 0x8)) & 0xFFFFFFFF) | ((cipher >> (32 - (i % 0x8))))
    return cipher

    def count(v1, v2, v3, v4):
    res = 0
    for i in range(4):
    res = (res + (v1 & 0xFF) + (v2 & 0xFF) + (v3 & 0xFF) + (v4 & 0xFF)) % 100
    v1 >>= 8
    v2 >>= 8
    v3 >>= 8
    v4 >>= 8

    return res

    in2 = [0x0C5D83690, 0x978162EA, 0x1932A96C, 0x4222669]
    out = [0x1F7902CC, 0x2FAE3D15, 0x0CEEBFE91, 0x0AFF6AF42]

    for v8 in range(100):
    in3 = foo(v8)
    in3 = "".join([chr(x) for x in in3])
    # print len(in3)
    in3 = md5(in3).digest()
    solver = Solver()
    k = [BitVec('k%d'%i, 32) for i in range(4)]
    for i in range(4):
    x1 = bytes_to_long(in3[4*i:(i+1)*4][::-1])
    x2 = in2[i]
    solver.add(((x1&x2&k[i]) ^ (x1|x2|k[i]) ^ (x1&x2) ^ (x1&k[i]) ^ (x2&k[i]))^0xFFFFFFFF == out[i])
    solver.check()
    x0 = solver.model().eval(k[0]).as_long()
    x1 = solver.model().eval(k[1]).as_long()
    x2 = solver.model().eval(k[2]).as_long()
    x3 = solver.model().eval(k[3]).as_long()
    x0 = decrypt(x0)
    x1 = decrypt(x1)
    x2 = decrypt(x2)
    x3 = decrypt(x3)
    # print x0,x1,x2,x3
    res = count(x0,x1,x2,x3)
    # print res
    if res == v8:
    print x0,x1,x2,x3
    final = (long_to_bytes(x0)[::-1]+long_to_bytes(x1)[::-1]+long_to_bytes(x2)[::-1]+long_to_bytes(x3)[::-1]).encode("hex")
    print final

    flag = "flag{"
    for i in range(len(final)):
    if i == 8 or i == 12 or i == 16 or i == 20:
    flag += "-"
    flag += final[i]
    flag += "}"

    print(flag)

    '''
    0C5D83690h, 1F7902CCh, 978162EAh, 2FAE3D15h, 1932A96Ch
    .data:00007FF6501E20E0 ; DATA XREF: sub_7FF6500BCCB0+55↑o
    .data:00007FF6501E20E0 dd 0CEEBFE91h, 4222669h, 0AFF6AF42h,
    '''
Author: Nop
Link: https://n0nop.com/2020/05/21/%E7%BD%91%E9%BC%8E%E6%9D%AF-%E7%AC%AC%E5%9B%9B%E5%9C%BA-rev/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.