vm题目记录

这里说的vm指的是出题人通过实现一个小型的虚拟机,把程序的代码转换为程序设计者自定义的操作码(opcode)然后在程序执行时通过解释操作码,执行对应的函数,从而实现程序原有的功能。

周二 4月 01 2025
1211 字 · 11 分钟

螺丝主站

vm0

image-20250401100044183

先在这里进行了初始化,将opcode跟函数关联起来。

C
void *vm_init()
{
vm_vpu *cpu;
cpu->r1 = 0;
cpu->r2 = 0;
cpu->r3 = 0;
cpu->eip = (unsigned char *)vm_code;//将eip指向opcode的地址
cpu->op_list[0].opcode = 0xf1;
cpu->op_list[0].handle = (void (*)(void *))mov;//将操作字节码与对应的handle函数关联在一起
cpu->op_list[1].opcode = 0xf2;
cpu->op_list[1].handle = (void (*)(void *))xor;
cpu->op_list[2].opcode = 0xf5;
cpu->op_list[2].handle = (void (*)(void *))read_;
vm_stack = malloc(0x512);
memset(vm_stack,0,0x512);//定义了一个新栈并在malloc上申请了0x512位的空间

image-20250401100238225

之后是入口函数。

C
void vm_start(vm_cpu *cpu)
{
cpu->eip = (unsigned char*)opcodes;//eip指向要被解释的opcode地址
while((*cpu->eip) != 0xf4)//如果opcode不为RET,就调用vm_dispatcher来解释执行
{
vm_dispatcher(*cpu->eip)
}

再之后就是vm_dispatcher

image-20250401100534108

C
void vm_dispatcher(vm_cpu *cpu)
{
int j;
for(j=0;j<OPCODE_N;j++)
{
if(*cpu->eip ==cpu->op_list[i].opcode)
{
cpu->op_list[i].handle(cpu);
break;
}
}
}

之后便是具体函数的实现。

现在来具体分析该题:

opcode函数功能
0xf1sub_564114800B5F移动数据到寄存器
0xf2sub_564114800A64r0=r0^r1
0xf5sub_564114800AC5判断输入长度是否为20
0xf4sub_564114800956无作用,跳转到下一条指令
0xf7sub_564114800A08r0=r0*r3
0xf8sub_5641148008F0交换r0和r1数据
0xf6sub_56411480099Cr0=r2+2*r1+3*r0

接下来写一个脚本来模拟一下程序。

脚本如下:

PYTHON
from sympy.strategies.core import switch

mycode = [
    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(mycode)):
    if mycode[i] == 0xF1:
        match mycode[i + 1]:
            case 0xE1:
                print(f"r0=input[{mycode[i + 2]}]")
            case 0xE2:
                print(f"r1=input[{mycode[i + 2]}]")
            case 0xE3:
                print(f"r2=input[{mycode[i + 2]}]")
            case 0xE4:
                print(f"input[{mycode[i + 2]}]=r0")
            case 0xE5:
                print(f"r3=input[{mycode[i + 2]}]")
            case 0xE7:
                print(f"input[{mycode[i + 2]}]=r1")
    if mycode[i] == 0xF4:
        pass
    if mycode[i] == 0xF2:
        print("r0=r0^r1")
    if mycode[i] == 0xF5:
        print("判断输入是否为20")
    if mycode[i] == 0xF7:
        print("r0=r0*r1")
    if mycode[i] == 0xF6:
        print("r0=r2+2*r1+3*r0")
    if mycode[i] == 0xF8:
        print("交换r0和r1")

执行结果:

PLAINTEXT
判断输入是否为20
r0=input[0]
r0=r0^r1
input[32]=r0
r0=input[1]
r0=r0^r1
input[33]=r0
r0=input[2]
r0=r0^r1
input[34]=r0
r0=input[3]
r0=r0^r1
input[35]=r0
r0=input[4]
r0=r0^r1
input[36]=r0
r0=input[5]
r0=r0^r1
input[37]=r0
r0=input[6]
r0=r0^r1
input[38]=r0
r0=input[7]
r0=r0^r1
input[39]=r0
r0=input[8]
r0=r0^r1
input[40]=r0
r0=input[9]
r0=r0^r1
input[41]=r0
r0=input[10]
r0=r0^r1
input[42]=r0
r0=input[11]
r0=r0^r1
input[43]=r0
r0=input[12]
r0=r0^r1
input[44]=r0
r0=input[13]
r0=r0^r1
input[45]=r0
r0=input[14]
r0=r0^r1
input[46]=r0
r0=input[15]
r0=r0^r1
input[47]=r0
r0=input[16]
r0=r0^r1
input[48]=r0
r0=input[17]
r0=r0^r1
input[49]=r0
r0=input[18]
r0=r0^r1
input[50]=r0
r0=input[19]
r0=r0^r1
input[51]=r0
判断输入是否为20
r0=input[0]
r1=input[1]
r0=r0^r1
input[0]=r0
r0=input[1]
r1=input[2]
r0=r0^r1
input[1]=r0
r0=input[2]
r1=input[3]
r0=r0^r1
input[2]=r0
r0=input[3]
r1=input[4]
r0=r0^r1
input[3]=r0
r0=input[4]
r1=input[5]
r0=r0^r1
input[4]=r0
r0=input[5]
r1=input[6]
r0=r0^r1
input[5]=r0
r0=input[6]
r1=input[7]
r2=input[8]
r3=input[12]
r0=r2+2*r1+3*r0
r0=r0*r3
input[6]=r0
r0=input[7]
r1=input[8]
r2=input[9]
r3=input[12]
r0=r2+2*r1+3*r0
r0=r0*r3
input[7]=r0

r0=input[8]
r1=input[9]
r2=input[10]
r3=input[12]
r0=r2+2*r1+3*r0
r0=r0*r3
input[8]=r0

r0=input[13]
r1=input[19]
交换r0和r1
input[13]=r0
input[19]=r1
r0=input[14]
r1=input[18]
交换r0和r1
input[14]=r0
input[18]=r1
r0=input[15]
r1=input[17]
交换r0和r1
input[15]=r0
input[17]=r1

r1初始值为18,第一段对其进行了异或。第一段解密如下:

image-20250401115010441

是错的。

第二段呢。

第二段进行了连续异或,然后进行了数学运算,然后进行了交换。

解密脚本如下:

PYTHON
def swapPositions(list, pos1, pos2):
    list[pos1], list[pos2] = list[pos2], list[pos1]
    return list
enc_data = [0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B, 0x5C, 0x72,
  0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5F, 0x33, 0x73, 0x72]
enc_data = swapPositions(enc_data,15,17)
enc_data = swapPositions(enc_data,14,18)
enc_data = swapPositions(enc_data,13,19)
r3 = enc_data[12]
for i in range(30,128):
    if enc_data[8]==(r3*(i*3+2*enc_data[9]+enc_data[10]))&0xff:
        enc_data[8]=i
        break
for i in range(30,128):
    if enc_data[7]==(r3*(i*3+2*enc_data[8]+enc_data[9]))&0xff:
        enc_data[7]=i
        break
for i in range(30,128):
    if enc_data[6]==(r3*(i*3+2*enc_data[7]+enc_data[8]))&0xff:
        enc_data[6]=i
        break
for i in range(5,-1,-1):
    enc_data[i]^=enc_data[i+1]
for i in range(len(enc_data)):
    print(chr(enc_data[i]),end="")
#Y0u_hav3_r3v3rs3_1t!

即得到最终答案

vm1

开幕就是花指令。

image-20250402112013168


Thanks for reading!

vm题目记录

周二 4月 01 2025
1211 字 · 11 分钟