文章目录
- 查壳
- 拖进ida
- vm函数代码
- 逐步分析vm函数
- push[input]
- print vm_stack[vm_sp]
- eip++
- push `*(_BYTE *)(code + vm_eip + 1)`
- push vm_reg[opcode+1]
- vm_reg[opcode+1]=vm_stack[vm_sp-1]
- push vm_var_arr[opcode+1]
- vm_var[opcode+1]=vm_stack[vm_sp-1]
- 加法
- 减法(分析同上)
- 乘法(分析同上)
- 除法(分析同上)
- 求余核心(分析同上)
- 异或核心
- 按位与核心
- 按位或核心
- 取地址单元值核心
- 取反核心
- vm_stack[vm_sp-1] != vm_stack[vm_sp-2]
- vm_stack[vm_sp-1] == vm_stack[vm_sp-2]
- vm_stack[vm_sp-2] <= vm_stack[vm_sp-1]
- vm_stack[vm_sp-2] < vm_stack[vm_sp-1]
- vm_stack[vm_sp-2] >=vm_stack[vm_sp-1]
- vm_stack[vm_sp-2] >vm_stack[vm_sp-1]
- vm_stack[vm_sp-1] = vm_arr[vm_stack[vm_sp-1]]
- vm_arr[vm_stack[vm_sp-1]] = vm_stack[vm_sp-2]
- vm_stack[vm_sp-1]=vm_reg[vm_stack[vm_sp-1]]
- vm_block[vm_stack[vm_sp-1]] = vm_stack[vm_sp-2]
- opcode >0x1D
查壳

拖进ida


有一个输入参数,记得调试时加上参数。即运行时要指定参数./vm , ida调试要在debugger -> process options -> parameters写上参数code

