虚拟机题目入门

笔记

IDADefines.cpp

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
#include <cstdio>

//测试 LOBYTE、HIBYTE
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long DWORD_PTR;
#define BYTE uint8
#define WORD uint16
#define DWORD unsigned long
#define LOBYTE(w) ((BYTE)(((DWORD_PTR)(w)) & 0xff))
#define HIBYTE(w) ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff))
#define BYTEn(x, n) (*((BYTE*)&(x)+n))
#define WORDn(x, n) (*((WORD*)&(x)+n))
#define BYTE0(x) BYTEn(x, 0) // byte 0 (counting from 0) 添加此宏定义
#define BYTE1(x) BYTEn(x, 1) // byte 1 (counting from 0)
#define BYTE2(x) BYTEn(x, 2)
#define BYTE3(x) BYTEn(x, 3)
#define BYTE4(x) BYTEn(x, 4)


unsigned int data = 0x12345678;

int main(void){
printf("%04X\n", LOBYTE(data));//0078 ,所以LOBYTE相当于就是BYTE0;
printf("%04X\n", HIBYTE(data));//0056 所以HIBYTE相当于就是BY

printf("%04X\n", BYTE3(data));
};

做题

[NCTF 2018]wcyvm

第一个VM题,看着题解搞懂了,但还不是太懂,主要是内存调用非常混乱…

dispatcher:

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
_BOOL8 dispatcher()
{
_BOOL8 result; // rax
char Flags[4]; // [rsp+Ch] [rbp-54h] BYREF
void *oprBytes; // [rsp+10h] [rbp-50h]
char *localMemory; // [rsp+18h] [rbp-48h]
_DWORD *registers[6]; // [rsp+20h] [rbp-40h] BYREF
__int64 VitualIP[2]; // [rsp+50h] [rbp-10h] BYREF

VitualIP[1] = __readfsqword(0x28u);
*(_DWORD *)Flags = 0;
oprBytes = malloc(0x200uLL);
localMemory = (char *)malloc(0x1400uLL);
memset(registers, 0, sizeof(registers));
memcpy(oprBytes, memory, 400uLL);
registers[0] = malloc(0x38uLL);
registers[1] = registers[0] + 1;
registers[2] = registers[0] + 2;
registers[3] = registers[0] + 3;
registers[4] = localMemory + 5120;
registers[5] = localMemory + 5120;
VitualIP[0] = (__int64)oprBytes;
while ( 2 )
{
if ( !*(_DWORD *)VitualIP[0] )
return 1LL;
switch ( (unsigned __int8)*(_DWORD *)VitualIP[0] )
{
case 8u:
opr_mov1(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], *(_DWORD *)(VitualIP[0] + 8), VitualIP);
continue;
case 9u:
opr_pop(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], &registers[4], VitualIP);
continue;
case 0xAu:
opr_push(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], &registers[4], VitualIP);
continue;
case 0xBu:
opr_getc(registers[0], VitualIP);
continue;
case 0xCu:
opr_putc(registers[0], VitualIP);
continue;
case 0xDu:
opr_cmp(
Flags,
registers[*(_DWORD *)(VitualIP[0] + 4) - 1],
registers[*(_DWORD *)(VitualIP[0] + 8) - 1],
VitualIP);
continue;
case 0xEu:
opr_jmp(VitualIP, *(_DWORD *)(VitualIP[0] + 4), (__int64)oprBytes);
continue;
case 0xFu:
opr_jnz(Flags[0], VitualIP, *(_DWORD *)(VitualIP[0] + 4), (__int64)oprBytes);
continue;
case 0x10u:
opr_jz(Flags[0], VitualIP, *(_DWORD *)(VitualIP[0] + 4), (__int64)oprBytes);
continue;
case 0x11u:
opr_inc(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], VitualIP);
continue;
case 0x12u:
opr_dec(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], VitualIP);
continue;
case 0x13u:
opr_add(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], *(_DWORD *)(VitualIP[0] + 8), VitualIP);
continue;
case 0x14u:
opr_sub(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], registers[*(_DWORD *)(VitualIP[0] + 8) - 1], VitualIP);
continue;
case 0x15u:
opr_xor(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], *(_DWORD *)(VitualIP[0] + 8), VitualIP);
continue;
case 0x16u:
opr_and(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], registers[*(_DWORD *)(VitualIP[0] + 8) - 1], VitualIP);
continue;
case 0x17u:
opr_or(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], registers[*(_DWORD *)(VitualIP[0] + 8) - 1], VitualIP);
continue;
case 0x19u:
opr_mov2(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], registers[*(_DWORD *)(VitualIP[0] + 8) - 1], VitualIP);
continue;
case 0x1Au:
opr_lea(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], (int)registers[*(_DWORD *)(VitualIP[0] + 8) - 1], VitualIP);
continue;
case 0x1Bu:
opr_mov3(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], registers[*(_DWORD *)(VitualIP[0] + 8) - 1], VitualIP);
continue;
case 0x1Cu:
opr_mov4(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], registers[*(_DWORD *)(VitualIP[0] + 8) - 1], VitualIP);
continue;
case 0x1Du:
opr_mul(registers[*(_DWORD *)(VitualIP[0] + 4) - 1], *(_DWORD *)(VitualIP[0] + 8), VitualIP);
continue;
case 0x64u:
result = check((__int64)registers[5]);
break;
default:
opr_nop(VitualIP);
continue;
}
break;
}
return result;
}

各指令代码实现:

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
void __fastcall opr_mov1(_DWORD *a1, int a2, _QWORD *a3)
{
*a1 = a2;
*a3 += 12LL;
}
void __fastcall opr_pop(_DWORD *a1, _DWORD **a2, _QWORD *a3)
{
*a1 = *(*a2)++;
*a3 += 8LL;
}
void __fastcall opr_push(_DWORD *a1, _QWORD *a2, _QWORD *a3)
{
*a2 -= 4LL;
*(_DWORD *)*a2 = *a1;
*a3 += 8LL;
}
void __fastcall opr_getc(int *a1, _QWORD *a2)
{
*a1 = getchar();
*a2 += 4LL;
}
void __fastcall opr_putc(int *a1, _QWORD *a2)
{
putchar(*a1);
*a2 += 4LL;
}
void __fastcall opr_cmp(_DWORD *Flags, _DWORD *a2, _DWORD *a3, _QWORD *VitualIP)
{
int tmp1; // eax
int tmp2; // eax
int tmp3; // eax

*Flags = 0;
if ( *a2 == *a3 )
tmp1 = 0x80;
else
tmp1 = 0;
*Flags |= tmp1;
if ( *a3 >= *a2 )
tmp2 = 0;
else
tmp2 = 0x40;
*Flags |= tmp2;
if ( *a2 >= *a3 )
tmp3 = 0;
else
tmp3 = 0x20;
*Flags |= tmp3;
*VitualIP += 12LL;
}
void __fastcall opr_jmp(_QWORD *a1, int a2, __int64 a3)
{
*a1 = a3 + 4LL * a2;
}
void __fastcall opr_jnz(char a1, __int64 *a2, unsigned int a3, __int64 a4)
{
__int64 v4; // rdx

if ( (a1 & 0x80) != 0 )
v4 = *a2 + 8;
else
v4 = a4 + 4LL * a3;
*a2 = v4;
}
void __fastcall opr_jz(char a1, __int64 *a2, unsigned int a3, __int64 a4)
{
__int64 v4; // rdx

if ( (a1 & 0x80) != 0 )
v4 = a4 + 4LL * a3;
else
v4 = *a2 + 8;
*a2 = v4;
}
void __fastcall opr_inc(_DWORD *a1, _QWORD *a2)
{
++*a1;
*a2 += 8LL;
}
void __fastcall opr_dec(_DWORD *a1, _QWORD *a2)
{
--*a1;
*a2 += 8LL;
}
void __fastcall opr_add(_DWORD *a1, int a2, _QWORD *a3)
{
*a1 += a2;
*a3 += 12LL;
}
void __fastcall opr_sub(_DWORD *a1, _DWORD *a2, _QWORD *a3)
{
*a1 -= *a2;
*a3 += 12LL;
}
void __fastcall opr_xor(_DWORD *a1, int a2, _QWORD *a3)
{
*a1 ^= a2;
*a3 += 12LL;
}
void __fastcall opr_and(_DWORD *a1, _DWORD *a2, _QWORD *a3)
{
*a1 &= *a2;
*a3 += 12LL;
}
void __fastcall opr_or(_DWORD *a1, _DWORD *a2, _QWORD *a3)
{
*a1 |= *a2;
*a3 += 12LL;
}
void __fastcall opr_mov2(_DWORD *a1, _DWORD *a2, _QWORD *a3)
{
*a1 = *a2;
*a3 += 12LL;
}
void __fastcall opr_lea(_DWORD *a1, int a2, _QWORD *a3)
{
*a1 = a2;
*a3 += 12LL;
}
void __fastcall opr_mov3(_DWORD *a1, unsigned int *a2, _QWORD *a3)
{
*a1 = *(_DWORD *)*a2;
*a3 += 12LL;
}
void __fastcall opr_mov4(unsigned int *a1, _DWORD *a2, _QWORD *a3)
{
*(_DWORD *)*a1 = *a2;
*a3 += 12LL;
}
void __fastcall opr_mul(_DWORD *a1, int a2, _QWORD *a3)
{
*a1 *= a2;
*a3 += 12LL;
}
_BOOL8 __fastcall check(__int64 a1)
{
int i; // [rsp+10h] [rbp-8h]
int v3; // [rsp+14h] [rbp-4h]

v3 = 0;
for ( i = 0; i <= 69; ++i )
v3 |= enc[i] != *(_DWORD *)(4LL * i - 280 + a1);
return v3 == 0;
}
_QWORD *__fastcall opr_nop(_QWORD *a1)
{
_QWORD *result; // rax

result = a1;
*a1 += 4LL;
return result;
}

