首页
社区
课程
招聘
[原创]hxp38c3 mbins wp 解释器,侧信道,模拟执行 all in one
发表于: 2025-1-11 20:25 4926

[原创]hxp38c3 mbins wp 解释器,侧信道,模拟执行 all in one

2025-1-11 20:25
4926

好折磨,这是我做过的最难的逆向题,题目给了1000个二进制程序,单个难度不大,但是把1000个统一起来自动化那真是太难了,根据这题是考自动化

题目给了chk0.bin-chk999.bin共1000个文件,每个文件接收0x12长度的16进制字符串,如果正确返回0,每个正确的字符串为一个x,y坐标,在 Shamir 秘密共享中,密钥可以通过拉格朗日插值法从足够多的点数中恢复,题目中规定的点数为 ≥ 950

所以至少需要搞对950.,好了,开始长征

可以看到核心逻辑是由一个指令解释器通过解析指令格式,完成各种操作:

指令在data段里,这里不管调试,使用pyda侧信道(关于pyda 看前面的文章),或者直接将这段代码复制出来放在本地跑,都可以知道这段程序的行为。

部分数据j结构可以猜出来,VM_context可以表示如下:

当然,也不是简单的复制,多打开几个bin,会发现在指令解析前都会有不同的操作,可以总结为(’big‘,’liitle’) X (’lfsr’,’no_lfsr’)的笛卡尔积,共四种情况,在个别的bin中,还会对指令码做初始化操作,这些初始化操作都是为了call 其他的函数

源代码模拟代码如下:

老粉应该比较熟悉pyda,在这里通过pyda 统计比较cmp,xor,来推测程序的行为

xor_cmplog脚本为:

pyda跑一下就能侧信道了

根据侧信道的结果,写了一个自动化的demo版本:

但是这个脚本太难做到对1000都适用,有太多的情况,需要往脚本里加,在编写这个脚本的时候也是改到后面,前面又跑不出来,循环往复,总之花了太多的时间,总之就是写了还能跑出不少解的侧信道demo版本。