bss_data{
Dword vm_eip;
Dword vm_sp;
Qword code; // *(bss_data+1)
Qword vm_stack; // *(bss_data+2)
Qword vm_var_arr; //*(bss_data+3)
Qword vm_reg; // *(bss_data+4)
}
核心也就是最后一个分析虚拟机函数这里
vm函数代码
__int64 __fastcall sub_400A50(unsigned int *a1)
{
__int64 v1; // rcx
unsigned int *v2; // rbx
__int64 result; // rax
__int64 v4; // rdx
unsigned int v5; // eax
__int64 v6; // rcx
_BYTE *v7; // rdx
int v8; // eax
char v9; // al
unsigned int v10; // edx
__int64 v11; // rsi
_BYTE *v12; // rax
__int64 v13; // rcx
char v14; // cl
int v15; // er8
signed int v16; // edx
__int64 v17; // rdi
int v18; // esi
int v19; // er8
signed int v20; // edx
__int64 v21; // rdi
int v22; // esi
int v23; // er8
signed int v24; // edx
__int64 v25; // rdi
int v26; // esi
signed int v27; // edx
__int64 v28; // rdi
int v29; // esi
int v30; // er8
signed int v31; // edx
__int64 v32; // rdi
int v33; // esi
int v34; // edi
signed int v35; // edx
__int64 v36; // r8
int v37; // esi
int v38; // ecx
_BYTE *v39; // rax
__int64 v40; // rdx
signed int v41; // eax
int v42; // esi
char v43; // cl
char v44; // cl
signed int v45; // eax
int v46; // esi
char v47; // cl
char v48; // cl
signed int v49; // eax
int v50; // esi
char v51; // cl
char v52; // cl
signed int v53; // eax
__int64 v54; // rdx
int v55; // esi
unsigned __int8 v56; // cl
_BYTE *v57; // rdx
signed int v58; // eax
__int64 v59; // rdx
int v60; // ecx
unsigned __int8 v61; // si
signed int v62; // edx
__int64 v63; // rcx
int v64; // esi
char v65; // al
signed int v66; // eax
char v67; // si
signed int v68; // eax
int v69; // esi
char v70; // cl
char v71; // cl
_BYTE *v72; // rdx
__int64 v73; // rcx
int v74; // eax
__int64 v75; // rax
__int64 v76; // rdx
char v77; // cl
__int64 v78; // rax
__int64 v79; // rdx
__int64 v80; // rdx
_IO_FILE *v81; // rsi
int v82; // eax
char v83; // al
__int64 v84; // rdx
__int64 v85; // rcx
v1 = *((_QWORD *)a1 + 1);
v2 = a1;
result = *a1;
LABEL_2:
v4 = (signed int)result;
while ( 1 )
{
switch ( *(_BYTE *)(v1 + v4) )
{
case 1:
v83 = _IO_getc(stdin);
v84 = (signed int)v2[1];
v85 = *((_QWORD *)v2 + 2);
v2[1] = v84 + 1;
*(_BYTE *)(v85 + v84) = v83;
v1 = *((_QWORD *)v2 + 1);
result = *v2 + 1;
*v2 = result;
goto LABEL_2;
case 2:
v80 = *((_QWORD *)v2 + 2);
v81 = stdout;
v82 = v2[1] - 1;
v2[1] = v82;
_IO_putc(*(unsigned __int8 *)(v80 + v82), v81);
v1 = *((_QWORD *)v2 + 1);
result = *v2 + 1;
*v2 = result;
goto LABEL_2;
case 3:
result = (unsigned int)(result + 1);
*v2 = result;
goto LABEL_2;
case 4:
v77 = *(_BYTE *)(v1 + v4 + 1);
goto LABEL_44;
case 5:
v75 = *(unsigned __int8 *)(v1 + v4 + 1);
v76 = *((_QWORD *)v2 + 4);
goto LABEL_43;
case 6:
v72 = (_BYTE *)(*((_QWORD *)v2 + 4) + *(unsigned __int8 *)(v1 + v4 + 1));
goto LABEL_41;
case 7:
v75 = *(unsigned __int8 *)(v1 + v4 + 1);
v76 = *((_QWORD *)v2 + 3);
LABEL_43:
v77 = *(_BYTE *)(v76 + v75);
LABEL_44:
v78 = (signed int)v2[1];
v79 = *((_QWORD *)v2 + 2);
v2[1] = v78 + 1;
*(_BYTE *)(v79 + v78) = v77;
v1 = *((_QWORD *)v2 + 1);
result = *v2 + 2;
*v2 = result;
goto LABEL_2;
case 8:
v72 = (_BYTE *)(*((_QWORD *)v2 + 3) + *(unsigned __int8 *)(v1 + v4 + 1));
LABEL_41:
v73 = *((_QWORD *)v2 + 2);
v74 = v2[1] - 1;
v2[1] = v74;
*v72 = *(_BYTE *)(v73 + v74);
v1 = *((_QWORD *)v2 + 1);
result = *v2 + 2;
*v2 = result;
goto LABEL_2;
case 9:
v68 = v2[1];
v40 = *((_QWORD *)v2 + 2);
v69 = v68 - 1;
v68 -= 2;
v2[1] = v69;
v70 = *(_BYTE *)(v40 + v69);
v2[1] = v68;
v39 = (_BYTE *)(v40 + v68);
v71 = *v39 + v70;
v2[1] = v69;
LOBYTE(v40) = v71;
goto LABEL_28;
case 0xA:
v66 = v2[1];
v40 = *((_QWORD *)v2 + 2);
v38 = v66 - 1;
v66 -= 2;
v2[1] = v38;
v67 = *(_BYTE *)(v40 + v38);
v2[1] = v66;
v39 = (_BYTE *)(v40 + v66);
LOBYTE(v40) = *v39 - v67;
goto LABEL_27;
case 0xB:
v62 = v2[1];
v63 = *((_QWORD *)v2 + 2);
v64 = v62 - 1;
v62 -= 2;
v2[1] = v64;
v65 = *(_BYTE *)(v63 + v64);
v2[1] = v62;
v7 = (_BYTE *)(v63 + v62);
v9 = *v7 * v65;
v2[1] = v64;
goto LABEL_8;
case 0xC:
v58 = v2[1];
v59 = *((_QWORD *)v2 + 2);
v60 = v58 - 1;
v58 -= 2;
v2[1] = v60;
v61 = *(_BYTE *)(v59 + v60);
v2[1] = v58;
v7 = (_BYTE *)(v58 + v59);
result = (unsigned __int8)*v7;
if ( !v61 )
return result;
v2[1] = v60;
v9 = (unsigned __int16)result / v61;
goto LABEL_8;
case 0xD:
v53 = v2[1];
v54 = *((_QWORD *)v2 + 2);
v55 = v53 - 1;
v53 -= 2;
v2[1] = v55;
v56 = *(_BYTE *)(v54 + v55);
v2[1] = v53;
v57 = (_BYTE *)(v53 + v54);
LOWORD(v53) = (unsigned __int8)*v57;
v2[1] = v55;
result = (unsigned __int8)((unsigned __int16)v53 % v56);
*v57 = result;
if ( !v56 )
return result;
goto LABEL_9;
case 0xE:
v49 = v2[1];
v40 = *((_QWORD *)v2 + 2);
v50 = v49 - 1;
v49 -= 2;
v2[1] = v50;
v51 = *(_BYTE *)(v40 + v50);
v2[1] = v49;
v39 = (_BYTE *)(v40 + v49);
v52 = *v39 ^ v51;
v2[1] = v50;
LOBYTE(v40) = v52;
goto LABEL_28;
case 0xF:
v45 = v2[1];
v40 = *((_QWORD *)v2 + 2);
v46 = v45 - 1;
v45 -= 2;
v2[1] = v46;
v47 = *(_BYTE *)(v40 + v46);
v2[1] = v45;
v39 = (_BYTE *)(v40 + v45);
v48 = *v39 & v47;
v2[1] = v46;
LOBYTE(v40) = v48;
goto LABEL_28;
case 0x10:
v41 = v2[1];
v40 = *((_QWORD *)v2 + 2);
v42 = v41 - 1;
v41 -= 2;
v2[1] = v42;
v43 = *(_BYTE *)(v40 + v42);
v2[1] = v41;
v39 = (_BYTE *)(v40 + v41);
v44 = *v39 | v43;
v2[1] = v42;
LOBYTE(v40) = v44;
goto LABEL_28;
case 0x11:
v38 = v2[1];
v2[1] = v38 - 1;
v39 = (_BYTE *)(*((_QWORD *)v2 + 2) + v38 - 1);
LODWORD(v40) = -(unsigned __int8)*v39;
goto LABEL_27;
case 0x12:
v38 = v2[1];
v2[1] = v38 - 1;
v39 = (_BYTE *)(*((_QWORD *)v2 + 2) + v38 - 1);
LOBYTE(v40) = ~*v39;
LABEL_27:
v2[1] = v38;
LABEL_28:
*v39 = v40;
v1 = *((_QWORD *)v2 + 1);
result = *v2 + 1;
*v2 = result;
goto LABEL_2;
case 0x13:
v15 = *(unsigned __int8 *)(v1 + v4 + 1);
v27 = v2[1];
v28 = *((_QWORD *)v2 + 2);
v29 = v27 - 1;
v27 -= 2;
v2[1] = v29;
LOBYTE(v29) = *(_BYTE *)(v28 + v29);
v2[1] = v27;
if ( *(_BYTE *)(v28 + v27) != (_BYTE)v29 )
goto LABEL_21;
goto LABEL_15;
case 0x14:
v34 = *(char *)(v1 + v4 + 1);
v35 = v2[1];
v36 = *((_QWORD *)v2 + 2);
v37 = v35 - 1;
v35 -= 2;
v2[1] = v37;
LOBYTE(v37) = *(_BYTE *)(v36 + v37);
v2[1] = v35;
if ( *(_BYTE *)(v36 + v35) == (_BYTE)v37 )
goto LABEL_21;
result = (unsigned int)(v34 + result);
*v2 = result;
goto LABEL_2;
case 0x15:
v30 = *(char *)(v1 + v4 + 1);
v31 = v2[1];
v32 = *((_QWORD *)v2 + 2);
v33 = v31 - 1;
v31 -= 2;
v2[1] = v33;
LOBYTE(v33) = *(_BYTE *)(v32 + v33);
v2[1] = v31;
if ( *(_BYTE *)(v32 + v31) <= (unsigned __int8)v33 )
goto LABEL_21;
result = (unsigned int)(v30 + result);
*v2 = result;
goto LABEL_2;
case 0x16:
v23 = *(char *)(v1 + v4 + 1);
v24 = v2[1];
v25 = *((_QWORD *)v2 + 2);
v26 = v24 - 1;
v24 -= 2;
v2[1] = v26;
LOBYTE(v26) = *(_BYTE *)(v25 + v26);
v2[1] = v24;
if ( *(_BYTE *)(v25 + v24) < (unsigned __int8)v26 )
goto LABEL_21;
result = (unsigned int)(v23 + result);
*v2 = result;
goto LABEL_2;
case 0x17:
v19 = *(char *)(v1 + v4 + 1);
v20 = v2[1];
v21 = *((_QWORD *)v2 + 2);
v22 = v20 - 1;
v20 -= 2;
v2[1] = v22;
LOBYTE(v22) = *(_BYTE *)(v21 + v22);
v2[1] = v20;
if ( *(_BYTE *)(v21 + v20) >= (unsigned __int8)v22 )
goto LABEL_21;
result = (unsigned int)(v19 + result);
*v2 = result;
goto LABEL_2;
case 0x18:
v15 = *(char *)(v1 + v4 + 1);
v16 = v2[1];
v17 = *((_QWORD *)v2 + 2);
v18 = v16 - 1;
v16 -= 2;
v2[1] = v18;
LOBYTE(v18) = *(_BYTE *)(v17 + v18);
v2[1] = v16;
if ( *(_BYTE *)(v17 + v16) > (unsigned __int8)v18 )
{
LABEL_21:
result = (unsigned int)(result + 2);
*v2 = result;
}
else
{
LABEL_15:
result = (unsigned int)(v15 + result);
*v2 = result;
}
goto LABEL_2;
case 0x19:
v10 = v2[1];
v11 = *((_QWORD *)v2 + 3);
v2[1] = v10 - 1;
v12 = (_BYTE *)(*((_QWORD *)v2 + 2) + (signed int)(v10 - 1));
v13 = (unsigned __int8)*v12;
goto LABEL_11;
case 0x1A:
v5 = v2[1];
v6 = *((_QWORD *)v2 + 2);
v2[1] = v5 - 1;
v7 = (_BYTE *)(*((_QWORD *)v2 + 3) + *(unsigned __int8 *)(v6 + (signed int)(v5 - 1)));
goto LABEL_7;
case 0x1B:
v10 = v2[1];
v11 = *((_QWORD *)v2 + 4);
v2[1] = v10 - 1;
v12 = (_BYTE *)(*((_QWORD *)v2 + 2) + (signed int)(v10 - 1));
v13 = (unsigned __int8)*v12;
LABEL_11:
v14 = *(_BYTE *)(v11 + v13);
v2[1] = v10;
*v12 = v14;
v1 = *((_QWORD *)v2 + 1);
result = *v2 + 1;
*v2 = result;
goto LABEL_2;
case 0x1C:
v5 = v2[1];
v6 = *((_QWORD *)v2 + 2);
v2[1] = v5 - 1;
v7 = (_BYTE *)(*((_QWORD *)v2 + 4) + *(unsigned __int8 *)(v6 + (signed int)(v5 - 1)));
LABEL_7:
v8 = v5 - 2;
v2[1] = v8;
v9 = *(_BYTE *)(v6 + v8);
LABEL_8:
*v7 = v9;
LABEL_9:
v1 = *((_QWORD *)v2 + 1);
result = *v2 + 1;
*v2 = result;
goto LABEL_2;
case 0x1D:
result = (unsigned int)(*(char *)(v1 + v4 + 1) + (_DWORD)result);
v4 = (signed int)result;
*v2 = result;
if ( *(_BYTE *)(v1 + (signed int)result) > 0x1Du )
return result;
break;
default:
return result;
}
}
}
逐步分析vm函数
push[input]
case 1:
v83 = _IO_getc(stdin);
v84 = (signed int)bss_data[1];
v85 = *((_QWORD *)bss_data + 2);
bss_data[1] = v84 + 1;
*(_BYTE *)(v85 + v84) = v83;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
v84是vm_sp,v85是vm_stack,v84+v85也就代表到了虚拟机栈顶,然后把输入参数v83赋值给它,这就是虚拟机的输入。(在赋值之前把结构体的vm_sp加了1,也就代表压入了参数后,栈顶指针需要抬高)赋值之后需要把eip(控制程序执行流程)往下挪动,放入vm_eip中,接下来就是取出bss_data中的code,然后准备下一个执行命令的opcode = *(&code + vm_eip)
print vm_stack[vm_sp]
case 2:
v80 = *((_QWORD *)bss_data + 2);
v81 = stdout;
v82 = bss_data[1] - 1;
bss_data[1] = v82;
_IO_putc(*(unsigned __int8 *)(v80 + v82), v81);
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
v80是vm_stack,v81是输出参数,v82是vm_sp-1,然后把结构体中的栈顶指针编程vm_sp-1,紧接调用函数,然后传入 vm_sp+vm_stack ,和输出参数v81,调用函数_IO_putc,接下来就是取出bss_data中的code,然后准备下一个执行命令的opcode = *(&code + vm_eip)
eip++
case 3:
vm_eip2 = (unsigned int)(vm_eip2 + 1);
*bss_data = vm_eip2;
goto next;
push *(_BYTE *)(code + vm_eip + 1)
case 4:
v77 = *(_BYTE *)(code + vm_eip + 1);
goto ;
:
v78 = (signed int)bss_data[1];
v79 = *((_QWORD *)bss_data + 2);
bss_data[1] = v78 + 1;
*(_BYTE *)(v79 + v78) = v77;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 2;
*bss_data = vm_eip2;
goto next;
*(&code + vm_eip)这个是opcode,然后把*(_BYTE *)(code + vm_eip + 1)压入栈顶(这个盲猜是一个变量),和上面一样,压入vm_sp+vm_stack的位置,然后改变code和vm_eip,也就是opcode,紧接着下一步的操作
push vm_reg[opcode+1]
case 5:
v75 = *(unsigned __int8 *)(code + vm_eip + 1);
v76 = *((_QWORD *)bss_data + 4);
goto push;
push:
v77 = *(_BYTE *)(v76 + v75);
:
v78 = (signed int)bss_data[1];
v79 = *((_QWORD *)bss_data + 2);
bss_data[1] = v78 + 1;
*(_BYTE *)(v79 + v78) = v77;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 2;
*bss_data = vm_eip2;
goto next;
code + vm_eip+1 赋给 v75,vm_reg赋给v76,然后vm_reg+opcode然后取内存值(这里我觉得这个vm_reg就是一个数组,然后opcode+1是一个索引),也就是取了一个vm_reg[opcode+1],然后把这个值push到了虚拟机栈顶
vm_reg[opcode+1]=vm_stack[vm_sp-1]
case 6:
v72 = (_BYTE *)(*((_QWORD *)bss_data + 4) + *(unsigned __int8 *)(code + vm_eip + 1));
goto LABEL_41;
LABEL_41:
v73 = *((_QWORD *)bss_data + 2);
v74 = bss_data[1] - 1;
bss_data[1] = v74;
*v72 = *(_BYTE *)(v73 + v74);
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 2;
*bss_data = vm_eip2;
goto next;
opcode+vm_reg的地址值赋值给v72,vm_stack赋给v73,vm_sp-1赋给v74,然后放入bss_data中,紧接着把栈中的值赋给opcode+vm_reg的地址单元(v72 = (_BYTE *)(v73 + v74);),总结如下:vm_reg[opcode]=vm_stack[vm_sp]
push vm_var_arr[opcode+1]
case 7:
v75 = *(unsigned __int8 *)(code + vm_eip + 1);
v76 = *((_QWORD *)bss_data + 3);
push:
v77 = *(_BYTE *)(v76 + v75);
:
v78 = (signed int)bss_data[1];
v79 = *((_QWORD *)bss_data + 2);
bss_data[1] = v78 + 1;
*(_BYTE *)(v79 + v78) = v77;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 2;
*bss_data = vm_eip2;
goto next;
v75也就是opcode+1,v76也就是vm_var_arr,v77也就是一个以arr为起始地址,以opcode+1为索引的数组值,然后把这个值放在栈顶,也就是push进去
vm_var[opcode+1]=vm_stack[vm_sp-1]
case 8:
v72 = (_BYTE *)(*((_QWORD *)bss_data + 3) + *(unsigned __int8 *)(code + vm_eip + 1));
LABEL_41:
v73 = *((_QWORD *)bss_data + 2);
v74 = bss_data[1] - 1;
bss_data[1] = v74;
*v72 = *(_BYTE *)(v73 + v74);
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 2;
*bss_data = vm_eip2;
goto next;
把opcode+1+vm_var的地址赋给v72,也就是以vm_var为起始地址,然后以opcode+1的索引值,也就到了相应数组元素的地址,紧接着把vm_stack[vm_sp-1]赋给vm_var[opcode+1]
加法
case 9:
v68 = bss_data[1];
v40 = *((_QWORD *)bss_data + 2);
v69 = v68 - 1;
v68 -= 2;
bss_data[1] = v69;
v70 = *(_BYTE *)(v40 + v69);
bss_data[1] = v68;
v39 = (_BYTE *)(v40 + v68);
v71 = *v39 + v70;
bss_data[1] = v69;
LOBYTE(v40) = v71;
goto LABEL_28;
LABEL_28:
*v39 = v40;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
把vm_sp赋给v68,vm_stack赋给v40,vm_sp-1+v40和vm_sp-2+v40分别取出两个变量,然后把它俩的和赋给v71,最后再放在v39地址单元中。
减法(分析同上)
case 0xA:
v66 = bss_data[1];
v40 = *((_QWORD *)bss_data + 2);
v38 = v66 - 1;
v66 -= 2;
bss_data[1] = v38;
v67 = *(_BYTE *)(v40 + v38);
bss_data[1] = v66;
v39 = (_BYTE *)(v40 + v66);
LOBYTE(v40) = *v39 - v67;
goto LABEL_27;
LABEL_27:
bss_data[1] = v38;
LABEL_28:
*v39 = v40;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
把vm_sp赋给v66,vm_stack赋给v40,vm_sp-1+v40和vm_sp-2+v40分别取出两个变量,然后把它俩的差赋给v40,最后再放在v39地址单元中。
乘法(分析同上)
case 0xB:
v62 = bss_data[1];
v63 = *((_QWORD *)bss_data + 2);
v64 = v62 - 1;
v62 -= 2;
bss_data[1] = v64;
v65 = *(_BYTE *)(v63 + v64);
bss_data[1] = v62;
v7 = (_BYTE *)(v63 + v62);
v9 = *v7 * v65;
bss_data[1] = v64;
goto LABEL_8;
LABEL_8:
*v7 = v9;
LABEL_9:
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
除法(分析同上)
case 0xC:
v58 = bss_data[1];
v59 = *((_QWORD *)bss_data + 2);
v60 = v58 - 1;
v58 -= 2;
bss_data[1] = v60;
v61 = *(_BYTE *)(v59 + v60);
bss_data[1] = v58;
v7 = (_BYTE *)(v58 + v59);
vm_eip2 = (unsigned __int8)*v7;
if ( !v61 )
return vm_eip2;
bss_data[1] = v60;
v9 = (unsigned __int16)vm_eip2 / v61;
goto LABEL_8;
LABEL_8:
*v7 = v9;
LABEL_9:
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
求余核心(分析同上)
case 0xD:
v53 = bss_data[1];
v54 = *((_QWORD *)bss_data + 2);
v55 = v53 - 1;
v53 -= 2;
bss_data[1] = v55;
v56 = *(_BYTE *)(v54 + v55);
bss_data[1] = v53;
v57 = (_BYTE *)(v53 + v54);
LOWORD(v53) = (unsigned __int8)*v57;
bss_data[1] = v55;
vm_eip2 = (unsigned __int8)((unsigned __int16)v53 % v56);
*v57 = vm_eip2;
if ( !v56 )
return vm_eip2;
goto LABEL_9;
LABEL_9:
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
异或核心
case 0xE:
v49 = bss_data[1];
v40 = *((_QWORD *)bss_data + 2);
v50 = v49 - 1;
v49 -= 2;
bss_data[1] = v50;
v51 = *(_BYTE *)(v40 + v50);
bss_data[1] = v49;
v39 = (_BYTE *)(v40 + v49);
v52 = *v39 ^ v51;
bss_data[1] = v50;
LOBYTE(v40) = v52;
goto LABEL_28;
按位与核心
case 0xF:
v45 = bss_data[1];
v40 = *((_QWORD *)bss_data + 2);
v46 = v45 - 1;
v45 -= 2;
bss_data[1] = v46;
v47 = *(_BYTE *)(v40 + v46);
bss_data[1] = v45;
v39 = (_BYTE *)(v40 + v45);
v48 = *v39 & v47;
bss_data[1] = v46;
LOBYTE(v40) = v48;
goto LABEL_28;
按位或核心
case 0x10:
v41 = bss_data[1];
v40 = *((_QWORD *)bss_data + 2);
v42 = v41 - 1;
v41 -= 2;
bss_data[1] = v42;
v43 = *(_BYTE *)(v40 + v42);
bss_data[1] = v41;
v39 = (_BYTE *)(v40 + v41);
v44 = *v39 | v43;
bss_data[1] = v42;
LOBYTE(v40) = v44;
goto LABEL_28;
取地址单元值核心
case 0x11:
v38 = bss_data[1];
bss_data[1] = v38 - 1;
v39 = (_BYTE *)(*((_QWORD *)bss_data + 2) + v38 - 1);
LODWORD(v40) = -(unsigned __int8)*v39;
goto LABEL_27;
LABEL_27:
bss_data[1] = v38;
LABEL_28:
*v39 = v40;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
取反核心
case 0x12:
v38 = bss_data[1];
bss_data[1] = v38 - 1;
v39 = (_BYTE *)(*((_QWORD *)bss_data + 2) + v38 - 1);
LOBYTE(v40) = ~*v39;
LABEL_27:
bss_data[1] = v38;
LABEL_28:
*v39 = v40;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
vm_stack[vm_sp-1] != vm_stack[vm_sp-2]
case 0x13:
v15 = *(unsigned __int8 *)(code + vm_eip + 1);
v27 = bss_data[1];
v28 = *((_QWORD *)bss_data + 2);
v29 = v27 - 1;
v27 -= 2;
bss_data[1] = v29;
LOBYTE(v29) = *(_BYTE *)(v28 + v29);
bss_data[1] = v27;
if ( *(_BYTE *)(v28 + v27) != (_BYTE)v29 )
goto LABEL_21;
goto LABEL_15;
vm_stack[vm_sp-1] == vm_stack[vm_sp-2]
case 0x14:
v34 = *(char *)(code + vm_eip + 1);
v35 = bss_data[1];
v36 = *((_QWORD *)bss_data + 2);
v37 = v35 - 1;
v35 -= 2;
bss_data[1] = v37;
LOBYTE(v37) = *(_BYTE *)(v36 + v37);
bss_data[1] = v35;
if ( *(_BYTE *)(v36 + v35) == (_BYTE)v37 )
goto LABEL_21;
vm_eip2 = (unsigned int)(v34 + vm_eip2);
*bss_data = vm_eip2;
goto next;
vm_stack[vm_sp-2] <= vm_stack[vm_sp-1]
case 0x15:
v30 = *(char *)(code + vm_eip + 1);
v31 = bss_data[1];
v32 = *((_QWORD *)bss_data + 2);
v33 = v31 - 1;
v31 -= 2;
bss_data[1] = v33;
LOBYTE(v33) = *(_BYTE *)(v32 + v33);
bss_data[1] = v31;
if ( *(_BYTE *)(v32 + v31) <= (unsigned __int8)v33 )
goto LABEL_21;
vm_eip2 = (unsigned int)(v30 + vm_eip2);
*bss_data = vm_eip2;
goto next;
vm_stack[vm_sp-2] < vm_stack[vm_sp-1]
case 0x16:
v23 = *(char *)(code + vm_eip + 1);
v24 = bss_data[1];
v25 = *((_QWORD *)bss_data + 2);
v26 = v24 - 1;
v24 -= 2;
bss_data[1] = v26;
LOBYTE(v26) = *(_BYTE *)(v25 + v26);
bss_data[1] = v24;
if ( *(_BYTE *)(v25 + v24) < (unsigned __int8)v26 )
goto LABEL_21;
vm_eip2 = (unsigned int)(v23 + vm_eip2);
*bss_data = vm_eip2;
goto next;
vm_stack[vm_sp-2] >=vm_stack[vm_sp-1]
case 0x17:
v19 = *(char *)(code + vm_eip + 1);
v20 = bss_data[1];
v21 = *((_QWORD *)bss_data + 2);
v22 = v20 - 1;
v20 -= 2;
bss_data[1] = v22;
LOBYTE(v22) = *(_BYTE *)(v21 + v22);
bss_data[1] = v20;
if ( *(_BYTE *)(v21 + v20) >= (unsigned __int8)v22 )
goto LABEL_21;
vm_eip2 = (unsigned int)(v19 + vm_eip2);
*bss_data = vm_eip2;
goto next;
vm_stack[vm_sp-2] >vm_stack[vm_sp-1]
case 0x18:
v15 = *(char *)(code + vm_eip + 1);
v16 = bss_data[1];
v17 = *((_QWORD *)bss_data + 2);
v18 = v16 - 1;
v16 -= 2;
bss_data[1] = v18;
LOBYTE(v18) = *(_BYTE *)(v17 + v18);
bss_data[1] = v16;
if ( *(_BYTE *)(v17 + v16) > (unsigned __int8)v18 )
{
LABEL_21:
vm_eip2 = (unsigned int)(vm_eip2 + 2);
*bss_data = vm_eip2;
}
else
{
LABEL_15:
vm_eip2 = (unsigned int)(v15 + vm_eip2);
*bss_data = vm_eip2;
}
goto next;
vm_stack[vm_sp-1] = vm_arr[vm_stack[vm_sp-1]]
case 0x19:
v10 = bss_data[1];
v11 = *((_QWORD *)bss_data + 3);
bss_data[1] = v10 - 1;
v12 = (_BYTE *)(*((_QWORD *)bss_data + 2) + (signed int)(v10 - 1));
v13 = (unsigned __int8)*v12;
goto LABEL_11;
LABEL_11:
v14 = *(_BYTE *)(v11 + v13);
bss_data[1] = v10;
*v12 = v14;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
vm_arr[vm_stack[vm_sp-1]] = vm_stack[vm_sp-2]
case 0x1A:
v5 = bss_data[1];
v6 = *((_QWORD *)bss_data + 2);
bss_data[1] = v5 - 1;
v7 = (_BYTE *)(*((_QWORD *)bss_data + 3) + *(unsigned __int8 *)(v6 + (signed int)(v5 - 1)));
goto LABEL_7;
LABEL_7:
v8 = v5 - 2;
bss_data[1] = v8;
v9 = *(_BYTE *)(v6 + v8);
LABEL_8:
*v7 = v9;
LABEL_9:
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
vm_stack[vm_sp-1]=vm_reg[vm_stack[vm_sp-1]]
case 0x1B:
v10 = bss_data[1];
v11 = *((_QWORD *)bss_data + 4);
bss_data[1] = v10 - 1;
v12 = (_BYTE *)(*((_QWORD *)bss_data + 2) + (signed int)(v10 - 1));
v13 = (unsigned __int8)*v12;
LABEL_11:
v14 = *(_BYTE *)(v11 + v13);
bss_data[1] = v10;
*v12 = v14;
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
vm_block[vm_stack[vm_sp-1]] = vm_stack[vm_sp-2]
case 0x1C:
v5 = bss_data[1];
v6 = *((_QWORD *)bss_data + 2);
bss_data[1] = v5 - 1;
v7 = (_BYTE *)(*((_QWORD *)bss_data + 4) + *(unsigned __int8 *)(v6 + (signed int)(v5 - 1)));
LABEL_7:
v8 = v5 - 2;
bss_data[1] = v8;
v9 = *(_BYTE *)(v6 + v8);
LABEL_8:
*v7 = v9;
LABEL_9:
code = *((_QWORD *)bss_data + 1);
vm_eip2 = *bss_data + 1;
*bss_data = vm_eip2;
goto next;
opcode >0x1D
case 0x1D:
vm_eip2 = (unsigned int)(*(char *)(code + vm_eip + 1) + (_DWORD)vm_eip2);
vm_eip = (signed int)vm_eip2;
*bss_data = vm_eip2;
if ( *(_BYTE *)(code + (signed int)vm_eip2) > 0x1Du )
return vm_eip2;
break;
default:
return vm_eip2;
本文详细分析了一个虚拟机的执行过程,包括输入参数的获取、栈顶元素的打印、指令计数器的递增、变量的压栈与赋值等操作。通过对不同指令的解析,展示了如何处理加法、减法、乘法、除法、比较操作等,并解释了如何更新虚拟机栈和寄存器状态。
1319





