首页
社区
课程
招聘
[原创][分享]发一个自己写的反汇编引擎
发表于: 2013-3-7 19:00 7230

[原创][分享]发一个自己写的反汇编引擎

2013-3-7 19:00
7230
说说大概的设计,不好之处,忘大神们指出
第一件事情是更具Intel指令手册来建立n张表,表结构的定义:
struct OpcodeMap
{
  uint32 Q;          // 如何定位到下一张表 
  uint32 P;          //指令是否支持锁前缀
  uint32 I1;         //是什么指令
  uint32 I2;         //是什么指令
  uint32 C;          //解析指令的参数的个数
  uint32 at[4];    // 解析指令的参数
};

表的类型,什么一比特的指令,2比特,浮点组之类的:
#define Q_TWOBYTE                1
#define Q_PREFIX                    2
#define Q_GRP1                       3
#define Q_GRP1A                     4
#define Q_GRP2                       5
#define Q_GRP11                     6
#define Q_ESC                         7
#define Q_GRP3                       8
#define Q_GRP4                       9
#define Q_GRP5                      10
#define Q_GRP6                      11
#define Q_GRP7                      12
........

定义操作参数类型(和指令手册上写的一样):
#define Eb                       1
#define Gb                       2
#define Ev                       3
#define Gv                       4
#define AL                       5
#define Ib                        6
#define eAX                      7
..............

要查的表的内容如:
OpcodeMap OneByte[] =

  /* 00 */ { 0, P_F0, I_ADD, 0, 2, Eb, Gb, 0, 0 },
  /* 01 */ { 0, P_F0, I_ADD, 0, 2, Ev, Gv, 0, 0 },
  /* 02 */ { 0, 0, I_ADD, 0, 2, Gb, Eb, 0, 0 },
  /* 03 */ { 0, 0, I_ADD, 0, 2, Gv, Ev, 0, 0 },
  /* 04 */ { 0, 0, I_ADD, 0, 2, AL, Ib, 0, 0 },
  /* 05 */ { 0, 0, I_ADD, 0, 2, eAX, Iz, 0, 0 },
        .....
}

OpcodeMap TwoByte[] = 

  /* 00 */ { Q_GRP6, 0, 0, 0, 0, 0, 0, 0, 0 },
  /* 01 */ { Q_GRP7, 0, 0, 0, 0, 0, 0, 0, 0 },
  /* 02 */ { 0, 0, I_LAR, 0, 2, Gv, Ew, 0, 0 },
  /* 03 */ { 0, 0, I_LSL, 0, 2, Gv, Ew, 0, 0 },
  /* 04 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  /* 05 */ { 0, 0, I_SYSCALL, 0, 0, 0, 0, 0, 0 },
        .....
}

OpcodeMap ThreeByte38[] =

  /* 00 */ { Q_PFX_00_66, 0, 0, 0, 0, 0, 0, 0, 0 },
  /* 01 */ { Q_PFX_00_66, 0, 0, 0, 1, 0, 0, 0, 0 },
  /* 02 */ { Q_PFX_00_66, 0, 0, 0, 2, 0, 0, 0, 0 },
  /* 03 */ { Q_PFX_00_66, 0, 0, 0, 3, 0, 0, 0, 0 },
  /* 04 */ { Q_PFX_00_66, 0, 0, 0, 4, 0, 0, 0, 0 },
  /* 05 */ { Q_PFX_00_66, 0, 0, 0, 5, 0, 0, 0, 0 },
  /* 06 */ { Q_PFX_00_66, 0, 0, 0, 6, 0, 0, 0, 0 },
       ....
}

OpcodeMap ThreeByte3A[] =
{
  /* 00 */ { Q_PFX_66, 0, I_VPERMQ, 0, 3, Vqq, Wqq, Ib, 0 },
  /* 01 */ { Q_PFX_66, 0, I_VPERMPD, 0, 3, Vqq, Wqq, Ib, 0 },
  /* 02 */ { Q_PFX_66, 0, I_VPBLENDD, 0, 3, Vx, Wx, Ib, 0 },
  /* 03 */ { 0, 0, 0, 0, 3, 0, 0, 0, 0 },
  /* 04 */ { Q_PFX_66, 0, I_VPERMILPS, 0, 3, Vx, Wx, Ib, 0 },
  /* 05 */ { Q_PFX_66, 0, I_VPERMILPD, 0, 3, Vx, Wx, Ib, 0 },
  /* 06 */ { Q_PFX_66, 0, I_VPERM2F128, 0, 3, Vqq, Wqq, Ib, 0 },
        ....
}

