虚拟机题目,到现在还没做过,依据前人的智慧学习一波。
有前人用angr跑出来了,试了下还真行,绷。
网上疑似搜到了源码NCTF2018/Reverse/wcyvm/wcyvm.c at master · NJUPT-coding-gay/NCTF2018 (github.com)
参照着写
虚拟机的函数长这样
有点折磨
照着前人写了一波,加了些自己的理解,干出死循环了。
悲。
发现原因了,把i+2写成了opcode[i+2],还是没理解透。
乱掉了,决定不做了
决定再做做。
发现做这题时得把类型转换隐藏掉,看着头疼。
#include<stdio.h>
unsigned int opcode[100] = {
0x00000008, 0x00000001, 0x00000000, 0x00000008, 0x00000003, 0x00000046, 0x0000000E, 0x00000015,
0x0000000A, 0x00000001, 0x00000009, 0x00000002, 0x0000000B, 0x0000000A, 0x00000001, 0x0000000A,
0x00000002, 0x00000009, 0x00000001, 0x00000011, 0x00000001, 0x0000000D, 0x00000001, 0x00000003,
0x0000000F, 0x00000008, 0x00000008, 0x00000001, 0x00000000, 0x00000008, 0x00000003, 0x00000047,
0x0000000E, 0x00000046, 0x0000000A, 0x00000001, 0x0000001A, 0x00000002, 0x00000006, 0x0000001D,
0x00000001, 0x00000004, 0x00000014, 0x00000002, 0x00000001, 0x00000019, 0x00000001, 0x00000002,
0x0000001B, 0x00000001, 0x00000001, 0x0000001D, 0x00000001, 0x0000006E, 0x00000013, 0x00000001,
0x00000063, 0x00000015, 0x00000001, 0x00000074, 0x00000013, 0x00000001, 0x00000066, 0x0000001C,
0x00000002, 0x00000001, 0x00000009, 0x00000001, 0x00000011, 0x00000001, 0x0000000D, 0x00000001,
0x00000003, 0x0000000F, 0x00000022, 0x00000064, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
int main()
{
int v1=0;
for (int i = 0;i < 75;)
{
if (opcode[i] == 8)
{
printf("%d mov R%d %d\n", i , opcode[i + 1] - 1, opcode[i + 2]);
i += 3;
continue;
}
if (opcode[i] == 9)
{
printf("%d pop R%d\n", i , opcode[i + 1] - 1);
i += 2;
continue;
}
if (opcode[i] == 0xA)
{
printf("%d push R%d\n", i , opcode[i + 1] - 1);
i += 2;
}
if (opcode[i] == 0xB)
{
printf("%d R0=getchar()\n", i );
i += 1;
continue;
}
if (opcode[i] == 0xC)
{
printf("%d R0=putchar()\n", i );
i += 1;
continue;
}
if (opcode[i] == 0xD)
{
printf("%d if R%d==R%d v1=128\n", i ,opcode[i+2]-1,opcode[i+1]-1);
printf(" if R%d>R%d v1=64\n", opcode[i + 2] - 1, opcode[i + 1] - 1);
printf(" if R%d<R%d v1=32\n", opcode[i + 2] - 1, opcode[i + 1] - 1);
i += 3;
continue;
}
if (opcode[i] == 0xE)
{
printf("%d jmp %d\n", i , opcode[i + 1]);
i += 2;
continue;
}
if (opcode[i] == 0xF)
{
printf("%d if v1&0x80!=0 jmp %d\n", i , i+2);
printf(" else jmp %d\n", opcode[i + 1]);
i += 2;
continue;
}
if (opcode[i] == 0x10)
{
printf("%d if v1&0x80!=0 jmp %d\n", i , opcode[i + 1]);
printf(" else jmp %d\n", i+2);
i += 2;
continue;
}
if (opcode[i] == 0x11)
{
printf("%d inc R%d\n", i , opcode[i + 1] - 1);
i += 2;
continue;
}
if (opcode[i] == 0x12)
{
printf("%d dec R%d\n", i , opcode[i + 1] - 1);
i += 2;
continue;
}
if (opcode[i] == 0x13)
{
printf("%d add R%d %d\n", i , opcode[i + 1] - 1,opcode[i+2]);
i += 3;
continue;
}
if (opcode[i] == 0x14)
{
printf("%d sub R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2]-1);
i += 3;
continue;
}
if (opcode[i] == 0x15)
{
printf("%d xor R%d %d\n", i , opcode[i + 1] - 1, opcode[i + 2]);
i += 3;
continue;
}
if (opcode[i] == 0x16)
{
printf("%d and R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2]-1);
i += 3;
continue;
}
if (opcode[i] == 0x17)
{
printf("%d or R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
i += 3;
continue;
}
if (opcode[i] == 0x19)
{
printf("%d mov R%d R%d\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
i += 3;
continue;
}
if (opcode[i] == 0x1A)
{
printf("%d lea R%d [R%d]\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
i += 3;
continue;
}
if (opcode[i] == 0x1B)
{
printf("%d mov R%d [R%d]\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
i += 3;
continue;
}
if (opcode[i] == 0x1C)
{
printf("%d mov [R%d] R%d\n", i , opcode[i + 1] - 1, opcode[i + 2] - 1);
i += 3;
continue;
}
if (opcode[i] == 0x1D)
{
printf("%d mul R%d %d\n", i , opcode[i + 1] - 1, opcode[i + 2]);
i += 3;
continue;
}
}
}
运行结果
0 mov R0 0
3 mov R2 70
6 jmp 21
8 push R0
10 pop R1
12 R0=getchar()
13 push R0
15 push R1
17 pop R0
19 inc R0
21 if R2==R0 v1=128
if R2>R0 v1=64
if R2<R0 v1=32
24 if v1&0x80!=0 jmp 26
else jmp 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 R0
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 R2==R0 v1=128
if R2>R0 v1=64
if R2<R0 v1=32
73 if v1&0x80!=0 jmp 75
else jmp 34
36行有个R5,对应的应该是栈底。
flag=[0x000036D3, 0x00002AFF, 0x00002ACB, 0x00002B95, 0x00002B95, 0x00002B95, 0x0000169F, 0x0000186D, 0x000018D7, 0x00001611, 0x000018D7, 0x00002B95, 0x00002C23, 0x00002CA9, 0x00001611, 0x00001611, 0x000018D7, 0x00002AFF, 0x00001849, 0x000018FB, 0x00002ACB, 0x00002A71, 0x00001735, 0x000018D7, 0x00001611, 0x00002ACB, 0x000015DD, 0x000018D7, 0x00002C23, 0x0000169F, 0x000015DD, 0x00002B95, 0x0000169F, 0x0000156B, 0x0000186D, 0x00002AFF, 0x00001611, 0x00001611, 0x000015DD, 0x00002AFF, 0x00002C23, 0x00002ACB, 0x000015DD, 0x000015DD, 0x0000186D, 0x00001849, 0x00002B95, 0x0000156B, 0x00001735, 0x000018FB, 0x000018FB, 0x00002A71, 0x00002AFF, 0x00001735, 0x00002C23, 0x000015DD, 0x000018D7, 0x00002A71, 0x000018D7, 0x000018D7, 0x00002C23, 0x00002AFF, 0x0000156B, 0x00002C23, 0x0000169F, 0x000035AF, 0x00002CA9, 0x000032B5, 0x00002AFF, 0x00003039]
for i in range(len(flag)-1,-1,-1):
flag[i]=(((flag[i]-102)^116)-99)//110
print(chr(flag[i]),end='')
#nctf{3e1ce77b70e4cb9941d6800aec022c813d03e70a274ba96c722fed72783dddac}
遭不住。