网鼎杯-wp

网鼎杯-wp

signal

很简单的vm,甚至可以一位一位解

1
2
3
4
5
6
7
8
9
10
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp+18h] [ebp-1D4h]

__main();
qmemcpy(&v4, &opcodes, 0x1C8u);
vm_operad(&v4, 114);
puts("good,The answer format is:flag {}");
return 0;
}

vm_operad中包含了一些指令,很好理解,甚至不需要调试就可以看懂

1
2
3
4
5
6
7
8
9
10
11
0xA: read
0x1: 将结果写入target
0x8: 暂存计算结果到input
0x7 x: input[i]==x ? i++ : exit(0)
0x2 x: input+x
0x3 x: input-LOBYTE(x)
0x4 x: input^x
0x5 x: input*x
0x6 x: nop
0xB: input--
0xC: input++

read函数进行了输入的一些控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
size_t __cdecl read(char *a1)
{
size_t result; // eax

printf("string:");
scanf("%s", a1);
result = strlen(a1);
if ( result != 15 )
{
puts("WRONG!\n");
exit(0);
}
return result;
}

flag的长度为15位,再观察opcode,可以发现是一位一位进行处理,经过一种运算然后0x8暂存,然后再经过一种计算将结果写入最终target,所以可以有两种解法,可以一位一位的逆flag,也可以逆vm的指令

  • 逐位计算flag

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    target = [0x22, 0x3F, 0x34, 0x32, 0x72, 0x33, 0x18, 0xA7, 0x31,
    0xF1, 0x28, 0x84, 0xC1, 0x1E, 0x7A]
    flag = ""
    flag += chr((target[0] + 5) ^ 0x10)
    flag += chr((target[1] // 3) ^ 0x20)
    flag += chr((target[2] + 1) + 2)
    flag += chr((target[3] - 1) ^ 4)
    flag += chr((target[4] + 0x21)//3)
    flag += chr(target[5] + 2)
    flag += chr((target[6] + 0x20) ^ 0x9)
    flag += chr((target[7] ^ 0x24) - 0x51)
    flag += chr(target[8])
    flag += chr((target[9] - 0x25) // 2)
    flag += chr((target[10] ^ 0x41) - 0x36)
    flag += chr(target[11] - 0x20)
    flag += chr((target[12] - 0x25) // 3)
    flag += chr((target[13] + 0x20) ^ 9)
    flag += chr((target[14] - 1) - 0x41)
    print(flag)
    # 757515121f3d478
  • 调整vm指令

    把每一个运算改成逆运算,然后将每一位的两次计算交换顺序

    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
    171
    172
    173
    174
    175
    #include <iostream>
    #include "ida.h"

    using namespace std;

    int __cdecl vm_operad(unsigned int *opcode, int len) {
    int result; // eax
    unsigned int input[100] = {0x22, 0x3F, 0x34, 0x32, 0x72, 0x33, 0x18, 0xA7, 0x31,
    0xF1, 0x28, 0x84, 0xC1, 0x1E, 0x7A}; // [esp+13h] [ebp-E5h]
    char v4[100] = {0}; // [esp+77h] [ebp-81h]
    string flag;
    unsigned char v5; // [esp+DBh] [ebp-1Dh]
    int v6; // [esp+DCh] [ebp-1Ch]
    int v7; // [esp+E0h] [ebp-18h]
    int v8; // [esp+E4h] [ebp-14h]
    int v9; // [esp+E8h] [ebp-10h]
    int opcode_index; // [esp+ECh] [ebp-Ch]

    opcode_index = 0;
    v9 = 0;
    v8 = 0;
    v7 = 0;
    v6 = 0;
    while (true) {
    result = opcode_index;
    if (opcode_index >= len) {
    cout << flag << endl;
    return result;
    }
    switch (opcode[opcode_index]) {
    case 1:
    flag += v5;
    ++opcode_index;
    ++v7;
    ++v9;
    break;
    case 2:
    v5 = input[v9] - opcode[opcode_index + 1];
    opcode_index += 2;
    break;
    case 3:
    v5 = input[v9] + LOBYTE(opcode[opcode_index + 1]);
    opcode_index += 2;
    break;
    case 4:
    v5 = opcode[opcode_index + 1] ^ input[v9];
    opcode_index += 2;
    break;
    case 5:
    v5 = input[v9] / opcode[opcode_index + 1];
    opcode_index += 2;
    break;
    case 6:
    ++opcode_index;
    break;
    case 7:
    ++v8;
    opcode_index += 2;
    break;
    case 8:
    input[v6] = v5;
    ++opcode_index;
    ++v6;
    break;
    case 10:
    // read(input);

    ++opcode_index;
    break;
    case 11:
    v5 = input[v9] + 1;
    ++opcode_index;
    break;
    case 12:
    v5 = input[v9] - 1;
    ++opcode_index;
    break;
    default:
    continue;
    }
    }

    }

    unsigned int opcodes[114] = {
    0x0000000A,

    0x00000003, 0x00000005,
    0x00000008,
    0x00000004, 0x00000010,
    0x00000001,

    0x00000005, 0x00000003,
    0x00000008,
    0x00000004, 0x00000020,
    0x00000001,

    0x0000000B,
    0x00000008,
    0x00000003, 0x00000002,
    0x00000001,

    0x00000004, 0x00000004,
    0x00000008,
    0x0000000C,
    0x00000001,

    0x00000003, 0x00000021,
    0x00000008,
    0x00000005, 0x00000003,
    0x00000001,

    0x0000000B,
    0x00000008,
    0x0000000B,
    0x00000001,

    0x00000003, 0x00000020,
    0x00000008,
    0x00000004, 0x00000009,
    0x00000001,

    0x00000004, 0x00000024,
    0x00000008,
    0x00000002, 0x00000051,
    0x00000001,

    0x0000000B,
    0x00000008,
    0x0000000C,
    0x00000001,

    0x00000002, 0x00000025,
    0x00000008,
    0x00000005, 0x00000002,
    0x00000001,

    0x00000004, 0x00000041,
    0x00000008,
    0x00000002, 0x00000036,
    0x00000001,

    0x00000005, 0x00000001,
    0x00000008,
    0x00000002, 0x00000020,
    0x00000001,

    0x00000002, 0x00000025,
    0x00000008,
    0x00000005, 0x00000003,
    0x00000001,

    0x00000003, 0x00000020,
    0x00000008,
    0x00000004, 0x00000009,
    0x00000001,

    0x0000000C,
    0x00000008,
    0x00000002, 0x00000041,
    0x00000001,

    0x00000007, 0x00000022, 0x00000007, 0x0000003F,
    0x00000007, 0x00000034, 0x00000007, 0x00000032, 0x00000007, 0x00000072, 0x00000007, 0x00000033,
    0x00000007, 0x00000018, 0x00000007, 0xFFFFFFA7, 0x00000007, 0x00000031, 0x00000007, 0xFFFFFFF1,
    0x00000007, 0x00000028, 0x00000007, 0xFFFFFF84, 0x00000007, 0xFFFFFFC1, 0x00000007, 0x0000001E,
    0x00000007, 0x0000007A
    };


    int main() {
    vm_operad(opcodes, 114);
    }

    // 757515121f3d478
36DCTF-wp NPUCTF-wp

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×