等n多表。

然后主要的逻辑:
先看前缀:
  memset(If, 0, sizeof(InsFrame));
  uint8  fPfx = 0; 
  uint8  Pfx = 0;
  uint32  Prefix[5] = {DEF_SEG, DEF_OPRAND, DEF_ADDRESS, DEF_REPEATLOCK};
  uint32  Offset = 0;

  OpcodeMap* Map = OneByte + *Code;
  for (; ;)
  {
    if (Map->Q != Q_PREFIX)
    {
      break;
    }

    // 前缀长度不超过15
    if (Offset > 15)
    {
      If->I = I_Nul;
      return E_UNKOWN;
    }

    Prefix[Map->at[0]] = Map->at[1];
    fPfx = Pfx;
    Pfx = *(Code + Offset);

    // 查看下一个
    if ((Offset + 1) >= Size)
    {
      return E_LEN;
    }
    ++Offset;
    Map = OneByte + *(Code + Offset);
  }

再查是几字节的表:
  if (Map->Q == Q_TWOBYTE)
  {
    if ((Offset + 1) >= Size)
    {
      return E_LEN;
    }
    ++Offset;
    Map = TwoByte + *(Code + Offset);

    if (Map->Q == Q_66THREEBYTE38)
    {
      if ((Offset + 1) >= Size)
      {
        return E_LEN;
      }
      ++Offset;
      Map = ThreeByte38 + *(Code + Offset);
    }
    else if (Map->Q == Q_66THREEBYTE3A)
    {
      if ((Offset + 1) >= Size)
      {
        return E_LEN;
      }
      ++Offset;
      Map = ThreeByte3A + *(Code + Offset);
    }
  }