Compiler:

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
v5=[8, 1, 0, 8, 3, 70, 14, 21, 10, 1, 9, 2, 11, 10, 1, 10, 2, 9, 1, 17, 1, 13, 1, 3, 15, 8, 8, 1, 0, 8, 3, 71, 14, 70, 10, 1, 26, 2, 6, 29, 1, 4, 20, 2, 1, 25, 1, 2, 27, 1, 1, 29, 1, 110, 19, 1, 99, 21, 1, 116, 19, 1, 102, 28, 2, 1, 9, 1, 17, 1, 13, 1, 3, 15, 34, 100]
ip=0
while v5[ip]!=0x64:
if v5[ip]==0x8:
print(f"{ip} mov r{v5[ip+1]-1} {v5[ip+2]}")
ip+=3
continue
if v5[ip]==0x9:
print(f"{ip} pop r{v5[ip+1]-1}")
ip+=2
continue
if v5[ip]==0xa:
print(f"{ip} push r{v5[ip+1]-1}")
ip+=2
continue
if v5[ip]==0xb:
print(f"{ip} getc")
ip+=1
continue
if v5[ip]==0xc:
print(f"{ip} putc")
ip+=1
continue
if v5[ip]==0xd:
print(f"{ip} if r{v5[ip+1]-1}==r{v5[ip+2]-1}")
print(f" mov Flags 128") #ZF=1 CF=0
print(f" if r{v5[ip+1]-1}<r{v5[ip+2]-1}")
print(f" mov Flags 64") #ZF=0 CF=1
print(f" if r{v5[ip+1]-1}>r{v5[ip+2]-1}")
print(f" mov Flags 32") #ZF=0 CF=0
ip+=3
continue
if v5[ip]==0xe:
print(f"{ip} jmp {v5[ip+1]}")
ip+=2
continue
if v5[ip]==0xf:
print(f"{ip} jnz {v5[ip+1]}")
ip+=2
continue
if v5[ip]==0x10:
print(f"{ip} jz {v5[ip+1]}")
ip+=2
continue
if v5[ip]==0x11:
print(f"{ip} inc r{v5[ip+1]-1}")
ip+=2
continue
if v5[ip]==0x12:
print(f"{ip} dec r{v5[ip + 1] - 1}")
ip += 2
continue
if v5[ip]==0x13:
print(f"{ip} add r{v5[ip+1]-1} {v5[ip+2]}")
ip+=3
continue
if v5[ip]==0x14:
print(f"{ip} sub r{v5[ip+1]-1} {v5[ip+2]-1}")
ip+=3
continue
if v5[ip]==0x15:
print(f"{ip} xor r{v5[ip+1]-1} {v5[ip+2]}")
ip+=3
continue
if v5[ip]==0x16:
print(f"{ip} and r{v5[ip+1]-1} {v5[ip+2]-1}")
ip+=3
continue
if v5[ip]==0x17:
print(f"{ip} or r{v5[ip + 1] - 1} {v5[ip + 2] - 1}")
ip += 3
continue
if v5[ip]==0x19:
print(f"{ip} mov r{v5[ip + 1] - 1} r{v5[ip + 2] - 1}")
ip+=3
continue
if v5[ip]==0x1a:
print(f"{ip} lea r{v5[ip + 1] - 1} r{v5[ip + 2] - 1}")
ip+=3
continue
if v5[ip]==0x1b:
print(f"{ip} mov r{v5[ip+1]-1} [r{v5[ip+2]-1}]")
ip+=3
continue
if v5[ip]==0x1c:
print(f"{ip} mov [r{v5[ip + 1] - 1}] r{v5[ip + 2] - 1}")
ip += 3
continue
if v5[ip]==0x1d:
print(f"{ip} mul r{v5[ip + 1] - 1} {v5[ip + 2]}")
ip += 3
continue
ip+=1
print(f"{ip} check")

Assembly:

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
0 mov  r0 0
3 mov r2 70
6 jmp 21
8 push r0
10 pop r1
12 getc
13 push r0
15 push r1
17 pop r0
19 inc r0
21 if r0==r2
mov Flags 128
if r0<r2
mov Flags 64
if r0>r2
mov Flags 32
24 jnz 8
26 mov r0 0
29 mov r2 71
32 jmp 70
34 push r0
36 lea r1 r5
39 mul r0 4
42 sub r1 0
45 mov r0 r1
48 mov r0 [r0]
51 mul r0 110
54 add r0 99
57 xor r0 116
60 add r0 102
63 mov [r1] r0
66 pop r0
68 inc r0
70 if r0==r2
mov Flags 128
if r0<r2
mov Flags 64
if r0>r2
mov Flags 32
73 jnz 34
75 check

大致加密逻辑:$(((r_0\times110)+99)\oplus116)+102$

由网上wp可知exp:

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
enc=[0xD3, 0x36, 0x00, 0x00, 0xFF, 0x2A, 0x00, 0x00, 0xCB, 0x2A,
0x00, 0x00, 0x95, 0x2B, 0x00, 0x00, 0x95, 0x2B, 0x00, 0x00,
0x95, 0x2B, 0x00, 0x00, 0x9F, 0x16, 0x00, 0x00, 0x6D, 0x18,
0x00, 0x00, 0xD7, 0x18, 0x00, 0x00, 0x11, 0x16, 0x00, 0x00,
0xD7, 0x18, 0x00, 0x00, 0x95, 0x2B, 0x00, 0x00, 0x23, 0x2C,
0x00, 0x00, 0xA9, 0x2C, 0x00, 0x00, 0x11, 0x16, 0x00, 0x00,
0x11, 0x16, 0x00, 0x00, 0xD7, 0x18, 0x00, 0x00, 0xFF, 0x2A,
0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0xFB, 0x18, 0x00, 0x00,
0xCB, 0x2A, 0x00, 0x00, 0x71, 0x2A, 0x00, 0x00, 0x35, 0x17,
0x00, 0x00, 0xD7, 0x18, 0x00, 0x00, 0x11, 0x16, 0x00, 0x00,
0xCB, 0x2A, 0x00, 0x00, 0xDD, 0x15, 0x00, 0x00, 0xD7, 0x18,
0x00, 0x00, 0x23, 0x2C, 0x00, 0x00, 0x9F, 0x16, 0x00, 0x00,
0xDD, 0x15, 0x00, 0x00, 0x95, 0x2B, 0x00, 0x00, 0x9F, 0x16,
0x00, 0x00, 0x6B, 0x15, 0x00, 0x00, 0x6D, 0x18, 0x00, 0x00,
0xFF, 0x2A, 0x00, 0x00, 0x11, 0x16, 0x00, 0x00, 0x11, 0x16,
0x00, 0x00, 0xDD, 0x15, 0x00, 0x00, 0xFF, 0x2A, 0x00, 0x00,
0x23, 0x2C, 0x00, 0x00, 0xCB, 0x2A, 0x00, 0x00, 0xDD, 0x15,
0x00, 0x00, 0xDD, 0x15, 0x00, 0x00, 0x6D, 0x18, 0x00, 0x00,
0x49, 0x18, 0x00, 0x00, 0x95, 0x2B, 0x00, 0x00, 0x6B, 0x15,
0x00, 0x00, 0x35, 0x17, 0x00, 0x00, 0xFB, 0x18, 0x00, 0x00,
0xFB, 0x18, 0x00, 0x00, 0x71, 0x2A, 0x00, 0x00, 0xFF, 0x2A,
0x00, 0x00, 0x35, 0x17, 0x00, 0x00, 0x23, 0x2C, 0x00, 0x00,
0xDD, 0x15, 0x00, 0x00, 0xD7, 0x18, 0x00, 0x00, 0x71, 0x2A,
0x00, 0x00, 0xD7, 0x18, 0x00, 0x00, 0xD7, 0x18, 0x00, 0x00,
0x23, 0x2C, 0x00, 0x00, 0xFF, 0x2A, 0x00, 0x00, 0x6B, 0x15,
0x00, 0x00, 0x23, 0x2C, 0x00, 0x00, 0x9F, 0x16, 0x00, 0x00,
0xAF, 0x35, 0x00, 0x00, 0xA9, 0x2C, 0x00, 0x00, 0xB5, 0x32,
0x00, 0x00, 0xFF, 0x2A, 0x00, 0x00, 0x39, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
t=[]
for i in range(0,len(enc),4):
tmp=0
for j in range(i,i+4):
tmp+=enc[j]*2**(8*j%32)
t.append(tmp)
# print(len(t))
#(((r0*110)+99)^116+102)
flag=[]
for i in t[:70]:
f=(((i-102)^116)-99)//110
flag.append(f)
print(bytes(flag)[::-1])

[HGAME 2022 week4]ezvm

虚拟机逆向,每个指令(可能是):

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
int oprcode; // eax

_init(argc, argv, envp);
printf(&Format_0, "input your flag:", 16i64);
unknow(&Format_0);
while ( 1 )
{
oprcode = data[data[0] + 109];
if ( oprcode == -1 )
return 0;
switch ( oprcode )
{
case 0:
op_mov(&data[3], &data[2]);
break;
case 1:
op_inc(&data[2]);
break;
case 2:
op_dec(&data[2]);
break;
case 3:
op_xor(&data[3], &data[7]);
break;
case 4:
op_push_reg6();
break;
case 5:
op_push_reg4();
break;
case 6:
op_push_reg5();
break;
case 7:
op_pop_reg6();
break;
case 8:
op_pop_reg4();
break;
case 9:
op_pop_reg5();
break;
case 10:
op_pop_reg3();
break;
case 11:
op_pop_reg7();
break;
case 12:
op_jz_reg1_n_nops((unsigned int)data[6]);
break;
case 13:
op_jnz_reg1_n_nops((unsigned int)data[6]);
break;
case 14:
op_n_nops((unsigned int)data[2]);
break;
case 15:
op_cmp_reg1((unsigned int)data[3], (unsigned int)data[5]);
break;
case 16:
op_inputchr(&data[3]);
break;
case 17:
op_outputchar(&data[3]);
break;
case 18:
op_push_REG2();
break;
case 19:
op_mov_REG3_to_reg6();
break;
case 20:
mov_reg6_to_REG3();
break;
case 21:
op_reg6_mul2();
break;
default:
break;
}
++data[0];
}
}

exp(不是我写的):

1
2
3
4
5
6
7
8
s=[94,70,97,67,14,83,73,31,81,94,54,55,41,65,99,59,100,59,21,24,91,62,34,80,70,94,53,78,67,35,96,59]
en=[142,136,163,153,196,165,195,221,25,236,108,155,243,27,139,91,62,155,241,134,243,244,164,248,248,152,171,134,137,97,34,193]
flag=''
for i in range(32):
en[i]^=s[i]
en[i]=en[i]//2
flag+=chr(en[i])
print(flag)

[watevrCTF 2019]Repyc