这部分来自于作者的github,但是我觉得这个题解有些过于复杂,作者实现了一个解释器,好几个python,而且都500多行的样子,我觉得对于ctf比赛,这样求解太浪费时间(难道是我太菜了orz

核心求解代码:

对于上面三种解法,我觉得还是模拟执行比较优雅,因为纯静态需要考虑很多情况,不如让程序动起来。虽然侧信道也是动起来,但是到个别chk,会有特别多的instructions,大于100万条,trace的文件都很大,显然这种chk不适合侧信道。

模拟执行代码:

模拟执行分为两部分:

这个题是我遇到的最难的题,中间尝试了各种方法,都不是很优雅,源代码虽然简单便捷但是自动化不太方便,pyda虽然可以自动化但是需要考虑的东西实在太多,来来回回改了好几天,太痛苦,结果也不尽人意。

模拟执行还是比较适合这道题,这也是我第一次学习模拟执行,写篇文章记录下。感谢你的阅读。

# This file was *autogenerated* from the file derive_key.sage
from sage.all_cmdline import *   # import sage library
 
_sage_const_202750432774689774479024096223623722409 = Integer(202750432774689774479024096223623722409); _sage_const_2 = Integer(2); _sage_const_950 = Integer(950); _sage_const_0 = Integer(0); _sage_const_16 = Integer(16)
p = _sage_const_202750432774689774479024096223623722409
 
F = Zmod(p)
G = F['x']; (x,) = G._first_ngens(1)
 
# just the accepted input values from the challenges
solutions = []
 
points = [*{int.from_bytes(s[:_sage_const_2 ], 'big'): int.from_bytes(s[_sage_const_2 :], 'big') for s in solutions}.items()]
 
if len(points) >= _sage_const_950 :
    key = G.lagrange_polynomial(points)[_sage_const_0 ]
 
    print(f"key: {key.lift().to_bytes(_sage_const_16 , 'big').hex()}")
# This file was *autogenerated* from the file derive_key.sage
from sage.all_cmdline import *   # import sage library
 
_sage_const_202750432774689774479024096223623722409 = Integer(202750432774689774479024096223623722409); _sage_const_2 = Integer(2); _sage_const_950 = Integer(950); _sage_const_0 = Integer(0); _sage_const_16 = Integer(16)
p = _sage_const_202750432774689774479024096223623722409
 
F = Zmod(p)
G = F['x']; (x,) = G._first_ngens(1)
 
# just the accepted input values from the challenges
solutions = []
 
points = [*{int.from_bytes(s[:_sage_const_2 ], 'big'): int.from_bytes(s[_sage_const_2 :], 'big') for s in solutions}.items()]
 
if len(points) >= _sage_const_950 :
    key = G.lagrange_polynomial(points)[_sage_const_0 ]
 
    print(f"key: {key.lift().to_bytes(_sage_const_16 , 'big').hex()}")
__int64 __fastcall VM(__int64 *a1)
{
  __int64 result; // rax
  unsigned int *v3; // rdx
  unsigned int v4; // edi
  __int64 v5; // r14
  __int64 v6; // rdi
  unsigned int v7; // r8d
  __int64 v8; // rsi
  __int64 v9; // rcx
  __int64 v10; // rdx
  unsigned int v11; // edi
  __int64 v12; // rcx
  __int64 *v13; // rax
  __int64 v14; // rdi
  __int64 (__fastcall *v15)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v16; // rax
  char v17; // cl
  __int64 v18; // rdx
  unsigned int v19; // edx
  unsigned int v20; // ecx
  unsigned __int64 *v21; // rax
  unsigned __int64 v22; // rcx
  __int64 v23; // [rsp-8h] [rbp-18h]
 
  v23 = result;
  v3 = (unsigned int *)a1[31];
  v4 = *v3;
  v5 = (__int64)(v3 + 1);
  a1[31] = (__int64)(v3 + 1);
  v6 = _byteswap_ulong(v4);
  v7 = (unsigned int)v6 >> 29;
  if ( (unsigned int)v6 < 0x20000000 || v7 == 1 && (result = v6 & 0x10000000, (v6 & 0x10000000) == 0) )
  {
    v8 = ((unsigned int)v6 >> 19) & 0x1F;
    if ( (BYTE3(v6) & 1 & (v7 == 1)) != 0 || (v6 & 0xE1000000) == 0 )
    {
      if ( v7 == 1 || (unsigned int)v6 >> 25 == 9 || (unsigned int)v6 >> 25 == 7 )// imm
        v9 = v6 << 50 >> 50;                    // low 14 bits signed
      else
        v9 = v6 & 0x3FFF;                       // low 14 bits unsigned
    }
    else
    {
      v9 = a1[((unsigned int)v6 >> 9) & 0x1F];
    }
    v10 = a1[((unsigned int)v6 >> 14) & 0x1F];
    v11 = (unsigned int)v6 >> 25;
    if ( v7 == 1 )
    {
      switch ( v11 & 7 )
      {
        case 0u:
          result = v10 == v9;
          a1[v8] = result;
          break;
        case 1u:
          result = v10 != v9;
          a1[v8] = result;
          break;
        case 2u:
          result = v10 <= v9;
          a1[v8] = result;
          break;
        case 3u:
          result = v10 < v9;
          a1[v8] = result;
          break;
        case 4u:
          result = v10 <= (unsigned __int64)v9;
          a1[v8] = result;
          break;
        case 5u:
          result = v10 < (unsigned __int64)v9;
          a1[v8] = result;
          break;
        default:
LABEL_20:
          result = 0LL;
          a1[v8] = 0LL;
          break;
      }
    }
    else
    {
      switch ( v11 & 0xF )
      {
        case 0u:
          v12 = v10 | v9;
          goto LABEL_38;
        case 1u:
          v12 = v10 ^ v9;
          goto LABEL_38;
        case 2u:
          v12 = v10 & v9;
          goto LABEL_38;
        case 3u:
          v12 = v10 + v9;
          goto LABEL_38;
        case 4u:
          v18 = v10 - v9;
          goto LABEL_48;
        case 5u:
          v12 = v10 * v9;
LABEL_38:
          result = v12;
          a1[v8] = v12;
          return result;
        case 6u:
          result = v10 / (unsigned __int64)v9;
          a1[v8] = v10 / (unsigned __int64)v9;
          return result;
        case 7u:
          result = v10 / v9;
          a1[v8] = v10 / v9;
          return result;
        case 8u:
          v18 = v10 % (unsigned __int64)v9;
          goto LABEL_48;
        case 9u:
          v18 = v10 % v9;
          goto LABEL_48;
        case 0xAu:
          v18 = v10 << v9;
          goto LABEL_48;
        case 0xBu:
          v18 = v10 >> v9;
          goto LABEL_48;
        case 0xCu:
          v18 = (unsigned __int64)v10 >> v9;
          goto LABEL_48;
        case 0xDu:
          v18 = __ROL8__(v10, v9);
          goto LABEL_48;
        case 0xEu:
          v18 = __ROR8__(v10, v9);
LABEL_48:
          result = v18;
          a1[v8] = v18;
          break;
        default:
          goto LABEL_20;
      }
    }
    return result;
  }
  if ( v7 == 1 )
  {
    v7 = ((unsigned int)v6 >> 26) & 3;
    if ( v7 == 2 )
    {
      v14 = ((unsigned int)v6 >> 20) & 0x1F;
      v15 = (__int64 (__fastcall *)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64))a1[v14];
      if ( (unsigned __int64)v15 < a1[32] || (unsigned __int64)v15 >= a1[33] )
      {
        result = v15(*a1, a1[1], a1[2], a1[3], a1[4], a1[5], v23);
        *a1 = result;
        a1[31] = v5;
      }
      else
      {
        v16 = a1[30];                           // PUSH
        *(_QWORD *)(v16 - 8) = v5;              // call
        result = v16 - 8;
        a1[31] = a1[v14];
        a1[30] = result;
      }
      return result;
    }
    if ( !v7 )
    {
      v13 = (__int64 *)a1[30];                  // pop
      a1[31] = *v13;                            // ret
      result = (__int64)(v13 + 1);
      a1[30] = result;
      return result;
    }
    if ( (v6 & 0x2000000) != 0 )                // check 26 bit
    {
      result = 37LL;
      v17 = 39;
    }
    else
    {
      result = ((unsigned int)v6 >> 20) & 0x1F; // 21-25
      if ( !a1[result] )
        goto LABEL_52;
      result = 42LL;
      v17 = 44;
    }
    a1[31] = (__int64)v3 + ((__int64)((unsigned __int64)(unsigned int)v6 << v17) >> result);
LABEL_52:
    if ( (v6 & 0x2000000) == 0 )
      return result;
  }
  if ( v7 == 2 )
  {
    if ( (((unsigned int)v6 >> 27) & 3) != 0 // 2829
    {
      v19 = ((unsigned int)v6 >> 21) & 0x1F;    // 22-26
      v20 = WORD1(v6) & 0x1F;
      result = (unsigned __int16)v6 - 0x8000LL;
      if ( (v6 & 0x8000u) == 0LL )
        result = (unsigned __int16)v6;
      if ( (((unsigned int)v6 >> 27) & 3) == 1 )
      {
        result = *(_QWORD *)(a1[v20] + result);
        a1[v19] = result;                       // load
      }
      else
      {
        switch ( ((unsigned int)v6 >> 26) & 3 ) // store
        {
          case 0u:
            *(_BYTE *)(a1[v20] + result) = a1[v19];
            break;
          case 1u:
            *(_WORD *)(a1[v20] + result) = a1[v19];
            break;
          case 2u:
            *(_DWORD *)(a1[v20] + result) = a1[v19];
            break;
          case 3u:
            *(_QWORD *)(a1[v20] + result) = a1[v19];
            break;
        }
      }
    }
    else
    {
      v21 = (unsigned __int64 *)a1[31];
      v22 = _byteswap_uint64(*v21);
      result = (__int64)(v21 + 1);
      a1[31] = result;
      a1[WORD1(v6) & 0x1F] = v22;
    }
  }
  return result;
}         
__int64 __fastcall VM(__int64 *a1)
{
  __int64 result; // rax
  unsigned int *v3; // rdx
  unsigned int v4; // edi
  __int64 v5; // r14
  __int64 v6; // rdi
  unsigned int v7; // r8d
  __int64 v8; // rsi
  __int64 v9; // rcx
  __int64 v10; // rdx
  unsigned int v11; // edi
  __int64 v12; // rcx
  __int64 *v13; // rax
  __int64 v14; // rdi
  __int64 (__fastcall *v15)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v16; // rax
  char v17; // cl
  __int64 v18; // rdx
  unsigned int v19; // edx
  unsigned int v20; // ecx
  unsigned __int64 *v21; // rax
  unsigned __int64 v22; // rcx
  __int64 v23; // [rsp-8h] [rbp-18h]
 
  v23 = result;
  v3 = (unsigned int *)a1[31];
  v4 = *v3;
  v5 = (__int64)(v3 + 1);
  a1[31] = (__int64)(v3 + 1);
  v6 = _byteswap_ulong(v4);
  v7 = (unsigned int)v6 >> 29;
  if ( (unsigned int)v6 < 0x20000000 || v7 == 1 && (result = v6 & 0x10000000, (v6 & 0x10000000) == 0) )
  {
    v8 = ((unsigned int)v6 >> 19) & 0x1F;
    if ( (BYTE3(v6) & 1 & (v7 == 1)) != 0 || (v6 & 0xE1000000) == 0 )
    {
      if ( v7 == 1 || (unsigned int)v6 >> 25 == 9 || (unsigned int)v6 >> 25 == 7 )// imm
        v9 = v6 << 50 >> 50;                    // low 14 bits signed
      else
        v9 = v6 & 0x3FFF;                       // low 14 bits unsigned
    }
    else
    {
      v9 = a1[((unsigned int)v6 >> 9) & 0x1F];
    }
    v10 = a1[((unsigned int)v6 >> 14) & 0x1F];
    v11 = (unsigned int)v6 >> 25;
    if ( v7 == 1 )
    {
      switch ( v11 & 7 )
      {
        case 0u:
          result = v10 == v9;
          a1[v8] = result;
          break;
        case 1u:
          result = v10 != v9;
          a1[v8] = result;
          break;
        case 2u:
          result = v10 <= v9;
          a1[v8] = result;
          break;
        case 3u:
          result = v10 < v9;
          a1[v8] = result;
          break;
        case 4u:
          result = v10 <= (unsigned __int64)v9;
          a1[v8] = result;
          break;
        case 5u:
          result = v10 < (unsigned __int64)v9;
          a1[v8] = result;
          break;
        default:
LABEL_20:
          result = 0LL;
          a1[v8] = 0LL;
          break;
      }
    }
    else
    {
      switch ( v11 & 0xF )
      {
        case 0u:
          v12 = v10 | v9;
          goto LABEL_38;
        case 1u:
          v12 = v10 ^ v9;
          goto LABEL_38;
        case 2u:
          v12 = v10 & v9;
          goto LABEL_38;
        case 3u:
          v12 = v10 + v9;
          goto LABEL_38;
        case 4u:
          v18 = v10 - v9;
          goto LABEL_48;
        case 5u:
          v12 = v10 * v9;
LABEL_38:
          result = v12;
          a1[v8] = v12;
          return result;
        case 6u:
          result = v10 / (unsigned __int64)v9;
          a1[v8] = v10 / (unsigned __int64)v9;
          return result;
        case 7u:
          result = v10 / v9;
          a1[v8] = v10 / v9;
          return result;
        case 8u:
          v18 = v10 % (unsigned __int64)v9;
          goto LABEL_48;
        case 9u:
          v18 = v10 % v9;
          goto LABEL_48;
        case 0xAu:
          v18 = v10 << v9;
          goto LABEL_48;
        case 0xBu:
          v18 = v10 >> v9;
          goto LABEL_48;
        case 0xCu:
          v18 = (unsigned __int64)v10 >> v9;
          goto LABEL_48;
        case 0xDu:
          v18 = __ROL8__(v10, v9);
          goto LABEL_48;
        case 0xEu:
          v18 = __ROR8__(v10, v9);
LABEL_48:
          result = v18;
          a1[v8] = v18;
          break;
        default:
          goto LABEL_20;
      }
    }
    return result;
  }
  if ( v7 == 1 )
  {
    v7 = ((unsigned int)v6 >> 26) & 3;
    if ( v7 == 2 )
    {
      v14 = ((unsigned int)v6 >> 20) & 0x1F;
      v15 = (__int64 (__fastcall *)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64))a1[v14];
      if ( (unsigned __int64)v15 < a1[32] || (unsigned __int64)v15 >= a1[33] )
      {
        result = v15(*a1, a1[1], a1[2], a1[3], a1[4], a1[5], v23);
        *a1 = result;
        a1[31] = v5;
      }
      else
      {
        v16 = a1[30];                           // PUSH
        *(_QWORD *)(v16 - 8) = v5;              // call
        result = v16 - 8;
        a1[31] = a1[v14];
        a1[30] = result;
      }
      return result;
    }
    if ( !v7 )
    {
      v13 = (__int64 *)a1[30];                  // pop
      a1[31] = *v13;                            // ret
      result = (__int64)(v13 + 1);
      a1[30] = result;
      return result;
    }
    if ( (v6 & 0x2000000) != 0 )                // check 26 bit
    {
      result = 37LL;
      v17 = 39;
    }
    else
    {
      result = ((unsigned int)v6 >> 20) & 0x1F; // 21-25
      if ( !a1[result] )
        goto LABEL_52;
      result = 42LL;
      v17 = 44;
    }
    a1[31] = (__int64)v3 + ((__int64)((unsigned __int64)(unsigned int)v6 << v17) >> result);
LABEL_52:
    if ( (v6 & 0x2000000) == 0 )
      return result;
  }
  if ( v7 == 2 )
  {
    if ( (((unsigned int)v6 >> 27) & 3) != 0 // 2829
    {
      v19 = ((unsigned int)v6 >> 21) & 0x1F;    // 22-26
      v20 = WORD1(v6) & 0x1F;
      result = (unsigned __int16)v6 - 0x8000LL;
      if ( (v6 & 0x8000u) == 0LL )
        result = (unsigned __int16)v6;
      if ( (((unsigned int)v6 >> 27) & 3) == 1 )
      {
        result = *(_QWORD *)(a1[v20] + result);
        a1[v19] = result;                       // load
      }
      else
      {
        switch ( ((unsigned int)v6 >> 26) & 3 ) // store
        {
          case 0u:
            *(_BYTE *)(a1[v20] + result) = a1[v19];
            break;
          case 1u:
            *(_WORD *)(a1[v20] + result) = a1[v19];
            break;
          case 2u:
            *(_DWORD *)(a1[v20] + result) = a1[v19];
            break;
          case 3u:
            *(_QWORD *)(a1[v20] + result) = a1[v19];
            break;
        }
      }
    }
    else
    {
      v21 = (unsigned __int64 *)a1[31];
      v22 = _byteswap_uint64(*v21);
      result = (__int64)(v21 + 1);
      a1[31] = result;
      a1[WORD1(v6) & 0x1F] = v22;
    }
  }
  return result;
}         
1-29 1-30 31 32 33 34
r0-r29 rsp(r30) rip(r31) start end encryption_flag
#include<stdio.h>
#include<stdint.h>
#include"defs.h"
#include <intrin.h>
#include<iostream>
#include <cstdarg>
 
using namespace std;
 
int lut[256] = {};
 
__int64 __fastcall VM_0(__int64 *a1) //big edian no lfsr
{
  __int64 result; // rax
  unsigned int *v3; // rdx
  unsigned int v4; // edi
  __int64 v5; // r14
  __int64 v6; // rdi
  unsigned int v7; // r8d
  __int64 v8; // rsi
  __int64 v9; // rcx
  __int64 v10; // rdx
  unsigned int v11; // edi
  __int64 v12; // rcx
  __int64 *v13; // rax
  __int64 v14; // rdi
  __int64 (__fastcall *v15)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v16; // rax
  char v17; // cl
  __int64 v18; // rdx
  unsigned int v19; // edx
  unsigned int v20; // ecx
  unsigned __int64 *v21; // rax
  unsigned __int64 v22; // rcx
  __int64 v23; // [rsp-8h] [rbp-18h]
 
  v23 = result;
  v3 = (unsigned int *)a1[31];
  v4 = *v3;
  v5 = (__int64)(v3 + 1);
  a1[31] = (__int64)(v3 + 1);
  v6 = _byteswap_ulong(v4);
  v7 = (unsigned int)v6 >> 29;
  if ( (unsigned int)v6 < 0x20000000 || v7 == 1 && (result = v6 & 0x10000000, (v6 & 0x10000000) == 0) )
  {
    v8 = ((unsigned int)v6 >> 19) & 0x1F;
    if ( (BYTE3(v6) & 1 & (v7 == 1)) != 0 || (v6 & 0xE1000000) == 0 )
    {
      if ( v7 == 1 || (unsigned int)v6 >> 25 == 9 || (unsigned int)v6 >> 25 == 7 )// imm
        v9 = v6 << 50 >> 50;                    // low 14 bits signed
      else
        v9 = v6 & 0x3FFF;                       // low 14 bits unsigned
    }
    else
    {
      v9 = a1[((unsigned int)v6 >> 9) & 0x1F];
    }
    v10 = a1[((unsigned int)v6 >> 14) & 0x1F];
    v11 = (unsigned int)v6 >> 25;
    if ( v7 == 1 )
    {
      switch ( v11 & 7 )
      {
        case 0u:
          result = v10 == v9;
          cout << "SETEQ " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 1u:
          result = v10 != v9;
          cout << "SETNOTEQ " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 2u:
          result = v10 <= v9;
          cout << "SETLE " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 3u:
          result = v10 < v9;
          cout << "SETL " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 4u:
          result = v10 <= (unsigned __int64)v9;
          cout << "SETBE " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 5u:
          result = v10 < (unsigned __int64)v9;
          cout << "SETB " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        default:
LABEL_20:
          result = 0LL;
          a1[v8] = 0LL;
          break;
      }
    }
    else
    {
      printf("r%d ",v8);
      switch ( v11 & 0xF )
      {
        case 0u:
          v12 = v10 | v9;
          cout << "OR " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
        case 1u:
          v12 = v10 ^ v9;
          cout << "XOR " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
           
        case 2u:
          v12 = v10 & v9;
          cout << "AND " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
        case 3u:
          v12 = v10 + v9;
          cout << "ADD " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
        case 4u:
          v18 = v10 - v9;
          cout << "SUB " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 5u:
          v12 = v10 * v9;
          cout << "MUL " << std::hex << v10 << " " << std::hex << v9 << endl;
LABEL_38:
          result = v12;
          a1[v8] = v12;
          return result;
        case 6u:
          result = v10 / (unsigned __int64)v9;
          a1[v8] = v10 / (unsigned __int64)v9;
          cout << "DIV " << std::hex << v10 << " " << std::hex << v9 << endl;
          return result;
        case 7u:
          result = v10 / v9;
          a1[v8] = v10 / v9;
          cout << "IDIV " << std::hex << v10 << " " << std::hex << v9 << endl;
          return result;
        case 8u:
          v18 = v10 % (unsigned __int64)v9;
          cout << "MOD " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 9u:
          v18 = v10 % v9;
          cout << "IMOD " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xAu:
          v18 = v10 << v9;
          cout << "letfRotate " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xBu:
          v18 = v10 >> v9;
          cout << "irightRotate " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xCu:
          v18 = (unsigned __int64)v10 >> v9;
          cout << "rightRotate " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xDu:
          v18 = __ROL8__(v10, v9);
          cout << "ROL8 " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xEu:
          v18 = __ROR8__(v10, v9);
          cout << "ROR8 " << std::hex << v10 << " " << std::hex << v9 << endl;
LABEL_48:
          result = v18;
          a1[v8] = v18;
          break;
        default:
          goto LABEL_20;
      }
    }
    return result;
  }
  if ( v7 == 1 )
  {
    v7 = ((unsigned int)v6 >> 26) & 3;
    if ( v7 == 2 )
    {
      v14 = ((unsigned int)v6 >> 20) & 0x1F;
      v15 = (__int64 (__fastcall *)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64))a1[v14];
      if ( (unsigned __int64)v15 < a1[32] || (unsigned __int64)v15 >= a1[33] )
      {
        result = v15(*a1, a1[1], a1[2], a1[3], a1[4], a1[5], v23);
        cout << "call_out" << endl;
        *a1 = result;
        a1[31] = v5;
      }
      else
      {
        cout << "call in" << endl;
        v16 = a1[30];                           // PUSH
        *(_QWORD *)(v16 - 8) = v5;              // call
        result = v16 - 8;
        a1[31] = a1[v14];
        a1[30] = result;
      }
      return result;
    }
    if ( !v7 )
    {
      cout << "ret" << endl;
      v13 = (__int64 *)a1[30];                  // pop
      a1[31] = *v13;                            // ret
      result = (__int64)(v13 + 1);
      a1[30] = result;
      return result;
    }
    if ( (v6 & 0x2000000) != 0 )                // check 26 bit
    {
      cout << "jump" << endl;
      result = 37LL;
      v17 = 39;
    }
    else
    {
      cout << "jcc" << endl;
      result = ((unsigned int)v6 >> 20) & 0x1F; // 21-25
      if ( !a1[result] )
        goto LABEL_52;
      result = 42LL;
      v17 = 44;
    }
    a1[31] = (__int64)v3 + ((__int64)((unsigned __int64)(unsigned int)v6 << v17) >> result);
LABEL_52:
    if ( (v6 & 0x2000000) == 0 )
      return result;
  }
  if ( v7 == 2 )
  {
    if ( (((unsigned int)v6 >> 27) & 3) != 0 )  // 2829
    {
      v19 = ((unsigned int)v6 >> 21) & 0x1F;    // 22-26
      v20 = WORD1(v6) & 0x1F;
      result = (unsigned __int16)v6 - 0x8000LL;
      if ( (v6 & 0x8000u) == 0LL )
        result = (unsigned __int16)v6;
      if ( (((unsigned int)v6 >> 27) & 3) == 1 )
      {
        printf("load r%d  [r%d+0x%x]\n",v19, v20, result);
        result = *(_QWORD *)(a1[v20] + result);
        a1[v19] = result;                       // load
         
      }
      else
      {
        switch ( ((unsigned int)v6 >> 26) & 3 ) // store
        {
          case 0u:
            printf("stb [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_BYTE *)(a1[v20] + result) = a1[v19];
            break;
          case 1u:
            printf("stw [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_WORD *)(a1[v20] + result) = a1[v19];
            break;
          case 2u:
            printf("stdw [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_DWORD *)(a1[v20] + result) = a1[v19];
            break;
          case 3u:
            printf("stqw [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_QWORD *)(a1[v20] + result) = a1[v19];
            break;
        }
      }
    }
    else
    {
      v21 = (unsigned __int64 *)a1[31];
      v22 = _byteswap_uint64(*v21);
      result = (__int64)(v21 + 1);
      a1[31] = result;
      a1[WORD1(v6) & 0x1F] = v22;
      printf("speical_load r%d  0x%x\n",WORD1(v6) & 0x1f,v22);
    }
  }
  return result;
}
 
__int64 __fastcall VM_1(__int64 *a1) // little lfsr
{
  unsigned int *v2; // rcx
  __int64 result; // rax
  _DWORD *v4; // r14
  int v5; // edx
  unsigned int v6; // edx
  unsigned int v7; // ebp
  unsigned int v8; // edi
  __int64 v9; // rsi
  __int64 v10; // rcx
  __int64 v11; // rdx
  unsigned int v12; // eax
  __int64 v13; // rcx
  __int64 v14; // rax
  __int64 v15; // rax
  __int64 (__fastcall *v16)(__int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v17; // rcx
  unsigned int v18; // r8d
  int v19; // edx
  __int64 v20; // rsi
  __int64 v21; // rdx
  unsigned int v22; // esi
  unsigned int v23; // edx
  __int64 v24; // rcx
  _QWORD *v25; // rcx
  __int64 v26; // rsi
  int v27; // edi
  unsigned int v28; // edx
  unsigned __int64 v29; // rdi
 
  v2 = (unsigned int *)a1[31];
  result = *v2;
  v4 = v2 + 1;
  a1[31] = (__int64)(v2 + 1);
  v5 = *((_DWORD *)a1 + 68);
  if ( !v5 )
  {
    *((_DWORD *)a1 + 68) = result;
    return result;
  }
  v6 = v5 ^ (v5 << 13) ^ ((v5 ^ (unsigned int)(v5 << 13)) >> 17);
  v7 = v6 ^ (32 * v6);
  *((_DWORD *)a1 + 68) = v7;
  result = v7 ^ (unsigned int)result;
  v8 = (unsigned int)result >> 29;
  if ( (unsigned int)result < 0x20000000 || v8 == 1 && (result & 0x10000000) == 0 )
  {
    v9 = ((unsigned int)result >> 19) & 0x1F;
    if ( (result & 0xE1000000) == 0 || (BYTE3(result) & 1 & (v8 == 1)) != 0 )
    {
      if ( v8 == 1 || (unsigned int)result >> 25 == 9 || (unsigned int)result >> 25 == 7 )
        v10 = result << 50 >> 50;
      else
        v10 = result & 0x3FFF;
    }
    else
    {
      v10 = a1[((unsigned int)result >> 9) & 0x1F];
    }
    v11 = a1[((unsigned int)result >> 14) & 0x1F];
    v12 = (unsigned int)result >> 25;
    if ( v8 == 1 )
    {
      switch ( v12 & 7 )
      {
        case 0u:
          result = v11 == v10;
          a1[v9] = result;
          break;
        case 1u:
          result = v11 != v10;
          cout << "SETNOTEQ " <<  std::hex << v11 << " " << std::hex << v10 <<endl;
          a1[v9] = result;
          break;
        case 2u:
          result = v11 <= v10;
          a1[v9] = result;
          break;
        case 3u:
          result = v11 < v10;
          a1[v9] = result;
          break;
        case 4u:
          result = v11 <= (unsigned __int64)v10;
          a1[v9] = result;
          break;
        case 5u:
          result = v11 < (unsigned __int64)v10;
          a1[v9] = result;
          break;
        default:
          goto LABEL_22;
      }
    }
    else
    {
      switch ( v12 & 0xF )
      {
        case 0u:
          v13 = v11 | v10;
          goto LABEL_40;
        case 1u:
          v13 = v11 ^ v10;
          cout << "XOR " << std::hex << v11 << " " << std::hex << v10 << endl;
          goto LABEL_40;
        case 2u:
          v13 = v11 & v10;
          goto LABEL_40;
        case 3u:
          v13 = v11 + v10;
          goto LABEL_40;
        case 4u:
          v21 = v11 - v10;
          goto LABEL_50;
        case 5u:
          v13 = v11 * v10;
LABEL_40:
          result = v13;
          a1[v9] = v13;
          return result;
        case 6u:
          result = v11 / (unsigned __int64)v10;
          a1[v9] = v11 / (unsigned __int64)v10;
          return result;
        case 7u:
          result = v11 / v10;
          a1[v9] = v11 / v10;
          return result;
        case 8u:
          v21 = v11 % (unsigned __int64)v10;
          goto LABEL_50;
        case 9u:
          v21 = v11 % v10;
          goto LABEL_50;
        case 0xAu:
          v21 = v11 << v10;
          goto LABEL_50;
        case 0xBu:
          v21 = v11 >> v10;
          goto LABEL_50;
        case 0xCu:
          v21 = (unsigned __int64)v11 >> v10;
          goto LABEL_50;
        case 0xDu:
          v21 = __ROL8__(v11, v10);
          goto LABEL_50;
        case 0xEu:
          v21 = __ROR8__(v11, v10);
LABEL_50:
          result = v21;
          a1[v9] = v21;
          break;
        default:
LABEL_22:
          result = 0LL;
          a1[v9] = 0LL;
          break;
      }
    }
    return result;
  }
  if ( v8 == 1 )
  {
    v8 = ((unsigned int)result >> 26) & 3;
    if ( v8 == 2 )
    {
      v15 = ((unsigned int)result >> 20) & 0x1F;
      v16 = (__int64 (__fastcall *)(__int64, __int64, __int64, __int64, __int64, __int64))a1[v15];
      if ( (unsigned __int64)v16 < a1[32] || (unsigned __int64)v16 >= a1[33] )
      {
        result = v16(*a1, a1[1], a1[2], a1[3], a1[4], a1[5]);
        *a1 = result;
        *((_DWORD *)a1 + 68) = v7;
        a1[31] = (__int64)v4;
      }
      else
      {
        v17 = a1[30];
        *(_QWORD *)(v17 - 8) = v7;
        *((_DWORD *)a1 + 68) = 0;
        *(_QWORD *)(v17 - 16) = a1[31];
        result = a1[v15];
        a1[31] = result;
        a1[30] = v17 - 16;
      }
      return result;
    }
    if ( !v8 )
    {
      v14 = a1[30];
      a1[31] = *(_QWORD *)v14;
      *((_DWORD *)a1 + 68) = *(_DWORD *)(v14 + 8);
      result = v14 + 16;
      a1[30] = result;
      return result;
    }
    v18 = v7 ^ (v7 << 13) ^ ((v7 ^ (v7 << 13)) >> 17) ^ (32 * (v7 ^ (v7 << 13) ^ ((v7 ^ (v7 << 13)) >> 17)));
    v19 = v18 ^ *v4;
    *((_DWORD *)a1 + 68) = v18;
    if ( (result & 0x2000000) != 0 )
    {
      v20 = result << 39 >> 37;
    }
    else
    {
      if ( !a1[((unsigned int)result >> 20) & 0x1F] )
      {
        a1[31] = (__int64)(v2 + 2);
        if ( (result & 0x2000000) == 0 )
          return result;
        goto LABEL_54;
      }
      v20 = result << 44 >> 42;
    }
    a1[31] = (__int64)v2 + v20;
    *((_DWORD *)a1 + 68) = v19;
    if ( (result & 0x2000000) == 0 )
      return result;
  }
LABEL_54:
  if ( v8 == 2 )
  {
    if ( (((unsigned int)result >> 27) & 3) != 0 )
    {
      v22 = ((unsigned int)result >> 21) & 0x1F;
      v23 = WORD1(result) & 0x1F;
      v24 = (unsigned __int16)result - 0x8000LL;
      if ( (result & 0x8000u) == 0LL )
        v24 = (unsigned __int16)result;
      if ( (((unsigned int)result >> 27) & 3) == 1 )
      {
        result = *(_QWORD *)(a1[v23] + v24);
        a1[v22] = result;
      }
      else
      {
        switch ( ((unsigned int)result >> 26) & 3 )
        {
          case 0u:
            result = LOBYTE(a1[v22]);
            *(_BYTE *)(a1[v23] + v24) = result;
            break;
          case 1u:
            result = LOWORD(a1[v22]);
            *(_WORD *)(a1[v23] + v24) = result;
            break;
          case 2u:
            result = LODWORD(a1[v22]);
            *(_DWORD *)(a1[v23] + v24) = result;
            break;
          case 3u:
            result = a1[v22];
            *(_QWORD *)(a1[v23] + v24) = result;
            break;
        }
      }
    }
    else
    {
      result = WORD1(result) & 0x1F;
      v25 = (_QWORD *)a1[31];
      v26 = *((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)));
      v27 = v26 ^ ((*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)))) << 13) ^ (((unsigned int)v26 ^ ((*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)))) << 13)) >> 17);
      v28 = v27 ^ (32 * v27);
      v29 = *v25 ^ (v26 | ((unsigned __int64)v28 << 32));
      *((_DWORD *)a1 + 68) = v28;
      a1[31] = (__int64)(v25 + 1);
      a1[result] = v29;
      printf("speical_load r%d  0x%x\n",result,v29);
    }
  }
  return result;
}
 