再查具体是那个分组的表:
  // 决定查什么表
  switch(Map->Q)
  {
  case Q_GRP1:
    if ((Offset + 1) >= Size)
    {
      return E_LEN;
    }
    Map = Grp1 + (Map->C * 8) + ((*(Code + Offset + 1) & 0x38) >> 3);
    break;
  case Q_GRP1A:
    if ((Offset + 1) >= Size)
    {
      return E_LEN;
    }
    Map = Grp1A + (Map->C * 8) + ((*(Code + Offset + 1) & 0x38) >> 3);
    break;
  case Q_GRP2:
    if ((Offset + 1) >= Size)
    {
      return E_LEN;
    }
    Map = Grp2 + (Map->C * 8) + ((*(Code + Offset + 1) & 0x38) >> 3);
    break;

具体定位到表后就是解析参数了:

  If->I = Map->I1;
  if (If->I == I_Nul)
  {
    return E_UNKOWN;
  }

  uint32 OffsetModRM = Offset + 1;
  If->Op.Size = Map->C;
  for (uint32 i = 0; i < Map->C; ++i)
  {
    uint32 SizeAddress;
    uint32 IndexReg;
    OpTag* T = &(If->Op.Tag[i]);

    switch(Map->at[i])
    {
    case Eb:
      SizeAddress = SIZE_8;
      IndexReg = R_INDEXREG8;
      goto LabModRM;
      break;
    case Ew:
      SizeAddress = SIZE_16;
      IndexReg = R_INDEXREG16;
      goto LabModRM;
      break;
    case Ev:
      if (Prefix[INDEX_OPRAND] == OPRAND_66)
      {
        SizeAddress = SIZE_16;
        IndexReg = R_INDEXREG16;
      }
      else
      {
        SizeAddress = SIZE_32;
        IndexReg = R_INDEXREG32;
      }
      goto LabModRM;
      break;

解析MOD和SIB也使用表,看结构定义:
#define MOD_00            0x0    // mod
#define MOD_01            0x2
#define MOD_10            0x3
#define MOD_11            0x4

#define REG_OP_0          0x0    // Reg/Op
#define REG_OP_1          0x1
#define REG_OP_2          0x2
#define REG_OP_3          0x3
#define REG_OP_4          0x4
#define REG_OP_5          0x5
#define REG_OP_6          0x6
#define REG_OP_7          0x7

#define RM_0              0x0    // RM
#define RM_1              0x1
#define RM_2              0x2
#define RM_3              0x3
#define RM_4              0x4
#define RM_5              0x5
#define RM_6              0x6
#define RM_7              0x7

// ModR/M32表专用宏
#define MODRM32_MEM_FREG      0x1      // 全寄存器寻址
#define MODRM32_MEM_FREG_IMM1    0x2      // 全寄存器加立即数1寻址
#define MODRM32_MEM_SSFREG_IMM1    0x3      // 全寄存器加立即数1寻址
#define MODRM32_MEM_FREG_IMM4    0x4      // 全寄存器加立即数4寻址
#define MODRM32_MEM_SSFREG_IMM4    0x5      // 全寄存器加立即数4寻址
#define MODRM32_MEM_IMM4      0x6      // 立即数4寻址
#define MODRM32_REG          0x7      // 寄存器作为操作数
#define MODRM32_SIB          0x8      // 存在SIB

// ModR/M32表
struct ModRM32
{
  uint32  Mode;              // 寻址模式
  uint32  Mod;   
  uint32  RegOp;
  uint32  RM;
};

// ModR/M16表专用宏
#define MODRM16_MEM_2REG      0x1    // 寄存器寻址 如:Opcode [bx + si], REG
#define MODRM16_MEM_1REG      0x2    // 寄存器寻址 如:Opcode [bx + si], REG
#define MODRM16_MEM_2REG_IMM1    0x3    // 寄存器加立即数1寻址 如:Opcode [bx + si + IMM1], REG
#define MODRM16_MEM_1REG_IMM1    0x4    // 寄存器加立即数1寻址 如:Opcode [bx + si + IMM1], REG
#define MODRM16_MEM_2REG_IMM2    0x5    // 寄存器加立即数2寻址 如:Opcode [bx + si + IMM2], REG
#define MODRM16_MEM_1REG_IMM2    0x6    // 寄存器加立即数2寻址 如:Opcode [bx + si + IMM2], REG
#define MODRM16_MEM_IMM2      0x7    // 立即数2寻址 Opcode [IMM2], REG
#define MODRM16_REG          0x8    // 寄存器作为操作数  如:Opcode REG, REG

struct ModRM16
{
  uint32  Mode;              // 寻址模式
  uint32  Mod;   
  uint32  RegOp;
  uint32  RM;
  uint32  Reg1;
  uint32  Reg2;
};

// SIB表表专用宏
#define SIB_NATURAL        0x1    // 普通
#define SIB_NO0          0x2    // 无比例因子
#define SIB_NO0_BASE100      0x3    // 无比例因子,使用ss段前缀
#define SIB_NO0_BASE101      0x4    // 无比例因子,要判断MOD是否是00
#define SIB_BASE100        0x5    // 使用ss段前缀
#define SIB_BASE101        0x6    // 要判断MOD是否是00
#define SIB_INDEX100      0x7    // 无索引寄存器,无比例因子
#define SIB_INDEX100_BASE100  0x8    // 无索引寄存器,无比例因子,使用ss段前缀
#define SIB_INDEX100_BASE101  0x9    // 无索引寄存器,无比例因子,要判断MOD是否是00

#define N_00        0x0
#define N_01        0x2
#define N_10        0x4
#define N_11        0x8 

#define INDEX_0        0x0
#define INDEX_1        0x1 
#define INDEX_2        0x2 
#define INDEX_3        0x3 
#define INDEX_4        0x4 
#define INDEX_5        0x5 
#define INDEX_6        0x6 
#define INDEX_7        0x7 

#define BASE_0        0x0
#define BASE_1        0x1
#define BASE_2        0x2
#define BASE_3        0x3
#define BASE_4        0x4
#define BASE_5        0x5
#define BASE_6        0x6
#define BASE_7        0x7

// SIB表
struct SIB
{
  uint32   Mode;            // 寻址模式
  uint32   N;         // 比例因子
  uint32   Index;           // 索引寄存器索引
  uint32   Base;            // 基址寄存器索引
};

然后表的内容:
ModRM32 g_TabModRM32[0x100] =
{
  /* 0x00 */   { MODRM32_MEM_FREG       , MOD_00, REG_OP_0, RM_0 },
  /* 0x01 */   { MODRM32_MEM_FREG       , MOD_00, REG_OP_0, RM_1 },
  /* 0x02 */   { MODRM32_MEM_FREG       , MOD_00, REG_OP_0, RM_2 },
  /* 0x03 */   { MODRM32_MEM_FREG       , MOD_00, REG_OP_0, RM_3 },
  /* 0x04 */   { MODRM32_SIB           , MOD_00, REG_OP_0, RM_4 },
  /* 0x05 */   { MODRM32_MEM_IMM4       , MOD_00, REG_OP_0, RM_5 },
        ......
}

ModRM16 g_TabModRM16[0x100] =
{
  /* 0x0 */   { MODRM16_MEM_2REG      , MOD_00, REG_OP_0, RM_0, R_BX, R_SI },
  /* 0x1 */   { MODRM16_MEM_2REG      , MOD_00, REG_OP_0, RM_1, R_BX, R_DI },
  /* 0x2 */   { MODRM16_MEM_2REG      , MOD_00, REG_OP_0, RM_2, R_BP, R_SI },
  /* 0x3 */   { MODRM16_MEM_2REG      , MOD_00, REG_OP_0, RM_3, R_BP, R_DI },
  /* 0x4 */   { MODRM16_MEM_1REG      , MOD_00, REG_OP_0, RM_4, R_SI, R_NO },
  /* 0x5 */   { MODRM16_MEM_1REG      , MOD_00, REG_OP_0, RM_5, R_DI, R_NO },
  /* 0x6 */   { MODRM16_MEM_IMM2      , MOD_00, REG_OP_0, RM_6, R_NO, R_NO },
  /* 0x7 */   { MODRM16_MEM_1REG      , MOD_00, REG_OP_0, RM_7, R_BX, R_NO },
        ....
}
等表。。。

解析mod和sib部分就这样:
          // 32位寻址址模式
          switch(TabModRM->Mode)
          {
            // 全寄存器寻址即:Mod == 00, R/M != 100, R/M != 101  如:Opcode [FEG], REG
          case MODRM32_MEM_FREG:
            {
              T->Type = OPERAND_MEM;

              T->u.Mem.Type = MEM_REG;
              T->u.Mem.Size = SizeAddress;
              T->u.Mem.Segment = Prefix[INDEX_SEG];

              T->u.Mem.u.Reg = g_TabReg[R_INDEXREG32][TabModRM->RM];
            }
            break;
            // 全寄存器加立即数1寻址即:Mod == 01, R/M != 100  如:Opcode [FEG + IMM1], REG
          case MODRM32_MEM_FREG_IMM1:
            {
              T->Type = OPERAND_MEM;

              T->u.Mem.Type = MEM_REGIMM;
              T->u.Mem.Size = SizeAddress;
              T->u.Mem.Segment = Prefix[INDEX_SEG];

              T->u.Mem.u.RegImm.Reg = g_TabReg[R_INDEXREG32][TabModRM->RM];
              T->u.Mem.u.RegImm.Imm.Size = IMM8;
              T->u.Mem.u.RegImm.Imm.u.Imm8 = *(int8*)(Code + Offset + 1);

              ++Offset;
            }
            break;

源码见附件:

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
免费 6
支持
分享
最新回复 (5)
雪    币: 292
活跃值: (153)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
今年 你是第5个 写反汇编引擎发在 看雪的人了~    :D
2013-3-7 19:39
0
雪    币: 143
活跃值: (263)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
偶准备写第六个 别和我抢
2013-3-7 22:31
0
雪    币: 357
活跃值: (3123)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
4
我也在写反汇编引擎..
2013-3-7 23:27
0
雪    币: 217
活跃值: (41)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
哈哈 是的 就是没人写64位的
2013-3-8 09:26
0
雪    币: 244
活跃值: (63)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
同求~
2013-5-10 21:29
0
游客
登录 | 注册 方可回帖
返回
//