Python虚拟机,解析不是自己写的:

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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# uncompyle6 version 3.7.4
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 08:53:46) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: circ.py
# Compiled at: 2019-12-14 02:29:55
# Size of source mod 2**32: 5146 bytes
a = 0
b = ~a * ~a #b=1
c = b + b #c=2
def fun(x):
t = a
t2 = a
m = [a] * c ** (c * c)
key1 = [a] * 100
key2 = []
while x[t][a] != 'NULL':
x1 = x[t][a].lower()
x2 = x[t][b:]
if x1 == 'ADD':
m[x2[a]] = m[x2[b]] + m[x2[c]]
else:
if x1 == 'XOR':
m[x2[a]] = m[x2[b]] ^ m[x2[c]]
else:
if x1 == 'SUB':
m[x2[a]] = m[x2[b]] - m[x2[c]]
else:
if x1 == 'X':
m[x2[a]] = m[x2[b]] * m[x2[c]]
else:
if x1 == '/':
m[x2[a]] = m[x2[b]] / m[x2[c]]
else:
if x1 == '&':
m[x2[a]] = m[x2[b]] & m[x2[c]]
else:
if x1 == '|':
m[x2[a]] = m[x2[b]] | m[x2[c]]
else:
if x1 == 'mov':
m[x2[a]] = m[x2[a]]
else:
if x1 == 'mov1':
m[x2[a]] = m[x2[b]]
else:
if x1 == 'mov2':
m[x2[a]] = x2[b]
else:
if x1 == 'mov3':
key1[x2[a]] = m[x2[b]]
else:
if x1 == 'mov4':
m[x2[a]] = key1[x2[b]]
else:
if x1 == 'mov5':
m[x2[a]] = a
else:
if x1 == 'mov6':
key1[x2[a]] = a
else:
if x1 == 'input1':
m[x2[a]] = input(m[x2[b]])
else:
if x1 == 'input2':
key1[x2[a]] = input(m[x2[b]])
else:
if x1 == 'print1':
print(m[x2[a]])
else:
if x1 == 'print2':
print(key1[x2[a]])
else:
if x1 == 'mov7':
t = m[x2[a]]
else:
if x1 == 'mov8':
t = key1[x2[a]]
else:
if x1 == 'POP':
t = key2.pop()
else:
if x1 == 'mov9':
if m[x2[b]] > m[x2[c]]:
t = x2[a]
key2.append(t)
continue
else:
if x1 == 'cmp':
m[7] = a
for i in range(len(m[x2[a]])):
if m[x2[a]] != m[x2[b]]:
m[7] = b
t = m[x2[c]]
key2.append(t)

else:
if x1 == 'for XOR':
flag = ''
for i in range(len(m[x2[a]])):
flag += chr(ord(m[x2[a]][i]) ^ m[x2[b]])

m[x2[a]] = flag
else:
if x1 == 'for SUB':
flag = ''
for i in range(len(m[x2[a]])):
flag += chr(ord(m[x2[a]][i]) - m[x2[b]])

m[x2[a]] = flag
else:
if x1 == 'mov10':
if m[x2[b]] > m[x2[c]]:
t = m[x2[a]]
key2.append(t)
continue
else:
if x1 == 'mov11':
if m[x2[b]] > m[x2[c]]:
t = key1[x2[a]]
key2.append(t)
continue
else:
if x1 == 'cmp1':
if m[x2[b]] == m[x2[c]]:
t = x2[a]
key2.append(t)
continue
else:
if x1 == 'cmp2':
if m[x2[b]] == m[x2[c]]:
t = m[x2[a]]
key2.append(t)
continue
else:
if x1 == 'cmp3':
if m[x2[b]] == m[x2[c]]:
t = key1[x2[a]]
key2.append(t)
continue
t += b
fun([
[#m[0]=="Authentication token: "
'mov2', a, 'Authentication token: '],
[#key1[0]=="答案"
'input2', a, a],
[#m[6]=="á×äÓâæíäàßåÉÛãåäÉÖÓÉäà......."
'mov2', 6, 'á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'],
[#m[2]==2**(3*2+1)-2**(2+1)==120
'mov2', c, c ** (3 * c + b) - c ** (c + b)],
[#m[4]==15
'mov2', 4, 15],
[#m[3]==1
'mov2', 3, b],
[#m[2]==m[2]*m[3]==120
'X', c, c, 3],
[#m[2]==m[2]+m[4]==135
'ADD', c, c, 4],
[#m[0]==m[0]
'mov', a, c],
[#m[3]==0
'mov5', 3],
[#m[6]==m[6]^m[3]
'for XOR', 6, 3],
[#m[0]=="Thanks."
'mov2', a, 'Thanks.'],
[#m[1]=="Authorizing access..."
'mov2', b, 'Authorizing access...'],
[#print("Thanks.")
'print1', a],
[#m[0]==key1[0]
'mov4', a, a],
[#m[0]==m[0]^m[2]
'for XOR', a, c],
[#m[0]==m[0]-m[4]
'for SUB', a, 4],
[#m[5]==19
'mov2', 5, 19],
[#m[0]!=a[6]
'cmp', a, 6, 5],
[#print("Authorizing access...")
'print1', b],
[
'NULL'],
[#m[1]=="Access denied!"
'mov2', b, 'Access denied!'],
[#print("Access denied!")
'print1', b],
[
'NULL']])

解密脚本:

1
2
3
4
5
x="á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë"
flag=""
for i in range(len(x)):
flag+=chr((ord(x[i])+15)^135)
print(flag)

[羊城杯 2023]vm_wo

第一次做MacOS的题,比想象中的要简单,简单虚拟机题目。

IDA8.3不支持反汇编为C,这里用7.7的。

myoperate函数中有操作指令,导出,interpretBytecode中有dispatcher。

翻译脚本不是自己写的,从网上copy的:

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
opcode = [26, 0, 3, 25, 1, 1, 13, 2, 7, 24, 1, 2, 1, 0, 3, 26, 0, 3, 25,
1, 2, 13, 2, 6, 24, 1, 2, 1, 0, 4, 26, 0, 3, 25, 1, 3, 13, 2, 5,
24, 1, 2, 1, 0, 5, 26, 0, 3, 25, 1, 4, 13, 2, 4, 24, 1, 2, 1, 0, 6]
# [26, 0, 3, 25, 1, 13, 2, 7, 24, 6, 4, 5]
i = 0
while opcode[i]:
match opcode[i]:
case 0:
print(f"{i} swap reg%d reg%d" % (opcode[i+1],opcode[i+2]))
case 1:
print(f"{i} xor reg%d reg%d" % (opcode[i+1],opcode[i+2]))
case 2:
print(f"{i} add reg%d %d" % (opcode[i+1],opcode[i+2]))
case 3:
print(f"{i} add reg%d reg%d" % (opcode[i+1],opcode[i+2]))
case 4:
print(f"{i} sub reg%d %d" % (opcode[i+1],opcode[i+2]))
case 5:
print(f"{i} sub reg%d reg%d" % (opcode[i+1],opcode[i+2]))
case 6:
print(f"{i} mul reg%d %d" % (opcode[i+1],opcode[i+2]))
case 7:
print(f"{i} mul reg%d reg%d" % (opcode[i+1],opcode[i+2]))
case 13:
print(f"{i} mov reg%d reg0<<%d" % (opcode[i+1],opcode[i+2]))
case 24:
print(f"{i} reg0 = reg2 | reg1")
case 25:
print(f"{i} mov reg%d reg0>>%d" % (opcode[i+1],opcode[i+2]))
case 26:
print(f"{i} mov reg%d %d" % (opcode[i+1],opcode[i+2]))
i += 3

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0 mov reg0 3
3 mov reg1 reg0>>1
6 mov reg2 reg0<<7
9 reg0 = reg2 | reg1
12 xor reg0 reg3
15 mov reg0 3
18 mov reg1 reg0>>2
21 mov reg2 reg0<<6
24 reg0 = reg2 | reg1
27 xor reg0 reg4
30 mov reg0 3
33 mov reg1 reg0>>3
36 mov reg2 reg0<<5
39 reg0 = reg2 | reg1
42 xor reg0 reg5
45 mov reg0 3
48 mov reg1 reg0>>4
51 mov reg2 reg0<<4
54 reg0 = reg2 | reg1
57 xor reg0 reg6

看到位移为3 4 5 6的寄存器,算vm_body偏移,看到初始化为0xBEEDBEEF,即为连着4个字节。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enc = [0xDF, 0xD5, 0xF1, 0xD1, 0xFF, 0xDB, 0xA1, 0xA5, 0x89, 0xBD, 0xE9, 0x95, 0xB3, 0x9D, 0xE9, 0xB3, 0x85, 0x99, 0x87,
0xBF, 0xE9, 0xB1, 0x89, 0xE9, 0x91, 0x89, 0x89, 0x8F, 0xAD]
key = 0xBEEDBEEF.to_bytes(4, 'little')
def decode(s):
s = s ^ key[3]
s = (s << 4 | s >> 4) & 0xFF
s = s ^ key[2]
s = (s << 3 | s >> 5) & 0xFF
s = s ^ key[1]
s = (s << 2 | s >> 6) & 0xFF
s = s ^ key[0]
s = (s << 1 | s >> 7) & 0xFF
return s
flag = []
for i in enc:
i = ((i >> 3) | (i << 5) & 0xFF)
flag.append(decode(i))
print(bytes(flag))
# b'DASCTF{you_are_right_so_cool}'

脚本依旧是偷的。

[HGAME 2023 week4]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
176
void __fastcall sub_1400018A0(vm *a1)
{
int v1; // eax

if ( LOBYTE(a1->zf) )
v1 = opcodes[a1->ip + 1];
else
v1 = a1->ip + 2;
a1->ip = v1;
}
void __fastcall op_je(vm *a1)
{
int v1; // eax

if ( LOBYTE(a1->zf) )
v1 = a1->ip + 2;
else
v1 = opcodes[a1->ip + 1];
a1->ip = v1;
}
void __fastcall op_jmp(vm *a1)
{
a1->ip = opcodes[a1->ip + 1];
}
void __fastcall op_cmp(vm *a1)
{
if ( a1->reg[0] == a1->reg[1] )
LOBYTE(a1->zf) = 0;
if ( a1->reg[0] != a1->reg[1] )
LOBYTE(a1->zf) = 1;
++a1->ip;
}
void __fastcall sub_1400014D0(vm *a1)
{
switch ( opcodes[a1->ip + 1] )
{
case 0u:
a1->reg[opcodes[a1->ip + 2]] += a1->reg[opcodes[a1->ip + 3]];
break;
case 1u:
a1->reg[opcodes[a1->ip + 2]] -= a1->reg[opcodes[a1->ip + 3]];
break;
case 2u:
a1->reg[opcodes[a1->ip + 2]] *= a1->reg[opcodes[a1->ip + 3]];
break;
case 3u:
a1->reg[opcodes[a1->ip + 2]] ^= a1->reg[opcodes[a1->ip + 3]];
break;
case 4u:
a1->reg[opcodes[a1->ip + 2]] <<= a1->reg[opcodes[a1->ip + 3]];
a1->reg[opcodes[a1->ip + 2]] &= 0xFF00u;
break;
case 5u:
a1->reg[opcodes[a1->ip + 2]] >>= a1->reg[opcodes[a1->ip + 3]];
break;
default:
break;
}
a1->ip += 4;
}
void __fastcall op_pop(vm *a1)
{
unsigned __int8 v1; // [rsp+0h] [rbp-18h]

v1 = opcodes[a1->ip + 1];
if ( v1 )
{
switch ( v1 )
{
case 1u:
a1->reg[1] = stack[a1->sp--];
break;
case 2u:
a1->reg[2] = stack[a1->sp--];
break;
case 3u:
a1->reg[3] = stack[a1->sp--];
break;
}
}
else
{
a1->reg[0] = stack[a1->sp--];
}
a1->ip += 2;
}
void __fastcall op_push(vm *a1)
{
unsigned __int8 v1; // [rsp+0h] [rbp-18h]

v1 = opcodes[a1->ip + 1];
if ( v1 )
{
switch ( v1 )
{
case 1u:
stack[++a1->sp] = a1->reg[0];
break;
case 2u:
stack[++a1->sp] = a1->reg[2];
break;
case 3u:
stack[++a1->sp] = a1->reg[3];
break;
}
}
else
{
stack[++a1->sp] = a1->reg[0];
}
a1->ip += 2;
}
void __fastcall op_mov(vm *a1)
{
unsigned __int8 v1; // [rsp+0h] [rbp-18h]

v1 = opcodes[a1->ip + 1];
if ( v1 )
{
switch ( v1 )
{
case 1u:
inputStr[a1->reg[2]] = a1->reg[0];
break;
case 2u:
a1->reg[opcodes[a1->ip + 2]] = a1->reg[opcodes[a1->ip + 3]];
break;
case 3u:
a1->reg[opcodes[a1->ip + 2]] = opcodes[a1->ip + 3];
break;
}
}
else
{
a1->reg[0] = inputStr[a1->reg[2]];
}
a1->ip += 4;
}
void __fastcall dispatcher(vm *a1)
{
switch ( opcodes[a1->ip] )
{
case 0u:
op_mov(a1);
break;
case 1u:
op_push(a1);
break;
case 2u:
op_pop(a1);
break;
case 3u:
op_cal(a1);
break;
case 4u:
op_cmp(a1);
break;
case 5u:
op_jmp(a1);
break;
case 6u:
op_je(a1);
break;
case 7u:
op_jne(a1);
break;
default:
return;
}
}
__int64 __fastcall vm_start(vm *a1)
{
while ( opcodes[a1->ip] != 255 )
dispatcher(a1);
return LOBYTE(a1->zf);
}