__int64 __fastcall VM_2(__int64 *a1) // little no lfsr
{
  __int64 result; // rax
  unsigned int *v3; // rdx
  __int64 v4; // rdi
  __int64 v5; // r14
  unsigned int v6; // r8d
  __int64 v7; // rsi
  __int64 v8; // rcx
  __int64 v9; // rdx
  unsigned int v10; // edi
  __int64 v11; // rcx
  __int64 *v12; // rax
  __int64 v13; // rdi
  __int64 (__fastcall *v14)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v15; // rax
  char v16; // cl
  __int64 v17; // rdx
  unsigned int v18; // edx
  unsigned int v19; // ecx
  __int64 *v20; // rax
  __int64 v21; // rcx
  __int64 v22; // [rsp-8h] [rbp-18h]
 
  v22 = result;
  v3 = (unsigned int *)a1[31];
  v4 = *v3;
  v5 = (__int64)(v3 + 1);
  a1[31] = (__int64)(v3 + 1);
  v6 = (unsigned int)v4 >> 29;
  if ( (unsigned int)v4 < 0x20000000 || v6 == 1 && (result = v4 & 0x10000000, (v4 & 0x10000000) == 0) )
  {
    v7 = ((unsigned int)v4 >> 19) & 0x1F;
    if ( (v4 & 0xE1000000) == 0 || (BYTE3(v4) & 1 & (v6 == 1)) != 0 )
    {
      if ( v6 == 1 || (unsigned int)v4 >> 25 == 9 || (unsigned int)v4 >> 25 == 7 )
        v8 = v4 << 50 >> 50;
      else
        v8 = v4 & 0x3FFF;
    }
    else
    {
      v8 = a1[((unsigned int)v4 >> 9) & 0x1F];
    }
    printf("r%d=",((unsigned int)v4 >> 19) & 0x1F);
    v9 = a1[((unsigned int)v4 >> 14) & 0x1F];
    v10 = (unsigned int)v4 >> 25;
    if ( v6 == 1 )
    {
      switch ( v10 & 7 )
      {
        case 0u:
          result = v9 == v8;
          printf("SETEQ r%d(%llx) r%d(%llx)\n",((unsigned int)v4 >> 14) & 0x1F,a1[0],((unsigned int)v4 >> 9) & 0x1F,a1[1]);
          a1[v7] = result;
          break;
        case 1u:
          result = v9 != v8;
          cout << "SETNOTEQ " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 2u:
          result = v9 <= v8;
          cout << "SETLE " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 3u:
          result = v9 < v8;
          cout << "SETL " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 4u:
          result = v9 <= (unsigned __int64)v8;
          cout << "SETBE " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 5u:
          result = v9 < (unsigned __int64)v8;
          cout << "SETB " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        default:
          goto LABEL_20;
      }
    }
    else
    {
      switch ( v10 & 0xF )
      {
        case 0u:
          v11 = v9 | v8;
          cout << "OR " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 1u:
          v11 = v9 ^ v8;
          cout << "XOR " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 2u:
          v11 = v9 & v8;
          cout << "AND " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 3u:
          v11 = v9 + v8;
          cout << "ADD " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 4u:
          v17 = v9 - v8;
          cout << "SUB " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 5u:
          v11 = v9 * v8;
          cout << "MUL " << std::hex << v9 << " " << std::hex << v8 << endl;
LABEL_38:
          result = v11;
          a1[v7] = v11;
          return result;
        case 6u:
          result = v9 / (unsigned __int64)v8;
          a1[v7] = v9 / (unsigned __int64)v8;
          cout << "DIV " << std::hex << v9 << " " << std::hex << v8 << endl;
          return result;
        case 7u:
          result = v9 / v8;
          a1[v7] = v9 / v8;
          cout << "iDIV " << std::hex << v9 << " " << std::hex << v8 << endl;
          return result;
        case 8u:
          v17 = v9 % (unsigned __int64)v8;
          cout << "MOD " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 9u:
          v17 = v9 % v8;
          cout << "IMOD " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xAu:
          v17 = v9 << v8;
          cout << "<< " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xBu:
          v17 = v9 >> v8;
          cout << "i>> " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xCu:
          v17 = (unsigned __int64)v9 >> v8;
          cout << ">> " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xDu:
          v17 = __ROL8__(v9, v8);
          cout << "ROL8 " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xEu:
          v17 = __ROR8__(v9, v8);
          cout << "ROR8 " << std::hex << v9 << " " << std::hex << v8 << endl;
LABEL_48:
          result = v17;
          a1[v7] = v17;
          break;
        default:
LABEL_20:
          result = 0LL;
          a1[v7] = 0LL;
          break;
      }
    }
    return result;
  }
  if ( v6 == 1 )
  {
    v6 = ((unsigned int)v4 >> 26) & 3;
    if ( v6 == 2 )
    {
      v13 = ((unsigned int)v4 >> 20) & 0x1F;
      v14 = (__int64 (__fastcall *)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64))a1[v13];
      if ( (unsigned __int64)v14 < a1[32] || (unsigned __int64)v14 >= a1[33] )
      {
        result = v14(*a1, a1[1], a1[2], a1[3], a1[4], a1[5], v22);
        *a1 = result;
        cout << "call_out ";
        if((unsigned __int64)v14 == (unsigned __int64)&malloc){
           cout << "malloc ";
        }
        else{
          cout << "sub_880 ";
        }
        cout << "load r0 0x" << std::hex << result << endl;
        a1[31] = v5;
      }
      else
      {
        cout << "call in" << endl;
        v15 = a1[30];
        *(_QWORD *)(v15 - 8) = v5;
        result = v15 - 8;
        a1[31] = a1[v13];
        a1[30] = result;
      }
      return result;
    }
    if ( !v6 )
    {
      cout << "ret" << endl;
      v12 = (__int64 *)a1[30];
      a1[31] = *v12;
      result = (__int64)(v12 + 1);
      a1[30] = result;
      return result;
    }
    if ( (v4 & 0x2000000) != 0 )
    {
      cout << "jump" << endl;
      result = 37LL;
      v16 = 39;
    }
    else
    {
      cout << "jcc" << endl;
      result = ((unsigned int)v4 >> 20) & 0x1F;
      if ( !a1[result] )
        goto LABEL_52;
      result = 42LL;
      v16 = 44;
    }
    a1[31] = (__int64)v3 + ((__int64)((unsigned __int64)(unsigned int)v4 << v16) >> result);
LABEL_52:
    if ( (v4 & 0x2000000) == 0 )
      return result;
  }
  if ( v6 == 2 )
  {
    if ( (((unsigned int)v4 >> 27) & 3) != 0 )
    {
      v18 = ((unsigned int)v4 >> 21) & 0x1F;
      v19 = WORD1(v4) & 0x1F;
      result = (unsigned __int16)v4 - 0x8000LL;
      if ( (v4 & 0x8000u) == 0LL )
        result = (unsigned __int16)v4;
      if ( (((unsigned int)v4 >> 27) & 3) == 1 )
      {
        printf("load r%d  [r%d+0x%x](%llx)\n",v18, v19, result,*(_QWORD *)(a1[v19] + result));
        result = *(_QWORD *)(a1[v19] + result);
        a1[v18] = result;
      }
      else
      {
        switch ( ((unsigned int)v4 >> 26) & 3 )
        {
          case 0u:
         printf("stb [r%d(0x%llx) + 0x%x] r%d(0x%x)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_BYTE *)(a1[v19] + result) = a1[v18];
            break;
          case 1u:
          printf("stw [r%d(0x%llx) + 0x%x] r%d(0x%x)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_WORD *)(a1[v19] + result) = a1[v18];
            break;
          case 2u:
          printf("stdw [r%d(0x%llx) + 0x%x] r%d(0x%x)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_DWORD *)(a1[v19] + result) = a1[v18];
            break;
          case 3u:
          printf("stqw [r%d(0x%llx) + 0x%x] r%d(0x%llx)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_QWORD *)(a1[v19] + result) = a1[v18];
            break;
        }
      }
    }
    else
    {
      v20 = (__int64 *)a1[31];
      v21 = *v20;
      result = (__int64)(v20 + 1);
      a1[31] = result;
      a1[WORD1(v4) & 0x1F] = v21;
      printf("speical_load r%d  0x%llx\n",WORD1(v4) & 0x1F,v21);
    }
  }
  return result;
}
 
__int64 __fastcall VM_3(__int64 *a1) //big lfsr
{
  unsigned int *v2; // rcx
  unsigned int v3; // eax
  unsigned int *v4; // r14
  int result; // rax
  int v6; // edx
  unsigned int v7; // edx
  unsigned int v8; // ebp
  unsigned int v9; // edi
  __int64 v10; // rsi
  __int64 v11; // rcx
  __int64 v12; // rdx
  unsigned int v13; // eax
  __int64 v14; // rcx
  __int64 v15; // rax
  __int64 v16; // rax
  __int64 (__fastcall *v17)(__int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v18; // rcx
  unsigned __int32 v19; // esi
  unsigned int v20; // edx
  int v21; // edx
  __int64 v22; // rsi
  __int64 v23; // rdx
  unsigned int v24; // esi
  unsigned int v25; // edx
  __int64 v26; // rcx
  unsigned __int64 *v27; // rcx
  unsigned __int64 v28; // rdx
  __int64 v29; // rdi
  unsigned int v30; // esi
  __int64 v31; // rsi
 
  v2 = (unsigned int *)a1[31];
  v3 = *v2;
  v4 = v2 + 1;
  a1[31] = (__int64)(v2 + 1);
  result = _byteswap_ulong(v3);
  v6 = *((_DWORD *)a1 + 68);
  if ( !v6 )
  {
    *((_DWORD *)a1 + 68) = result;
    return result;
  }
  v7 = v6 ^ (v6 << 13) ^ ((v6 ^ (unsigned int)(v6 << 13)) >> 17);
  v8 = v7 ^ (32 * v7);
  *((_DWORD *)a1 + 68) = v8;
  result = v8 ^ (unsigned int)result;
  int op = result;
  v9 = (unsigned int)result >> 29;
  if ( (unsigned int)result < 0x20000000 || v9 == 1 && (result & 0x10000000) == 0 )
  {
    v10 = ((unsigned int)result >> 19) & 0x1F;
    if ( (BYTE3(result) & 1 & (v9 == 1)) != 0 || (result & 0xE1000000) == 0 )
    {
      if ( v9 == 1 || (unsigned int)result >> 25 == 9 || (unsigned int)result >> 25 == 7 )
        v11 = result << 50 >> 50;
      else
        v11 = result & 0x3FFF;
    }
    else
    {
      v11 = a1[((unsigned int)result >> 9) & 0x1F];
    }
    v12 = a1[((unsigned int)result >> 14) & 0x1F];
    v13 = (unsigned int)result >> 25;
    if ( v9 == 1 )
    {
      switch ( v13 & 7 )
      {
        case 0u:
          result = v12 == v11;
          a1[v10] = result;
          break;
        case 1u:
          result = v12 != v11;
          a1[v10] = result;
          break;
        case 2u:
          result = v12 <= v11;
          a1[v10] = result;
          break;
        case 3u:
          result = v12 < v11;
          a1[v10] = result;
          break;
        case 4u:
          result = v12 <= (unsigned __int64)v11;
          a1[v10] = result;
          break;
        case 5u:
          result = v12 < (unsigned __int64)v11;
          a1[v10] = result;
          break;
        default:
LABEL_22:
          result = 0LL;
          a1[v10] = 0LL;
          break;
      }
    }
    else
    {
      switch ( v13 & 0xF )
      {
        case 0u:
          v14 = v12 | v11;
          cout << "OR " << std::hex << v12 << " " << std::hex << v11 << endl;
          goto LABEL_40;
        case 1u:
          v14 = v12 ^ v11;
          cout << "XOR " << std::hex << v12 << " " << std::hex << v11 << endl;
          goto LABEL_40;
        case 2u:
          v14 = v12 & v11;
          goto LABEL_40;
        case 3u:
          v14 = v12 + v11;
          goto LABEL_40;
        case 4u:
          v23 = v12 - v11;
          goto LABEL_50;
        case 5u:
          v14 = v12 * v11;
LABEL_40:
          result = v14;
          a1[v10] = v14;
          return result;
        case 6u:
          result = v12 / (unsigned __int64)v11;
          a1[v10] = v12 / (unsigned __int64)v11;
          return result;
        case 7u:
          result = v12 / v11;
          a1[v10] = v12 / v11;
          return result;
        case 8u:
          v23 = v12 % (unsigned __int64)v11;
          goto LABEL_50;
        case 9u:
          v23 = v12 % v11;
          goto LABEL_50;
        case 0xAu:
          v23 = v12 << v11;
          goto LABEL_50;
        case 0xBu:
          v23 = v12 >> v11;
          goto LABEL_50;
        case 0xCu:
          v23 = (unsigned __int64)v12 >> v11;
          goto LABEL_50;
        case 0xDu:
          v23 = __ROL8__(v12, v11);
          goto LABEL_50;
        case 0xEu:
          v23 = __ROR8__(v12, v11);
LABEL_50:
          result = v23;
          a1[v10] = v23;
          break;
        default:
          goto LABEL_22;
      }
    }
    return result;
  }
  if ( v9 == 1 )
  {
    v9 = ((unsigned int)result >> 26) & 3;
    if ( v9 == 2 )
    {
      v16 = ((unsigned int)result >> 20) & 0x1F;
      v17 = (__int64 (__fastcall *)(__int64, __int64, __int64, __int64, __int64, __int64))a1[v16];
      if ( (unsigned __int64)v17 < a1[32] || (unsigned __int64)v17 >= a1[33] )
      {
        result = v17(*a1, a1[1], a1[2], a1[3], a1[4], a1[5]);
        *a1 = result;
        *((_DWORD *)a1 + 68) = v8;
        a1[31] = (__int64)v4;
      }
      else
      {
        v18 = a1[30];
        *(_QWORD *)(v18 - 8) = v8;
        *((_DWORD *)a1 + 68) = 0;
        *(_QWORD *)(v18 - 16) = a1[31];
        result = a1[v16];
        a1[31] = result;
        a1[30] = v18 - 16;
      }
      return result;
    }
    if ( !v9 )
    {
      v15 = a1[30];
      a1[31] = *(_QWORD *)v15;
      *((_DWORD *)a1 + 68) = *(_DWORD *)(v15 + 8);
      result = v15 + 16;
      a1[30] = result;
      return result;
    }
    v19 = _byteswap_ulong(*v4);
    v20 = v8 ^ (v8 << 13) ^ ((v8 ^ (v8 << 13)) >> 17) ^ (32 * (v8 ^ (v8 << 13) ^ ((v8 ^ (v8 << 13)) >> 17)));
    *((_DWORD *)a1 + 68) = v20;
    v21 = v19 ^ v20;
    if ( (result & 0x2000000) != 0 )
    {
      v22 = result << 39 >> 37;
    }
    else
    {
      if ( !a1[((unsigned int)result >> 20) & 0x1F] )
      {
        a1[31] = (__int64)(v2 + 2);
        if ( (result & 0x2000000) == 0 )
          return result;
        goto LABEL_54;
      }
      v22 = result << 44 >> 42;
    }
    a1[31] = (__int64)v2 + v22;
    *((_DWORD *)a1 + 68) = v21;
    if ( (result & 0x2000000) == 0 )
      return result;
  }
LABEL_54:
  if ( v9 == 2 )
  {
    if ( (((unsigned int)result >> 27) & 3) != 0 )
    {
      v24 = ((unsigned int)result >> 21) & 0x1F;
      v25 = WORD1(result) & 0x1F;
      v26 = (unsigned __int16)result - 0x8000LL;
      if ( (result & 0x8000u) == 0LL )
        v26 = (unsigned __int16)result;
      if ( (((unsigned int)result >> 27) & 3) == 1 )
      {
        result = *(_QWORD *)(a1[v25] + v26);
        a1[v24] = result;
      }
      else
      {
        switch ( ((unsigned int)result >> 26) & 3 )
        {
          case 0u:
            result = LOBYTE(a1[v24]);
            // printf("stb [r%d(0x%llx) + 0x%x] %d\n",v25,a1[v25],v26,result);
            *(_BYTE *)(a1[v25] + v26) = result;
            lut[v26] = result;
            break;
          case 1u:
            result = LOWORD(a1[v24]);
            *(_WORD *)(a1[v25] + v26) = result;
            break;
          case 2u:
            result = LODWORD(a1[v24]);
            // printf("stb [r%d(0x%llx) + 0x%x] %d\n",v25,a1[v25],v26,result);
            *(_DWORD *)(a1[v25] + v26) = result;
            break;
          case 3u:
            result = a1[v24];
            *(_QWORD *)(a1[v25] + v26) = result;
            break;
        }
      }
    }
    else
    {
      v27 = (unsigned __int64 *)a1[31];
      v28 = _byteswap_uint64(*v27);
      result = WORD1(result) & 0x1F;
      v29 = *((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)));
      v30 = v29 ^ ((*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)))) << 13);
      v31 = v30 ^ (v30 >> 17) ^ (32 * (v30 ^ (v30 >> 17)));
      *((_DWORD *)a1 + 68) = v31;
      a1[31] = (__int64)(v27 + 1);
      a1[result] = v28 ^ ((v29 << 32) | v31);
    }
  }
  return result;
}
 