从网上wp嗦个脚本跑:

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
opcode = [0x00, 0x03, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x02, 0x32,
0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
0x01, 0x00, 0x00, 0x03, 0x02, 0x64, 0x03, 0x00, 0x02, 0x03,
0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00, 0x00, 0x03,
0x00, 0x08, 0x00, 0x02, 0x02, 0x01, 0x03, 0x04, 0x01, 0x00,
0x03, 0x05, 0x02, 0x00, 0x03, 0x00, 0x01, 0x02, 0x00, 0x02,
0x00, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x03, 0x00,
0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x01, 0x28,
0x04, 0x06, 0x5F, 0x05, 0x00, 0x00, 0x03, 0x03, 0x00, 0x02,
0x01, 0x00, 0x03, 0x02, 0x96, 0x03, 0x00, 0x02, 0x03, 0x00,
0x00, 0x00, 0x00, 0x04, 0x07, 0x88, 0x00, 0x03, 0x00, 0x01,
0x03, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03,
0x01, 0x28, 0x04, 0x07, 0x63, 0xFF, 0xFF]
input1 = []
i = 0
while opcode[i] != 0xFF:
match opcode[i]:
case 0x00:
print(f'{i}', end=' ')
o = i + 1
if opcode[o]:
match opcode[o]:
case 0x01:
print("mov input[reg[2]], reg[0]")
case 0x02:
print("mov reg[%d], reg[%d]" % (opcode[i+2],opcode[i+3]))
case 0x03:
print("mov reg[%d], %d" % (opcode[i+2], opcode[i+3]))
else:
print("mov reg[0], input[reg[2]]")
i += 4
case 0x01:
print(f'{i}', end=' ')
o = i + 1
if opcode[o]:
match opcode[o]:
case 0x01:
print("push reg[0]")
case 0x02:
print("push reg[2]")
case 0x03:
print("push reg[3]")
else:
print("push reg[0]")
i += 2
case 0x02:
print(f'{i}', end=' ')
o = i + 1
if opcode[o]:
match opcode[o]:
case 0x01:
print("pop reg[1]")
case 0x02:
print("pop reg[2]")
case 0x03:
print("pop reg[3]")
else:
print("pop reg[0]")
i += 2
case 0x03:
print(f'{i}', end=' ')
o = i + 1
match opcode[o]:
case 0:
print("add reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
case 1:
print("sup reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
case 2:
print("mul reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
case 3:
print("xor reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
case 4:
print("shl reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
case 5:
print("shr reg[%d],reg[%d]" % (opcode[i + 2], opcode[i + 3]))
i += 4
case 0x04:
print(f'{i} cmp reg[0], reg[1]')
i += 1
case 0x05:
print(f'{i} jmp %d ' % (opcode[i+1]))
i += 2
case 0x06:
print(f'{i} je %d ' % (opcode[i+1]))
i += 2
case 0x07:
print(f'{i} jne %d ' % (opcode[i+1]))
i += 2

结果这样:

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
0 mov reg[2], 0
4 add reg[2],reg[3]
8 mov reg[0], input[reg[2]]
12 mov reg[1], reg[0]
16 mov reg[2], 50
20 add reg[2],reg[3]
24 mov reg[0], input[reg[2]]
28 add reg[1],reg[0]
32 mov reg[2], 100
36 add reg[2],reg[3]
40 mov reg[0], input[reg[2]]
44 xor reg[1],reg[0]
48 mov reg[0], 8
52 mov reg[2], reg[1]
56 shl reg[1],reg[0]
60 shr reg[2],reg[0]
64 add reg[1],reg[2]
68 mov reg[0], reg[1]
72 push reg[0]
74 mov reg[0], 1
78 add reg[3],reg[0]
82 mov reg[0], reg[3]
86 mov reg[1], 40
90 cmp reg[0], reg[1]
91 je 95
93 jmp 0
95 mov reg[3], 0
99 pop reg[1]
101 mov reg[2], 150
105 add reg[2],reg[3]
109 mov reg[0], input[reg[2]]
113 cmp reg[0], reg[1]
114 jne 136
116 mov reg[0], 1
120 add reg[3],reg[0]
124 mov reg[0], reg[3]
128 mov reg[1], 40
132 cmp reg[0], reg[1]
133 jne 99

然后inputStr布局这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.data:0000000140005040                             ; _DWORD inputStr[200]
.data:0000000140005040 00 00 00 00 00 00 00 00 inputStr dd 32h dup(0) ; DATA XREF: op_mov+55↑o
.data:0000000140005040 00 00 00 00 00 00 00 00 ; op_mov+90↑o
.data:0000000140005040 00 00 00 00 00 00 00 00… ; main+75↑o
.data:0000000140005108 9B 00 00 00 A8 00 00 00… dd 155, 168, 2, 188, 172, 156, 206, 250, 2, 185, 255, 58
.data:0000000140005138 74 00 00 00 48 00 00 00… dd 116, 72, 25, 105, 232, 3, 203, 201, 255, 252, 128, 214
.data:0000000140005168 8D 00 00 00 D7 00 00 00… dd 141, 215, 114, 0, 167, 29, 61, 153, 136, 153, 191, 232
.data:0000000140005198 96 00 00 00 2E 00 00 00… dd 150, 46, 93, 87, 10 dup(0)
.data:00000001400051D0 C9 00 00 00 A9 00 00 00… dd 201, 169, 189, 139, 23, 194, 110, 248, 245, 110, 2 dup(99)
.data:0000000140005200 D5 00 00 00 46 00 00 00… dd 213, 70, 93, 22, 152, 56, 48, 115, 56, 193, 94, 237
.data:0000000140005230 B0 00 00 00 29 00 00 00… dd 176, 41, 90, 24, 64, 167, 253, 10, 30, 120, 139, 98
.data:0000000140005260 DB 00 00 00 0F 00 00 00… dd 219, 15, 143, 156, 10 dup(0)
.data:0000000140005298 00 48 00 00 00 F1 00 00… dd 18432, 61696, 16384, 8448, 13569, 25600, 30721, 63744
.data:00000001400052B8 01 18 00 00 00 52 00 00… dd 6145, 20992, 9472, 23809, 18176, 64768, 26881, 23552
.data:00000001400052D8 01 AF 00 00 00 B2 00 00… dd 44801, 45568, 60417, 20993, 20225, 6657, 20480, 34049
.data:00000001400052F8 00 CD 00 00 00 23 00 00… dd 52480, 8960, 63488, 3072, 52992, 15617, 17665, 33280
.data:0000000140005318 01 D2 00 00 01 29 00 00… dd 53761, 10497, 54529, 1537, 41473, 56832, 42497, 51713
.data:0000000140005338 00 00 00 00 00 00 00 00… dd 10 dup(0)

input[0]是读入,input[50+i]a1input[100+i]a2input[150+i]a3

大致看一下,写exp:

1
2
3
4
5
6
7
8
9
10
11
a1=[0x0000009B,0x000000A8,0x00000002,0x000000BC,0x000000AC,0x0000009C,0x000000CE,0x000000FA,0x00000002,0x000000B9,0x000000FF,0x0000003A,0x00000074,0x00000048,0x00000019,0x00000069,0x000000E8,0x00000003,0x000000CB,0x000000C9,0x000000FF,0x000000FC,0x00000080,0x000000D6,0x0000008D,0x000000D7,0x00000072,0x00000000,0x000000A7,0x0000001D,0x0000003D,0x00000099,0x00000088,0x00000099,0x000000BF,0x000000E8,0x00000096,0x0000002E,0x0000005D,0x00000057]
a2=[0x000000C9,0x000000A9,0x000000BD,0x0000008B,0x00000017,0x000000C2,0x0000006E,0x000000F8,0x000000F5,0x0000006E,0x00000063,0x00000063,0x000000D5,0x00000046,0x0000005D,0x00000016,0x00000098,0x00000038,0x00000030,0x00000073,0x00000038,0x000000C1,0x0000005E,0x000000ED,0x000000B0,0x00000029,0x0000005A,0x00000018,0x00000040,0x000000A7,0x000000FD,0x0000000A,0x0000001E,0x00000078,0x0000008B,0x00000062,0x000000DB,0x0000000F,0x0000008F,0x0000009C]
a3=[0x00004800,0x0000F100,0x00004000,0x00002100,0x00003501,0x00006400,0x00007801,0x0000F900,0x00001801,0x00005200,0x00002500,0x00005D01,0x00004700,0x0000FD00,0x00006901,0x00005C00,0x0000AF01,0x0000B200,0x0000EC01,0x00005201,0x00004F01,0x00001A01,0x00005000,0x00008501,0x0000CD00,0x00002300,0x0000F800,0x00000C00,0x0000CF00,0x00003D01,0x00004501,0x00008200,0x0000D201,0x00002901,0x0000D501,0x00000601,0x0000A201,0x0000DE00,0x0000A601,0x0000CA01]
a3=a3[::-1]
flag=[0]*40
for i in range(40):
flag[i]=(a3[i]>>8)+(a3[i]<<8)
flag[i]^=a2[i]
flag[i]-=a1[i]
for i in range(40):
print(chr(flag[i]&0xFF),end='')

[GWCTF 2019]babyvm

简单虚拟机,先识别指令集:

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
void __fastcall op_cal(__int64 a1)
{
*(_DWORD *)a1 = *(_DWORD *)(a1 + 8) + 2 * *(_DWORD *)(a1 + 4) + 3 * *(_DWORD *)a1;
++*(_QWORD *)(a1 + 16);
}
void __fastcall op_swp(int *a1)
{
int v1; // [rsp+14h] [rbp-Ch]

v1 = *a1;
*a1 = a1[1];
a1[1] = v1;
++*((_QWORD *)a1 + 2);
}
void __fastcall op_mul(__int64 a1)
{
*(_DWORD *)a1 *= *(_DWORD *)(a1 + 12);
++*(_QWORD *)(a1 + 16);
}
void __fastcall op_nop(__int64 a1)
{
++*(_QWORD *)(a1 + 16);
}
void __fastcall op_input(__int64 a1)
{
const char *buf; // [rsp+10h] [rbp-10h]

buf = (const char *)res;
read(0, res, 0x20uLL);
dword_2022A4 = strlen(buf);
if ( dword_2022A4 != 21 )
{
puts("WRONG!");
exit(0);
}
++*(_QWORD *)(a1 + 16);
}
void __fastcall op_xor(__int64 a1)
{
*(_DWORD *)a1 ^= *(_DWORD *)(a1 + 4);
++*(_QWORD *)(a1 + 16);
}
void __fastcall op_mov(__int64 a1)
{
int *v1; // [rsp+28h] [rbp-18h]

v1 = (int *)(*(_QWORD *)(a1 + 16) + 2LL);
switch ( *(_BYTE *)(*(_QWORD *)(a1 + 16) + 1LL) )
{
case 0xE1:
*(_DWORD *)a1 = *((char *)res + *v1);
break;
case 0xE2:
*(_DWORD *)(a1 + 4) = *((char *)res + *v1);
break;
case 0xE3:
*(_DWORD *)(a1 + 8) = *((char *)res + *v1);
break;
case 0xE4:
*((_BYTE *)res + *v1) = *(_DWORD *)a1;
break;
case 0xE5:
*(_DWORD *)(a1 + 12) = *((char *)res + *v1);
break;
case 0xE7:
*((_BYTE *)res + *v1) = *(_DWORD *)(a1 + 4);
break;
default:
break;
}
*(_QWORD *)(a1 + 16) += 6LL;
}
void __fastcall dispatcher(__int64 a1)
{
*(_DWORD *)a1 = 0;
*(_DWORD *)(a1 + 4) = 18;
*(_DWORD *)(a1 + 8) = 0;
*(_DWORD *)(a1 + 12) = 0;
*(_QWORD *)(a1 + 16) = &opcode;
*(_BYTE *)(a1 + 24) = 0xF1;
*(_QWORD *)(a1 + 32) = op_mov;
*(_BYTE *)(a1 + 40) = 0xF2;
*(_QWORD *)(a1 + 48) = op_xor;
*(_BYTE *)(a1 + 56) = 0xF5;
*(_QWORD *)(a1 + 64) = op_input;
*(_BYTE *)(a1 + 72) = 0xF4;
*(_QWORD *)(a1 + 80) = op_nop;
*(_BYTE *)(a1 + 88) = 0xF7;
*(_QWORD *)(a1 + 96) = op_mul;
*(_BYTE *)(a1 + 104) = 0xF8;
*(_QWORD *)(a1 + 112) = op_swp;
*(_BYTE *)(a1 + 120) = 0xF6;
*(_QWORD *)(a1 + 128) = op_cal;
res = malloc(0x512uLL);
memset(res, 0, 0x512uLL);
}
void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
__int64 v3[2]; // [rsp+10h] [rbp-10h] BYREF

v3[1] = __readfsqword(0x28u);
v3[0] = 0LL;
puts("Please input something:");
dispatcher((__int64)v3);
vm_run((__int64)v3);
check_flag();
puts("And the flag is GWHT{true flag}");
exit(0);
}

从网上嗦个脚本跑:

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
opcode = [0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00,
0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00,
0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2D,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0F, 0x00,
0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2F, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x10, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x30, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x13, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x33, 0x00, 0x00,
0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF1,
0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00,
0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1,
0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00,
0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1,
0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09,
0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6,
0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1,
0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00,
0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E,
0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x11, 0x00, 0x00, 0x00, 0xF4]
for i in range(len(opcode)):
match opcode[i]:
case 0xF1:
print(f"{i}", end=" ")
k = i + 1
match opcode[k]:
case 0xE1:
print("mov reg[0], flag[%d]" % opcode[i + 2])
case 0xE2:
print("mov reg[1], flag[%d]" % opcode[i + 2])
case 0xE3:
print("mov reg[2], flag[%d]" % opcode[i + 2])
case 0xE4:
print("mov flag[%d], reg[0]" % opcode[i + 2])
case 0xE5:
print("mov reg[3], flag[%d]" % opcode[i + 2])
case 0xE7:
print("mov flag[%d], reg[1]" % opcode[i + 2])
i += 6
case 0xF2:
print(f"{i} xor reg[0], reg[1]")
i += 1
case 0xF5:
print(f"{i} cmp 21")
i += 1
case 0xF4:
print(f"{i} nop")
i += 1
case 0xF7:
print(f"{i} mul reg[0], reg[3]")
i += 1
case 0xF8:
print(f"{i} swap reg[0], reg[1]")
i += 1
case 0xF6:
print(f"{i} reg[0] = reg[2] + reg[1]*2 + reg[0]*3")
i += 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
0 cmp 21
1 mov reg[0], flag[0]
7 xor reg[0], reg[1]
8 mov flag[32], reg[0]
14 mov reg[0], flag[1]
20 xor reg[0], reg[1]
21 mov flag[33], reg[0]
27 mov reg[0], flag[2]
33 xor reg[0], reg[1]
34 mov flag[34], reg[0]
40 mov reg[0], flag[3]
46 xor reg[0], reg[1]
47 mov flag[35], reg[0]
53 mov reg[0], flag[4]
59 xor reg[0], reg[1]
60 mov flag[36], reg[0]
66 mov reg[0], flag[5]
72 xor reg[0], reg[1]
73 mov flag[37], reg[0]
79 mov reg[0], flag[6]
85 xor reg[0], reg[1]
86 mov flag[38], reg[0]
92 mov reg[0], flag[7]
98 xor reg[0], reg[1]
99 mov flag[39], reg[0]
105 mov reg[0], flag[8]
111 xor reg[0], reg[1]
112 mov flag[40], reg[0]
118 mov reg[0], flag[9]
124 xor reg[0], reg[1]
125 mov flag[41], reg[0]
131 mov reg[0], flag[10]
137 xor reg[0], reg[1]
138 mov flag[42], reg[0]
144 mov reg[0], flag[11]
150 xor reg[0], reg[1]
151 mov flag[43], reg[0]
157 mov reg[0], flag[12]
163 xor reg[0], reg[1]
164 mov flag[44], reg[0]
170 mov reg[0], flag[13]
176 xor reg[0], reg[1]
177 mov flag[45], reg[0]
183 mov reg[0], flag[14]
189 xor reg[0], reg[1]
190 mov flag[46], reg[0]
196 mov reg[0], flag[15]
202 xor reg[0], reg[1]
203 mov flag[47], reg[0]
209 mov reg[0], flag[16]
215 xor reg[0], reg[1]
216 mov flag[48], reg[0]
222 mov reg[0], flag[17]
228 xor reg[0], reg[1]
229 mov flag[49], reg[0]
235 mov reg[0], flag[18]
241 xor reg[0], reg[1]
242 mov flag[50], reg[0]
248 mov reg[0], flag[19]
254 xor reg[0], reg[1]
255 mov flag[51], reg[0]
261 nop
288 cmp 21
289 mov reg[0], flag[0]
295 mov reg[1], flag[1]
301 xor reg[0], reg[1]
302 mov flag[0], reg[0]
308 mov reg[0], flag[1]
314 mov reg[1], flag[2]
320 xor reg[0], reg[1]
321 mov flag[1], reg[0]
327 mov reg[0], flag[2]
333 mov reg[1], flag[3]
339 xor reg[0], reg[1]
340 mov flag[2], reg[0]
346 mov reg[0], flag[3]
352 mov reg[1], flag[4]
358 xor reg[0], reg[1]
359 mov flag[3], reg[0]
365 mov reg[0], flag[4]
371 mov reg[1], flag[5]
377 xor reg[0], reg[1]
378 mov flag[4], reg[0]
384 mov reg[0], flag[5]
390 mov reg[1], flag[6]
396 xor reg[0], reg[1]
397 mov flag[5], reg[0]
403 mov reg[0], flag[6]
409 mov reg[1], flag[7]
415 mov reg[2], flag[8]
421 mov reg[3], flag[12]
427 reg[0] = reg[2] + reg[1]*2 + reg[0]*3
428 mul reg[0], reg[3]
429 mov flag[6], reg[0]
435 mov reg[0], flag[7]
441 mov reg[1], flag[8]
447 mov reg[2], flag[9]
453 mov reg[3], flag[12]
459 reg[0] = reg[2] + reg[1]*2 + reg[0]*3
460 mul reg[0], reg[3]
461 mov flag[7], reg[0]
467 mov reg[0], flag[8]
473 mov reg[1], flag[9]
479 mov reg[2], flag[10]
485 mov reg[3], flag[12]
491 reg[0] = reg[2] + reg[1]*2 + reg[0]*3
492 mul reg[0], reg[3]
493 mov flag[8], reg[0]
499 mov reg[0], flag[13]
505 mov reg[1], flag[19]
511 swap reg[0], reg[1]
512 mov flag[13], reg[0]
518 mov flag[19], reg[1]
524 mov reg[0], flag[14]
530 mov reg[1], flag[18]
536 swap reg[0], reg[1]
537 mov flag[14], reg[0]
543 mov flag[18], reg[1]
549 mov reg[0], flag[15]
555 mov reg[1], flag[17]
561 swap reg[0], reg[1]
562 mov flag[15], reg[0]
568 mov flag[17], reg[1]
574 nop

发现288处是输入,也就是说前面部分都是忽悠人的。

看一下后面的加密逻辑差不多是:

1
2
3
4
5
6
7
8
9
10
11
12
flag[0] = flag[0] ^ flag[1]
flag[1] = flag[1] ^ flag[2]
flag[2] = flag[2] ^ flag[3]
flag[3] = flag[3] ^ flag[4]
flag[4] = flag[4] ^ flag[5]
flag[5] = flag[5] ^ flag[6]
flag[6] = (flag[6]*3+flag[7]*2+flag[8])*flag[12]
flag[7] = (flag[7]*3+flag[8]*2+flag[9])*flag[12]
flag[8] = (flag[8]*3+flag[9]*2+flag[10])*flag[12]
swap flag[13] flag[19]
swap flag[14] flag[18]
swap flag[15] flag[17]

网上偷的exp:

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
from z3 import *
f1 = [0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B, 0x5C, 0x72,
0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5F, 0x33, 0x73, 0x72]
f1[15], f1[17] = f1[17], f1[15]
f1[13], f1[19] = f1[19], f1[13]
f1[14], f1[18] = f1[18], f1[14]
s = Solver()
f = [BitVec(f"f{[i]}", 8) for i in range(13)]
s.add(f1[0] == f[0] ^ f[1])
s.add(f1[1] == f[1] ^ f[2])
s.add(f1[2] == f[2] ^ f[3])
s.add(f1[3] == f[3] ^ f[4])
s.add(f1[4] == f[4] ^ f[5])
s.add(f1[5] == f[5] ^ f[6])
s.add(f1[6] == (3 * f[6] + 2 * f[7] + f[8]) * f[12])
s.add(f1[7] == (3 * f[7] + 2 * f[8] + f[9]) * f[12])
s.add(f1[8] == (3 * f[8] + 2 * f[9] + f[10]) * f[12])
s.add(f1[9] == f[9])
s.add(f1[10] == f[10])
s.add(f1[11] == f[11])
s.add(f1[12] == f[12])
if s.check() == sat:
t = s.model()
for i in f:
print(chr(t[i].as_long()), end='')
print(bytes(f1[-7:]).decode())

[羊城杯 2021]Babyvm

先是TEA类的SMC,动调找到Dispatcher和opcodes,写脚本跑,下面代码都是网上的:

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
opcode = [0xA1, 0xC1, 0x00, 0xB1, 0x77, 0xC2, 0x4A, 0x01, 0x00, 0x00,
0xC1, 0x01, 0xB2, 0x77, 0xC2, 0x19, 0x01, 0x00, 0x00, 0xC1,
0x02, 0xB4, 0x77, 0xC2, 0xDD, 0x01, 0x00, 0x00, 0xC1, 0x03,
0xB3, 0x77, 0xC2, 0x0F, 0x01, 0x00, 0x00, 0xC1, 0x04, 0xB2,
0x77, 0xC2, 0x1B, 0x01, 0x00, 0x00, 0xC1, 0x05, 0xB4, 0x77,
0xC2, 0x89, 0x01, 0x00, 0x00, 0xC1, 0x06, 0xB1, 0x77, 0xC2,
0x19, 0x01, 0x00, 0x00, 0xC1, 0x07, 0xB3, 0x77, 0xC2, 0x54,
0x01, 0x00, 0x00, 0xC1, 0x08, 0xB1, 0x77, 0xC2, 0x4F, 0x01,
0x00, 0x00, 0xC1, 0x09, 0xB1, 0x77, 0xC2, 0x4E, 0x01, 0x00,
0x00, 0xC1, 0x0A, 0xB3, 0x77, 0xC2, 0x55, 0x01, 0x00, 0x00,
0xC1, 0x0B, 0xB3, 0x77, 0xC2, 0x56, 0x01, 0x00, 0x00, 0xC1,
0x0C, 0xB4, 0x77, 0xC2, 0x8E, 0x00, 0x00, 0x00, 0xC1, 0x0D,
0xB2, 0x77, 0xC2, 0x49, 0x00, 0x00, 0x00, 0xC1, 0x0E, 0xB3,
0x77, 0xC2, 0x0E, 0x01, 0x00, 0x00, 0xC1, 0x0F, 0xB1, 0x77,
0xC2, 0x4B, 0x01, 0x00, 0x00, 0xC1, 0x10, 0xB3, 0x77, 0xC2,
0x06, 0x01, 0x00, 0x00, 0xC1, 0x11, 0xB3, 0x77, 0xC2, 0x54,
0x01, 0x00, 0x00, 0xC1, 0x12, 0xB2, 0x77, 0xC2, 0x1A, 0x00,
0x00, 0x00, 0xC1, 0x13, 0xB1, 0x77, 0xC2, 0x42, 0x01, 0x00,
0x00, 0xC1, 0x14, 0xB3, 0x77, 0xC2, 0x53, 0x01, 0x00, 0x00,
0xC1, 0x15, 0xB1, 0x77, 0xC2, 0x1F, 0x01, 0x00, 0x00, 0xC1,
0x16, 0xB3, 0x77, 0xC2, 0x52, 0x01, 0x00, 0x00, 0xC1, 0x17,
0xB4, 0x77, 0xC2, 0xDB, 0x00, 0x00, 0x00, 0xC1, 0x18, 0xB1,
0x77, 0xC2, 0x19, 0x01, 0x00, 0x00, 0xC1, 0x19, 0xB4, 0x77,
0xC2, 0xD9, 0x00, 0x00, 0x00, 0xC1, 0x1A, 0xB1, 0x77, 0xC2,
0x19, 0x01, 0x00, 0x00, 0xC1, 0x1B, 0xB3, 0x77, 0xC2, 0x55,
0x01, 0x00, 0x00, 0xC1, 0x1C, 0xB2, 0x77, 0xC2, 0x19, 0x00,
0x00, 0x00, 0xC1, 0x1D, 0xB3, 0x77, 0xC2, 0x00, 0x01, 0x00,
0x00, 0xC1, 0x1E, 0xB1, 0x77, 0xC2, 0x4B, 0x01, 0x00, 0x00,
0xC1, 0x1F, 0xB2, 0x77, 0xC2, 0x1E, 0x00, 0x00, 0x00, 0xC1,
0x20, 0x80, 0x02, 0x18, 0x00, 0x00, 0x00, 0x23, 0x10, 0xC1,
0x21, 0x80, 0x02, 0x10, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1,
0x22, 0x80, 0x02, 0x08, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1,
0x23, 0xF7, 0xFE, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x22,
0x77, 0x10, 0x80, 0x02, 0x07, 0x00, 0x00, 0x00, 0x23, 0x80,
0x02, 0x23, 0x77, 0xF1, 0x98, 0x31, 0x77, 0x10, 0x80, 0x02,
0x18, 0x00, 0x00, 0x00, 0x23, 0x80, 0x02, 0x20, 0xB9, 0xE4,
0x35, 0x31, 0x77, 0x10, 0x80, 0x02, 0x12, 0x00, 0x00, 0x00,
0x22, 0x77, 0xA0, 0xC1, 0x24, 0x80, 0x02, 0x18, 0x00, 0x00,
0x00, 0x23, 0x10, 0xC1, 0x25, 0x80, 0x02, 0x10, 0x00, 0x00,
0x00, 0x23, 0xF7, 0xC1, 0x26, 0x80, 0x02, 0x08, 0x00, 0x00,
0x00, 0x23, 0xF7, 0xC1, 0x27, 0xF7, 0xFE, 0x32, 0x20, 0x43,
0x33, 0x77, 0x80, 0x02, 0x11, 0x00, 0x00, 0x00, 0x22, 0x35,
0x37, 0x38, 0x77, 0x80, 0x02, 0x0D, 0x00, 0x00, 0x00, 0x23,
0x77, 0x38, 0x39, 0x10, 0x32, 0x20, 0x43, 0x33, 0x77, 0x80,
0x02, 0x11, 0x00, 0x00, 0x00, 0x22, 0x35, 0x37, 0x38, 0x77,
0x80, 0x02, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x77, 0x38, 0x39,
0xC7, 0xC1, 0x28, 0x80, 0x02, 0x18, 0x00, 0x00, 0x00, 0x23,
0x10, 0xC1, 0x29, 0x80, 0x02, 0x10, 0x00, 0x00, 0x00, 0x23,
0xF7, 0xC1, 0x2A, 0x80, 0x02, 0x08, 0x00, 0x00, 0x00, 0x23,
0xF7, 0xC1, 0x2B, 0xF7, 0xFE, 0x32, 0x20, 0x43, 0x33, 0x77,
0x80, 0x02, 0x11, 0x00, 0x00, 0x00, 0x22, 0x35, 0x37, 0x38,
0x77, 0x80, 0x02, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x77, 0x38,
0x39, 0x10, 0x32, 0x20, 0x43, 0x33, 0x77, 0x80, 0x02, 0x11,
0x00, 0x00, 0x00, 0x22, 0x35, 0x37, 0x38, 0x77, 0x80, 0x02,
0x0D, 0x00, 0x00, 0x00, 0x23, 0x77, 0x38, 0x39, 0xC8, 0x99]
i = 0
while opcode[i] != 0x99:
match opcode[i]:
case 0x71:
print(f"{i} push %d" % (opcode[i+1]))
i += 5
case 0x41:
print(f"{i} add reg[1] reg[2]")
i += 1
case 0x42:
print(f"{i} sub reg[1] reg[4]")
i += 1
case 0x43:
print(f"{i} mul reg[1] reg[3]")
i += 1
case 0x37:
print(f"{i} mov reg[1] reg[5]")
i += 1
case 0x38:
print(f"{i} xor reg[1] reg[4]")
i += 1
case 0x39:
print(f"{i} xor reg[1] reg[5]")
i += 1
case 0x35:
print(f"{i} mov reg[5] reg[1]")
i += 1
case 0xF7:
print(f"{i} add reg[9] reg[1]")
i += 1
case 0x44:
print(f"{i} div reg[1] reg[5]")
i += 1
case 0x80:
int_val = int.from_bytes(bytes(opcode[i + 2:i + 6]), 'little')
print(f"{i} mov reg[?] {int_val}")
i += 6
case 0x77:
print(f"{i} xor reg[1] reg[9]")
i += 1
case 0x53:
print(f"{i} put reg[3]")
i += 2
case 0x22:
print(f"{i} shr reg[1] reg[2]")
i += 1
case 0x23:
print(f"{i} shl reg[1] reg[2]")
i += 1
case 0x76:
print(f"{i} pop reg[3]")
i += 5
case 0x54:
print(f"{i} get")
i += 2
case 0x30:
print(f"{i} or reg[1] reg[2]")
i += 1
case 0x31:
print(f"{i} and reg[1] reg[2]")
i += 1
case 0x32:
print(f"{i} mov reg[3] %d" % (opcode[i+1]))
i += 2
case 0x09:
print(f"{i} mov reg[1] 0x6FEBF967")
i += 1
case 0x10:
print(f"{i} mov reg[9] reg[1]")
i += 1
case 0x33:
print(f"{i} mov reg[4] reg[1]")
i += 1
case 0x34:
print(f"{i} mov reg[2] %d" % (opcode[i+1]))
i += 2
case 0xFE:
print(f"{i} mov reg[1] reg[9]")
i += 1
case 0x11:
print(f"{i} print reg[1]")
i += 1
case 0xA0:
print(f"{i} cmp reg[1] 0x6FEBF967")
i += 1
case 0xA1:
print(f"{i} cmp len 44")
i += 1
case 0xB1:
print(f"{i} mov reg[9] v[0]")
i += 1
case 0xB2:
print(f"{i} mov reg[9] v[1]")
i += 1
case 0xA4:
print(f"{i} mov v[%d] reg[1]" % (opcode[i + 1]))
i += 4
case 0xB3:
print(f"{i} mov reg[9] v[2]")
i += 1
case 0xB4:
print(f"{i} mov reg[9] v[3]")
i += 1
case 0xC1:
print(f"{i} mov reg[1] s[%d]" % (opcode[i + 1]))
i += 2
case 0xC7:
print(f"{i} cmp d[0] reg[1]")
i += 1
case 0xC8:
print(f"{i} cmp d[1] reg[1]")
i += 1
case 0xC2:
print(f"{i} cmp %d reg[1]" % (opcode[i+1]))
i += 5

找出指令流:

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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
0 cmp len 44
1 mov reg[1] s[0]
3 mov reg[9] v[0]
4 xor reg[1] reg[9]
5 cmp 74 reg[1]
10 mov reg[1] s[1]
12 mov reg[9] v[1]
13 xor reg[1] reg[9]
14 cmp 25 reg[1]
19 mov reg[1] s[2]
21 mov reg[9] v[3]
22 xor reg[1] reg[9]
23 cmp 221 reg[1]
28 mov reg[1] s[3]
30 mov reg[9] v[2]
31 xor reg[1] reg[9]
32 cmp 15 reg[1]
37 mov reg[1] s[4]
39 mov reg[9] v[1]
40 xor reg[1] reg[9]
41 cmp 27 reg[1]
46 mov reg[1] s[5]
48 mov reg[9] v[3]
49 xor reg[1] reg[9]
50 cmp 137 reg[1]
55 mov reg[1] s[6]
57 mov reg[9] v[0]
58 xor reg[1] reg[9]
59 cmp 25 reg[1]
64 mov reg[1] s[7]
66 mov reg[9] v[2]
67 xor reg[1] reg[9]
68 cmp 84 reg[1]
73 mov reg[1] s[8]
75 mov reg[9] v[0]
76 xor reg[1] reg[9]
77 cmp 79 reg[1]
82 mov reg[1] s[9]
84 mov reg[9] v[0]
85 xor reg[1] reg[9]
86 cmp 78 reg[1]
91 mov reg[1] s[10]
93 mov reg[9] v[2]
94 xor reg[1] reg[9]
95 cmp 85 reg[1]
100 mov reg[1] s[11]
102 mov reg[9] v[2]
103 xor reg[1] reg[9]
104 cmp 86 reg[1]
109 mov reg[1] s[12]
111 mov reg[9] v[3]
112 xor reg[1] reg[9]
113 cmp 142 reg[1]
118 mov reg[1] s[13]
120 mov reg[9] v[1]
121 xor reg[1] reg[9]
122 cmp 73 reg[1]
127 mov reg[1] s[14]
129 mov reg[9] v[2]
130 xor reg[1] reg[9]
131 cmp 14 reg[1]
136 mov reg[1] s[15]
138 mov reg[9] v[0]
139 xor reg[1] reg[9]
140 cmp 75 reg[1]
145 mov reg[1] s[16]
147 mov reg[9] v[2]
148 xor reg[1] reg[9]
149 cmp 6 reg[1]
154 mov reg[1] s[17]
156 mov reg[9] v[2]
157 xor reg[1] reg[9]
158 cmp 84 reg[1]
163 mov reg[1] s[18]
165 mov reg[9] v[1]
166 xor reg[1] reg[9]
167 cmp 26 reg[1]
172 mov reg[1] s[19]
174 mov reg[9] v[0]
175 xor reg[1] reg[9]
176 cmp 66 reg[1]
181 mov reg[1] s[20]
183 mov reg[9] v[2]
184 xor reg[1] reg[9]
185 cmp 83 reg[1]
190 mov reg[1] s[21]
192 mov reg[9] v[0]
193 xor reg[1] reg[9]
194 cmp 31 reg[1]
199 mov reg[1] s[22]
201 mov reg[9] v[2]
202 xor reg[1] reg[9]
203 cmp 82 reg[1]
208 mov reg[1] s[23]
210 mov reg[9] v[3]
211 xor reg[1] reg[9]
212 cmp 219 reg[1]
217 mov reg[1] s[24]
219 mov reg[9] v[0]
220 xor reg[1] reg[9]
221 cmp 25 reg[1]
226 mov reg[1] s[25]
228 mov reg[9] v[3]
229 xor reg[1] reg[9]
230 cmp 217 reg[1]
235 mov reg[1] s[26]
237 mov reg[9] v[0]
238 xor reg[1] reg[9]
239 cmp 25 reg[1]
244 mov reg[1] s[27]
246 mov reg[9] v[2]
247 xor reg[1] reg[9]
248 cmp 85 reg[1]
253 mov reg[1] s[28]
255 mov reg[9] v[1]
256 xor reg[1] reg[9]
257 cmp 25 reg[1]
262 mov reg[1] s[29]
264 mov reg[9] v[2]
265 xor reg[1] reg[9]
266 cmp 0 reg[1]
271 mov reg[1] s[30]
273 mov reg[9] v[0]
274 xor reg[1] reg[9]
275 cmp 75 reg[1]
280 mov reg[1] s[31]
282 mov reg[9] v[1]
283 xor reg[1] reg[9]
284 cmp 30 reg[1]
289 mov reg[1] s[32]
291 mov reg[?] 24
297 shl reg[1] reg[2]
298 mov reg[9] reg[1]
299 mov reg[1] s[33]
301 mov reg[?] 16
307 shl reg[1] reg[2]
308 add reg[9] reg[1]
309 mov reg[1] s[34]
311 mov reg[?] 8
317 shl reg[1] reg[2]
318 add reg[9] reg[1]
319 mov reg[1] s[35]
321 add reg[9] reg[1]
322 mov reg[1] reg[9]
323 mov reg[?] 5
329 shr reg[1] reg[2]
330 xor reg[1] reg[9]
331 mov reg[9] reg[1]
332 mov reg[?] 7
338 shl reg[1] reg[2]
339 mov reg[?] 2565961507
345 and reg[1] reg[2]
346 xor reg[1] reg[9]
347 mov reg[9] reg[1]
348 mov reg[?] 24
354 shl reg[1] reg[2]
355 mov reg[?] 904182048
361 and reg[1] reg[2]
362 xor reg[1] reg[9]
363 mov reg[9] reg[1]
364 mov reg[?] 18
370 shr reg[1] reg[2]
371 xor reg[1] reg[9]
372 cmp reg[1] 0x6FEBF967
373 mov reg[1] s[36]
375 mov reg[?] 24
381 shl reg[1] reg[2]
382 mov reg[9] reg[1]
383 mov reg[1] s[37]
385 mov reg[?] 16
391 shl reg[1] reg[2]
392 add reg[9] reg[1]
393 mov reg[1] s[38]
395 mov reg[?] 8
401 shl reg[1] reg[2]
402 add reg[9] reg[1]
403 mov reg[1] s[39]
405 add reg[9] reg[1]
406 mov reg[1] reg[9]
407 mov reg[3] 32
409 mul reg[1] reg[3]
410 mov reg[4] reg[1]
411 xor reg[1] reg[9]
412 mov reg[?] 17
418 shr reg[1] reg[2]
419 mov reg[5] reg[1]
420 mov reg[1] reg[5]
421 xor reg[1] reg[4]
422 xor reg[1] reg[9]
423 mov reg[?] 13
429 shl reg[1] reg[2]
430 xor reg[1] reg[9]
431 xor reg[1] reg[4]
432 xor reg[1] reg[5]
433 mov reg[9] reg[1]
434 mov reg[3] 32
436 mul reg[1] reg[3]
437 mov reg[4] reg[1]
438 xor reg[1] reg[9]
439 mov reg[?] 17
445 shr reg[1] reg[2]
446 mov reg[5] reg[1]
447 mov reg[1] reg[5]
448 xor reg[1] reg[4]
449 xor reg[1] reg[9]
450 mov reg[?] 13
456 shl reg[1] reg[2]
457 xor reg[1] reg[9]
458 xor reg[1] reg[4]
459 xor reg[1] reg[5]
460 cmp d[0] reg[1]
461 mov reg[1] s[40]
463 mov reg[?] 24
469 shl reg[1] reg[2]
470 mov reg[9] reg[1]
471 mov reg[1] s[41]
473 mov reg[?] 16
479 shl reg[1] reg[2]
480 add reg[9] reg[1]
481 mov reg[1] s[42]
483 mov reg[?] 8
489 shl reg[1] reg[2]
490 add reg[9] reg[1]
491 mov reg[1] s[43]
493 add reg[9] reg[1]
494 mov reg[1] reg[9]
495 mov reg[3] 32
497 mul reg[1] reg[3]
498 mov reg[4] reg[1]
499 xor reg[1] reg[9]
500 mov reg[?] 17
506 shr reg[1] reg[2]
507 mov reg[5] reg[1]
508 mov reg[1] reg[5]
509 xor reg[1] reg[4]
510 xor reg[1] reg[9]
511 mov reg[?] 13
517 shl reg[1] reg[2]
518 xor reg[1] reg[9]
519 xor reg[1] reg[4]
520 xor reg[1] reg[5]
521 mov reg[9] reg[1]
522 mov reg[3] 32
524 mul reg[1] reg[3]
525 mov reg[4] reg[1]
526 xor reg[1] reg[9]
527 mov reg[?] 17
533 shr reg[1] reg[2]
534 mov reg[5] reg[1]
535 mov reg[1] reg[5]
536 xor reg[1] reg[4]
537 xor reg[1] reg[9]
538 mov reg[?] 13
544 shl reg[1] reg[2]
545 xor reg[1] reg[9]
546 xor reg[1] reg[4]
547 xor reg[1] reg[5]
548 cmp d[1] reg[1]

前32字符就是异或加密:

1
print(chr(0x7b^74)+chr(0x2f^25)+chr(0xe8^221)+chr(0x37^15)+chr(0x2f^27)+chr(0xe8^137)+chr(0x7b^25)+chr(0x37^84)+chr(0x7b^79)+chr(0x7b^78)+chr(0x37^85)+chr(0x37^86)+chr(0xe8^142)+chr(0x2f^73)+chr(0x37^14)+chr(0x7b^75)+chr(0x37^6)+chr(0x37^84)+chr(0x2f^26)+chr(0x7b^66)+chr(0x37^83)+chr(0x7b^31)+chr(0x37^82)+chr(0xe8^219)+chr(0x7b^25)+chr(0xe8^217)+chr(0x7b^25)+chr(0x37^85)+chr(0x2f^25)+chr(0x37^0)+chr(0x7b^75)+chr(0x2f^30))

接下来4个爆破:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
start = 0x20202020
while start <= 0xffffffff:
s = start
reg9 = s
s >>= 5
s ^= reg9
reg9 = s
s <<= 7
s &= 2565961507
s ^= reg9
reg9 = s
s <<= 24
s &= 904182048
s ^= reg9
reg9 = s
s >>= 18
s ^= reg9
if s == 1877735783:
print(start)
exit(0)
else:
start += 1

还是4个爆破:

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
#include <cstdio>
int main(){
unsigned int record, reg1, reg2, reg3, reg4, reg5, reg6, unknown2;
for(unsigned int unknown2=0x20202020;unknown2<0xffffffff;unknown2+=1){
record = unknown2;
reg1 = unknown2;
reg3 = 32;
reg1 *= reg3;
reg4 = reg1;
reg1 ^= unknown2;
reg2 = 17;
reg1 >>= reg2;
reg6 = reg1;
reg1 = reg6;
reg1 ^= reg4;
reg1 ^= unknown2;
reg2 = 13;
reg1 <<= reg2;
reg1 ^= unknown2;
reg1 ^= reg4;
reg1 ^= reg6;
unknown2 = reg1;
reg3 = 32;
reg1 *= reg3;
reg4 = reg1;
reg1 ^= unknown2;
reg2 = 17;
reg1 >>= reg2;
reg6 = reg1;
reg1 = reg6;
reg1 ^= reg4;
reg1 ^= unknown2;
reg2 = 13;
reg1 <<= reg2;
reg1 ^= unknown2;
reg1 ^= reg4;
reg1 ^= reg6;
unknown2 = record;
if(reg1 == 0x0CF1304DC){
printf("%u\n", record);
break;
}
}
}

最后4个爆破:

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
#include <cstdio>
int main(){
unsigned int record, reg1, reg2, reg3, reg4, reg5, reg6, unknown2;
for(unsigned int unknown2=0x20202020;unknown2<0xffffffff;unknown2+=1){
record = unknown2;
reg1 = unknown2;
reg3 = 32;
reg1 *= reg3;
reg4 = reg1;
reg1 ^= unknown2;
reg2 = 17;
reg1 >>= reg2;
reg6 = reg1;
reg1 = reg6;
reg1 ^= reg4;
reg1 ^= unknown2;
reg2 = 13;
reg1 <<= reg2;
reg1 ^= unknown2;
reg1 ^= reg4;
reg1 ^= reg6;
unknown2 = reg1;
reg3 = 32;
reg1 *= reg3;
reg4 = reg1;
reg1 ^= unknown2;
reg2 = 17;
reg1 >>= reg2;
reg6 = reg1;
reg1 = reg6;
reg1 ^= reg4;
reg1 ^= unknown2;
reg2 = 13;
reg1 <<= reg2;
reg1 ^= unknown2;
reg1 ^= reg4;
reg1 ^= reg6;
unknown2 = record;
if(reg1 == 0x283B8E84){
printf("%u\n", record);
break;
}
}
}

拼起来:16584abc45baff901c59dde3b1bb6701a254b06cdc23

[GKCTF 2020]EzMachine

很常规很贴近现实的虚拟机题,找到opcodes、reg_table、regs、dispatcher。

函数分别为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
nop
mov
push reg
push data
pop reg
printf
add
sub
mul
divmod
xor
jmp
cmp
jz
jnz
jg
jl
scanf strlen
memset0
stack2reg
input2reg
hlt

dump出opcodes,翻译成伪汇编:

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
opcode = [0x01, 0x03, 0x03, 0x05, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01,
0x01, 0x11, 0x0C, 0x00, 0x01, 0x0D, 0x0A, 0x00, 0x01, 0x03,
0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0x02, 0x00,
0x01, 0x00, 0x11, 0x0C, 0x00, 0x02, 0x0D, 0x2B, 0x00, 0x14,
0x00, 0x02, 0x01, 0x01, 0x61, 0x0C, 0x00, 0x01, 0x10, 0x1A,
0x00, 0x01, 0x01, 0x7A, 0x0C, 0x00, 0x01, 0x0F, 0x1A, 0x00,
0x01, 0x01, 0x47, 0x0A, 0x00, 0x01, 0x01, 0x01, 0x01, 0x06,
0x00, 0x01, 0x0B, 0x24, 0x00, 0x01, 0x01, 0x41, 0x0C, 0x00,
0x01, 0x10, 0x24, 0x00, 0x01, 0x01, 0x5A, 0x0C, 0x00, 0x01,
0x0F, 0x24, 0x00, 0x01, 0x01, 0x4B, 0x0A, 0x00, 0x01, 0x01,
0x01, 0x01, 0x07, 0x00, 0x01, 0x01, 0x01, 0x10, 0x09, 0x00,
0x01, 0x03, 0x01, 0x00, 0x03, 0x00, 0x00, 0x01, 0x01, 0x01,
0x06, 0x02, 0x01, 0x0B, 0x0B, 0x00, 0x02, 0x07, 0x00, 0x02,
0x0D, 0x00, 0x02, 0x00, 0x00, 0x02, 0x05, 0x00, 0x02, 0x01,
0x00, 0x02, 0x0C, 0x00, 0x02, 0x01, 0x00, 0x02, 0x00, 0x00,
0x02, 0x00, 0x00, 0x02, 0x0D, 0x00, 0x02, 0x05, 0x00, 0x02,
0x0F, 0x00, 0x02, 0x00, 0x00, 0x02, 0x09, 0x00, 0x02, 0x05,
0x00, 0x02, 0x0F, 0x00, 0x02, 0x03, 0x00, 0x02, 0x00, 0x00,
0x02, 0x02, 0x00, 0x02, 0x05, 0x00, 0x02, 0x03, 0x00, 0x02,
0x03, 0x00, 0x02, 0x01, 0x00, 0x02, 0x07, 0x00, 0x02, 0x07,
0x00, 0x02, 0x0B, 0x00, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00,
0x02, 0x02, 0x00, 0x02, 0x07, 0x00, 0x02, 0x02, 0x00, 0x02,
0x0C, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02,
0x01, 0x13, 0x01, 0x02, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x01,
0x0E, 0x5B, 0x00, 0x01, 0x01, 0x22, 0x0C, 0x02, 0x01, 0x0D,
0x59, 0x00, 0x01, 0x01, 0x01, 0x06, 0x02, 0x01, 0x0B, 0x4E,
0x00, 0x01, 0x03, 0x00, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x01, 0x03, 0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00]
opcode_key = {
0: 'nop',
1: 'mov reg data',
2: 'push data',
3: 'push_reg',
4: 'pop_reg',
5: 'printf',
6: 'add_reg_reg1',
7: 'sub_reg_reg1',
8: 'mul',
9: 'div',
10: 'xor',
11: 'jmp',
12: 'cmp',
13: 'je',
14: 'jne',
15: 'jg',
16: 'jl',
17: 'scan_strlen',
18: 'mem_init',
19: 'stack_to_reg',
20: 'load_input',
0xff: 'exit'}
count = 0
code_index = 1
for x in opcode: # 读取每一个opcode
if count % 3 == 0:
print(str(code_index) + ':', end='')
print(opcode_key[x], end=' ')
code_index += 1
elif count % 3 == 1:
print(str(x) + ',', end='')
else:
print(str(x))
count += 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
1:mov reg data 3,3
2:printf 0,0
3:scan_strlen 0,0
4:mov reg data 1,17
5:cmp 0,1
6:je 10,0
7:mov reg data 3,1
8:printf 0,0
9:exit 0,0
10:mov reg data 2,0
11:mov reg data 0,17
12:cmp 0,2
13:je 43,0
14:load_input 0,2
15:mov reg data 1,97
16:cmp 0,1
17:jl 26,0
18:mov reg data 1,122
19:cmp 0,1
20:jg 26,0
21:mov reg data 1,71
22:xor 0,1
23:mov reg data 1,1
24:add_reg_reg1 0,1
25:jmp 36,0
26:mov reg data 1,65
27:cmp 0,1
28:jl 36,0
29:mov reg data 1,90
30:cmp 0,1
31:jg 36,0
32:mov reg data 1,75
33:xor 0,1
34:mov reg data 1,1
35:sub_reg_reg1 0,1
36:mov reg data 1,16
37:div 0,1
38:push_reg 1,0
39:push_reg 0,0
40:mov reg data 1,1
41:add_reg_reg1 2,1
42:jmp 11,0
43:push data 7,0
44:push data 13,0
45:push data 0,0
46:push data 5,0
47:push data 1,0
48:push data 12,0
49:push data 1,0
50:push data 0,0
51:push data 0,0
52:push data 13,0
53:push data 5,0
54:push data 15,0
55:push data 0,0
56:push data 9,0
57:push data 5,0
58:push data 15,0
59:push data 3,0
60:push data 0,0
61:push data 2,0
62:push data 5,0
63:push data 3,0
64:push data 3,0
65:push data 1,0
66:push data 7,0
67:push data 7,0
68:push data 11,0
69:push data 2,0
70:push data 1,0
71:push data 2,0
72:push data 7,0
73:push data 2,0
74:push data 12,0
75:push data 2,0
76:push data 2,0
77:mov reg data 2,1
78:stack_to_reg 1,2
79:pop_reg 0,0
80:cmp 0,1
81:jne 91,0
82:mov reg data 1,34
83:cmp 2,1
84:je 89,0
85:mov reg data 1,1
86:add_reg_reg1 2,1
87:jmp 78,0
88:mov reg data 3,0
89:printf 0,0
90:exit 0,0
91:mov reg data 3,1
92:printf 0,0
93:exit 0,0
94:nop

凑合着看,能发现简单加密逻辑,脚本是网上的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
data = [0x7,0xd,0x0,0x5,0x1,0xc,0x1,0x0,0x0,0xd,0x5,0xf,0x0,0x9,0x5,0xf,0x3,0x0,0x2,0x5,0x3,0x3,0x1,0x7,0x7,0xb,0x2,0x1,0x2,0x7,0x2,0xc,0x2,0x2,]
data = data[::-1]
flag = ''
for i in range(0, 34, 2):
temp = data[i] + data[i+1]*16
x = ((temp+1) ^ 75)
y = ((temp-1) ^ 71)
if 65 <= x <= 90: # 'A'-'Z'
flag += chr(x)
elif 97 <= y <= 122: # 'a' - 'z'
flag += chr(y)
else:
flag += chr(temp) # 没有处于'a'-'z'或'A'-'Z'之间
print(flag)