uint64_t *VM_context[35] = {};
// uint32_t vm_op[] ={1976427875, 1351343259, 1612664318, 2433205737, 3046975632, 626481909, 3975013335, 1283834271, 383842469, 2798764607, 3696776187, 4170144409, 3927840730, 140005937, 296365805, 3006110615, 114327633, 907844063, 3022702211, 2094777016, 380884373, 2122175971, 4071574588, 3938022081, 1291573375, 2485753974, 1637416006, 4225852075, 2071585308, 2944719709, 1829101233, 1110572158, 1226074819, 3195242372, 3700808210, 2358660209, 773180593, 1613267327, 3521386025, 3193100902, 3286298012, 125790494, 3739056418, 868714240, 449803732, 1162871038, 3284082516, 1132005886, 219434964, 3270653390, 2439627356, 2288841484, 2833712748, 3361731726, 24685703, 212809789, 1942064915, 1678065084, 2333851310, 3395827190, 2523335453, 2394389613, 4165418664, 2903638873, 2164667506, 1851059343, 3730292360, 2165542698, 751933430, 3570644408, 3807533179, 3001106151, 2765902712, 15013466, 3163343218, 1901037579, 2067435631, 2686188370, 102989091, 449875783, 3845053741, 3789950633, 1049668332, 3217047880, 3254166107, 2081737864, 1762950497, 3288320157, 2445723366, 3485236189, 2829750486, 1316492443, 1828739766, 1216936220, 102664883, 860567771, 666288825, 2690740270, 3401968968, 3296031195, 2576567149, 1404238554, 2460817723, 1316752377, 1142163556, 634933654, 4139592741, 3944930753, 4201007861, 2565907881, 3515769792, 509629095, 1914959267, 3413268951, 3866941944, 2570884892, 130754488, 3476344395, 2941373444, 954938226, 3115950279, 1910313443, 3539974380, 1152694459, 161957162, 2027389803, 3256243228, 2202601580, 350258403, 420305581, 4158379088, 4147748253, 3782528332, 415810441, 3851463627, 1900178605, 1706351520, 12261950, 710745188, 1618400571, 3758136596, 3588723718, 4019777524, 5730523, 2711857345, 1593930573, 1238076068, 1565171299, 1746162131, 3076237801, 3529845435, 614467621, 4127683123, 2985137187, 712499802, 2258687668, 4011166297, 2007954013, 2461237807, 4051514471, 3788240089, 3981309296, 2155578576, 4274358913, 1044119006, 1797312874, 471180725, 2668645079, 2959703070, 1449104858, 1351292286, 1380416001, 1017187931, 2488176202, 1607611593, 2568349725, 269334228, 1322262420, 640788365, 854822713, 3479197977, 336484541, 301774093, 3685430230, 3430961642, 3294824626, 572559954, 3106371047, 3554052626, 2863905378, 1451040142, 2715236917, 1748692918, 815704389, 1245897369, 3529752260, 679872560, 1370670363, 3128954428, 194210382, 4215132095, 726643573, 2759775927, 1682022233, 1696861348, 1056704786, 623808445, 1817613680, 1538512307, 304297361, 1635128254, 3900760555, 1476473223, 1018071399, 3189200443, 1836668397, 1960361774, 2710665026, 2884304536, 2635971280, 1561188051, 799781246, 92290065, 955077766, 3321361990, 3940059321, 1156565456, 4114932330, 1786488397, 3365007865, 1100625809, 936833548, 2979980210, 4229890500, 533880377, 925117089, 1826796659, 2547436593, 2610515177, 754195478, 2428611002, 108115699, 3195984300, 4279480768, 1152860825, 1863578395, 146548328, 1840985960, 370213461, 3867179729, 2930101134, 1122732950, 1385093301, 588295429, 1261484657, 1455895265, 1353137825, 1067233262, 1297469336, 1443126045, 1939277798, 633014186, 3830243538, 775906197, 3793847937, 2900344786, 1930660129, 3339283805, 1461562198, 3800375221, 1034336979, 2989177160, 2045478884, 1530852102, 551868518, 833271568, 1348848761, 667249786, 2936189850, 285406341, 1116977808, 3978840504, 3068398612, 718431417, 2728910183, 921714326, 3769690485, 1535139857, 3798540057, 1855735377, 3013788154, 4197447741, 707913497, 3179598374, 2522184863, 3887899534, 1106283519, 3830502288, 3445392769, 730899274, 390027277, 1329558143, 275693576, 3916701319, 1213562715, 1448912296, 4146302020, 615974141, 2100384564, 1655463229, 3594536881, 2283379794, 2546644164, 3034885571, 277358008, 3980187918, 2103533347, 3054831619, 3402918421, 2752064401, 3307441361, 2350121419, 3535283195, 254933546, 203278039, 4077109433, 4211117231, 1874972668, 62911161, 599812366, 1510336986, 2602272400, 855339023, 2378668339, 931522116, 2691745340, 1420807049, 2708482394, 2332824275, 3707675361, 2761457235, 651371181, 429313852, 1471549740, 3542725217, 3599514006, 2385987184, 2979421507, 3056159203, 2380437801, 1349115791, 4165110556, 2329890254, 3592472800, 945181790, 3006540133, 1383837718, 1867099648, 2322736858, 3921766584, 3532443784, 2518731666, 1166480143, 2792859296, 3602109062, 4002587877, 1254091688, 3571947805, 1441661741, 1582185579, 670679198, 891293598, 947512857, 2600189485, 3444708488, 2623533162, 1763844706, 3636180936, 3464387303, 1056783259, 2125213268, 2455875221, 1332525393, 1319767510, 2411771964, 1868983187, 1621258024, 2646446968, 685295305, 3778207848, 1809969305, 3080879647, 3548738700, 962705829, 421938331, 2085543119, 523486628, 1215521652, 2034761339, 3461503728, 2471650520, 1192339508, 3818188999, 333418330, 3085733036, 1150209842, 3197148033, 2995955619, 3877787727, 1123794442, 1727832910, 4211330100, 208769819, 3649236463, 3104632734, 1657641648, 2775384300, 2690320885, 3231005233, 2166903089, 2140359358, 1043298635, 3914777503, 1640666740, 2636542005, 2417480486, 1380143074, 1173041005, 3097732539, 623693782, 2978779769, 443041291, 2946671661, 2844290215, 4220230618, 1503471348, 665683958, 3134492485, 2009290111, 3426629379, 534377307, 518299929, 2198340002, 1834404033, 1065468552, 4092711909, 764324806, 2901802363, 2452610125, 2712933359, 694886536, 1271040013, 1862142351, 3299906953, 1975076334, 1001504596, 2484425936, 2679339055, 2401030456, 1611021906, 1085535213, 4147039947, 3584583917, 383184342, 3249397962, 507169557, 35340291, 1450476838, 3840114600, 1602399221, 1089751835, 2145786364, 4041202427, 4109495431, 2527477250, 1560142377, 1837578652, 1808661526, 1299374663, 986565150, 3329195914, 1234758580, 2347279129, 3226408400, 2283658599, 3054740073, 1395572083, 3333841720, 1249219001, 656682067, 266554370, 2568096635, 485770513, 1349780853, 3078283914, 3799628881, 4280716332, 1633676419, 1830263082, 3381782820, 754256877, 2155187655, 1873190764, 2284714928, 3170428765, 3709621214, 122043686, 1494935408, 1568900548, 4113005769, 517960156, 2779759669, 3997109150, 1983003883, 2389480438, 2535771608, 672561366, 2033616224, 2042009132, 3037516435, 3225373369, 2209908234, 226424653, 3288949959, 1603318959, 1724629419, 2951514084, 912198427, 1471589204, 2507804994, 38149107, 3992306371, 2279069712, 213979244, 3277221841, 4090877293, 2201702145, 132699456, 427025349, 3966146747, 585410742, 1336227915, 2310964976, 413787785, 3256452950, 1968866743, 4000753537, 1444861975, 2705673868, 3516843675, 1131836880, 3514215189, 2807317813, 631444731, 1758503386, 645321110, 1389336314, 284431831, 3618102503, 719646775, 2545039835, 304479513, 4213119349, 2305190346, 154682538, 2812761913, 1482546777, 631844162, 4054050127, 1164531181, 3989276939, 3263324551, 1370503188, 2693784221, 352106250, 786440075, 2429447376, 2022937001, 1607349664, 4148609264, 1153818047, 3970449212, 1218584233, 4097117707, 418894655, 2081597627, 2767007972, 3605553748, 3099373403, 3291767689, 393889897, 952465676, 1206685658, 2883904375, 3642302740, 3119229219, 3726804543, 1548873331, 2523391537, 2557398516, 1473029336, 1019096754, 2432653575, 3509505769, 1728861234, 2471189853, 2431092479, 1526585802, 3346184365, 536927635, 3168541128, 2604483109, 2085935216, 1082083765, 4155611789, 95955942, 3667132573, 1086915312, 3736694213, 4111004249, 3398619340, 2553566595, 928751317, 2339079072, 460666010, 80584458, 491019742, 2456251340, 369776954, 3540814068, 3887147804, 3434058825, 3001551096, 2292526794, 607773318, 2276948120, 247335351, 2697667605, 3708134991, 2482947853, 898780984, 1988741127, 1938251904, 337591520, 401067696, 3240706405, 3831635463, 1161394882, 121646438, 2585624199, 1788675476, 3729774771, 1149066903, 2899232714, 3870573595, 3928339543, 3829877435, 1396804105, 1892179772, 2024212238, 1112390287, 245347464, 1959506234, 1531925529, 1245788559, 724758985, 2244370256, 574368177, 1977157958, 123223131, 845450955, 758150329, 895304849, 3304635462, 3591885291, 678196720};
uint32_t vm_op[] = {1976427875, 1351343259, 1612664318, 2433205737, 3046975632, 626481909, 3975013335, 1283834271, 383842469, 2798764607, 3696776187, 4170144409, 3927840730, 140005937, 296365805, 3006110615, 114327633, 907844063, 3022702211, 2094777016, 380884373, 2122175971, 4071574588, 3938022081, 1291573375, 2485753974, 1637416006, 4225852075, 2071585308, 2944719709, 1829101233, 1110572158, 1226074819, 3195242372, 3700808210, 2358660209, 773180593, 1613267327, 3521386025, 3193100902, 3286298012, 125790494, 3739056418, 868714240, 449803732, 1162871038, 3284082516, 1132005886, 219434964, 3270653390, 2439627356, 2288841484, 2833712748, 3361731726, 24685703, 212809789, 1942064915, 1678065084, 2333851310, 3395827190, 2523335453, 2394389613, 4165418664, 2903638873, 2164667506, 1851059343, 3730292360, 2165542698, 751933430, 3570644408, 3807533179, 3001106151, 2765902712, 15013466, 3163343218, 1901037579, 2067435631, 2686188370, 102989091, 449875783, 3845053741, 3789950633, 1049668332, 3217047880, 3254166107, 2081737864, 1762950497, 3288320157, 2445723366, 3485236189, 2829750486, 1316492443, 1828739766, 1216936220, 102664883, 860567771, 666288825, 2690740270, 3401968968, 3296031195, 2576567149, 1404238554, 2460817723, 1316752377, 1142163556, 634933654, 4139592741, 3944930753, 4201007861, 2565907881, 3515769792, 509629095, 1914959267, 3413268951, 3866941944, 2570884892, 130754488, 3476344395, 2941373444, 954938226, 3115950279, 1910313443, 3539974380, 1152694459, 161957162, 2027389803, 3256243228, 2202601580, 350258403, 420305581, 4158379088, 4147748253, 3782528332, 415810441, 3851463627, 1900178605, 1706351520, 12261950, 710745188, 1618400571, 3758136596, 3588723718, 4019777524, 5730523, 2711857345, 1593930573, 1238076068, 1565171299, 1746162131, 3076237801, 3529845435, 614467621, 4127683123, 2985137187, 712499802, 2258687668, 4011166297, 2007954013, 2461237807, 4051514471, 3788240089, 3981309296, 2155578576, 4274358913, 1044119006, 1797312874, 471180725, 2668645079, 2959703070, 1449104858, 1351292286, 1380416001, 1017187931, 2488176202, 1607611593, 2568349725, 269334228, 1322262420, 640788365, 854822713, 3479197977, 336484541, 301774093, 3685430230, 3430961642, 3294824626, 572559954, 3106371047, 3554052626, 2863905378, 1451040142, 2715236917, 1748692918, 815704389, 1245897369, 3529752260, 679872560, 1370670363, 3128954428, 194210382, 4215132095, 726643573, 2759775927, 1682022233, 1696861348, 1056704786, 623808445, 1817613680, 1538512307, 304297361, 1635128254, 3900760555, 1476473223, 1018071399, 3189200443, 1836668397, 1960361774, 2710665026, 2884304536, 2635971280, 1561188051, 799781246, 92290065, 955077766, 3321361990, 3940059321, 1156565456, 4114932330, 1786488397, 3365007865, 1100625809, 936833548, 2979980210, 4229890500, 533880377, 925117089, 1826796659, 2547436593, 2610515177, 754195478, 2428611002, 108115699, 3195984300, 4279480768, 1152860825, 1863578395, 146548328, 1840985960, 370213461, 3867179729, 2930101134, 1122732950, 1385093301, 588295429, 1261484657, 1455895265, 1353137825, 1067233262, 1297469336, 1443126045, 1939277798, 633014186, 3830243538, 775906197, 3793847937, 2900344786, 1930660129, 3339283805, 1461562198, 3800375221, 1034336979, 2989177160, 2045478884, 1530852102, 551868518, 833271568, 1348848761, 667249786, 2936189850, 285406341, 1116977808, 3978840504, 3068398612, 718431417, 2728910183, 921714326, 3769690485, 1535139857, 3798540057, 1855735377, 3013788154, 4197447741, 707913497, 3179598374, 2522184863, 3887899534, 1106283519, 3830502288, 3445392769, 730899274, 390027277, 1329558143, 275693576, 3916701319, 1213562715, 1448912296, 4146302020, 615974141, 2100384564, 1655463229, 3594536881, 2283379794, 2546644164, 3034885571, 277358008, 3980187918, 2103533347, 3054831619, 3402918421, 2752064401, 3307441361, 2350121419, 3535283195, 254933546, 203278039, 4077109433, 4211117231, 1874972668, 62911161, 599812366, 1510336986, 2602272400, 855339023, 2378668339, 931522116, 2691745340, 1420807049, 2708482394, 2332824275, 3707675361, 2761457235, 651371181, 429313852, 1471549740, 3542725217, 3599514006, 2385987184, 2979421507, 3056159203, 2380437801, 1349115791, 4165110556, 2329890254, 3592472800, 945181790, 3006540133, 1383837718, 1867099648, 2322736858, 3921766584, 3532443784, 2518731666, 1166480143, 2792859296, 3602109062, 4002587877, 1254091688, 3571947805, 1441661741, 1582185579, 670679198, 891293598, 947512857, 2600189485, 3444708488, 2623533162, 1763844706, 3636180936, 3464387303, 1056783259, 2125213268, 2455875221, 1332525393, 1319767510, 2411771964, 1868983187, 1621258024, 2646446968, 685295305, 3778207848, 1809969305, 3080879647, 3548738700, 962705829, 421938331, 2085543119, 523486628, 1215521652, 2034761339, 3461503728, 2471650520, 1192339508, 3818188999, 333418330, 3085733036, 1150209842, 3197148033, 2995955619, 3877787727, 1123794442, 1727832910, 4211330100, 208769819, 3649236463, 3104632734, 1657641648, 2775384300, 2690320885, 3231005233, 2166903089, 2140359358, 1043298635, 3914777503, 1640666740, 2636542005, 2417480486, 1380143074, 1173041005, 3097732539, 623693782, 2978779769, 443041291, 2946671661, 2844290215, 4220230618, 1503471348, 665683958, 3134492485, 2009290111, 3426629379, 534377307, 518299929, 2198340002, 1834404033, 1065468552, 4092711909, 764324806, 2901802363, 2452610125, 2712933359, 694886536, 1271040013, 1862142351, 3299906953, 1975076334, 1001504596, 2484425936, 2679339055, 2401030456, 1611021906, 1085535213, 4147039947, 3584583917, 383184342, 3249397962, 507169557, 35340291, 1450476838, 3840114600, 1602399221, 1089751835, 2145786364, 4041202427, 4109495431, 2527477250, 1560142377, 1837578652, 1808661526, 1299374663, 986565150, 3329195914, 1234758580, 2347279129, 3226408400, 2283658599, 3054740073, 1395572083, 3333841720, 1249219001, 656682067, 266554370, 2568096635, 485770513, 1349780853, 3078283914, 3799628881, 4280716332, 1633676419, 1830263082, 3381782820, 754256877, 2155187655, 1873190764, 2284714928, 3170428765, 3709621214, 122043686, 1494935408, 1568900548, 4113005769, 517960156, 2779759669, 3997109150, 1983003883, 2389480438, 2535771608, 672561366, 2033616224, 2042009132, 3037516435, 3225373369, 2209908234, 226424653, 3288949959, 1603318959, 1724629419, 2951514084, 912198427, 1471589204, 2507804994, 38149107, 3992306371, 2279069712, 213979244, 3277221841, 4090877293, 2201702145, 132699456, 427025349, 3966146747, 585410742, 1336227915, 2310964976, 413787785, 3256452950, 1968866743, 4000753537, 1444861975, 2705673868, 3516843675, 1131836880, 3514215189, 2807317813, 631444731, 1758503386, 645321110, 1389336314, 284431831, 3618102503, 719646775, 2545039835, 304479513, 4213119349, 2305190346, 154682538, 2812761913, 1482546777, 631844162, 4054050127, 1164531181, 3989276939, 3263324551, 1370503188, 2693784221, 352106250, 786440075, 2429447376, 2022937001, 1607349664, 4148609264, 1153818047, 3970449212, 1218584233, 4097117707, 418894655, 2081597627, 2767007972, 3605553748, 3099373403, 3291767689, 393889897, 952465676, 1206685658, 2883904375, 3642302740, 3119229219, 3726804543, 1548873331, 2523391537, 2557398516, 1473029336, 1019096754, 2432653575, 3509505769, 1728861234, 2471189853, 2431092479, 1526585802, 3346184365, 536927635, 3168541128, 2604483109, 2085935216, 1082083765, 4155611789, 95955942, 3667132573, 1086915312, 3736694213, 4111004249, 3398619340, 2553566595, 928751317, 2339079072, 460666010, 80584458, 491019742, 2456251340, 369776954, 3540814068, 3887147804, 3434058825, 3001551096, 2292526794, 607773318, 2276948120, 247335351, 2697667605, 3708134991, 2482947853, 898780984, 1988741127, 1938251904, 337591520, 401067696, 3240706405, 3831635463, 1161394882, 121646438, 2585624199, 1788675476, 3729774771, 1149066903, 2899232714, 3870573595, 3928339543, 3829877435, 1396804105, 1892179772, 2024212238, 1112390287, 245347464, 1959506234, 1531925529, 1245788559, 724758985, 2244370256, 574368177, 1977157958, 123223131, 845450955, 758150329, 895304849, 3304635462, 3591885291, 678196720};
 
uint8_t input[0x12] = { 0x11, //0
                        0x42, //1
                        0x43, //2
                        0x44, //3
                        0x45, //4
                        0x46, //5
                        0x47, //6
                        0x48, //7
                        0x49, //8
                        0x4a, //9
                        0x4b, //0xa
                        0x4c, //0xb
                        0x4d, //0xc
                        0x4e, //0xd
                        0x4f, //0xe
                        0x50, //0xf
                        0x51, //0x10
                        0x52  //0x11
                        };
 
uint64_t do_vm2(int start, uint64_t count, ...);
 
uint64_t __fastcall sub_555555555880(__int64 *a1)
{
  __int64 v2; // rdi
  __int64 v4; // rbx
  __int64 v5; // rax
  int v6; // ecx
  __int64 v7; // rdi
  if ( *(_DWORD *)a1 == 4 )
  {
    v2 = 76LL;
    cout << "call 4" << endl;
    return do_vm2(v2, 1uLL, a1);
  }
  if ( *(_DWORD *)a1 == 3 )
  {
    v2 = 60LL;
    cout << "call 3" << endl;
   return do_vm2(v2, 1uLL, a1);
  }
  v4 = sub_555555555880((__int64 *)a1[1]);
  v5 = sub_555555555880((__int64 *)a1[2]);
  v6 = *(_DWORD *)a1;
  if ( *(_DWORD *)a1 == 2 )
  {
    v7 = 16LL;
    cout << "call 2" << endl;
    return do_vm2(v7, 2uLL, v4, v5);
  }
  if ( v6 == 1 ){
     cout << "call 1" << endl;
    return do_vm2(0LL, 2uLL, v4, v5);
  }
     
  if ( !v6 )
  {
    v7 = 40LL;
    cout << "call 0" << endl;
   return do_vm2(v7, 2uLL, v4, v5);
  }
  return 0LL;
}
 
int once = 1;
 
uint64_t do_vm2(int start, uint64_t count, ...){
 
    uint64_t **arr = VM_context;
 
    va_list args;          
    va_start(args, count); 
 
    int total = 0;
    for (int i = 0; i < count; ++i) {
        arr[i] = (uint64_t *)va_arg(args, uint64_t); 
    }
 
    va_end(args);
     
    if(once){   
      arr[30] = (uint64_t *)operator new[](0x2000uLL) + 0x2000LL;
      arr[32] = (uint64_t *)vm_op;
      arr[33] = (uint64_t *)vm_op+sizeof(vm_op);
      arr[0] = (uint64_t *)input;
      arr[1] = (uint64_t *)0x12;
      _QWORD * v6 = (_QWORD *)arr[32];
      *(_QWORD *)((char *)v6 + 84) ^= (unsigned __int64)(v6 + 292);
      v6[16] ^= (unsigned __int64)(v6 + 293);
      *(_QWORD *)((char *)v6 + 244) ^= (unsigned __int64)(v6 + 293);
      *(_QWORD *)((char *)v6 + 260) ^= (unsigned __int64)(v6 + 292);
      *(_QWORD *)((char *)v6 + 324) ^= (unsigned __int64)&malloc;
      v6[281] ^= (unsigned __int64)sub_555555555880;
      once = 0;
    }
 
    uint64_t * old_rsp = arr[30];
    uint64_t * rsp = old_rsp;
    *(rsp-1) = 0x13371337;
    arr[30]--;
    arr[31] = (uint64_t *)&vm_op[start/4];
 
    while(arr[31] != (uint64_t *)0x13371337){
      VM_2((int64_t *)arr);
    }
    arr[30] = old_rsp;
    return (uint64_t)arr[0];
}
 
int main(){
 
  uint64_t **arr = VM_context;
  arr[30] = (uint64_t *)operator new[](0x2000uLL) + 0x2000LL;
  arr[32] = (uint64_t *)vm_op;
  arr[33] = (uint64_t *)vm_op+sizeof(vm_op);
  arr[0] = (uint64_t *)input;
  arr[1] = (uint64_t *)0x12;
  uint64_t * old_rsp = arr[30];
  uint64_t * rsp = old_rsp;
  *(rsp-1) = 0x13371337;
  arr[30]--;
  arr[31] = (uint64_t *)&vm_op[0];
  arr[34] = 0;
 
  while(arr[31] != (uint64_t *)0x13371337){
    VM_3((int64_t *)arr);
  }
  arr[30] = old_rsp;
  return (uint64_t)arr[0];
}
#include<stdio.h>
#include<stdint.h>
#include"defs.h"
#include <intrin.h>
#include<iostream>
#include <cstdarg>
 
using namespace std;
 
int lut[256] = {};
 
__int64 __fastcall VM_0(__int64 *a1) //big edian no lfsr
{
  __int64 result; // rax
  unsigned int *v3; // rdx
  unsigned int v4; // edi
  __int64 v5; // r14
  __int64 v6; // rdi
  unsigned int v7; // r8d
  __int64 v8; // rsi
  __int64 v9; // rcx
  __int64 v10; // rdx
  unsigned int v11; // edi
  __int64 v12; // rcx
  __int64 *v13; // rax
  __int64 v14; // rdi
  __int64 (__fastcall *v15)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v16; // rax
  char v17; // cl
  __int64 v18; // rdx
  unsigned int v19; // edx
  unsigned int v20; // ecx
  unsigned __int64 *v21; // rax
  unsigned __int64 v22; // rcx
  __int64 v23; // [rsp-8h] [rbp-18h]
 
  v23 = result;
  v3 = (unsigned int *)a1[31];
  v4 = *v3;
  v5 = (__int64)(v3 + 1);
  a1[31] = (__int64)(v3 + 1);
  v6 = _byteswap_ulong(v4);
  v7 = (unsigned int)v6 >> 29;
  if ( (unsigned int)v6 < 0x20000000 || v7 == 1 && (result = v6 & 0x10000000, (v6 & 0x10000000) == 0) )
  {
    v8 = ((unsigned int)v6 >> 19) & 0x1F;
    if ( (BYTE3(v6) & 1 & (v7 == 1)) != 0 || (v6 & 0xE1000000) == 0 )
    {
      if ( v7 == 1 || (unsigned int)v6 >> 25 == 9 || (unsigned int)v6 >> 25 == 7 )// imm
        v9 = v6 << 50 >> 50;                    // low 14 bits signed
      else
        v9 = v6 & 0x3FFF;                       // low 14 bits unsigned
    }
    else
    {
      v9 = a1[((unsigned int)v6 >> 9) & 0x1F];
    }
    v10 = a1[((unsigned int)v6 >> 14) & 0x1F];
    v11 = (unsigned int)v6 >> 25;
    if ( v7 == 1 )
    {
      switch ( v11 & 7 )
      {
        case 0u:
          result = v10 == v9;
          cout << "SETEQ " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 1u:
          result = v10 != v9;
          cout << "SETNOTEQ " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 2u:
          result = v10 <= v9;
          cout << "SETLE " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 3u:
          result = v10 < v9;
          cout << "SETL " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 4u:
          result = v10 <= (unsigned __int64)v9;
          cout << "SETBE " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        case 5u:
          result = v10 < (unsigned __int64)v9;
          cout << "SETB " <<  std::hex << v10 << " " << std::hex << v9 <<endl;
          a1[v8] = result;
          break;
        default:
LABEL_20:
          result = 0LL;
          a1[v8] = 0LL;
          break;
      }
    }
    else
    {
      printf("r%d ",v8);
      switch ( v11 & 0xF )
      {
        case 0u:
          v12 = v10 | v9;
          cout << "OR " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
        case 1u:
          v12 = v10 ^ v9;
          cout << "XOR " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
           
        case 2u:
          v12 = v10 & v9;
          cout << "AND " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
        case 3u:
          v12 = v10 + v9;
          cout << "ADD " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_38;
        case 4u:
          v18 = v10 - v9;
          cout << "SUB " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 5u:
          v12 = v10 * v9;
          cout << "MUL " << std::hex << v10 << " " << std::hex << v9 << endl;
LABEL_38:
          result = v12;
          a1[v8] = v12;
          return result;
        case 6u:
          result = v10 / (unsigned __int64)v9;
          a1[v8] = v10 / (unsigned __int64)v9;
          cout << "DIV " << std::hex << v10 << " " << std::hex << v9 << endl;
          return result;
        case 7u:
          result = v10 / v9;
          a1[v8] = v10 / v9;
          cout << "IDIV " << std::hex << v10 << " " << std::hex << v9 << endl;
          return result;
        case 8u:
          v18 = v10 % (unsigned __int64)v9;
          cout << "MOD " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 9u:
          v18 = v10 % v9;
          cout << "IMOD " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xAu:
          v18 = v10 << v9;
          cout << "letfRotate " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xBu:
          v18 = v10 >> v9;
          cout << "irightRotate " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xCu:
          v18 = (unsigned __int64)v10 >> v9;
          cout << "rightRotate " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xDu:
          v18 = __ROL8__(v10, v9);
          cout << "ROL8 " << std::hex << v10 << " " << std::hex << v9 << endl;
          goto LABEL_48;
        case 0xEu:
          v18 = __ROR8__(v10, v9);
          cout << "ROR8 " << std::hex << v10 << " " << std::hex << v9 << endl;
LABEL_48:
          result = v18;
          a1[v8] = v18;
          break;
        default:
          goto LABEL_20;
      }
    }
    return result;
  }
  if ( v7 == 1 )
  {
    v7 = ((unsigned int)v6 >> 26) & 3;
    if ( v7 == 2 )
    {
      v14 = ((unsigned int)v6 >> 20) & 0x1F;
      v15 = (__int64 (__fastcall *)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64))a1[v14];
      if ( (unsigned __int64)v15 < a1[32] || (unsigned __int64)v15 >= a1[33] )
      {
        result = v15(*a1, a1[1], a1[2], a1[3], a1[4], a1[5], v23);
        cout << "call_out" << endl;
        *a1 = result;
        a1[31] = v5;
      }
      else
      {
        cout << "call in" << endl;
        v16 = a1[30];                           // PUSH
        *(_QWORD *)(v16 - 8) = v5;              // call
        result = v16 - 8;
        a1[31] = a1[v14];
        a1[30] = result;
      }
      return result;
    }
    if ( !v7 )
    {
      cout << "ret" << endl;
      v13 = (__int64 *)a1[30];                  // pop
      a1[31] = *v13;                            // ret
      result = (__int64)(v13 + 1);
      a1[30] = result;
      return result;
    }
    if ( (v6 & 0x2000000) != 0 )                // check 26 bit
    {
      cout << "jump" << endl;
      result = 37LL;
      v17 = 39;
    }
    else
    {
      cout << "jcc" << endl;
      result = ((unsigned int)v6 >> 20) & 0x1F; // 21-25
      if ( !a1[result] )
        goto LABEL_52;
      result = 42LL;
      v17 = 44;
    }
    a1[31] = (__int64)v3 + ((__int64)((unsigned __int64)(unsigned int)v6 << v17) >> result);
LABEL_52:
    if ( (v6 & 0x2000000) == 0 )
      return result;
  }
  if ( v7 == 2 )
  {
    if ( (((unsigned int)v6 >> 27) & 3) != 0 )  // 2829
    {
      v19 = ((unsigned int)v6 >> 21) & 0x1F;    // 22-26
      v20 = WORD1(v6) & 0x1F;
      result = (unsigned __int16)v6 - 0x8000LL;
      if ( (v6 & 0x8000u) == 0LL )
        result = (unsigned __int16)v6;
      if ( (((unsigned int)v6 >> 27) & 3) == 1 )
      {
        printf("load r%d  [r%d+0x%x]\n",v19, v20, result);
        result = *(_QWORD *)(a1[v20] + result);
        a1[v19] = result;                       // load
         
      }
      else
      {
        switch ( ((unsigned int)v6 >> 26) & 3 ) // store
        {
          case 0u:
            printf("stb [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_BYTE *)(a1[v20] + result) = a1[v19];
            break;
          case 1u:
            printf("stw [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_WORD *)(a1[v20] + result) = a1[v19];
            break;
          case 2u:
            printf("stdw [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_DWORD *)(a1[v20] + result) = a1[v19];
            break;
          case 3u:
            printf("stqw [r%d + 0x%d] r%d\n",v20,result,v19);
            *(_QWORD *)(a1[v20] + result) = a1[v19];
            break;
        }
      }
    }
    else
    {
      v21 = (unsigned __int64 *)a1[31];
      v22 = _byteswap_uint64(*v21);
      result = (__int64)(v21 + 1);
      a1[31] = result;
      a1[WORD1(v6) & 0x1F] = v22;
      printf("speical_load r%d  0x%x\n",WORD1(v6) & 0x1f,v22);
    }
  }
  return result;
}
 
__int64 __fastcall VM_1(__int64 *a1) // little lfsr
{
  unsigned int *v2; // rcx
  __int64 result; // rax
  _DWORD *v4; // r14
  int v5; // edx
  unsigned int v6; // edx
  unsigned int v7; // ebp
  unsigned int v8; // edi
  __int64 v9; // rsi
  __int64 v10; // rcx
  __int64 v11; // rdx
  unsigned int v12; // eax
  __int64 v13; // rcx
  __int64 v14; // rax
  __int64 v15; // rax
  __int64 (__fastcall *v16)(__int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v17; // rcx
  unsigned int v18; // r8d
  int v19; // edx
  __int64 v20; // rsi
  __int64 v21; // rdx
  unsigned int v22; // esi
  unsigned int v23; // edx
  __int64 v24; // rcx
  _QWORD *v25; // rcx
  __int64 v26; // rsi
  int v27; // edi
  unsigned int v28; // edx
  unsigned __int64 v29; // rdi
 
  v2 = (unsigned int *)a1[31];
  result = *v2;
  v4 = v2 + 1;
  a1[31] = (__int64)(v2 + 1);
  v5 = *((_DWORD *)a1 + 68);
  if ( !v5 )
  {
    *((_DWORD *)a1 + 68) = result;
    return result;
  }
  v6 = v5 ^ (v5 << 13) ^ ((v5 ^ (unsigned int)(v5 << 13)) >> 17);
  v7 = v6 ^ (32 * v6);
  *((_DWORD *)a1 + 68) = v7;
  result = v7 ^ (unsigned int)result;
  v8 = (unsigned int)result >> 29;
  if ( (unsigned int)result < 0x20000000 || v8 == 1 && (result & 0x10000000) == 0 )
  {
    v9 = ((unsigned int)result >> 19) & 0x1F;
    if ( (result & 0xE1000000) == 0 || (BYTE3(result) & 1 & (v8 == 1)) != 0 )
    {
      if ( v8 == 1 || (unsigned int)result >> 25 == 9 || (unsigned int)result >> 25 == 7 )
        v10 = result << 50 >> 50;
      else
        v10 = result & 0x3FFF;
    }
    else
    {
      v10 = a1[((unsigned int)result >> 9) & 0x1F];
    }
    v11 = a1[((unsigned int)result >> 14) & 0x1F];
    v12 = (unsigned int)result >> 25;
    if ( v8 == 1 )
    {
      switch ( v12 & 7 )
      {
        case 0u:
          result = v11 == v10;
          a1[v9] = result;
          break;
        case 1u:
          result = v11 != v10;
          cout << "SETNOTEQ " <<  std::hex << v11 << " " << std::hex << v10 <<endl;
          a1[v9] = result;
          break;
        case 2u:
          result = v11 <= v10;
          a1[v9] = result;
          break;
        case 3u:
          result = v11 < v10;
          a1[v9] = result;
          break;
        case 4u:
          result = v11 <= (unsigned __int64)v10;
          a1[v9] = result;
          break;
        case 5u:
          result = v11 < (unsigned __int64)v10;
          a1[v9] = result;
          break;
        default:
          goto LABEL_22;
      }
    }
    else
    {
      switch ( v12 & 0xF )
      {
        case 0u:
          v13 = v11 | v10;
          goto LABEL_40;
        case 1u:
          v13 = v11 ^ v10;
          cout << "XOR " << std::hex << v11 << " " << std::hex << v10 << endl;
          goto LABEL_40;
        case 2u:
          v13 = v11 & v10;
          goto LABEL_40;
        case 3u:
          v13 = v11 + v10;
          goto LABEL_40;
        case 4u:
          v21 = v11 - v10;
          goto LABEL_50;
        case 5u:
          v13 = v11 * v10;
LABEL_40:
          result = v13;
          a1[v9] = v13;
          return result;
        case 6u:
          result = v11 / (unsigned __int64)v10;
          a1[v9] = v11 / (unsigned __int64)v10;
          return result;
        case 7u:
          result = v11 / v10;
          a1[v9] = v11 / v10;
          return result;
        case 8u:
          v21 = v11 % (unsigned __int64)v10;
          goto LABEL_50;
        case 9u:
          v21 = v11 % v10;
          goto LABEL_50;
        case 0xAu:
          v21 = v11 << v10;
          goto LABEL_50;
        case 0xBu:
          v21 = v11 >> v10;
          goto LABEL_50;
        case 0xCu:
          v21 = (unsigned __int64)v11 >> v10;
          goto LABEL_50;
        case 0xDu:
          v21 = __ROL8__(v11, v10);
          goto LABEL_50;
        case 0xEu:
          v21 = __ROR8__(v11, v10);
LABEL_50:
          result = v21;
          a1[v9] = v21;
          break;
        default:
LABEL_22:
          result = 0LL;
          a1[v9] = 0LL;
          break;
      }
    }
    return result;
  }
  if ( v8 == 1 )
  {
    v8 = ((unsigned int)result >> 26) & 3;
    if ( v8 == 2 )
    {
      v15 = ((unsigned int)result >> 20) & 0x1F;
      v16 = (__int64 (__fastcall *)(__int64, __int64, __int64, __int64, __int64, __int64))a1[v15];
      if ( (unsigned __int64)v16 < a1[32] || (unsigned __int64)v16 >= a1[33] )
      {
        result = v16(*a1, a1[1], a1[2], a1[3], a1[4], a1[5]);
        *a1 = result;
        *((_DWORD *)a1 + 68) = v7;
        a1[31] = (__int64)v4;
      }
      else
      {
        v17 = a1[30];
        *(_QWORD *)(v17 - 8) = v7;
        *((_DWORD *)a1 + 68) = 0;
        *(_QWORD *)(v17 - 16) = a1[31];
        result = a1[v15];
        a1[31] = result;
        a1[30] = v17 - 16;
      }
      return result;
    }
    if ( !v8 )
    {
      v14 = a1[30];
      a1[31] = *(_QWORD *)v14;
      *((_DWORD *)a1 + 68) = *(_DWORD *)(v14 + 8);
      result = v14 + 16;
      a1[30] = result;
      return result;
    }
    v18 = v7 ^ (v7 << 13) ^ ((v7 ^ (v7 << 13)) >> 17) ^ (32 * (v7 ^ (v7 << 13) ^ ((v7 ^ (v7 << 13)) >> 17)));
    v19 = v18 ^ *v4;
    *((_DWORD *)a1 + 68) = v18;
    if ( (result & 0x2000000) != 0 )
    {
      v20 = result << 39 >> 37;
    }
    else
    {
      if ( !a1[((unsigned int)result >> 20) & 0x1F] )
      {
        a1[31] = (__int64)(v2 + 2);
        if ( (result & 0x2000000) == 0 )
          return result;
        goto LABEL_54;
      }
      v20 = result << 44 >> 42;
    }
    a1[31] = (__int64)v2 + v20;
    *((_DWORD *)a1 + 68) = v19;
    if ( (result & 0x2000000) == 0 )
      return result;
  }
LABEL_54:
  if ( v8 == 2 )
  {
    if ( (((unsigned int)result >> 27) & 3) != 0 )
    {
      v22 = ((unsigned int)result >> 21) & 0x1F;
      v23 = WORD1(result) & 0x1F;
      v24 = (unsigned __int16)result - 0x8000LL;
      if ( (result & 0x8000u) == 0LL )
        v24 = (unsigned __int16)result;
      if ( (((unsigned int)result >> 27) & 3) == 1 )
      {
        result = *(_QWORD *)(a1[v23] + v24);
        a1[v22] = result;
      }
      else
      {
        switch ( ((unsigned int)result >> 26) & 3 )
        {
          case 0u:
            result = LOBYTE(a1[v22]);
            *(_BYTE *)(a1[v23] + v24) = result;
            break;
          case 1u:
            result = LOWORD(a1[v22]);
            *(_WORD *)(a1[v23] + v24) = result;
            break;
          case 2u:
            result = LODWORD(a1[v22]);
            *(_DWORD *)(a1[v23] + v24) = result;
            break;
          case 3u:
            result = a1[v22];
            *(_QWORD *)(a1[v23] + v24) = result;
            break;
        }
      }
    }
    else
    {
      result = WORD1(result) & 0x1F;
      v25 = (_QWORD *)a1[31];
      v26 = *((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)));
      v27 = v26 ^ ((*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)))) << 13) ^ (((unsigned int)v26 ^ ((*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17) ^ (32 * (*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13) ^ ((unsigned int)(*((_DWORD *)a1 + 68) ^ (*((_DWORD *)a1 + 68) << 13)) >> 17)))) << 13)) >> 17);
      v28 = v27 ^ (32 * v27);
      v29 = *v25 ^ (v26 | ((unsigned __int64)v28 << 32));
      *((_DWORD *)a1 + 68) = v28;
      a1[31] = (__int64)(v25 + 1);
      a1[result] = v29;
      printf("speical_load r%d  0x%x\n",result,v29);
    }
  }
  return result;
}
 
__int64 __fastcall VM_2(__int64 *a1) // little no lfsr
{
  __int64 result; // rax
  unsigned int *v3; // rdx
  __int64 v4; // rdi
  __int64 v5; // r14
  unsigned int v6; // r8d
  __int64 v7; // rsi
  __int64 v8; // rcx
  __int64 v9; // rdx
  unsigned int v10; // edi
  __int64 v11; // rcx
  __int64 *v12; // rax
  __int64 v13; // rdi
  __int64 (__fastcall *v14)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v15; // rax
  char v16; // cl
  __int64 v17; // rdx
  unsigned int v18; // edx
  unsigned int v19; // ecx
  __int64 *v20; // rax
  __int64 v21; // rcx
  __int64 v22; // [rsp-8h] [rbp-18h]
 
  v22 = result;
  v3 = (unsigned int *)a1[31];
  v4 = *v3;
  v5 = (__int64)(v3 + 1);
  a1[31] = (__int64)(v3 + 1);
  v6 = (unsigned int)v4 >> 29;
  if ( (unsigned int)v4 < 0x20000000 || v6 == 1 && (result = v4 & 0x10000000, (v4 & 0x10000000) == 0) )
  {
    v7 = ((unsigned int)v4 >> 19) & 0x1F;
    if ( (v4 & 0xE1000000) == 0 || (BYTE3(v4) & 1 & (v6 == 1)) != 0 )
    {
      if ( v6 == 1 || (unsigned int)v4 >> 25 == 9 || (unsigned int)v4 >> 25 == 7 )
        v8 = v4 << 50 >> 50;
      else
        v8 = v4 & 0x3FFF;
    }
    else
    {
      v8 = a1[((unsigned int)v4 >> 9) & 0x1F];
    }
    printf("r%d=",((unsigned int)v4 >> 19) & 0x1F);
    v9 = a1[((unsigned int)v4 >> 14) & 0x1F];
    v10 = (unsigned int)v4 >> 25;
    if ( v6 == 1 )
    {
      switch ( v10 & 7 )
      {
        case 0u:
          result = v9 == v8;
          printf("SETEQ r%d(%llx) r%d(%llx)\n",((unsigned int)v4 >> 14) & 0x1F,a1[0],((unsigned int)v4 >> 9) & 0x1F,a1[1]);
          a1[v7] = result;
          break;
        case 1u:
          result = v9 != v8;
          cout << "SETNOTEQ " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 2u:
          result = v9 <= v8;
          cout << "SETLE " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 3u:
          result = v9 < v8;
          cout << "SETL " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 4u:
          result = v9 <= (unsigned __int64)v8;
          cout << "SETBE " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        case 5u:
          result = v9 < (unsigned __int64)v8;
          cout << "SETB " <<  std::hex << v9 << " " << std::hex << v8 <<endl;
          a1[v7] = result;
          break;
        default:
          goto LABEL_20;
      }
    }
    else
    {
      switch ( v10 & 0xF )
      {
        case 0u:
          v11 = v9 | v8;
          cout << "OR " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 1u:
          v11 = v9 ^ v8;
          cout << "XOR " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 2u:
          v11 = v9 & v8;
          cout << "AND " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 3u:
          v11 = v9 + v8;
          cout << "ADD " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_38;
        case 4u:
          v17 = v9 - v8;
          cout << "SUB " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 5u:
          v11 = v9 * v8;
          cout << "MUL " << std::hex << v9 << " " << std::hex << v8 << endl;
LABEL_38:
          result = v11;
          a1[v7] = v11;
          return result;
        case 6u:
          result = v9 / (unsigned __int64)v8;
          a1[v7] = v9 / (unsigned __int64)v8;
          cout << "DIV " << std::hex << v9 << " " << std::hex << v8 << endl;
          return result;
        case 7u:
          result = v9 / v8;
          a1[v7] = v9 / v8;
          cout << "iDIV " << std::hex << v9 << " " << std::hex << v8 << endl;
          return result;
        case 8u:
          v17 = v9 % (unsigned __int64)v8;
          cout << "MOD " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 9u:
          v17 = v9 % v8;
          cout << "IMOD " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xAu:
          v17 = v9 << v8;
          cout << "<< " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xBu:
          v17 = v9 >> v8;
          cout << "i>> " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xCu:
          v17 = (unsigned __int64)v9 >> v8;
          cout << ">> " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xDu:
          v17 = __ROL8__(v9, v8);
          cout << "ROL8 " << std::hex << v9 << " " << std::hex << v8 << endl;
          goto LABEL_48;
        case 0xEu:
          v17 = __ROR8__(v9, v8);
          cout << "ROR8 " << std::hex << v9 << " " << std::hex << v8 << endl;
LABEL_48:
          result = v17;
          a1[v7] = v17;
          break;
        default:
LABEL_20:
          result = 0LL;
          a1[v7] = 0LL;
          break;
      }
    }
    return result;
  }
  if ( v6 == 1 )
  {
    v6 = ((unsigned int)v4 >> 26) & 3;
    if ( v6 == 2 )
    {
      v13 = ((unsigned int)v4 >> 20) & 0x1F;
      v14 = (__int64 (__fastcall *)(_QWORD, __int64, __int64, __int64, __int64, __int64, __int64))a1[v13];
      if ( (unsigned __int64)v14 < a1[32] || (unsigned __int64)v14 >= a1[33] )
      {
        result = v14(*a1, a1[1], a1[2], a1[3], a1[4], a1[5], v22);
        *a1 = result;
        cout << "call_out ";
        if((unsigned __int64)v14 == (unsigned __int64)&malloc){
           cout << "malloc ";
        }
        else{
          cout << "sub_880 ";
        }
        cout << "load r0 0x" << std::hex << result << endl;
        a1[31] = v5;
      }
      else
      {
        cout << "call in" << endl;
        v15 = a1[30];
        *(_QWORD *)(v15 - 8) = v5;
        result = v15 - 8;
        a1[31] = a1[v13];
        a1[30] = result;
      }
      return result;
    }
    if ( !v6 )
    {
      cout << "ret" << endl;
      v12 = (__int64 *)a1[30];
      a1[31] = *v12;
      result = (__int64)(v12 + 1);
      a1[30] = result;
      return result;
    }
    if ( (v4 & 0x2000000) != 0 )
    {
      cout << "jump" << endl;
      result = 37LL;
      v16 = 39;
    }
    else
    {
      cout << "jcc" << endl;
      result = ((unsigned int)v4 >> 20) & 0x1F;
      if ( !a1[result] )
        goto LABEL_52;
      result = 42LL;
      v16 = 44;
    }
    a1[31] = (__int64)v3 + ((__int64)((unsigned __int64)(unsigned int)v4 << v16) >> result);
LABEL_52:
    if ( (v4 & 0x2000000) == 0 )
      return result;
  }
  if ( v6 == 2 )
  {
    if ( (((unsigned int)v4 >> 27) & 3) != 0 )
    {
      v18 = ((unsigned int)v4 >> 21) & 0x1F;
      v19 = WORD1(v4) & 0x1F;
      result = (unsigned __int16)v4 - 0x8000LL;
      if ( (v4 & 0x8000u) == 0LL )
        result = (unsigned __int16)v4;
      if ( (((unsigned int)v4 >> 27) & 3) == 1 )
      {
        printf("load r%d  [r%d+0x%x](%llx)\n",v18, v19, result,*(_QWORD *)(a1[v19] + result));
        result = *(_QWORD *)(a1[v19] + result);
        a1[v18] = result;
      }
      else
      {
        switch ( ((unsigned int)v4 >> 26) & 3 )
        {
          case 0u:
         printf("stb [r%d(0x%llx) + 0x%x] r%d(0x%x)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_BYTE *)(a1[v19] + result) = a1[v18];
            break;
          case 1u:
          printf("stw [r%d(0x%llx) + 0x%x] r%d(0x%x)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_WORD *)(a1[v19] + result) = a1[v18];
            break;
          case 2u:
          printf("stdw [r%d(0x%llx) + 0x%x] r%d(0x%x)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_DWORD *)(a1[v19] + result) = a1[v18];
            break;
          case 3u:
          printf("stqw [r%d(0x%llx) + 0x%x] r%d(0x%llx)\n",v19,a1[v19],result,v18,a1[v18]);
            *(_QWORD *)(a1[v19] + result) = a1[v18];
            break;
        }
      }
    }
    else
    {
      v20 = (__int64 *)a1[31];
      v21 = *v20;
      result = (__int64)(v20 + 1);
      a1[31] = result;
      a1[WORD1(v4) & 0x1F] = v21;
      printf("speical_load r%d  0x%llx\n",WORD1(v4) & 0x1F,v21);
    }
  }
  return result;
}
 
__int64 __fastcall VM_3(__int64 *a1) //big lfsr
{
  unsigned int *v2; // rcx
  unsigned int v3; // eax
  unsigned int *v4; // r14
  int result; // rax
  int v6; // edx
  unsigned int v7; // edx
  unsigned int v8; // ebp
  unsigned int v9; // edi
  __int64 v10; // rsi
  __int64 v11; // rcx
  __int64 v12; // rdx
  unsigned int v13; // eax
  __int64 v14; // rcx
  __int64 v15; // rax
  __int64 v16; // rax
  __int64 (__fastcall *v17)(__int64, __int64, __int64, __int64, __int64, __int64); // r10
  __int64 v18; // rcx
  unsigned __int32 v19; // esi
  unsigned int v20; // edx
  int v21; // edx
  __int64 v22; // rsi
  __int64 v23; // rdx
  unsigned int v24; // esi
  unsigned int v25; // edx
  __int64 v26; // rcx
  unsigned __int64 *v27; // rcx
  unsigned __int64 v28; // rdx
  __int64 v29; // rdi
  unsigned int v30; // esi
  __int64 v31; // rsi
 
  v2 = (unsigned int *)a1[31];
  v3 = *v2;
  v4 = v2 + 1;
  a1[31] = (__int64)(v2 + 1);
  result = _byteswap_ulong(v3);
  v6 = *((_DWORD *)a1 + 68);
  if ( !v6 )
  {
    *((_DWORD *)a1 + 68) = result;
    return result;
  }
  v7 = v6 ^ (v6 << 13) ^ ((v6 ^ (unsigned int)(v6 << 13)) >> 17);
  v8 = v7 ^ (32 * v7);
  *((_DWORD *)a1 + 68) = v8;
  result = v8 ^ (unsigned int)result;
  int op = result;
  v9 = (unsigned int)result >> 29;
  if ( (unsigned int)result < 0x20000000 || v9 == 1 && (result & 0x10000000) == 0 )
  {
    v10 = ((unsigned int)result >> 19) & 0x1F;
    if ( (BYTE3(result) & 1 & (v9 == 1)) != 0 || (result & 0xE1000000) == 0 )
    {
      if ( v9 == 1 || (unsigned int)result >> 25 == 9 || (unsigned int)result >> 25 == 7 )
        v11 = result << 50 >> 50;
      else
        v11 = result & 0x3FFF;
    }
    else
    {
      v11 = a1[((unsigned int)result >> 9) & 0x1F];
    }
    v12 = a1[((unsigned int)result >> 14) & 0x1F];
    v13 = (unsigned int)result >> 25;
    if ( v9 == 1 )
    {
      switch ( v13 & 7 )
      {
        case 0u:
          result = v12 == v11;
          a1[v10] = result;
          break;
        case 1u:
          result = v12 != v11;
          a1[v10] = result;
          break;
        case 2u:
          result = v12 <= v11;
          a1[v10] = result;
          break;
        case 3u:
          result = v12 < v11;
          a1[v10] = result;
          break;
        case 4u:
          result = v12 <= (unsigned __int64)v11;
          a1[v10] = result;
          break;
        case 5u:
          result = v12 < (unsigned __int64)v11;
          a1[v10] = result;
          break;
        default:
LABEL_22:
          result = 0LL;
          a1[v10] = 0LL;
          break;
      }
    }
    else
    {
      switch ( v13 & 0xF )
      {
        case 0u:
          v14 = v12 | v11;
          cout << "OR " << std::hex << v12 << " " << std::hex << v11 << endl;
          goto LABEL_40;
        case 1u:
          v14 = v12 ^ v11;
          cout << "XOR " << std::hex << v12 << " " << std::hex << v11 << endl;
          goto LABEL_40;
        case 2u:
          v14 = v12 & v11;
          goto LABEL_40;
        case 3u:
          v14 = v12 + v11;
          goto LABEL_40;
        case 4u:
          v23 = v12 - v11;
          goto LABEL_50;
        case 5u:
          v14 = v12 * v11;
LABEL_40:
          result = v14;
          a1[v10] = v14;
          return result;
        case 6u:
          result = v12 / (unsigned __int64)v11;
          a1[v10] = v12 / (unsigned __int64)v11;
          return result;
        case 7u:
          result = v12 / v11;
          a1[v10] = v12 / v11;
          return result;
        case 8u:
          v23 = v12 % (unsigned __int64)v11;
          goto LABEL_50;

[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

收藏
免费
支持
分享
最新回复 (5)
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2025-1-12 08:27
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
请问一下pyda适合安卓逆向吗
2025-1-12 10:23
0
雪    币: 3831
活跃值: (1195)
能力值: ( LV9,RANK:150 )
在线值:
发帖
回帖
粉丝
4
mb_ldbucrik 请问一下pyda适合安卓逆向吗
不适合 pyda只适合 elf
2025-1-12 16:58
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
so也是elf,可以辅助分析吗
2025-1-13 08:23
0
雪    币: 3831
活跃值: (1195)
能力值: ( LV9,RANK:150 )
在线值:
发帖
回帖
粉丝
6
mb_ldbucrik so也是elf,可以辅助分析吗
pyda的原理是先objdump源程序的汇编指令 然后在特定位置插桩 ,如果要分析so的话 但是so又不是源程序 而是加载的库 所以不会插桩到so里 
2025-1-13 10:38
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册