首页
论坛
课程
招聘
[原创]以"2021强网杯unicorn_like_a_pro"入门unicorn
2021-6-17 20:13 9706

[原创]以"2021强网杯unicorn_like_a_pro"入门unicorn

2021-6-17 20:13
9706

以"2021强网杯unicorn_like_a_pro"学习unicorn

一:Ready

unicorn编译安装:

 

https://github.com/unicorn-engine/unicorn

 

(./make.sh之后./make.sh install)

1
2
3
4
5
6
使用 C 和 Python 语言编程的教程。
http://unicorn-engine.org/docs/tutorial.html
比较 Unicorn 和 QEMU
http://unicorn-engine.org/docs/beyond_qemu.html
Micro Uncorn-Engine API 中文文档
https://github.com/kabeor/Micro-Unicorn-Engine-API-Documentation

unicorn简介:

1
2
3
4
5
6
7
8
9
10
Unicorn 是一个轻量级, 多平台, 多架构的 CPU 模拟器框架.
我们可以更好地关注 CPU 操作, 忽略机器设备的差异. 想象一下, 我们可以将其应用于这些情景:
比如我们单纯只是需要模拟代码的执行而非需要一个真的 CPU 去完成那些操作, 又或者想要更安全地
分析恶意代码, 检测病毒特征, 或者想要在逆向过程中验证某些代码的含义. 使用 CPU 模拟器可以很好
地帮助我们提供便捷.
它的亮点 (这也归功于 Unicorn 是基于 qemu 而开发的) 包括:
支持多种架构: Arm, Arm64 (Armv8), M68K, Mips, Sparc, & X86 (include X86_64).
对 Windows 和 nix 系统 (已确认包含 Mac OSX, Linux, BSD & Solaris) 的原生支持
具有平台独立且简洁易于使用的 API
使用 JIT 编译技术, 性能表现优异

应用场景:

1
2
3
4
5
• 你可以调用恶意软件中一些有趣的函数, 而不用创建一个有害的进程.
• 用于 CTF 竞赛
• 用于模糊测试
• 用于 gdb 插件, 基于代码模拟执行的插件
• 模拟执行一些混淆代码

python模拟X86_32:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from unicorn import *
from unicorn.x86_const import *
# 需要使用一些x86常量, import一下
X86_CODE32 = b"\x41\x4a"    # 这是我们要模拟的代码,这里使用16进制表示,表示两个x86指令“INC ecx”和”DEC dex“
Address = 0x1000000         # 指定虚拟地址,我们将在这儿模拟上述代码
mu = Uc(UC_ARCH_X86, UC_MODE_32)
# 使用Uc类初始化Unicorn, 该类接受2个参数:硬件架构和硬件模式。 在这里,我们希望模拟X86体系结构的32位代码
mu.mem_map(Address, 2*1024*1024)
# 使用mem_map方法在前面声明的地址处映射2MB内存。此过程中的所有CPU操作都只能访问此内存。 此内存使用默认权限READ,WRITE和EXECUTE进行映射
mu.mem_write(Address, X86_CODE32)
# 将要模拟的代码写入我们刚刚映射到的内存中。 mem_write方法有两个参数:要写入的地址和要写入内存的代码
mu.reg_write(UC_X86_REG_ECX, 0X1234)
mu.reg_write(UC_X86_REG_EDX, 0X7890)    # 使用reg_write方法设置ECX,EDX寄存器的值
mu.emu_start(Address, Address+len(X86_CODE32))
# 使用emu_start方法开始模拟。该API采用4个参数:需要模拟的代码的地址、模拟停止的地址(正好在X86_CODE32的最后一个字节之后)、要模拟的时间和要模拟的指令数量。如果我们忽略最后两个参数,比如这个例子,unicorn将在无限时间和无限数量的指令中模拟代码
r_ecx = mu.reg_read(UC_X86_REG_ECX)
r_edx = mu.reg_read(UC_X86_REG_EDX)
# 通过reg_read函数读取
print(">> ecx = 0x%x" % r_ecx)
print(">> edx = 0x%x" % r_edx)        # 打印出寄存器ECX,EDX的值

更多的python使用unicorn的实例请参考:https://github.com/unicorn-engine/unicorn/tree/master/bindings/python

 

C语言模拟X86_32:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <unicorn.h>
#include <stdio.h>
 
#define X86_CODE32 "\x41\x4a"      //INC ecx; DEC edx
#define Address 0x1000000          //定义一个虚拟地址,我们将在这里模拟上述代码
                                   //memory address where emulation starts
int main(int argc, char **argv, char **envp)
{
    uc_engine *uc;
    uc_err err;
    int r_ecx = 0x1234;     // ECX register
    int r_edx = 0x7890;     // EDX register
    printf("Emulate i386 code\n");
 
   err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); //以X86_32的模式初始化
   if (err != UC_ERR_OK)
   {
       printf("Failed on uc_open() with error returned: %u\n", err);
       return -1;
    }
 
    c_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);     //在对应地址出映射2M的内存
 
    // write machine code to be emulated to memory
    if (uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)){
        printf("Failed to write emulation code to memory, quit!\n");
        return -1;
    }
 
    uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);         //初始话寄存器的值
 
    //最后两个参数没有指定,在无限时间和无限指令中模拟代码
    err=uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0);
    if (err){
      printf("Failed on uc_emu_start() with error returned %u: %s\n",
        err, uc_strerror(err));
    }
 
    // now print out some registers
    printf("Emulation done. Below is the CPU context\n");
 
    uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
    uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
    printf(">>> ECX = 0x%x\n", r_ecx);
    printf(">>> EDX = 0x%x\n", r_edx);
 
    uc_close(uc);
    return 0;
}

更多的C语言使用unicorn的实例请参考:

 

https://github.com/unicorn-engine/unicorn/tree/master/samples

二:符号还原

bindiff安装地址和安装教程:https://www.cnblogs.com/lsdb/p/10543411.html

 

IDA7.5我装过bindiff5和bindiff6,bindiff7装的时候没识别到我的ida路径,不知为何

 

先不使用bindiff的ida插件模式,就普通使用方法,先创建一个workspace之后,将两个i64文件导入即可
图片描述

 

这里可以看出相似度

 

但是一个一个导入还是比较麻烦

 

在安装bindiff的时候,选择你的IDA的路径,就可以顺手将bindiff插件安装到ida中

 

先将那份so文件libunicorn.so(在./make.sh和./make.sh install之后会在文件夹中生成)拖入对应版本IDA进行分析之后,保存i64文件

 

然后使用IDA载入要分析的文件,然后ctrl+6,点击Diff Database
图片描述

 

将那个i64文件载入,载入之后,再次ctrl+6,点击
图片描述
图片描述

三:关键函数

1. uc_open函数解析:

函数声明:

1
2
3
4
5
6
7
8
9
10
11
12
/*
 Create new instance of unicorn engine.
 
 @arch: architecture type (UC_ARCH_*)
 @mode: hardware mode. This is combined of UC_MODE_*
 @uc: pointer to uc_engine, which will be updated at return time
 
 @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
   for detailed error).
*/
UNICORN_EXPORT
uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **uc);
1
2
3
4
5
@arch:架构类型(UC_ARCH_*
@mode:硬件模式。 这是结合 UC_MODE_*
@uc:指向uc_engine的指针,返回时会更新
@return UC_ERR_OK 成功,或其他值失败(参考 uc_err 枚举
  详细错误)。

uc_arch和uc_mode的枚举值:

1
2
3
4
5
6
7
8
9
10
typedef enum uc_arch {
    UC_ARCH_ARM = 1,    // ARM architecture (including Thumb, Thumb-2)
    UC_ARCH_ARM64,      // ARM-64, also called AArch64
    UC_ARCH_MIPS,       // Mips architecture
    UC_ARCH_X86,        // X86 architecture (including x86 & x86-64)
    UC_ARCH_PPC,        // PowerPC architecture (currently unsupported)
    UC_ARCH_SPARC,      // Sparc architecture
    UC_ARCH_M68K,       // M68K architecture
    UC_ARCH_MAX,
} uc_arch;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Mode type
typedef enum uc_mode {
    UC_MODE_LITTLE_ENDIAN = 0,    // little-endian mode (default mode)
    UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode
 
    // arm / arm64
    UC_MODE_ARM = 0,              // ARM mode
    UC_MODE_THUMB = 1 << 4,       // THUMB mode (including Thumb-2)
    UC_MODE_MCLASS = 1 << 5,      // ARM's Cortex-M series (currently unsupported)
    UC_MODE_V8 = 1 << 6,          // ARMv8 A32 encodings for ARM (currently unsupported)
 
    // arm (32bit) cpu types
    UC_MODE_ARM926 = 1 << 7,      // ARM926 CPU type
    UC_MODE_ARM946 = 1 << 8,      // ARM946 CPU type
    UC_MODE_ARM1176 = 1 << 9,      // ARM1176 CPU type
 
    // ARM BE8
    UC_MODE_ARMBE8 = 1 << 10,     // Big-endian data and Little-endian code
 
    // mips
    UC_MODE_MICRO = 1 << 4,       // MicroMips mode (currently unsupported)
    UC_MODE_MIPS3 = 1 << 5,       // Mips III ISA (currently unsupported)
    UC_MODE_MIPS32R6 = 1 << 6,    // Mips32r6 ISA (currently unsupported)
    UC_MODE_MIPS32 = 1 << 2,      // Mips32 ISA
    UC_MODE_MIPS64 = 1 << 3,      // Mips64 ISA
 
    // x86 / x64
    UC_MODE_16 = 1 << 1,          // 16-bit mode
    UC_MODE_32 = 1 << 2,          // 32-bit mode
    UC_MODE_64 = 1 << 3,          // 64-bit mode
 
    // ppc
    UC_MODE_PPC32 = 1 << 2,       // 32-bit mode (currently unsupported)
    UC_MODE_PPC64 = 1 << 3,       // 64-bit mode (currently unsupported)
    UC_MODE_QPX = 1 << 4,         // Quad Processing eXtensions mode (currently unsupported)
 
    // sparc
    UC_MODE_SPARC32 = 1 << 2,     // 32-bit mode
    UC_MODE_SPARC64 = 1 << 3,     // 64-bit mode
    UC_MODE_V9 = 1 << 4,          // SparcV9 mode (currently unsupported)
 
    // m68k
} uc_mode;

然后在程序中是uc_open(4u, 8, &uc);

 

图片描述

 

即uc_open(UC_ARCH_X86, UC_MODE_64, &uc);

2. uc_mem_map函数解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 Map memory in for emulation.
 This API adds a memory region that can be used by emulation.
 
 @uc: handle returned by uc_open()
 @address: starting address of the new memory region to be mapped in.
    This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
 @size: size of the new memory region to be mapped in.
    This size must be a multiple of 4KB, or this will return with UC_ERR_ARG error.
 @perms: Permissions for the newly mapped region.
    This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
    or this will return with UC_ERR_ARG error.
 
 @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
   for detailed error).
*/
UNICORN_EXPORT
uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms);
1
2
3
4
5
6
7
8
9
10
11
12
13
映射内存以进行仿真。
  该API添加了一个可供仿真使用的内存区域。
参数:
  @uc: uc_open() 返回的句柄
  @address:要映射到的新内存区域的起始地址。
     该地址必须与 4KB 对齐,否则将返回 UC_ERR_ARG 错误。
  @size:要映射到的新内存区域的大小。
     此大小必须是 4KB 的倍数,否则将返回 UC_ERR_ARG 错误。
  @perms:新映射区域的权限。
     这必须是 UC_PROT_READ | 的某种组合。 UC_PROT_WRITE | UC_PROT_EXEC,
     否则这将返回 UC_ERR_ARG 错误。
  @return UC_ERR_OK 成功,或其他值失败(参考 uc_err 枚举
    详细错误)。

最后一个参数是uc_prot的枚举值:

1
2
3
4
5
6
7
typedef enum uc_prot {
   UC_PROT_NONE = 0,
   UC_PROT_READ = 1,
   UC_PROT_WRITE = 2,
   UC_PROT_EXEC = 4,
   UC_PROT_ALL = 7,
} uc_prot;

例如程序中:

 

uc_mem_map(uc, 0x1000LL, 0x2000LL, 7u);

 

图片描述

 

说明这个是从0x1000开始映射了0x2000大小的内存,最后一个参数是权限,uc_prot值为7代表UC_PROT_ALL

3. uc_mem_write

函数声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 Write to a range of bytes in memory.
 
 @uc: handle returned by uc_open()
 @address: starting memory address of bytes to set.
 @bytes:   pointer to a variable containing data to be written to memory.
 @size:   size of memory to write to.
 
 NOTE: @bytes must be big enough to contain @size bytes.
 
 @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
   for detailed error).
*/
UNICORN_EXPORT
uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size);
1
2
3
4
5
6
7
8
写入内存中的字节范围。
  @uc: uc_open() 返回的句柄
  @address:要设置的字节的起始内存地址。
  @bytes:指向包含要写入内存的数据的变量的指针。
  @size:要写入的内存大小。
  注意:@bytes 必须足够大以包含 @size 字节。
  @return UC_ERR_OK 成功,或其他值失败(参考 uc_err 枚举
    详细错误)

例程序中:

 

uc_mem_write(uc, 0x1000LL, &code, 0x1027LL);

 

从0x1000开始写入我们的X86_CODE64,最后一个参数是0x1027,这个是说明code的最小大小的,查看内存可知,code共0x104F,大于0x1027字节

4. uc_reg_write

函数声明:

1
2
3
4
5
6
7
8
9
10
11
12
/*
 Write to register.
 
 @uc: handle returned by uc_open()
 @regid:  register ID that is to be modified.
 @value:  pointer to the value that will set to register @regid
 
 @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
   for detailed error).
*/
UNICORN_EXPORT
uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
1
2
3
4
5
@uc: uc_open() 返回的句柄
  @regid:要修改的注册ID
  @value:指向将设置为注册@regid 的值的指针
  @return UC_ERR_OK 成功,或其他值失败(参考 uc_err 枚举
    详细错误)。

第二个值是unicorn规定的x86寄存器的枚举值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//> X86 registers
typedef enum uc_x86_reg {
    UC_X86_REG_INVALID = 0,
    UC_X86_REG_AH, UC_X86_REG_AL, UC_X86_REG_AX, UC_X86_REG_BH, UC_X86_REG_BL,
    UC_X86_REG_BP, UC_X86_REG_BPL, UC_X86_REG_BX, UC_X86_REG_CH, UC_X86_REG_CL,
    UC_X86_REG_CS, UC_X86_REG_CX, UC_X86_REG_DH, UC_X86_REG_DI, UC_X86_REG_DIL,
    UC_X86_REG_DL, UC_X86_REG_DS, UC_X86_REG_DX, UC_X86_REG_EAX, UC_X86_REG_EBP,
    UC_X86_REG_EBX, UC_X86_REG_ECX, UC_X86_REG_EDI, UC_X86_REG_EDX, UC_X86_REG_EFLAGS,
    UC_X86_REG_EIP, UC_X86_REG_EIZ, UC_X86_REG_ES, UC_X86_REG_ESI, UC_X86_REG_ESP,
    UC_X86_REG_FPSW, UC_X86_REG_FS, UC_X86_REG_GS, UC_X86_REG_IP, UC_X86_REG_RAX,
    UC_X86_REG_RBP, UC_X86_REG_RBX, UC_X86_REG_RCX, UC_X86_REG_RDI, UC_X86_REG_RDX,
    UC_X86_REG_RIP, UC_X86_REG_RIZ, UC_X86_REG_RSI, UC_X86_REG_RSP, UC_X86_REG_SI,
    UC_X86_REG_SIL, UC_X86_REG_SP, UC_X86_REG_SPL, UC_X86_REG_SS, UC_X86_REG_CR0,
    UC_X86_REG_CR1, UC_X86_REG_CR2, UC_X86_REG_CR3, UC_X86_REG_CR4, UC_X86_REG_CR5,
    UC_X86_REG_CR6, UC_X86_REG_CR7, UC_X86_REG_CR8, UC_X86_REG_CR9, UC_X86_REG_CR10,
    UC_X86_REG_CR11, UC_X86_REG_CR12, UC_X86_REG_CR13, UC_X86_REG_CR14, UC_X86_REG_CR15,
    UC_X86_REG_DR0, UC_X86_REG_DR1, UC_X86_REG_DR2, UC_X86_REG_DR3, UC_X86_REG_DR4,
    UC_X86_REG_DR5, UC_X86_REG_DR6, UC_X86_REG_DR7, UC_X86_REG_DR8, UC_X86_REG_DR9,
    UC_X86_REG_DR10, UC_X86_REG_DR11, UC_X86_REG_DR12, UC_X86_REG_DR13, UC_X86_REG_DR14,
    UC_X86_REG_DR15, UC_X86_REG_FP0, UC_X86_REG_FP1, UC_X86_REG_FP2, UC_X86_REG_FP3,
    UC_X86_REG_FP4, UC_X86_REG_FP5, UC_X86_REG_FP6, UC_X86_REG_FP7,
    UC_X86_REG_K0, UC_X86_REG_K1, UC_X86_REG_K2, UC_X86_REG_K3, UC_X86_REG_K4,
    UC_X86_REG_K5, UC_X86_REG_K6, UC_X86_REG_K7, UC_X86_REG_MM0, UC_X86_REG_MM1,
    UC_X86_REG_MM2, UC_X86_REG_MM3, UC_X86_REG_MM4, UC_X86_REG_MM5, UC_X86_REG_MM6,
    UC_X86_REG_MM7, UC_X86_REG_R8, UC_X86_REG_R9, UC_X86_REG_R10, UC_X86_REG_R11,
    UC_X86_REG_R12, UC_X86_REG_R13, UC_X86_REG_R14, UC_X86_REG_R15,
    UC_X86_REG_ST0, UC_X86_REG_ST1, UC_X86_REG_ST2, UC_X86_REG_ST3,
    UC_X86_REG_ST4, UC_X86_REG_ST5, UC_X86_REG_ST6, UC_X86_REG_ST7,
    UC_X86_REG_XMM0, UC_X86_REG_XMM1, UC_X86_REG_XMM2, UC_X86_REG_XMM3, UC_X86_REG_XMM4,
    UC_X86_REG_XMM5, UC_X86_REG_XMM6, UC_X86_REG_XMM7, UC_X86_REG_XMM8, UC_X86_REG_XMM9,
    UC_X86_REG_XMM10, UC_X86_REG_XMM11, UC_X86_REG_XMM12, UC_X86_REG_XMM13, UC_X86_REG_XMM14,
    UC_X86_REG_XMM15, UC_X86_REG_XMM16, UC_X86_REG_XMM17, UC_X86_REG_XMM18, UC_X86_REG_XMM19,
    UC_X86_REG_XMM20, UC_X86_REG_XMM21, UC_X86_REG_XMM22, UC_X86_REG_XMM23, UC_X86_REG_XMM24,
    UC_X86_REG_XMM25, UC_X86_REG_XMM26, UC_X86_REG_XMM27, UC_X86_REG_XMM28, UC_X86_REG_XMM29,
    UC_X86_REG_XMM30, UC_X86_REG_XMM31, UC_X86_REG_YMM0, UC_X86_REG_YMM1, UC_X86_REG_YMM2,
    UC_X86_REG_YMM3, UC_X86_REG_YMM4, UC_X86_REG_YMM5, UC_X86_REG_YMM6, UC_X86_REG_YMM7,
    UC_X86_REG_YMM8, UC_X86_REG_YMM9, UC_X86_REG_YMM10, UC_X86_REG_YMM11, UC_X86_REG_YMM12,
    UC_X86_REG_YMM13, UC_X86_REG_YMM14, UC_X86_REG_YMM15, UC_X86_REG_YMM16, UC_X86_REG_YMM17,
    UC_X86_REG_YMM18, UC_X86_REG_YMM19, UC_X86_REG_YMM20, UC_X86_REG_YMM21, UC_X86_REG_YMM22,
    UC_X86_REG_YMM23, UC_X86_REG_YMM24, UC_X86_REG_YMM25, UC_X86_REG_YMM26, UC_X86_REG_YMM27,
    UC_X86_REG_YMM28, UC_X86_REG_YMM29, UC_X86_REG_YMM30, UC_X86_REG_YMM31, UC_X86_REG_ZMM0,
    UC_X86_REG_ZMM1, UC_X86_REG_ZMM2, UC_X86_REG_ZMM3, UC_X86_REG_ZMM4, UC_X86_REG_ZMM5,
    UC_X86_REG_ZMM6, UC_X86_REG_ZMM7, UC_X86_REG_ZMM8, UC_X86_REG_ZMM9, UC_X86_REG_ZMM10,
    UC_X86_REG_ZMM11, UC_X86_REG_ZMM12, UC_X86_REG_ZMM13, UC_X86_REG_ZMM14, UC_X86_REG_ZMM15,
    UC_X86_REG_ZMM16, UC_X86_REG_ZMM17, UC_X86_REG_ZMM18, UC_X86_REG_ZMM19, UC_X86_REG_ZMM20,
    UC_X86_REG_ZMM21, UC_X86_REG_ZMM22, UC_X86_REG_ZMM23, UC_X86_REG_ZMM24, UC_X86_REG_ZMM25,
    UC_X86_REG_ZMM26, UC_X86_REG_ZMM27, UC_X86_REG_ZMM28, UC_X86_REG_ZMM29, UC_X86_REG_ZMM30,
    UC_X86_REG_ZMM31, UC_X86_REG_R8B, UC_X86_REG_R9B, UC_X86_REG_R10B, UC_X86_REG_R11B,
    UC_X86_REG_R12B, UC_X86_REG_R13B, UC_X86_REG_R14B, UC_X86_REG_R15B, UC_X86_REG_R8D,
    UC_X86_REG_R9D, UC_X86_REG_R10D, UC_X86_REG_R11D, UC_X86_REG_R12D, UC_X86_REG_R13D,
    UC_X86_REG_R14D, UC_X86_REG_R15D, UC_X86_REG_R8W, UC_X86_REG_R9W, UC_X86_REG_R10W,
    UC_X86_REG_R11W, UC_X86_REG_R12W, UC_X86_REG_R13W, UC_X86_REG_R14W, UC_X86_REG_R15W,
    UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW,
    UC_X86_REG_FPTAG,
    UC_X86_REG_MSR, // Model-Specific Register
    UC_X86_REG_MXCSR,
    UC_X86_REG_FS_BASE, // Base regs for x86_64
    UC_X86_REG_GS_BASE,
    UC_X86_REG_ENDING        // <-- mark the end of the list of registers
} uc_x86_reg;

5. uc_hook_add函数解析:

uc_hook_add函数声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 Register callback for a hook event.
 The callback will be run when the hook event is hit.
 
 @uc: handle returned by uc_open()
 @hh: hook handle returned from this registration. To be used in uc_hook_del() API
 @type: hook type, refer to uc_hook_type enum
 @callback: callback to be run when instruction is hit
 @user_data: user-defined data. This will be passed to callback function in its
      last argument @user_data
 @begin: start address of the area where the callback is in effect (inclusive)
 @end: end address of the area where the callback is in effect (inclusive)
   NOTE 1: the callback is called only if related address is in range [@begin, @end]
   NOTE 2: if @begin > @end, callback is called whenever this hook type is triggered
 @...: variable arguments (depending on @type)
   NOTE: if @type = UC_HOOK_INSN, this is the instruction ID (ex: UC_X86_INS_OUT)
 
 @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
   for detailed error).
*/
UNICORN_EXPORT
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
        void *user_data, uint64_t begin, uint64_t end, ...);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
**为钩子事件注册回调
当钩子事件被命中时,回调将运行**
 
@uc: uc_open() 返回的句柄
@hh**从这个注册函数返回的钩子句柄**。用于 uc_hook_del() API
**@type:钩子类型,参考uc_hook_type枚举**
**@callback:当指令被命中时运行的回调**
**@user_data:用户定义的数据。这将传递给回调函数的最后一个参数@user_data**
@begin:回调生效区域的起始地址(含)
@end:回调生效区域的结束地址(含)
  注意 1:仅当相关地址在 [@begin, @end] 范围内时才会调用回调
  注意 2:如果 @begin > @end,每当触发此钩子类型时都会调用回调
@...:可变参数(取决于@type
  **注意:如果@type = UC_HOOK_INSN,这是指令ID(例如:UC_X86_INS_OUT)**
@return UC_ERR_OK 成功,或其他值失败(参考 uc_err 枚举
  详细错误)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// All type of hooks for uc_hook_add() API.
typedef enum uc_hook_type {
    // Hook all interrupt/syscall events
    UC_HOOK_INTR = 1 << 0,
    **// Hook a particular instruction - only a very small subset of instructions supported here
    UC_HOOK_INSN = 1 << 1,**
    // Hook a range of code
    UC_HOOK_CODE = 1 << 2,
    // Hook basic blocks
    UC_HOOK_BLOCK = 1 << 3,
    // Hook for memory read on unmapped memory
    UC_HOOK_MEM_READ_UNMAPPED = 1 << 4,
    // Hook for invalid memory write events
    UC_HOOK_MEM_WRITE_UNMAPPED = 1 << 5,
    // Hook for invalid memory fetch for execution events
    UC_HOOK_MEM_FETCH_UNMAPPED = 1 << 6,
    // Hook for memory read on read-protected memory
    UC_HOOK_MEM_READ_PROT = 1 << 7,
    // Hook for memory write on write-protected memory
    UC_HOOK_MEM_WRITE_PROT = 1 << 8,
    // Hook for memory fetch on non-executable memory
    UC_HOOK_MEM_FETCH_PROT = 1 << 9,
    **// Hook memory read events.
    UC_HOOK_MEM_READ = 1 << 10,**
    // Hook memory write events.
    UC_HOOK_MEM_WRITE = 1 << 11,
    // Hook memory fetch for execution events
    UC_HOOK_MEM_FETCH = 1 << 12,
    // Hook memory read events, but only successful access.
    // The callback will be triggered after successful read.
    UC_HOOK_MEM_READ_AFTER = 1 << 13,
    // Hook invalid instructions exceptions.
    UC_HOOK_INSN_INVALID = 1 << 14,
} uc_hook_type;

uc_hook_add的第三个参数的值是2,即(uc_hook_type)UC_HOOK_INSN, 钩住一个特定的指令——这里只支持非常小的指令子集

 

如果第三个参数的值是0x400,说明这是钩取的内存读 // Hook memory read events.

 

反正这个函数的关键就在第三个参数

 

最后一个参数,就像函数声明中说的一样,如果@type = UC_HOOK_INSN,这是指令ID(例如:UC_X86_INS_OUT,就是一些X86的指令,枚举值如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
//> X86 instructions
typedef enum uc_x86_insn {
    UC_X86_INS_INVALID = 0,
    UC_X86_INS_AAA,
    UC_X86_INS_AAD,
    UC_X86_INS_AAM,
    UC_X86_INS_AAS,
    UC_X86_INS_FABS,
    UC_X86_INS_ADC,
    UC_X86_INS_ADCX,
    UC_X86_INS_ADD,
    UC_X86_INS_ADDPD,
    UC_X86_INS_ADDPS,
    UC_X86_INS_ADDSD,
    UC_X86_INS_ADDSS,
    UC_X86_INS_ADDSUBPD,
    UC_X86_INS_ADDSUBPS,
    UC_X86_INS_FADD,
    UC_X86_INS_FIADD,
    UC_X86_INS_FADDP,
    UC_X86_INS_ADOX,
    UC_X86_INS_AESDECLAST,
    UC_X86_INS_AESDEC,
    UC_X86_INS_AESENCLAST,
    UC_X86_INS_AESENC,
    UC_X86_INS_AESIMC,
    UC_X86_INS_AESKEYGENASSIST,
    UC_X86_INS_AND,
    UC_X86_INS_ANDN,
    UC_X86_INS_ANDNPD,
    UC_X86_INS_ANDNPS,
    UC_X86_INS_ANDPD,
    UC_X86_INS_ANDPS,
    UC_X86_INS_ARPL,
    UC_X86_INS_BEXTR,
    UC_X86_INS_BLCFILL,
    UC_X86_INS_BLCI,
    UC_X86_INS_BLCIC,
    UC_X86_INS_BLCMSK,
    UC_X86_INS_BLCS,
    UC_X86_INS_BLENDPD,
    UC_X86_INS_BLENDPS,
    UC_X86_INS_BLENDVPD,
    UC_X86_INS_BLENDVPS,
    UC_X86_INS_BLSFILL,
    UC_X86_INS_BLSI,
    UC_X86_INS_BLSIC,
    UC_X86_INS_BLSMSK,
    UC_X86_INS_BLSR,
    UC_X86_INS_BOUND,
    UC_X86_INS_BSF,
    UC_X86_INS_BSR,
    UC_X86_INS_BSWAP,
    UC_X86_INS_BT,
    UC_X86_INS_BTC,
    UC_X86_INS_BTR,
    UC_X86_INS_BTS,
    UC_X86_INS_BZHI,
    UC_X86_INS_CALL,
    UC_X86_INS_CBW,
    UC_X86_INS_CDQ,
    UC_X86_INS_CDQE,
    UC_X86_INS_FCHS,
    UC_X86_INS_CLAC,
    UC_X86_INS_CLC,
    UC_X86_INS_CLD,
    UC_X86_INS_CLFLUSH,
    UC_X86_INS_CLFLUSHOPT,
    UC_X86_INS_CLGI,
    UC_X86_INS_CLI,
    UC_X86_INS_CLTS,
    UC_X86_INS_CLWB,
    UC_X86_INS_CMC,
    UC_X86_INS_CMOVA,
    UC_X86_INS_CMOVAE,
    UC_X86_INS_CMOVB,
    UC_X86_INS_CMOVBE,
    UC_X86_INS_FCMOVBE,
    UC_X86_INS_FCMOVB,
    UC_X86_INS_CMOVE,
    UC_X86_INS_FCMOVE,
    UC_X86_INS_CMOVG,
    UC_X86_INS_CMOVGE,
    UC_X86_INS_CMOVL,
    UC_X86_INS_CMOVLE,
    UC_X86_INS_FCMOVNBE,
    UC_X86_INS_FCMOVNB,
    UC_X86_INS_CMOVNE,
    UC_X86_INS_FCMOVNE,
    UC_X86_INS_CMOVNO,
    UC_X86_INS_CMOVNP,
    UC_X86_INS_FCMOVNU,
    UC_X86_INS_CMOVNS,
    UC_X86_INS_CMOVO,
    UC_X86_INS_CMOVP,
    UC_X86_INS_FCMOVU,
    UC_X86_INS_CMOVS,
    UC_X86_INS_CMP,
    UC_X86_INS_CMPPD,
    UC_X86_INS_CMPPS,
    UC_X86_INS_CMPSB,
    UC_X86_INS_CMPSD,
    UC_X86_INS_CMPSQ,
    UC_X86_INS_CMPSS,
    UC_X86_INS_CMPSW,
    UC_X86_INS_CMPXCHG16B,
    UC_X86_INS_CMPXCHG,
    UC_X86_INS_CMPXCHG8B,
    UC_X86_INS_COMISD,
    UC_X86_INS_COMISS,
    UC_X86_INS_FCOMP,
    UC_X86_INS_FCOMPI,
    UC_X86_INS_FCOMI,
    UC_X86_INS_FCOM,
    UC_X86_INS_FCOS,
    UC_X86_INS_CPUID,
    UC_X86_INS_CQO,
    UC_X86_INS_CRC32,
    UC_X86_INS_CVTDQ2PD,
    UC_X86_INS_CVTDQ2PS,
    UC_X86_INS_CVTPD2DQ,
    UC_X86_INS_CVTPD2PS,
    UC_X86_INS_CVTPS2DQ,
    UC_X86_INS_CVTPS2PD,
    UC_X86_INS_CVTSD2SI,
    UC_X86_INS_CVTSD2SS,
    UC_X86_INS_CVTSI2SD,
    UC_X86_INS_CVTSI2SS,
    UC_X86_INS_CVTSS2SD,
    UC_X86_INS_CVTSS2SI,
    UC_X86_INS_CVTTPD2DQ,
    UC_X86_INS_CVTTPS2DQ,
    UC_X86_INS_CVTTSD2SI,
    UC_X86_INS_CVTTSS2SI,
    UC_X86_INS_CWD,
    UC_X86_INS_CWDE,
    UC_X86_INS_DAA,
    UC_X86_INS_DAS,
    UC_X86_INS_DATA16,
    UC_X86_INS_DEC,
    UC_X86_INS_DIV,
    UC_X86_INS_DIVPD,
    UC_X86_INS_DIVPS,
    UC_X86_INS_FDIVR,
    UC_X86_INS_FIDIVR,
    UC_X86_INS_FDIVRP,
    UC_X86_INS_DIVSD,
    UC_X86_INS_DIVSS,
    UC_X86_INS_FDIV,
    UC_X86_INS_FIDIV,
    UC_X86_INS_FDIVP,
    UC_X86_INS_DPPD,
    UC_X86_INS_DPPS,
    UC_X86_INS_RET,
    UC_X86_INS_ENCLS,
    UC_X86_INS_ENCLU,
    UC_X86_INS_ENTER,
    UC_X86_INS_EXTRACTPS,
    UC_X86_INS_EXTRQ,
    UC_X86_INS_F2XM1,
    UC_X86_INS_LCALL,
    UC_X86_INS_LJMP,
    UC_X86_INS_FBLD,
    UC_X86_INS_FBSTP,
    UC_X86_INS_FCOMPP,
    UC_X86_INS_FDECSTP,
    UC_X86_INS_FEMMS,
    UC_X86_INS_FFREE,
    UC_X86_INS_FICOM,
    UC_X86_INS_FICOMP,
    UC_X86_INS_FINCSTP,
    UC_X86_INS_FLDCW,
    UC_X86_INS_FLDENV,
    UC_X86_INS_FLDL2E,
    UC_X86_INS_FLDL2T,
    UC_X86_INS_FLDLG2,
    UC_X86_INS_FLDLN2,
    UC_X86_INS_FLDPI,
    UC_X86_INS_FNCLEX,
    UC_X86_INS_FNINIT,
    UC_X86_INS_FNOP,
    UC_X86_INS_FNSTCW,
    UC_X86_INS_FNSTSW,
    UC_X86_INS_FPATAN,
    UC_X86_INS_FPREM,
    UC_X86_INS_FPREM1,
    UC_X86_INS_FPTAN,
    UC_X86_INS_FFREEP,
    UC_X86_INS_FRNDINT,
    UC_X86_INS_FRSTOR,
    UC_X86_INS_FNSAVE,
    UC_X86_INS_FSCALE,
    UC_X86_INS_FSETPM,
    UC_X86_INS_FSINCOS,
    UC_X86_INS_FNSTENV,
    UC_X86_INS_FXAM,
    UC_X86_INS_FXRSTOR,
    UC_X86_INS_FXRSTOR64,
    UC_X86_INS_FXSAVE,
    UC_X86_INS_FXSAVE64,
    UC_X86_INS_FXTRACT,
    UC_X86_INS_FYL2X,
    UC_X86_INS_FYL2XP1,
    UC_X86_INS_MOVAPD,
    UC_X86_INS_MOVAPS,
    UC_X86_INS_ORPD,
    UC_X86_INS_ORPS,
    UC_X86_INS_VMOVAPD,
    UC_X86_INS_VMOVAPS,
    UC_X86_INS_XORPD,
    UC_X86_INS_XORPS,
    UC_X86_INS_GETSEC,
    UC_X86_INS_HADDPD,
    UC_X86_INS_HADDPS,
    UC_X86_INS_HLT,
    UC_X86_INS_HSUBPD,
    UC_X86_INS_HSUBPS,
    UC_X86_INS_IDIV,
    UC_X86_INS_FILD,
    UC_X86_INS_IMUL,
    UC_X86_INS_IN,
    UC_X86_INS_INC,
    UC_X86_INS_INSB,
    UC_X86_INS_INSERTPS,
    UC_X86_INS_INSERTQ,
    UC_X86_INS_INSD,
    UC_X86_INS_INSW,
    UC_X86_INS_INT,
    UC_X86_INS_INT1,
    UC_X86_INS_INT3,
    UC_X86_INS_INTO,
    UC_X86_INS_INVD,
    UC_X86_INS_INVEPT,
    UC_X86_INS_INVLPG,
    UC_X86_INS_INVLPGA,
    UC_X86_INS_INVPCID,
    UC_X86_INS_INVVPID,
    UC_X86_INS_IRET,
    UC_X86_INS_IRETD,
    UC_X86_INS_IRETQ,
    UC_X86_INS_FISTTP,
    UC_X86_INS_FIST,
    UC_X86_INS_FISTP,
    UC_X86_INS_UCOMISD,
    UC_X86_INS_UCOMISS,
    UC_X86_INS_VCOMISD,
    UC_X86_INS_VCOMISS,
    UC_X86_INS_VCVTSD2SS,
    UC_X86_INS_VCVTSI2SD,
    UC_X86_INS_VCVTSI2SS,
    UC_X86_INS_VCVTSS2SD,
    UC_X86_INS_VCVTTSD2SI,
    UC_X86_INS_VCVTTSD2USI,
    UC_X86_INS_VCVTTSS2SI,
    UC_X86_INS_VCVTTSS2USI,
    UC_X86_INS_VCVTUSI2SD,
    UC_X86_INS_VCVTUSI2SS,
    UC_X86_INS_VUCOMISD,
    UC_X86_INS_VUCOMISS,
    UC_X86_INS_JAE,
    UC_X86_INS_JA,
    UC_X86_INS_JBE,
    UC_X86_INS_JB,
    UC_X86_INS_JCXZ,
    UC_X86_INS_JECXZ,
    UC_X86_INS_JE,
    UC_X86_INS_JGE,
    UC_X86_INS_JG,
    UC_X86_INS_JLE,
    UC_X86_INS_JL,
    UC_X86_INS_JMP,
    UC_X86_INS_JNE,
    UC_X86_INS_JNO,
    UC_X86_INS_JNP,
    UC_X86_INS_JNS,
    UC_X86_INS_JO,
    UC_X86_INS_JP,
    UC_X86_INS_JRCXZ,
    UC_X86_INS_JS,
    UC_X86_INS_KANDB,
    UC_X86_INS_KANDD,
    UC_X86_INS_KANDNB,
    UC_X86_INS_KANDND,
    UC_X86_INS_KANDNQ,
    UC_X86_INS_KANDNW,
    UC_X86_INS_KANDQ,
    UC_X86_INS_KANDW,
    UC_X86_INS_KMOVB,
    UC_X86_INS_KMOVD,
    UC_X86_INS_KMOVQ,
    UC_X86_INS_KMOVW,
    UC_X86_INS_KNOTB,
    UC_X86_INS_KNOTD,
    UC_X86_INS_KNOTQ,
    UC_X86_INS_KNOTW,
    UC_X86_INS_KORB,
    UC_X86_INS_KORD,
    UC_X86_INS_KORQ,
    UC_X86_INS_KORTESTB,
    UC_X86_INS_KORTESTD,
    UC_X86_INS_KORTESTQ,
    UC_X86_INS_KORTESTW,
    UC_X86_INS_KORW,
    UC_X86_INS_KSHIFTLB,
    UC_X86_INS_KSHIFTLD,
    UC_X86_INS_KSHIFTLQ,
    UC_X86_INS_KSHIFTLW,
    UC_X86_INS_KSHIFTRB,
    UC_X86_INS_KSHIFTRD,
    UC_X86_INS_KSHIFTRQ,
    UC_X86_INS_KSHIFTRW,
    UC_X86_INS_KUNPCKBW,
    UC_X86_INS_KXNORB,
    UC_X86_INS_KXNORD,
    UC_X86_INS_KXNORQ,
    UC_X86_INS_KXNORW,
    UC_X86_INS_KXORB,
    UC_X86_INS_KXORD,
    UC_X86_INS_KXORQ,
    UC_X86_INS_KXORW,
    UC_X86_INS_LAHF,
    UC_X86_INS_LAR,
    UC_X86_INS_LDDQU,
    UC_X86_INS_LDMXCSR,
    UC_X86_INS_LDS,
    UC_X86_INS_FLDZ,
    UC_X86_INS_FLD1,
    UC_X86_INS_FLD,
    UC_X86_INS_LEA,
    UC_X86_INS_LEAVE,
    UC_X86_INS_LES,
    UC_X86_INS_LFENCE,
    UC_X86_INS_LFS,
    UC_X86_INS_LGDT,
    UC_X86_INS_LGS,
    UC_X86_INS_LIDT,
    UC_X86_INS_LLDT,
    UC_X86_INS_LMSW,
    UC_X86_INS_OR,
    UC_X86_INS_SUB,
    UC_X86_INS_XOR,
    UC_X86_INS_LODSB,
    UC_X86_INS_LODSD,
    UC_X86_INS_LODSQ,
    UC_X86_INS_LODSW,
    UC_X86_INS_LOOP,
    UC_X86_INS_LOOPE,
    UC_X86_INS_LOOPNE,
    UC_X86_INS_RETF,
    UC_X86_INS_RETFQ,
    UC_X86_INS_LSL,
    UC_X86_INS_LSS,
    UC_X86_INS_LTR,
    UC_X86_INS_XADD,
    UC_X86_INS_LZCNT,
    UC_X86_INS_MASKMOVDQU,
    UC_X86_INS_MAXPD,
    UC_X86_INS_MAXPS,
    UC_X86_INS_MAXSD,
    UC_X86_INS_MAXSS,
    UC_X86_INS_MFENCE,
    UC_X86_INS_MINPD,
    UC_X86_INS_MINPS,
    UC_X86_INS_MINSD,
    UC_X86_INS_MINSS,
    UC_X86_INS_CVTPD2PI,
    UC_X86_INS_CVTPI2PD,
    UC_X86_INS_CVTPI2PS,
    UC_X86_INS_CVTPS2PI,
    UC_X86_INS_CVTTPD2PI,
    UC_X86_INS_CVTTPS2PI,
    UC_X86_INS_EMMS,
    UC_X86_INS_MASKMOVQ,
    UC_X86_INS_MOVD,
    UC_X86_INS_MOVDQ2Q,
    UC_X86_INS_MOVNTQ,
    UC_X86_INS_MOVQ2DQ,
    UC_X86_INS_MOVQ,
    UC_X86_INS_PABSB,
    UC_X86_INS_PABSD,
    UC_X86_INS_PABSW,
    UC_X86_INS_PACKSSDW,
    UC_X86_INS_PACKSSWB,
    UC_X86_INS_PACKUSWB,
    UC_X86_INS_PADDB,
    UC_X86_INS_PADDD,
    UC_X86_INS_PADDQ,
    UC_X86_INS_PADDSB,
    UC_X86_INS_PADDSW,
    UC_X86_INS_PADDUSB,
    UC_X86_INS_PADDUSW,
    UC_X86_INS_PADDW,
    UC_X86_INS_PALIGNR,
    UC_X86_INS_PANDN,
    UC_X86_INS_PAND,
    UC_X86_INS_PAVGB,
    UC_X86_INS_PAVGW,
    UC_X86_INS_PCMPEQB,
    UC_X86_INS_PCMPEQD,
    UC_X86_INS_PCMPEQW,
    UC_X86_INS_PCMPGTB,
    UC_X86_INS_PCMPGTD,
    UC_X86_INS_PCMPGTW,
    UC_X86_INS_PEXTRW,
    UC_X86_INS_PHADDSW,
    UC_X86_INS_PHADDW,
    UC_X86_INS_PHADDD,
    UC_X86_INS_PHSUBD,
    UC_X86_INS_PHSUBSW,
    UC_X86_INS_PHSUBW,
    UC_X86_INS_PINSRW,
    UC_X86_INS_PMADDUBSW,
    UC_X86_INS_PMADDWD,
    UC_X86_INS_PMAXSW,
    UC_X86_INS_PMAXUB,
    UC_X86_INS_PMINSW,
    UC_X86_INS_PMINUB,
    UC_X86_INS_PMOVMSKB,
    UC_X86_INS_PMULHRSW,
    UC_X86_INS_PMULHUW,
    UC_X86_INS_PMULHW,
    UC_X86_INS_PMULLW,
    UC_X86_INS_PMULUDQ,
    UC_X86_INS_POR,
    UC_X86_INS_PSADBW,
    UC_X86_INS_PSHUFB,
    UC_X86_INS_PSHUFW,
    UC_X86_INS_PSIGNB,
    UC_X86_INS_PSIGND,
    UC_X86_INS_PSIGNW,
    UC_X86_INS_PSLLD,
    UC_X86_INS_PSLLQ,
    UC_X86_INS_PSLLW,
    UC_X86_INS_PSRAD,
    UC_X86_INS_PSRAW,
    UC_X86_INS_PSRLD,
    UC_X86_INS_PSRLQ,
    UC_X86_INS_PSRLW,
    UC_X86_INS_PSUBB,
    UC_X86_INS_PSUBD,
    UC_X86_INS_PSUBQ,
    UC_X86_INS_PSUBSB,
    UC_X86_INS_PSUBSW,
    UC_X86_INS_PSUBUSB,
    UC_X86_INS_PSUBUSW,
    UC_X86_INS_PSUBW,
    UC_X86_INS_PUNPCKHBW,
    UC_X86_INS_PUNPCKHDQ,
    UC_X86_INS_PUNPCKHWD,
    UC_X86_INS_PUNPCKLBW,
    UC_X86_INS_PUNPCKLDQ,
    UC_X86_INS_PUNPCKLWD,
    UC_X86_INS_PXOR,
    UC_X86_INS_MONITOR,
    UC_X86_INS_MONTMUL,
    UC_X86_INS_MOV,
    UC_X86_INS_MOVABS,
    UC_X86_INS_MOVBE,
    UC_X86_INS_MOVDDUP,
    UC_X86_INS_MOVDQA,
    UC_X86_INS_MOVDQU,
    UC_X86_INS_MOVHLPS,
    UC_X86_INS_MOVHPD,
    UC_X86_INS_MOVHPS,
    UC_X86_INS_MOVLHPS,
    UC_X86_INS_MOVLPD,
    UC_X86_INS_MOVLPS,
    UC_X86_INS_MOVMSKPD,
    UC_X86_INS_MOVMSKPS,
    UC_X86_INS_MOVNTDQA,
    UC_X86_INS_MOVNTDQ,
    UC_X86_INS_MOVNTI,
    UC_X86_INS_MOVNTPD,
    UC_X86_INS_MOVNTPS,
    UC_X86_INS_MOVNTSD,
    UC_X86_INS_MOVNTSS,
    UC_X86_INS_MOVSB,
    UC_X86_INS_MOVSD,
    UC_X86_INS_MOVSHDUP,
    UC_X86_INS_MOVSLDUP,
    UC_X86_INS_MOVSQ,
    UC_X86_INS_MOVSS,
    UC_X86_INS_MOVSW,
    UC_X86_INS_MOVSX,
    UC_X86_INS_MOVSXD,
    UC_X86_INS_MOVUPD,
    UC_X86_INS_MOVUPS,
    UC_X86_INS_MOVZX,
    UC_X86_INS_MPSADBW,
    UC_X86_INS_MUL,
    UC_X86_INS_MULPD,
    UC_X86_INS_MULPS,
    UC_X86_INS_MULSD,
    UC_X86_INS_MULSS,
    UC_X86_INS_MULX,
    UC_X86_INS_FMUL,
    UC_X86_INS_FIMUL,
    UC_X86_INS_FMULP,
    UC_X86_INS_MWAIT,
    UC_X86_INS_NEG,
    UC_X86_INS_NOP,
    UC_X86_INS_NOT,
    UC_X86_INS_OUT,
    UC_X86_INS_OUTSB,
    UC_X86_INS_OUTSD,
    UC_X86_INS_OUTSW,
    UC_X86_INS_PACKUSDW,
    UC_X86_INS_PAUSE,
    UC_X86_INS_PAVGUSB,
    UC_X86_INS_PBLENDVB,
    UC_X86_INS_PBLENDW,
    UC_X86_INS_PCLMULQDQ,
    UC_X86_INS_PCMPEQQ,
    UC_X86_INS_PCMPESTRI,
    UC_X86_INS_PCMPESTRM,
    UC_X86_INS_PCMPGTQ,
    UC_X86_INS_PCMPISTRI,
    UC_X86_INS_PCMPISTRM,
    UC_X86_INS_PCOMMIT,
    UC_X86_INS_PDEP,
    UC_X86_INS_PEXT,
    UC_X86_INS_PEXTRB,
    UC_X86_INS_PEXTRD,
    UC_X86_INS_PEXTRQ,
    UC_X86_INS_PF2ID,
    UC_X86_INS_PF2IW,
    UC_X86_INS_PFACC,
    UC_X86_INS_PFADD,
    UC_X86_INS_PFCMPEQ,
    UC_X86_INS_PFCMPGE,
    UC_X86_INS_PFCMPGT,
    UC_X86_INS_PFMAX,
    UC_X86_INS_PFMIN,
    UC_X86_INS_PFMUL,
    UC_X86_INS_PFNACC,
    UC_X86_INS_PFPNACC,
    UC_X86_INS_PFRCPIT1,
    UC_X86_INS_PFRCPIT2,
    UC_X86_INS_PFRCP,
    UC_X86_INS_PFRSQIT1,
    UC_X86_INS_PFRSQRT,
    UC_X86_INS_PFSUBR,
    UC_X86_INS_PFSUB,
    UC_X86_INS_PHMINPOSUW,
    UC_X86_INS_PI2FD,
    UC_X86_INS_PI2FW,
    UC_X86_INS_PINSRB,
    UC_X86_INS_PINSRD,
    UC_X86_INS_PINSRQ,
    UC_X86_INS_PMAXSB,
    UC_X86_INS_PMAXSD,
    UC_X86_INS_PMAXUD,
    UC_X86_INS_PMAXUW,
    UC_X86_INS_PMINSB,
    UC_X86_INS_PMINSD,
    UC_X86_INS_PMINUD,
    UC_X86_INS_PMINUW,
    UC_X86_INS_PMOVSXBD,
    UC_X86_INS_PMOVSXBQ,
    UC_X86_INS_PMOVSXBW,
    UC_X86_INS_PMOVSXDQ,
    UC_X86_INS_PMOVSXWD,
    UC_X86_INS_PMOVSXWQ,
    UC_X86_INS_PMOVZXBD,
    UC_X86_INS_PMOVZXBQ,
    UC_X86_INS_PMOVZXBW,
    UC_X86_INS_PMOVZXDQ,
    UC_X86_INS_PMOVZXWD,
    UC_X86_INS_PMOVZXWQ,
    UC_X86_INS_PMULDQ,
    UC_X86_INS_PMULHRW,
    UC_X86_INS_PMULLD,
    UC_X86_INS_POP,
    UC_X86_INS_POPAW,
    UC_X86_INS_POPAL,
    UC_X86_INS_POPCNT,
    UC_X86_INS_POPF,
    UC_X86_INS_POPFD,
    UC_X86_INS_POPFQ,
    UC_X86_INS_PREFETCH,
    UC_X86_INS_PREFETCHNTA,
    UC_X86_INS_PREFETCHT0,
    UC_X86_INS_PREFETCHT1,
    UC_X86_INS_PREFETCHT2,
    UC_X86_INS_PREFETCHW,
    UC_X86_INS_PSHUFD,
    UC_X86_INS_PSHUFHW,
    UC_X86_INS_PSHUFLW,
    UC_X86_INS_PSLLDQ,
    UC_X86_INS_PSRLDQ,
    UC_X86_INS_PSWAPD,
    UC_X86_INS_PTEST,
    UC_X86_INS_PUNPCKHQDQ,
    UC_X86_INS_PUNPCKLQDQ,
    UC_X86_INS_PUSH,
    UC_X86_INS_PUSHAW,
    UC_X86_INS_PUSHAL,
    UC_X86_INS_PUSHF,
    UC_X86_INS_PUSHFD,
    UC_X86_INS_PUSHFQ,
    UC_X86_INS_RCL,
    UC_X86_INS_RCPPS,
    UC_X86_INS_RCPSS,
    UC_X86_INS_RCR,
    UC_X86_INS_RDFSBASE,
    UC_X86_INS_RDGSBASE,
    UC_X86_INS_RDMSR,
    UC_X86_INS_RDPMC,
    UC_X86_INS_RDRAND,
    UC_X86_INS_RDSEED,
    UC_X86_INS_RDTSC,
    UC_X86_INS_RDTSCP,
    UC_X86_INS_ROL,
    UC_X86_INS_ROR,
    UC_X86_INS_RORX,
    UC_X86_INS_ROUNDPD,
    UC_X86_INS_ROUNDPS,
    UC_X86_INS_ROUNDSD,
    UC_X86_INS_ROUNDSS,
    UC_X86_INS_RSM,
    UC_X86_INS_RSQRTPS,
    UC_X86_INS_RSQRTSS,
    UC_X86_INS_SAHF,
    UC_X86_INS_SAL,
    UC_X86_INS_SALC,
    UC_X86_INS_SAR,
    UC_X86_INS_SARX,
    UC_X86_INS_SBB,
    UC_X86_INS_SCASB,
    UC_X86_INS_SCASD,
    UC_X86_INS_SCASQ,
    UC_X86_INS_SCASW,
    UC_X86_INS_SETAE,
    UC_X86_INS_SETA,
    UC_X86_INS_SETBE,
    UC_X86_INS_SETB,
    UC_X86_INS_SETE,
    UC_X86_INS_SETGE,
    UC_X86_INS_SETG,
    UC_X86_INS_SETLE,
    UC_X86_INS_SETL,
    UC_X86_INS_SETNE,
    UC_X86_INS_SETNO,
    UC_X86_INS_SETNP,
    UC_X86_INS_SETNS,
    UC_X86_INS_SETO,
    UC_X86_INS_SETP,
    UC_X86_INS_SETS,
    UC_X86_INS_SFENCE,
    UC_X86_INS_SGDT,
    UC_X86_INS_SHA1MSG1,
    UC_X86_INS_SHA1MSG2,
    UC_X86_INS_SHA1NEXTE,
    UC_X86_INS_SHA1RNDS4,
    UC_X86_INS_SHA256MSG1,
    UC_X86_INS_SHA256MSG2,
    UC_X86_INS_SHA256RNDS2,
    UC_X86_INS_SHL,
    UC_X86_INS_SHLD,
    UC_X86_INS_SHLX,
    UC_X86_INS_SHR,
    UC_X86_INS_SHRD,
    UC_X86_INS_SHRX,
    UC_X86_INS_SHUFPD,
    UC_X86_INS_SHUFPS,
    UC_X86_INS_SIDT,
    UC_X86_INS_FSIN,
    UC_X86_INS_SKINIT,
    UC_X86_INS_SLDT,
    UC_X86_INS_SMSW,
    UC_X86_INS_SQRTPD,
    UC_X86_INS_SQRTPS,
    UC_X86_INS_SQRTSD,
    UC_X86_INS_SQRTSS,
    UC_X86_INS_FSQRT,
    UC_X86_INS_STAC,
    UC_X86_INS_STC,
    UC_X86_INS_STD,
    UC_X86_INS_STGI,
    UC_X86_INS_STI,
    UC_X86_INS_STMXCSR,
    UC_X86_INS_STOSB,
    UC_X86_INS_STOSD,
    UC_X86_INS_STOSQ,
    UC_X86_INS_STOSW,
    UC_X86_INS_STR,
    UC_X86_INS_FST,
    UC_X86_INS_FSTP,
    UC_X86_INS_FSTPNCE,
    UC_X86_INS_FXCH,
    UC_X86_INS_SUBPD,
    UC_X86_INS_SUBPS,
    UC_X86_INS_FSUBR,
    UC_X86_INS_FISUBR,
    UC_X86_INS_FSUBRP,
    UC_X86_INS_SUBSD,
    UC_X86_INS_SUBSS,
    UC_X86_INS_FSUB,
    UC_X86_INS_FISUB,
    UC_X86_INS_FSUBP,
    UC_X86_INS_SWAPGS,
    UC_X86_INS_SYSCALL,
    UC_X86_INS_SYSENTER,
    UC_X86_INS_SYSEXIT,
    UC_X86_INS_SYSRET,
    UC_X86_INS_T1MSKC,
    UC_X86_INS_TEST,
    UC_X86_INS_UD2,
    UC_X86_INS_FTST,
    UC_X86_INS_TZCNT,
    UC_X86_INS_TZMSK,
    UC_X86_INS_FUCOMPI,
    UC_X86_INS_FUCOMI,
    UC_X86_INS_FUCOMPP,
    UC_X86_INS_FUCOMP,
    UC_X86_INS_FUCOM,
    UC_X86_INS_UD2B,
    UC_X86_INS_UNPCKHPD,
    UC_X86_INS_UNPCKHPS,
    UC_X86_INS_UNPCKLPD,
    UC_X86_INS_UNPCKLPS,
    UC_X86_INS_VADDPD,
    UC_X86_INS_VADDPS,
    UC_X86_INS_VADDSD,
    UC_X86_INS_VADDSS,
    UC_X86_INS_VADDSUBPD,
    UC_X86_INS_VADDSUBPS,
    UC_X86_INS_VAESDECLAST,
    UC_X86_INS_VAESDEC,
    UC_X86_INS_VAESENCLAST,
    UC_X86_INS_VAESENC,
    UC_X86_INS_VAESIMC,
    UC_X86_INS_VAESKEYGENASSIST,
    UC_X86_INS_VALIGND,
    UC_X86_INS_VALIGNQ,
    UC_X86_INS_VANDNPD,
    UC_X86_INS_VANDNPS,
    UC_X86_INS_VANDPD,
    UC_X86_INS_VANDPS,
    UC_X86_INS_VBLENDMPD,
    UC_X86_INS_VBLENDMPS,
    UC_X86_INS_VBLENDPD,
    UC_X86_INS_VBLENDPS,
    UC_X86_INS_VBLENDVPD,
    UC_X86_INS_VBLENDVPS,
    UC_X86_INS_VBROADCASTF128,
    UC_X86_INS_VBROADCASTI32X4,
    UC_X86_INS_VBROADCASTI64X4,
    UC_X86_INS_VBROADCASTSD,
    UC_X86_INS_VBROADCASTSS,
    UC_X86_INS_VCMPPD,
    UC_X86_INS_VCMPPS,
    UC_X86_INS_VCMPSD,
    UC_X86_INS_VCMPSS,
    UC_X86_INS_VCOMPRESSPD,
    UC_X86_INS_VCOMPRESSPS,
    UC_X86_INS_VCVTDQ2PD,
    UC_X86_INS_VCVTDQ2PS,
    UC_X86_INS_VCVTPD2DQX,
    UC_X86_INS_VCVTPD2DQ,
    UC_X86_INS_VCVTPD2PSX,
    UC_X86_INS_VCVTPD2PS,
    UC_X86_INS_VCVTPD2UDQ,
    UC_X86_INS_VCVTPH2PS,
    UC_X86_INS_VCVTPS2DQ,
    UC_X86_INS_VCVTPS2PD,
    UC_X86_INS_VCVTPS2PH,
    UC_X86_INS_VCVTPS2UDQ,
    UC_X86_INS_VCVTSD2SI,
    UC_X86_INS_VCVTSD2USI,
    UC_X86_INS_VCVTSS2SI,
    UC_X86_INS_VCVTSS2USI,
    UC_X86_INS_VCVTTPD2DQX,
    UC_X86_INS_VCVTTPD2DQ,
    UC_X86_INS_VCVTTPD2UDQ,
    UC_X86_INS_VCVTTPS2DQ,
    UC_X86_INS_VCVTTPS2UDQ,
    UC_X86_INS_VCVTUDQ2PD,
    UC_X86_INS_VCVTUDQ2PS,
    UC_X86_INS_VDIVPD,
    UC_X86_INS_VDIVPS,
    UC_X86_INS_VDIVSD,
    UC_X86_INS_VDIVSS,
    UC_X86_INS_VDPPD,
    UC_X86_INS_VDPPS,
    UC_X86_INS_VERR,
    UC_X86_INS_VERW,
    UC_X86_INS_VEXP2PD,
    UC_X86_INS_VEXP2PS,
    UC_X86_INS_VEXPANDPD,
    UC_X86_INS_VEXPANDPS,
    UC_X86_INS_VEXTRACTF128,
    UC_X86_INS_VEXTRACTF32X4,
    UC_X86_INS_VEXTRACTF64X4,
    UC_X86_INS_VEXTRACTI128,
    UC_X86_INS_VEXTRACTI32X4,
    UC_X86_INS_VEXTRACTI64X4,
    UC_X86_INS_VEXTRACTPS,
    UC_X86_INS_VFMADD132PD,
    UC_X86_INS_VFMADD132PS,
    UC_X86_INS_VFMADDPD,
    UC_X86_INS_VFMADD213PD,
    UC_X86_INS_VFMADD231PD,
    UC_X86_INS_VFMADDPS,
    UC_X86_INS_VFMADD213PS,
    UC_X86_INS_VFMADD231PS,
    UC_X86_INS_VFMADDSD,
    UC_X86_INS_VFMADD213SD,
    UC_X86_INS_VFMADD132SD,
    UC_X86_INS_VFMADD231SD,
    UC_X86_INS_VFMADDSS,
    UC_X86_INS_VFMADD213SS,
    UC_X86_INS_VFMADD132SS,
    UC_X86_INS_VFMADD231SS,
    UC_X86_INS_VFMADDSUB132PD,
    UC_X86_INS_VFMADDSUB132PS,
    UC_X86_INS_VFMADDSUBPD,
    UC_X86_INS_VFMADDSUB213PD,
    UC_X86_INS_VFMADDSUB231PD,
    UC_X86_INS_VFMADDSUBPS,
    UC_X86_INS_VFMADDSUB213PS,
    UC_X86_INS_VFMADDSUB231PS,
    UC_X86_INS_VFMSUB132PD,
    UC_X86_INS_VFMSUB132PS,
    UC_X86_INS_VFMSUBADD132PD,
    UC_X86_INS_VFMSUBADD132PS,
    UC_X86_INS_VFMSUBADDPD,
    UC_X86_INS_VFMSUBADD213PD,
    UC_X86_INS_VFMSUBADD231PD,
    UC_X86_INS_VFMSUBADDPS,
    UC_X86_INS_VFMSUBADD213PS,
    UC_X86_INS_VFMSUBADD231PS,
    UC_X86_INS_VFMSUBPD,
    UC_X86_INS_VFMSUB213PD,
    UC_X86_INS_VFMSUB231PD,
    UC_X86_INS_VFMSUBPS,
    UC_X86_INS_VFMSUB213PS,
    UC_X86_INS_VFMSUB231PS,
    UC_X86_INS_VFMSUBSD,
    UC_X86_INS_VFMSUB213SD,
    UC_X86_INS_VFMSUB132SD,
    UC_X86_INS_VFMSUB231SD,
    UC_X86_INS_VFMSUBSS,
    UC_X86_INS_VFMSUB213SS,
    UC_X86_INS_VFMSUB132SS,
    UC_X86_INS_VFMSUB231SS,
    UC_X86_INS_VFNMADD132PD,
    UC_X86_INS_VFNMADD132PS,
    UC_X86_INS_VFNMADDPD,
    UC_X86_INS_VFNMADD213PD,
    UC_X86_INS_VFNMADD231PD,
    UC_X86_INS_VFNMADDPS,
    UC_X86_INS_VFNMADD213PS,
    UC_X86_INS_VFNMADD231PS,
    UC_X86_INS_VFNMADDSD,
    UC_X86_INS_VFNMADD213SD,
    UC_X86_INS_VFNMADD132SD,
    UC_X86_INS_VFNMADD231SD,
    UC_X86_INS_VFNMADDSS,
    UC_X86_INS_VFNMADD213SS,
    UC_X86_INS_VFNMADD132SS,
    UC_X86_INS_VFNMADD231SS,
    UC_X86_INS_VFNMSUB132PD,
    UC_X86_INS_VFNMSUB132PS,
    UC_X86_INS_VFNMSUBPD,
    UC_X86_INS_VFNMSUB213PD,
    UC_X86_INS_VFNMSUB231PD,
    UC_X86_INS_VFNMSUBPS,
    UC_X86_INS_VFNMSUB213PS,
    UC_X86_INS_VFNMSUB231PS,
    UC_X86_INS_VFNMSUBSD,
    UC_X86_INS_VFNMSUB213SD,
    UC_X86_INS_VFNMSUB132SD,
    UC_X86_INS_VFNMSUB231SD,
    UC_X86_INS_VFNMSUBSS,
    UC_X86_INS_VFNMSUB213SS,
    UC_X86_INS_VFNMSUB132SS,
    UC_X86_INS_VFNMSUB231SS,
    UC_X86_INS_VFRCZPD,
    UC_X86_INS_VFRCZPS,
    UC_X86_INS_VFRCZSD,
    UC_X86_INS_VFRCZSS,
    UC_X86_INS_VORPD,
    UC_X86_INS_VORPS,
    UC_X86_INS_VXORPD,
    UC_X86_INS_VXORPS,
    UC_X86_INS_VGATHERDPD,
    UC_X86_INS_VGATHERDPS,
    UC_X86_INS_VGATHERPF0DPD,
    UC_X86_INS_VGATHERPF0DPS,
    UC_X86_INS_VGATHERPF0QPD,
    UC_X86_INS_VGATHERPF0QPS,
    UC_X86_INS_VGATHERPF1DPD,
    UC_X86_INS_VGATHERPF1DPS,
    UC_X86_INS_VGATHERPF1QPD,
    UC_X86_INS_VGATHERPF1QPS,
    UC_X86_INS_VGATHERQPD,
    UC_X86_INS_VGATHERQPS,
    UC_X86_INS_VHADDPD,
    UC_X86_INS_VHADDPS,
    UC_X86_INS_VHSUBPD,
    UC_X86_INS_VHSUBPS,
    UC_X86_INS_VINSERTF128,
    UC_X86_INS_VINSERTF32X4,
    UC_X86_INS_VINSERTF32X8,
    UC_X86_INS_VINSERTF64X2,
    UC_X86_INS_VINSERTF64X4,
    UC_X86_INS_VINSERTI128,
    UC_X86_INS_VINSERTI32X4,
    UC_X86_INS_VINSERTI32X8,
    UC_X86_INS_VINSERTI64X2,
    UC_X86_INS_VINSERTI64X4,
    UC_X86_INS_VINSERTPS,
    UC_X86_INS_VLDDQU,
    UC_X86_INS_VLDMXCSR,
    UC_X86_INS_VMASKMOVDQU,
    UC_X86_INS_VMASKMOVPD,
    UC_X86_INS_VMASKMOVPS,
    UC_X86_INS_VMAXPD,
    UC_X86_INS_VMAXPS,
    UC_X86_INS_VMAXSD,
    UC_X86_INS_VMAXSS,
    UC_X86_INS_VMCALL,
    UC_X86_INS_VMCLEAR,
    UC_X86_INS_VMFUNC,
    UC_X86_INS_VMINPD,
    UC_X86_INS_VMINPS,
    UC_X86_INS_VMINSD,
    UC_X86_INS_VMINSS,
    UC_X86_INS_VMLAUNCH,
    UC_X86_INS_VMLOAD,
    UC_X86_INS_VMMCALL,
    UC_X86_INS_VMOVQ,
    UC_X86_INS_VMOVDDUP,
    UC_X86_INS_VMOVD,
    UC_X86_INS_VMOVDQA32,
    UC_X86_INS_VMOVDQA64,
    UC_X86_INS_VMOVDQA,
    UC_X86_INS_VMOVDQU16,
    UC_X86_INS_VMOVDQU32,
    UC_X86_INS_VMOVDQU64,
    UC_X86_INS_VMOVDQU8,
    UC_X86_INS_VMOVDQU,
    UC_X86_INS_VMOVHLPS,
    UC_X86_INS_VMOVHPD,
    UC_X86_INS_VMOVHPS,
    UC_X86_INS_VMOVLHPS,
    UC_X86_INS_VMOVLPD,
    UC_X86_INS_VMOVLPS,
    UC_X86_INS_VMOVMSKPD,
    UC_X86_INS_VMOVMSKPS,
    UC_X86_INS_VMOVNTDQA,
    UC_X86_INS_VMOVNTDQ,
    UC_X86_INS_VMOVNTPD,
    UC_X86_INS_VMOVNTPS,
    UC_X86_INS_VMOVSD,
    UC_X86_INS_VMOVSHDUP,
    UC_X86_INS_VMOVSLDUP,
    UC_X86_INS_VMOVSS,
    UC_X86_INS_VMOVUPD,
    UC_X86_INS_VMOVUPS,
    UC_X86_INS_VMPSADBW,
    UC_X86_INS_VMPTRLD,
    UC_X86_INS_VMPTRST,
    UC_X86_INS_VMREAD,
    UC_X86_INS_VMRESUME,
    UC_X86_INS_VMRUN,
    UC_X86_INS_VMSAVE,
    UC_X86_INS_VMULPD,
    UC_X86_INS_VMULPS,
    UC_X86_INS_VMULSD,
    UC_X86_INS_VMULSS,
    UC_X86_INS_VMWRITE,
    UC_X86_INS_VMXOFF,
    UC_X86_INS_VMXON,
    UC_X86_INS_VPABSB,
    UC_X86_INS_VPABSD,
    UC_X86_INS_VPABSQ,
    UC_X86_INS_VPABSW,
    UC_X86_INS_VPACKSSDW,
    UC_X86_INS_VPACKSSWB,
    UC_X86_INS_VPACKUSDW,
    UC_X86_INS_VPACKUSWB,
    UC_X86_INS_VPADDB,
    UC_X86_INS_VPADDD,
    UC_X86_INS_VPADDQ,
    UC_X86_INS_VPADDSB,
    UC_X86_INS_VPADDSW,
    UC_X86_INS_VPADDUSB,
    UC_X86_INS_VPADDUSW,
    UC_X86_INS_VPADDW,
    UC_X86_INS_VPALIGNR,
    UC_X86_INS_VPANDD,
    UC_X86_INS_VPANDND,
    UC_X86_INS_VPANDNQ,
    UC_X86_INS_VPANDN,
    UC_X86_INS_VPANDQ,
    UC_X86_INS_VPAND,
    UC_X86_INS_VPAVGB,
    UC_X86_INS_VPAVGW,
    UC_X86_INS_VPBLENDD,
    UC_X86_INS_VPBLENDMB,
    UC_X86_INS_VPBLENDMD,
    UC_X86_INS_VPBLENDMQ,
    UC_X86_INS_VPBLENDMW,
    UC_X86_INS_VPBLENDVB,
    UC_X86_INS_VPBLENDW,
    UC_X86_INS_VPBROADCASTB,
    UC_X86_INS_VPBROADCASTD,
    UC_X86_INS_VPBROADCASTMB2Q,
    UC_X86_INS_VPBROADCASTMW2D,
    UC_X86_INS_VPBROADCASTQ,
    UC_X86_INS_VPBROADCASTW,
    UC_X86_INS_VPCLMULQDQ,
    UC_X86_INS_VPCMOV,
    UC_X86_INS_VPCMPB,
    UC_X86_INS_VPCMPD,
    UC_X86_INS_VPCMPEQB,
    UC_X86_INS_VPCMPEQD,
    UC_X86_INS_VPCMPEQQ,
    UC_X86_INS_VPCMPEQW,
    UC_X86_INS_VPCMPESTRI,
    UC_X86_INS_VPCMPESTRM,
    UC_X86_INS_VPCMPGTB,
    UC_X86_INS_VPCMPGTD,
    UC_X86_INS_VPCMPGTQ,
    UC_X86_INS_VPCMPGTW,
    UC_X86_INS_VPCMPISTRI,
    UC_X86_INS_VPCMPISTRM,
    UC_X86_INS_VPCMPQ,
    UC_X86_INS_VPCMPUB,
    UC_X86_INS_VPCMPUD,
    UC_X86_INS_VPCMPUQ,
    UC_X86_INS_VPCMPUW,
    UC_X86_INS_VPCMPW,
    UC_X86_INS_VPCOMB,
    UC_X86_INS_VPCOMD,
    UC_X86_INS_VPCOMPRESSD,
    UC_X86_INS_VPCOMPRESSQ,
    UC_X86_INS_VPCOMQ,
    UC_X86_INS_VPCOMUB,
    UC_X86_INS_VPCOMUD,
    UC_X86_INS_VPCOMUQ,
    UC_X86_INS_VPCOMUW,
    UC_X86_INS_VPCOMW,
    UC_X86_INS_VPCONFLICTD,
    UC_X86_INS_VPCONFLICTQ,
    UC_X86_INS_VPERM2F128,
    UC_X86_INS_VPERM2I128,
    UC_X86_INS_VPERMD,
    UC_X86_INS_VPERMI2D,
    UC_X86_INS_VPERMI2PD,
    UC_X86_INS_VPERMI2PS,
    UC_X86_INS_VPERMI2Q,
    UC_X86_INS_VPERMIL2PD,
    UC_X86_INS_VPERMIL2PS,
    UC_X86_INS_VPERMILPD,
    UC_X86_INS_VPERMILPS,
    UC_X86_INS_VPERMPD,
    UC_X86_INS_VPERMPS,
    UC_X86_INS_VPERMQ,
    UC_X86_INS_VPERMT2D,
    UC_X86_INS_VPERMT2PD,
    UC_X86_INS_VPERMT2PS,
    UC_X86_INS_VPERMT2Q,
    UC_X86_INS_VPEXPANDD,
    UC_X86_INS_VPEXPANDQ,
    UC_X86_INS_VPEXTRB,
    UC_X86_INS_VPEXTRD,
    UC_X86_INS_VPEXTRQ,
    UC_X86_INS_VPEXTRW,
    UC_X86_INS_VPGATHERDD,
    UC_X86_INS_VPGATHERDQ,
    UC_X86_INS_VPGATHERQD,
    UC_X86_INS_VPGATHERQQ,
    UC_X86_INS_VPHADDBD,
    UC_X86_INS_VPHADDBQ,
    UC_X86_INS_VPHADDBW,
    UC_X86_INS_VPHADDDQ,
    UC_X86_INS_VPHADDD,
    UC_X86_INS_VPHADDSW,
    UC_X86_INS_VPHADDUBD,
    UC_X86_INS_VPHADDUBQ,
    UC_X86_INS_VPHADDUBW,
    UC_X86_INS_VPHADDUDQ,
    UC_X86_INS_VPHADDUWD,
    UC_X86_INS_VPHADDUWQ,
    UC_X86_INS_VPHADDWD,
    UC_X86_INS_VPHADDWQ,
    UC_X86_INS_VPHADDW,
    UC_X86_INS_VPHMINPOSUW,
    UC_X86_INS_VPHSUBBW,
    UC_X86_INS_VPHSUBDQ,
    UC_X86_INS_VPHSUBD,
    UC_X86_INS_VPHSUBSW,
    UC_X86_INS_VPHSUBWD,
    UC_X86_INS_VPHSUBW,
    UC_X86_INS_VPINSRB,
    UC_X86_INS_VPINSRD,
    UC_X86_INS_VPINSRQ,
    UC_X86_INS_VPINSRW,
    UC_X86_INS_VPLZCNTD,
    UC_X86_INS_VPLZCNTQ,
    UC_X86_INS_VPMACSDD,
    UC_X86_INS_VPMACSDQH,
    UC_X86_INS_VPMACSDQL,
    UC_X86_INS_VPMACSSDD,
    UC_X86_INS_VPMACSSDQH,
    UC_X86_INS_VPMACSSDQL,
    UC_X86_INS_VPMACSSWD,
    UC_X86_INS_VPMACSSWW,
    UC_X86_INS_VPMACSWD,
    UC_X86_INS_VPMACSWW,
    UC_X86_INS_VPMADCSSWD,
    UC_X86_INS_VPMADCSWD,
    UC_X86_INS_VPMADDUBSW,
    UC_X86_INS_VPMADDWD,
    UC_X86_INS_VPMASKMOVD,
    UC_X86_INS_VPMASKMOVQ,
    UC_X86_INS_VPMAXSB,
    UC_X86_INS_VPMAXSD,
    UC_X86_INS_VPMAXSQ,
    UC_X86_INS_VPMAXSW,
    UC_X86_INS_VPMAXUB,
    UC_X86_INS_VPMAXUD,
    UC_X86_INS_VPMAXUQ,
    UC_X86_INS_VPMAXUW,
    UC_X86_INS_VPMINSB,
    UC_X86_INS_VPMINSD,
    UC_X86_INS_VPMINSQ,
    UC_X86_INS_VPMINSW,
    UC_X86_INS_VPMINUB,
    UC_X86_INS_VPMINUD,
    UC_X86_INS_VPMINUQ,
    UC_X86_INS_VPMINUW,
    UC_X86_INS_VPMOVDB,
    UC_X86_INS_VPMOVDW,
    UC_X86_INS_VPMOVM2B,
    UC_X86_INS_VPMOVM2D,
    UC_X86_INS_VPMOVM2Q,
    UC_X86_INS_VPMOVM2W,
    UC_X86_INS_VPMOVMSKB,
    UC_X86_INS_VPMOVQB,
    UC_X86_INS_VPMOVQD,
    UC_X86_INS_VPMOVQW,
    UC_X86_INS_VPMOVSDB,
    UC_X86_INS_VPMOVSDW,
    UC_X86_INS_VPMOVSQB,
    UC_X86_INS_VPMOVSQD,
    UC_X86_INS_VPMOVSQW,
    UC_X86_INS_VPMOVSXBD,
    UC_X86_INS_VPMOVSXBQ,
    UC_X86_INS_VPMOVSXBW,
    UC_X86_INS_VPMOVSXDQ,
    UC_X86_INS_VPMOVSXWD,
    UC_X86_INS_VPMOVSXWQ,
    UC_X86_INS_VPMOVUSDB,
    UC_X86_INS_VPMOVUSDW,
    UC_X86_INS_VPMOVUSQB,
    UC_X86_INS_VPMOVUSQD,
    UC_X86_INS_VPMOVUSQW,
    UC_X86_INS_VPMOVZXBD,
    UC_X86_INS_VPMOVZXBQ,
    UC_X86_INS_VPMOVZXBW,
    UC_X86_INS_VPMOVZXDQ,
    UC_X86_INS_VPMOVZXWD,
    UC_X86_INS_VPMOVZXWQ,
    UC_X86_INS_VPMULDQ,
    UC_X86_INS_VPMULHRSW,
    UC_X86_INS_VPMULHUW,
    UC_X86_INS_VPMULHW,
    UC_X86_INS_VPMULLD,
    UC_X86_INS_VPMULLQ,
    UC_X86_INS_VPMULLW,
    UC_X86_INS_VPMULUDQ,
    UC_X86_INS_VPORD,
    UC_X86_INS_VPORQ,
    UC_X86_INS_VPOR,
    UC_X86_INS_VPPERM,
    UC_X86_INS_VPROTB,
    UC_X86_INS_VPROTD,
    UC_X86_INS_VPROTQ,
    UC_X86_INS_VPROTW,
    UC_X86_INS_VPSADBW,
    UC_X86_INS_VPSCATTERDD,
    UC_X86_INS_VPSCATTERDQ,
    UC_X86_INS_VPSCATTERQD,
    UC_X86_INS_VPSCATTERQQ,
    UC_X86_INS_VPSHAB,
    UC_X86_INS_VPSHAD,
    UC_X86_INS_VPSHAQ,
    UC_X86_INS_VPSHAW,
    UC_X86_INS_VPSHLB,
    UC_X86_INS_VPSHLD,
    UC_X86_INS_VPSHLQ,
    UC_X86_INS_VPSHLW,
    UC_X86_INS_VPSHUFB,
    UC_X86_INS_VPSHUFD,
    UC_X86_INS_VPSHUFHW,
    UC_X86_INS_VPSHUFLW,
    UC_X86_INS_VPSIGNB,
    UC_X86_INS_VPSIGND,
    UC_X86_INS_VPSIGNW,
    UC_X86_INS_VPSLLDQ,
    UC_X86_INS_VPSLLD,
    UC_X86_INS_VPSLLQ,
    UC_X86_INS_VPSLLVD,
    UC_X86_INS_VPSLLVQ,
    UC_X86_INS_VPSLLW,
    UC_X86_INS_VPSRAD,
    UC_X86_INS_VPSRAQ,
    UC_X86_INS_VPSRAVD,
    UC_X86_INS_VPSRAVQ,
    UC_X86_INS_VPSRAW,
    UC_X86_INS_VPSRLDQ,
    UC_X86_INS_VPSRLD,
    UC_X86_INS_VPSRLQ,
    UC_X86_INS_VPSRLVD,
    UC_X86_INS_VPSRLVQ,
    UC_X86_INS_VPSRLW,
    UC_X86_INS_VPSUBB,
    UC_X86_INS_VPSUBD,
    UC_X86_INS_VPSUBQ,
    UC_X86_INS_VPSUBSB,
    UC_X86_INS_VPSUBSW,
    UC_X86_INS_VPSUBUSB,
    UC_X86_INS_VPSUBUSW,
    UC_X86_INS_VPSUBW,
    UC_X86_INS_VPTESTMD,
    UC_X86_INS_VPTESTMQ,
    UC_X86_INS_VPTESTNMD,
    UC_X86_INS_VPTESTNMQ,
    UC_X86_INS_VPTEST,
    UC_X86_INS_VPUNPCKHBW,
    UC_X86_INS_VPUNPCKHDQ,
    UC_X86_INS_VPUNPCKHQDQ,
    UC_X86_INS_VPUNPCKHWD,
    UC_X86_INS_VPUNPCKLBW,
    UC_X86_INS_VPUNPCKLDQ,
    UC_X86_INS_VPUNPCKLQDQ,
    UC_X86_INS_VPUNPCKLWD,
    UC_X86_INS_VPXORD,
    UC_X86_INS_VPXORQ,
    UC_X86_INS_VPXOR,
    UC_X86_INS_VRCP14PD,
    UC_X86_INS_VRCP14PS,
    UC_X86_INS_VRCP14SD,
    UC_X86_INS_VRCP14SS,
    UC_X86_INS_VRCP28PD,
    UC_X86_INS_VRCP28PS,
    UC_X86_INS_VRCP28SD,
    UC_X86_INS_VRCP28SS,
    UC_X86_INS_VRCPPS,
    UC_X86_INS_VRCPSS,
    UC_X86_INS_VRNDSCALEPD,
    UC_X86_INS_VRNDSCALEPS,
    UC_X86_INS_VRNDSCALESD,
    UC_X86_INS_VRNDSCALESS,
    UC_X86_INS_VROUNDPD,
    UC_X86_INS_VROUNDPS,
    UC_X86_INS_VROUNDSD,
    UC_X86_INS_VROUNDSS,
    UC_X86_INS_VRSQRT14PD,
    UC_X86_INS_VRSQRT14PS,
    UC_X86_INS_VRSQRT14SD,
    UC_X86_INS_VRSQRT14SS,
    UC_X86_INS_VRSQRT28PD,
    UC_X86_INS_VRSQRT28PS,
    UC_X86_INS_VRSQRT28SD,
    UC_X86_INS_VRSQRT28SS,
    UC_X86_INS_VRSQRTPS,
    UC_X86_INS_VRSQRTSS,
    UC_X86_INS_VSCATTERDPD,
    UC_X86_INS_VSCATTERDPS,
    UC_X86_INS_VSCATTERPF0DPD,
    UC_X86_INS_VSCATTERPF0DPS,
    UC_X86_INS_VSCATTERPF0QPD,
    UC_X86_INS_VSCATTERPF0QPS,
    UC_X86_INS_VSCATTERPF1DPD,
    UC_X86_INS_VSCATTERPF1DPS,
    UC_X86_INS_VSCATTERPF1QPD,
    UC_X86_INS_VSCATTERPF1QPS,
    UC_X86_INS_VSCATTERQPD,
    UC_X86_INS_VSCATTERQPS,
    UC_X86_INS_VSHUFPD,
    UC_X86_INS_VSHUFPS,
    UC_X86_INS_VSQRTPD,
    UC_X86_INS_VSQRTPS,
    UC_X86_INS_VSQRTSD,
    UC_X86_INS_VSQRTSS,
    UC_X86_INS_VSTMXCSR,
    UC_X86_INS_VSUBPD,
    UC_X86_INS_VSUBPS,
    UC_X86_INS_VSUBSD,
    UC_X86_INS_VSUBSS,
    UC_X86_INS_VTESTPD,
    UC_X86_INS_VTESTPS,
    UC_X86_INS_VUNPCKHPD,
    UC_X86_INS_VUNPCKHPS,
    UC_X86_INS_VUNPCKLPD,
    UC_X86_INS_VUNPCKLPS,
    UC_X86_INS_VZEROALL,
    UC_X86_INS_VZEROUPPER,
    UC_X86_INS_WAIT,
    UC_X86_INS_WBINVD,
    UC_X86_INS_WRFSBASE,
    UC_X86_INS_WRGSBASE,
    UC_X86_INS_WRMSR,
    UC_X86_INS_XABORT,
    UC_X86_INS_XACQUIRE,
    UC_X86_INS_XBEGIN,
    UC_X86_INS_XCHG,
    UC_X86_INS_XCRYPTCBC,
    UC_X86_INS_XCRYPTCFB,
    UC_X86_INS_XCRYPTCTR,
    UC_X86_INS_XCRYPTECB,
    UC_X86_INS_XCRYPTOFB,
    UC_X86_INS_XEND,
    UC_X86_INS_XGETBV,
    UC_X86_INS_XLATB,
    UC_X86_INS_XRELEASE,
    UC_X86_INS_XRSTOR,
    UC_X86_INS_XRSTOR64,
    UC_X86_INS_XRSTORS,
    UC_X86_INS_XRSTORS64,
    UC_X86_INS_XSAVE,
    UC_X86_INS_XSAVE64,
    UC_X86_INS_XSAVEC,
    UC_X86_INS_XSAVEC64,
    UC_X86_INS_XSAVEOPT,
    UC_X86_INS_XSAVEOPT64,
    UC_X86_INS_XSAVES,
    UC_X86_INS_XSAVES64,
    UC_X86_INS_XSETBV,
    UC_X86_INS_XSHA1,
    UC_X86_INS_XSHA256,
    UC_X86_INS_XSTORE,
    UC_X86_INS_XTEST,
    UC_X86_INS_FDISI8087_NOP,
    UC_X86_INS_FENI8087_NOP,
    UC_X86_INS_ENDING, // mark the end of the list of insn
} uc_x86_insn;

分析程序中的函数:
图片描述

1
2
uc_hook_add(uc, &hook_handle, 2, input + 1, 0LL, 1LL, 0LL, 0xDAu);
// 2 == (uc_hook_type)UC_HOOK_INSN

由参数三为2可知,钩取的是指令,查询最后一个参数指令的枚举值,得到钩取的指令是UC_X86_INS_IN

1
2
uc_hook_add(uc, &hook_handle, 2, output, 0LL, 1LL, 0LL, 0x1F4u);
// 2 = (uc_hook_type)UC_HOOK_INSN

同理,得到钩取的指令是:UC_X86_INS_OUT

1
2
uc_hook_add(uc, &hook_handle, 2, syscall_time, 0LL, 1LL, 0LL, 0x2BBu);
// 2 = (uc_hook_type)UC_HOOK_INSN

钩取指令为:UC_X86_INS_SYSCALL

1
2
3
uc_hook_add(uc, &hook_handle, 0x400, changeKey, 0LL, 0x66660000LL, 0x66661000LL, v4);
// 0x400 = (uc_hook_type)UC_HOOK_MEM_READ
// **Hook memory read events.**

fs内存访问处理,改变 fs:0 的值,关键算法部分很重要

1
2
uc_hook_add(uc, &hook_handle, 8, decrypt, &user_data, 1LL, 0LL, v5);
// UC_HOOK_BLOCK

第三个参数的值为8:

 

 

// Hook basic blocks

 

UC_HOOK_BLOCK = 1 << 3,

 

钩取了基本块,代码解密回调

1
2
uc_hook_add(uc, &hook_handle, 0x4000, ControlFlow1, &user_data, 1LL, 0LL, v6);
// UC_HOOK_INSN_INVALID

第三个参数的值为0x4000,即UC_HOOK_INSN_INVALID

 

钩取了非法指令,执行的回调函数是ControlFlow1
代码控制流控制回调1

1
2
uc_hook_add(uc, &hook_handle, 4, ControlFlow2, &user_data, 0x10A3LL, 0x10A4LL, v7);
// UC_HOOK_CODE

代码控制流控制回调2

6. input和out函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__int64 __fastcall input(__int64 a1, int a2, int a3)
{
  __int64 v3; // rbp
  _DWORD v5[2]; // [rsp-18h] [rbp-20h] BYREF
  unsigned __int64 v6; // [rsp-10h] [rbp-18h]
  __int64 v7; // [rsp-8h] [rbp-10h]
 
  v7 = v3;
  v6 = __readfsqword(0x28u);
  v5[1] = a2;
  v5[0] = 0;
  read(a2, v5, a3);
  return v5[0];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
ssize_t __fastcall sub_55BD73F8CA3F(__int64 a1, int a2, int a3, int a4)
{
  int buf[3]; // [rsp+Ch] [rbp-24h] BYREF
  __int64 v6; // [rsp+18h] [rbp-18h]
  int fd; // [rsp+2Ch] [rbp-4h]
 
  v6 = a1;
  buf[2] = a2;
  buf[1] = a3;
  buf[0] = a4;
  fd = a2;
  return write(a2, buf, a3);
}

7. syscall_time

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unsigned __int64 __fastcall reg(__int64 a1)
{
  __int64 v2; // [rsp+18h] [rbp-18h] BYREF
  time_t v3; // [rsp+20h] [rbp-10h] BYREF
  unsigned __int64 v4; // [rsp+28h] [rbp-8h]
 
  v4 = __readfsqword(0x28u);
  v2 = 0LL;
  uc_reg_read(a1, 0x23LL, &v2);                 // UC_X86_REG_RAX
  if ( v2 == 0x1337 )                           // 如果rax寄存器的值为0x1337
  {
    v3 = time(0LL);
    uc_reg_write(a1, 0x23, &v3);                // 设置rax寄存器值为time(0)
  }
  return __readfsqword(0x28u) ^ v4;
}

8. changekey

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__int64 __fastcall changeKey(__int64 uc, int type, unsigned __int64 address, int size, int aa)
{
  __int64 temp[2]; // [rsp+30h] [rbp-10h] BYREF
 
  temp[1] = __readfsqword(0x28u);
  if ( type == 16 && address > 0x6665FFFF && address <= 0x66660FFF && size == 8 )
  {
    temp[0] = 0LL;
    uc_mem_read(uc, address, temp, 8LL);
    temp[0] = 0x756E69636F726E03LL * temp[0] + 0xBADC0DEC001CAFELL;
    uc_mem_write(uc, address, temp, 8LL);
  }
  return 1LL;
}

9. **decrypt函数(加解密代码块)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
void __fastcall decrypt(__int64 uc, unsigned __int64 address, __int64 size_1, user_info1 *user_data)
{
  unsigned __int64 RIP_; // [rsp+10h] [rbp-40h] BYREF
  __int64 v5; // [rsp+18h] [rbp-38h]
  unsigned int i; // [rsp+24h] [rbp-2Ch]
  unsigned int j; // [rsp+28h] [rbp-28h]
  unsigned int k; // [rsp+2Ch] [rbp-24h]
  int block_key; // [rsp+30h] [rbp-20h]
  unsigned int size[3]; // [rsp+34h] [rbp-1Ch]
  void *ptr; // [rsp+40h] [rbp-10h]
  void *tmp; // [rsp+48h] [rbp-8h]
 
  v5 = uc;
  RIP_ = address;
  *&size[1] = user_data;
  if ( user_data[1].field_4 == address )
  {
    *(*&size[1] + 16LL) = 0;
    return;
  }
  if ( *(*&size[1] + 4LL) )                     // 执行完后重新加密
  {
    if ( *(*&size[1] + 4LL) <= RIP_ && (*(*&size[1] + 4LL) + *(*&size[1] + 8LL)) > RIP_ )
      return;
    ptr = malloc(*(*&size[1] + 8LL));
    uc_mem_read(v5, *(*&size[1] + 4LL), ptr, *(*&size[1] + 8LL));// 读取已经执行完,准备再次加密的机器码
    crypt(ptr, *(*&size[1] + 8LL), *(*&size[1] + 12LL));// 再次加密
    uc_mem_write(v5, *(*&size[1] + 4LL), ptr, *(*&size[1] + 8LL));// 加密后又写回
    free(ptr);
  }
  block_key = miniDec(**&size[1], RIP_);        // 基本块密钥用miniDec函数计算,参数为上一个基本块的密钥key与当前基本块入口rip
  for ( i = 0; i <= 85; ++i )
  {
    if ( block_key == *&size_table[8 * i] )     // 获取基本块异或的key值,从crypt函数的^=a33[i % 4]可以看出是一个四字节的值,和表中相同
    {
      size[0] = *&size_table[8 * i + 4];        // 获取代码块的长度
      tmp = malloc(size[0]);                    // size_table 是一个数组,该数组保存了基本块密钥与基本块大小的关系,元素结构如下
      uc_mem_read(v5, RIP_, tmp, size[0]);
      for ( j = 0; size[0] > j; ++j )
        ;
      crypt(tmp, size[0], **&size[1]);
      uc_mem_write(v5, RIP_, tmp, size[0]);
      for ( k = 0; size[0] > k; ++k )
        ;
      free(tmp);
      *(*&size[1] + 4LL) = RIP_;
      *(*&size[1] + 12LL) = **&size[1];
      *(*&size[1] + 8LL) = size[0];
      *(*&size[1] + 16LL) = RIP_;
      uc_reg_write(v5, 41, &RIP_);              // UC_X86_REG_RIP
    }
  }
**}**

10. ControlFlow1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
__int64 __fastcall ControlFlow1(__int64 a1, unsigned int *user_data)
{
  __int64 v2; // rdx
  __int16 v4; // [rsp+16h] [rbp-2Ah] BYREF
  unsigned int i; // [rsp+18h] [rbp-28h]
  int key2; // [rsp+1Ch] [rbp-24h]
  __int64 rip_1; // [rsp+20h] [rbp-20h] BYREF
  __int64 REG_EFLAGS; // [rsp+28h] [rbp-18h] BYREF
  unsigned int *v9; // [rsp+30h] [rbp-10h]
  unsigned __int64 v10; // [rsp+38h] [rbp-8h]
 
  v10 = __readfsqword(0x28u);
  rip_1 = 0LL;
  v4 = 0;
  uc_reg_read(a1, 41LL, &rip_1);                // 0x104F
  uc_mem_read(a1, rip_1, &v4, 2LL);             // 3f0f
  if ( v4 != 0x3F0F )                           // 0x3F0F这是一个代码块被执行完了的标志,调试的时候看解密的代码块可以知道
    return 0LL;
  v9 = user_data;
  key2 = miniDec(*user_data, rip_1);
  for ( i = 0; ; ++i )
  {
    if ( i > 84 )
      return 0LL;
    if ( key2 == flowInfo[5 * i] )
      break;
  }
  REG_EFLAGS = 0LL;
  uc_reg_read(a1, 25LL, &REG_EFLAGS);           // UC_X86_REG_EFLAGS
  if ( (REG_EFLAGS & 0x40) != 0 )               // ZF flag
  {
    *v9 += flowInfo[5 * i + 4];                 // zf = 1
                                                //
    v2 = flowInfo[5 * i + 3];
  }
  else
  {
    *v9 += flowInfo[5 * i + 2];                 // zf = 0
    v2 = flowInfo[5 * i + 1];
  }
  rip_1 += v2;
  uc_reg_write(a1, 41, &rip_1);
  return 1LL;
}

11. ControlFlow2

1
2
3
4
5
6
7
8
9
10
11
12
unsigned __int64 __fastcall proces(__int64 a1, __int64 a2, __int64 a3, _DWORD *a4)
{
  __int64 v5[2]; // [rsp+28h] [rbp-18h] BYREF
  unsigned __int64 v6; // [rsp+38h] [rbp-8h]
 
  v6 = __readfsqword(0x28u);
  v5[1] = a4;
  *a4 -= 0x2B09B990;                            // change key
  v5[0] = 0x1EECLL;                             // change rip
  uc_reg_write(a1, 41, v5);                     // 修改RIP, UC_X86_REG_RIP
  return __readfsqword(0x28u) ^ v6;
}

四:逻辑梳理

以第一块和第二块为例:

 

最开始给了一个user_data,然后开始执行,最开始执行第一个块会触发块回调函数decrypt,然后里面先判断这个块是否被执行,显然第一次是没有的,然后就会使用这个初值和当前入口块的RIP调用函数miniDec计算出这个区块解密的key,然后调用crypt和key进行异或解密之后,设置了RIP执行这个区块,到后面会有读取内存fs,然后cmp的指令,当读取内存的时候,就会触发内存回调函数,用(0x756E69636F726E03LL * temp[0] + 0xBADC0DEC001CAFELL)重新更改那个地址的值,所以cmp得的值就会不同,ZF就为0,之后又执行0x3F0F指令(代码块结束的标志),会触发非法指令回调ControlFlow1,在这个回调里面先判断rip是否是0x3F0F,然后通过key和当前rip的0x3F0F值,计算出一个key2,然后for循环得到flowInfo表中的i下标,然后读取EFLAGS的ZF标志位来判断如何读取下一个标准块的信息(key+=,rip+=),然后就执行rip所指向的第二个块,又会触发回调函数decrypt,将之前的块重新加密,并利用变化后的rip(即第二个代码块的入口rip)和之前的key计算出下一个代码块的key,然后对下一个区块进行异或解密,并设置好rip......以此类推下去

五:调试代码逻辑

在decrypt函数最开始下断点,然后单步

 

图片描述

 

发现那个加密代码没有被执行,说明那个if条件就是判断代码有没有被执行

 

然后继续执行,就会发现下方代码在解密代码块

 

图片描述
在write函数写回去之前,查看tmp变量(注意tmp是地址,引用过去)即可得到解密后的代码

 

如图:

 

图片描述

 

然后这段解密后的代码会被执行,触发之前我们uc_hook_add设置的回调函数(syscall,mov r15, fs:0x100,以及3F0F触发非法指令回调)

 

syscall的回调

 

图片描述
mov r15, fs:0x100的回调

 

图片描述

 

改变了内存,然后之后cmp比较的值就不同了,然后ZF标志位就不会被置为1

 

所以说下面其实每次都是执行的else,即ZF标志位为0执行的那个条件
图片描述

 

3F0F非法指令的回调:(控制执行流程的)

 

图片描述

 

在最后设置了rip

 

之后便会开始准备执行第二个块,但是此时又会触发代码块回调函数decrypt

 

发现这次会执行if条件里面的内容,其实就是重新将代码块加密回去,我们将断点设置到crypt函数,然后查看ptr地址指向的值

 

图片描述

 

图片描述

 

可以看到就是我们之前解密出来的代码,说明这里就是将代码进行了重新加密

 

然后下方又通过上一次的key和即将要执行的代码块的入口RIP,通过函数miniDec得到下一个key

 

图片描述

 

然后下方又进行解密即将要执行的代码块

 

图片描述
以此类推.......跟着执行下去

 

在一些地址会触发特定的回调,ControlFlow2就是执行到0x10A3-0x10A4地址的时候调用的

 

图片描述

 

然后这个函数内,调整了控制流并更改 key

六:控制流重建

重建思路:

 

以 bfs 遍历顺序,每一个块当成一个节点,从入口基本块开始解密,解密后再查询分支信息表获取后继基本块的相对偏移与key,最后将新基本块的信息加入到队列,等待分析。遍历时注意维护路径上的 key 累计值。

 

所有基本块解密完成后,可以得到每个基本块的后继基本块的相对偏移。

 

要在基本块的结尾插入跳转指令,这将改变代码布局,使得原始相对偏移不可用,所以我采取重编译来解决这个问题,重编译之前将原始基本块的入口地址作为基本的符号名,基本块结尾用 jmp/jz 等指令连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import ctypes
from capstone import *
from keystone import *
from pwn import *
 
context.arch = 'amd64'
 
from pwn import *
fuckTable = [0x00412F5E, 0xFFFFFA22, 0x14252652, 0xFFFFF9AC, 0x66CEF8EC, 0x0251D934, 0x0000009F, 0xC56FBF59, 0xFFFFFF61, 0xAA4D5B7C, 0x02745896, 0xFFFFFB7F, 0x34B6D31E, 0xFFFFFBB0, 0x302CC828, 0x02AC5992, 0xFFFFF524, 0x67CC4064, 0xFFFFF483, 0x8A5D9B26, 0x046254D0, 0xFFFFFC37, 0x074AB936, 0xFFFFFC7F, 0xB8EA37F7, 0x0CACD9FE, 0x0000007F, 0x6112F222, 0x00000002, 0x47A72561, 0x0F0FE6EB, 0xFFFFFBAE, 0x0A1411E7, 0xFFFFFC85, 0x3BE88B46, 0x0FC59DC2, 0xFFFFF72F, 0x7D12A5EF, 0xFFFFF691, 0xE67393D6, 0x10B1EBCA, 0x000001CF, 0x473A1295, 0x0000022E, 0x7BC15385, 0x1565D41D, 0xFFFFFDC4, 0x05D337BE, 0xFFFFFE7E, 0xE12982E4, 0x18909E40, 0x000005EB, 0xAE2337AF, 0x000005B1, 0x8E0AB2ED, 0x1AE7593A, 0xFFFFF3BC, 0x23E9058D, 0xFFFFF40B, 0xDFA6CF3E, 0x1B47DA81, 0xFFFFF8C3, 0x349CC616, 0xFFFFF7E9, 0x70C290D0, 0x1D816435, 0x00000002, 0x43F999C9, 0xFFFFFFD8, 0xAB0BCA16, 0x1DACC905, 0xFFFFFF54, 0x5C129962, 0xFFFFFD06, 0xE4515A41, 0x1E03B13C, 0xFFFFFF80, 0x7E763806, 0xFFFFF36A, 0xA25F3D93, 0x22FEFC06, 0xFFFFFCDD, 0xB94E0C2F, 0xFFFFFCB6, 0xF023033D, 0x26B1E690, 0xFFFFFDAB, 0xD0C7ED0C, 0xFFFFFE9B, 0xD49872C6, 0x2A652084, 0x000001EA, 0xDF9B65EE, 0x00000051, 0x5CC5AB90, 0x2FBEBD25, 0x0000048F, 0x60A4E9F2, 0x000009AF, 0x42FE8B0D, 0x34F12D90, 0x000004C0, 0xF6257D94, 0x00000480, 0x5227DE21, 0x35F591D0, 0xFFFFFCA1, 0xDA83E113, 0xFFFFF998, 0x805C7ECB, 0x37EB0B72, 0xFFFFF3EC, 0x7480201A, 0xFFFFF903, 0xAC977E11, 0x389A58A8, 0x00000189, 0xE4005CD7, 0xFFFFFDEC, 0xB043695F, 0x3CB24155, 0x0000084C, 0x8ACB6FF1, 0x00000899, 0xACB471A5, 0x3DCBCDE3, 0x000007A8, 0xA84E3072, 0x00000384, 0xB2624259, 0x3F5290DE, 0xFFFFFE25, 0x8AC11F92, 0xFFFFFD8A, 0x44ACCD78, 0x47FF9B7E, 0x00000A81, 0x9833BF9C, 0x00000B35, 0x9B7199CD, 0x4C7867E6, 0x0000011C, 0x68BB4F80, 0x0000002E, 0x75B675CD, 0x53ADCD80, 0x000004E8, 0x6AA4F705, 0x00000452, 0xBA7C314B, 0x566E1640, 0x00000C8E, 0x203E3737, 0x00000C38, 0xF9367ED9, 0x5EDBB130, 0x000004FF, 0xD4F71A40, 0x000002AA, 0x35DC4141, 0x6C29C83A, 0x00000013, 0xBEAD8A76, 0xFFFFFFB5, 0x7A8A43EF, 0x6E036C9C, 0x00000BD5, 0x225F81E0, 0x00000D89, 0x3C25944D, 0x6FDCCE50, 0x00000605, 0xD3126740, 0x000003D5, 0xA3DA544C, 0x7132D345, 0x0000064E, 0x00915A5A, 0x000006DD, 0x5BCB6B22, 0x720DBD5C, 0x000008C3, 0x64DCFDF6, 0x00000858, 0x190B20BB, 0x7A035AD4, 0x00000424, 0x4DD955FB, 0x000004BF, 0xF65150B5, 0x7CBAED22, 0x00000AA1, 0x62CC154B, 0xFFFFFC58, 0x8DD5CEDB, 0x7EBF8EA8, 0x00000458, 0xCE844A0E, 0xFFFFF734, 0x9079D6BA, 0x804885CD, 0x000007BB, 0x89A8DA66, 0x00000136, 0x7185B813, 0x82190F37, 0xFFFFF58C, 0x013FA7D4, 0xFFFFF4AB, 0x7518093D, 0x83F7826A, 0x00000917, 0x2F33C3DD, 0xFFFFFBF0, 0x02A289B1, 0x8481BFD5, 0xFFFFF927, 0x72EED2D1, 0xFFFFF80A, 0xF46FD351, 0x85A69D6E, 0x000000B4, 0x27A3BB0F, 0x00000181, 0x49235BC0, 0x85F73150, 0x00000259, 0xA300692F, 0x000009BD, 0x5A3E46A9, 0x86E2497A, 0xFFFFFB53, 0xE7614707, 0xFFFFFBB3, 0xFA190B2A, 0x8B261F60, 0xFFFFF323, 0x97B9CC33, 0xFFFFFAB7, 0x2CB73BF0, 0x8B42B00C, 0x00000871, 0xA57A2DE3, 0x00000797, 0xA73082D6, 0x8E4C5C94, 0x000000FE, 0xEE4B594B, 0xFFFFF999, 0xDCE3B74D, 0x913A9FDB, 0xFFFFFE1C, 0x1BFFA329, 0xFFFFFD31, 0x49B21C95, 0x922BFB96, 0xFFFFF61B, 0x4FAFD829, 0xFFFFFBBA, 0x6BD5D317, 0x9F4B8702, 0xFFFFFEC1, 0xB691AD49, 0xFFFFFEF2, 0xCE6C6FE9, 0xA2CEAAA6, 0xFFFFFD89, 0x60E52701, 0xFFFFFCB2, 0x25AD9A9D, 0xAA970D72, 0xFFFFF2BB, 0xC1F58CAC, 0xFFFFF2AB, 0x20B8FE22, 0xABC02B72, 0xFFFFF94B, 0xFF6EA5A6, 0xFFFFFA6A, 0x1CD46647, 0xAE535E9E, 0x000003EC, 0x31246F6B, 0x0000035B, 0x50E2A20A, 0xB7337941, 0xFFFFF856, 0xD1A79AD7, 0xFFFFF955, 0x14673B75, 0xBB8DB95E, 0xFFFFFEEB, 0x6A7F1E5A, 0xFFFFF3B3, 0x1EF2F3AA, 0xBC1EDA22, 0xFFFFFB90, 0xE247955F, 0xFFFFFCE6, 0xA0351A85, 0xBCD91FE8, 0x0000008C, 0x71A348B9, 0x00000030, 0x821754EF, 0xBD38E305, 0xFFFFFF59, 0xE694333F, 0xFFFFFEF9, 0x436B1A45, 0xBE1AA65A, 0xFFFFF93D, 0x8761A810, 0xFFFFFEEB, 0xB2DB19FA, 0xC052453C, 0x000009B5, 0xB05027D7, 0x000009C5, 0xBCA91679, 0xC4A2D780, 0x000008B9, 0xE42FD068, 0x000007C1, 0x9F8B2B83, 0xC6A236BA, 0xFFFFFDBB, 0x20649A12, 0xFFFFFD09, 0x5F73FD94, 0xC6BB5160, 0xFFFFFE90, 0x0ED42674, 0xFFFFFF4B, 0xA76699CC, 0xCB74E940, 0x000003E3, 0x7DA194FF, 0xFFFFFCDA, 0xB23E5B15, 0xD027B387, 0xFFFFF701, 0x880BCC4F, 0xFFFFF785, 0xFEA3D685, 0xD1127D6B, 0xFFFFFAC0, 0xDF3D499A, 0x00000362, 0x84B7777D, 0xD6F5F913, 0xFFFFFCCD, 0xA5D89DB8, 0xFFFFFCAB, 0xF69BAE29, 0xDD04F828, 0xFFFFF705, 0xE18F3BA0, 0xFFFFF64D, 0xEBC799B0, 0xDDF22CB8, 0x0000075D, 0x47F7B857, 0x000001B3, 0x5C1CDEA9, 0xDF34D0A8, 0x0000014D, 0xBFE2CAD5, 0x00000201, 0x1F0C8A89, 0xE146EA40, 0x0000046D, 0x189EB8F9, 0xFFFFF6FB, 0x4CA1090D, 0xE231C560, 0x00000710, 0x2E586529, 0xFFFFFF17, 0x0E9AA776, 0xE2FC6838, 0x00000733, 0xB73DDD7A, 0x00000753, 0x14A1BDE4, 0xE44AE35D, 0x000002C8, 0x46B1F3D1, 0xFFFFFA2D, 0xD2295816, 0xE5AF4AB1, 0x00000DB0, 0x0AFF4FF9, 0x00000D91, 0xB17A4340, 0xE7E3CF21, 0x00000656, 0x9FC50924, 0x00000658, 0x31615022, 0xE8815965, 0x00000BCB, 0x6F51A655, 0x00000C0A, 0x72F5680C, 0xEBDF0F14, 0xFFFFF2B1, 0xD36EC5D4, 0xFFFFF239, 0x3B711343, 0xEC12E59B, 0x00000270, 0x3A38D2E8, 0x0000023D, 0x68D07674, 0xF4013920, 0x00000703, 0xD83CCFAA, 0x000007BA, 0x46891EEB, 0xF6847EC1, 0xFFFFFE62, 0x6D4BAAFC, 0xFFFFFD92, 0x5E6F5A94]
 
size_table = [0x02F73020, 0x00000015, 0x09D3473A, 0x00000051, 0x0EF87B55, 0x0000000D, 0x147CB028, 0x00000023, 0x15F833AA, 0x00000030, 0x17086780, 0x00000018, 0x1733A9D4, 0x00000014, 0x17D61EE8, 0x00000051, 0x1D52F19E, 0x00000011, 0x1F732DE0, 0x0000000D, 0x1FBECFAD, 0x0000001B, 0x245BD7C8, 0x00000055, 0x25E7ABEE, 0x00000009, 0x2882C190, 0x000000A2, 0x2A2084A0, 0x00000075, 0x326AA6AE, 0x00000036, 0x33074A36, 0x00000024, 0x3440BD69, 0x0000002C, 0x362A1FC3, 0x0000002C, 0x3C0450D0, 0x0000000D, 0x3CB575FD, 0x00000011, 0x41B3B26E, 0x0000004E, 0x46005120, 0x00000011, 0x465A72CF, 0x00000002, 0x492145A0, 0x0000000D, 0x49AA4CE0, 0x0000002D, 0x4BD63647, 0x0000004E, 0x4BF84A87, 0x0000000D, 0x4D102445, 0x00000033, 0x4D4D3C55, 0x0000001B, 0x53723232, 0x0000000A, 0x5809B5CB, 0x000000A2, 0x5B12FFCE, 0x00000015, 0x5B1F3000, 0x00000051, 0x5D9FBD20, 0x00000027, 0x6219EED9, 0x0000008A, 0x65D82D17, 0x0000004C, 0x67F5671A, 0x00000063, 0x6CE2CBC1, 0x00000033, 0x718A739C, 0x0000000B, 0x71A62DD7, 0x00000015, 0x7693A1F6, 0x00000014, 0x7A473FB0, 0x00000047, 0x7AEFEDDC, 0x00000011, 0x7AF2CF90, 0x0000004F, 0x7BE0B8B0, 0x0000001B, 0x80EB3E88, 0x0000000A, 0x8213506A, 0x0000000C, 0x82468114, 0x00000011, 0x86B872A2, 0x0000001C, 0x87FBD296, 0x00000019, 0x88719339, 0x00000016, 0x89E2630A, 0x00000024, 0x8CB6536E, 0x0000004E, 0x92316E00, 0x00000015, 0x9415A51E, 0x0000004F, 0x94D658E0, 0x0000002B, 0x97E8DFCD, 0x00000036, 0x992E3874, 0x0000002A, 0x9B06958D, 0x00000030, 0x9B36B480, 0x0000000D, 0xA03CEFAD, 0x0000005A, 0xA39F47E6, 0x0000004E, 0xA946DEC4, 0x000000B4, 0xAE6173DC, 0x00000051, 0xB044A68D, 0x0000008C, 0xB29E36A8, 0x0000000B, 0xB82781F4, 0x0000000D, 0xC14DFAF8, 0x00000011, 0xC3F42E20, 0x0000001E, 0xC5E0065E, 0x00000067, 0xCAD68B21, 0x00000039, 0xCBF29AC7, 0x00000011, 0xCE8729BC, 0x0000001B, 0xD2A85A94, 0x00000004, 0xD34FA4F3, 0x00000011, 0xD64611B0, 0x00000058, 0xD814FD56, 0x00000018, 0xDD386A80, 0x0000000A, 0xDE82DFAC, 0x00000011, 0xEC68D16F, 0x0000001B, 0xEEDE845B, 0x0000003F, 0xF235F260, 0x0000008D, 0xF9AA1F0B, 0x00000087, 0xFC200887, 0x00000011, 0xFED657A3, 0x0000000C, 0x00000000]
zf_0_jmp = 0
zf_0_key = 1
zf_1_jmp = 2
zf_1_key = 3
 
code_bin = open("code.bin", "rb").read()
print("code size: ", hex(len(code_bin)))
 
def get_size(key):
    for i in range(85):
        if size_table[i * 2] == key:
            return  size_table[i * 2 + 1]
    return None
 
def get_jmps(key):
    for i in range(85):
        base = i * 5
        if fuckTable[base] == key:
            # zf_0_jmp, zf_0_key, zf_1_jmp, zf_1_key
            return fuckTable[base + 1: base + 5]
    print("not found2: ", hex(key))
    return None
 
def fuck(prev_key, rip):
    return rip ^ prev_key ^ ((rip * prev_key) & 0xffffffff) ^ (prev_key + rip)
 
def deXor(data, key):
    key = p32(key)
    data = bytearray(data)
    for i in range(len(data)):
        data[i] ^=  key[i % 4]
    return data
 
def decrypt_block(key, rip):
    key2 = fuck(key, rip)
    blockSize = get_size(key2)
 
    if blockSize is None:
        print("Not found1: rip:%x key:%x" % (rip, key2))
        return None, None, None
 
    offset = rip - 0x1000
    code_data = code_bin[offset: offset + blockSize]
    code_data = deXor(code_data, key)
    next_rip = rip + blockSize - 2
    key2 = fuck(key, next_rip)
 
    jmps = get_jmps(key2)
 
    return code_data, jmps, next_rip
 
class Node:
    def __init__(self, data, rip):
        self.code_data = data
        self.child1 = 0
        self.child2 = 0
        self.end_rip = None
        self.rip = rip
 
def disasm(data, baseaddr):
    md = Cs(CS_ARCH_X86, CS_MODE_64)
    ins = ''
    for i in md.disasm(data, baseaddr):
        asm_code = "%s\t%s" % (i.mnemonic, i.op_str)
        ins += asm_code + "\n"
    return ins
 
def buildNode(key_, rip_):
    work_queue = [(key_, rip_)]
    log_map = {}
    while len(work_queue) > 0:
        T = work_queue[0]
        work_queue.remove(T)
        key, rip = T
 
        if rip in log_map:
            continue
 
        if rip == 0x10A3:
            key -= 0x2B09B990
            rip = 0x1EEC
 
        code_data, jmps, next_rip = decrypt_block(key, rip)
 
        if code_data is None:
            continue
 
        node_cur = Node(code_data, rip)
 
        node_cur.end_rip = next_rip
        log_map[rip] = node_cur
 
        if jmps is None:
            continue
 
        asm_text = disasm(node_cur.code_data, rip)
 
        newrip = next_rip + ctypes.c_int32(jmps[zf_0_jmp]).value
        node_cur.child1 = newrip
        if newrip not in log_map:
            work_queue.append(((key + jmps[zf_0_key]) & 0xffffffff, newrip))
 
        if 'qword ptr fs:[' in asm_text.splitlines()[-1]:
            continue
 
        newrip = next_rip + ctypes.c_int32(jmps[zf_1_jmp]).value
        node_cur.child2 = newrip
        if newrip not in log_map:
            work_queue.append(((key + jmps[zf_1_key]) & 0xffffffff, newrip))
 
    jmptables = {}
    for i in sorted(log_map.keys()):
        if log_map[i].child1 is None:
            log_map[i].child1 = 0
 
        if log_map[i].child2 is None:
            log_map[i].child2 = 0
 
        jmptables[hex(log_map[i].end_rip)] = (hex(log_map[i].rip), hex(log_map[i].child1), hex(log_map[i].child2))
    print("len:", len(jmptables))
    print(jmptables)
 
    all_asm = ''
    for i in sorted(log_map.keys()):
        print(hex(i))
        node = log_map[i]
        if i == 0x1EEC:
            all_asm += "_0x10a3:\n"
 
        all_asm += "_" + hex(i) + ":\n"
        all_asm += disasm(node.code_data, i)
 
        if node.child1 != 0 and node.child2 != 0:
            jmp_code = "jz _" + hex(node.child2) + "\n"
            jmp_code += "jmp _" + hex(node.child1) + "\n"
 
        elif node.child1 == 0 and node.child2 != 0:
            jmp_code = "jmp _" + hex(node.child2) + "\n"
 
        elif node.child2 == 0 and node.child1 != 0:
            jmp_code = "jmp _" + hex(node.child1) + "\n"
        else:
            jmp_code = '\n'
 
        all_asm += jmp_code
 
    all_asm = all_asm.replace("endbr64", "nop\n" * 4)
    code_bin = asm(all_asm)
    open('1.bin', 'wb').write(code_bin)
    print(all_asm)
    print("all nodes: ", len(log_map))
 
buildNode(0x3265B1F5, 0x1000)

七:重建后的代码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
// rsp = 0x7777F000
void __noreturn sub_4()
{
  unsigned __int8 v0; // al
  int v1; // eax
  __int64 v2; // rax
  __int64 xorKey[4]; // [rsp+0h] [rbp-2C0h]
  __int128 v4; // [rsp+21h] [rbp-29Fh] BYREF
  char v5[14]; // [rsp+31h] [rbp-28Fh] BYREF
  char v6[17]; // [rsp+3Fh] [rbp-281h] BYREF
  __int64 compare[5]; // [rsp+50h] [rbp-270h] BYREF
  __int64 v8; // [rsp+78h] [rbp-248h]
  __int64 FlagInData[8]; // [rsp+80h] [rbp-240h] BYREF
  unsigned __int8 v10; // [rsp+C2h] [rbp-1FEh]
  unsigned __int8 v11; // [rsp+C3h] [rbp-1FDh]
  int kk; // [rsp+C4h] [rbp-1FCh]
  __int64 v13; // [rsp+C8h] [rbp-1F8h]
  __int128 *v14; // [rsp+D0h] [rbp-1F0h]
  unsigned __int8 v15; // [rsp+DAh] [rbp-1E6h]
  unsigned __int8 v16; // [rsp+DBh] [rbp-1E5h]
  int mm; // [rsp+DCh] [rbp-1E4h]
  __int64 v18; // [rsp+E0h] [rbp-1E0h]
  __int64 v19; // [rsp+E8h] [rbp-1D8h]
  unsigned __int8 v20; // [rsp+F3h] [rbp-1CDh]
  int jj; // [rsp+F4h] [rbp-1CCh]
  __int64 v22; // [rsp+F8h] [rbp-1C8h]
  __int64 *v23; // [rsp+100h] [rbp-1C0h]
  __int64 *v24; // [rsp+108h] [rbp-1B8h]
  int ii; // [rsp+110h] [rbp-1B0h]
  unsigned int v26; // [rsp+114h] [rbp-1ACh]
  int v27; // [rsp+118h] [rbp-1A8h]
  unsigned int v28; // [rsp+11Ch] [rbp-1A4h]
  unsigned int *v29; // [rsp+120h] [rbp-1A0h]
  int n; // [rsp+12Ch] [rbp-194h]
  unsigned __int64 data2_1; // [rsp+130h] [rbp-190h]
  unsigned __int64 data2_2; // [rsp+138h] [rbp-188h]
  unsigned __int64 data2_3; // [rsp+140h] [rbp-180h]
  unsigned __int64 data2; // [rsp+148h] [rbp-178h]
  int m; // [rsp+154h] [rbp-16Ch]
  unsigned __int64 v35; // [rsp+158h] [rbp-168h]
  unsigned __int64 data1; // [rsp+160h] [rbp-160h]
  int i_0; // [rsp+16Ch] [rbp-154h]
  __int64 v39; // [rsp+170h] [rbp-150h]
  unsigned __int64 from_t0; // [rsp+178h] [rbp-148h]
  __int64 const_32; // [rsp+180h] [rbp-140h]
  __int64 *flag_ptr; // [rsp+188h] [rbp-138h]
  unsigned __int64 v43; // [rsp+190h] [rbp-130h]
  __int64 v44; // [rsp+198h] [rbp-128h]
  __int64 *v45; // [rsp+1A0h] [rbp-120h]
  unsigned __int8 v46; // [rsp+202h] [rbp-BEh]
  unsigned __int8 v47; // [rsp+203h] [rbp-BDh]
  int nn; // [rsp+204h] [rbp-BCh]
  __int64 v49; // [rsp+208h] [rbp-B8h]
  char *v50; // [rsp+210h] [rbp-B0h]
  __int64 flagLen; // [rsp+218h] [rbp-A8h]
  __int64 *v52; // [rsp+220h] [rbp-A0h]
  unsigned __int8 v53; // [rsp+22Ah] [rbp-96h]
  unsigned __int8 v54; // [rsp+22Bh] [rbp-95h]
  int i1; // [rsp+22Ch] [rbp-94h]
  __int64 v56; // [rsp+230h] [rbp-90h]
  char *v57; // [rsp+238h] [rbp-88h]
  __int64 v58; // [rsp+240h] [rbp-80h]
  __int64 time0; // [rsp+248h] [rbp-78h]
  __int64 v60; // [rsp+250h] [rbp-70h]
  __int64 d2; // [rsp+258h] [rbp-68h]
  __int64 v62; // [rsp+260h] [rbp-60h]
  __int64 d1; // [rsp+268h] [rbp-58h]
  int i; // [rsp+274h] [rbp-4Ch]
  __int64 data0; // [rsp+278h] [rbp-48h]
  unsigned __int8 v66; // [rsp+282h] [rbp-3Eh]
  unsigned __int8 v67; // [rsp+283h] [rbp-3Dh]
  int j; // [rsp+284h] [rbp-3Ch]
  __int64 v69; // [rsp+288h] [rbp-38h]
  char *v70; // [rsp+290h] [rbp-30h]
  unsigned __int8 v71; // [rsp+29Ah] [rbp-26h]
  unsigned __int8 v72; // [rsp+29Bh] [rbp-25h]
  int k; // [rsp+29Ch] [rbp-24h]
  __int64 v74; // [rsp+2A0h] [rbp-20h]
  __int64 *flagIn; // [rsp+2A8h] [rbp-18h]
  __int64 v76; // [rsp+2B0h] [rbp-10h]
  unsigned __int64 time0_1; // [rsp+2B8h] [rbp-8h]
 
  v58 = 0x7177625F32303231i64;
  __writefsqword(0, 0x7177625F32303231ui64);
  __asm { syscall; Low latency system call }    // 触发系统调用的那个回调函数
  time0 = MEMORY[0x1337];                       // time(0)
  time0_1 = MEMORY[0x1337];
  v2 = MEMORY[0x1337] / 0xE10ui64;
  data0 = MEMORY[0x1337] / 0xE10ui64;           // 下面是验证这个生成的随机数值
  for ( i = 0; i != 256; ++i )
  {
    d1 = 0i64;
    d1 = *(_QWORD *)v2;                         // fs:0
    v62 = d1;                                   // 触发回调修改了值
    d2 = 0i64;
    d2 = *(_QWORD *)(d1 + 1);                   // fs:0
    v60 = d2;
    data0 = __ROL8__((data0 ^ d1) + d2 + 33 * data0 + 1, 13);
    if ( (i & 1) != 0 )
      data0 = v60 ^ (v62 + data0);
    if ( (i & 2) != 0 )
      data0 ^= v62 + v60;
    if ( (i & 4) != 0 )
      data0 ^= v60 ^ v62;
    v2 = i & 8;
    if ( (i & 8) != 0 )
    {
      v2 = data0 + v62 + v60;
      data0 = v2;
    }
  }                                             // 上面是生成v76
  v76 = data0;                                  // assert(v76 == 0x1C986C3B22EA63E5)
  strcpy(v6, "input flag:\n");
  v70 = v6;
  v69 = 12i64;
  for ( j = 0; v69 != j; ++j )
  {
    v67 = v70[j];
    v66 = v67;
    __outbyte(1u, v67);                         // 等价于printf("input flag:\n");
  }
  memset(FlagInData, 0, sizeof(FlagInData));
  flagIn = FlagInData;
  v74 = 64i64;
  for ( k = 0; ; ++k )
  {
    if ( v74 == k )
      goto LABEL_3;
    v0 = __inbyte(0);                           // get_char
    v72 = v0;
    v71 = v0;
    if ( v0 == '\n' )
      break;
    *((_BYTE *)flagIn + k) = v71;
  }                                             // 等价于scanf("%s",flagIn);
  *((_BYTE *)flagIn + k) = 0;
LABEL_3:
  if ( v76 == 0x1C986C3B22EA63E5i64 )           // 判断生成的v76
  {
    v52 = FlagInData;
    for ( flagLen = 0i64; *((_BYTE *)v52 + flagLen); ++flagLen )
      ;
    v8 = flagLen;
    if ( flagLen == 32 )                        // 判断输入长度是否为32
    {
      v45 = FlagInData;
      v44 = 32i64;
      v43 = time0_1 / 0xE10;
      flag_ptr = FlagInData;
      const_32 = 32i64;
      from_t0 = time0_1 / 0xE10;
      v39 = 0x5249415452455451i64;              // 初值有,变化式子有,可以计算出最后和flag进行异或的值
      __writefsqword(0, 0x5249415452455451ui64);// 写入0x5249415452455451
      for ( i_0 = 0; const_32 != i_0; ++i_0 )
      {
        data1 = __readfsqword(0);               // 0x5249415452455451
        v35 = i_0;                              // v36的初值
        for ( m = 0; m != 256; ++m )
        {
          data2 = __readfsqword(0);             // 每次读内存都会触发回调函数
          data2_3 = data2;
          data2_2 = data2;
          data2_1 = data2;
          v35 = (v35 ^ data2) + data2 + 0x21 * v35 + 1;
          v35 = __ROL8__(v35, 13);              // 更新v36的值
          if ( (m & 1) != 0 )
            v35 = data2_1 ^ (data2_3 + v35);
          if ( (m & 2) != 0 )
            v35 ^= data2_3 + data2_1;
          if ( (m & 4) != 0 )
            v35 ^= data2_1 ^ data2_3;
          if ( (m & 8) != 0 )
            v35 += data2_3 + data2_1;
        }
        *((_BYTE *)flag_ptr + i_0) ^= (_BYTE)data1 + (_BYTE)v35;// 将flag每位与一个值进行异或,这个值可以计算得出
      }
      for ( n = 0; const_32 != n; n += 4 )
      {
        v29 = (unsigned int *)((char *)flag_ptr + n);
        v28 = *v29;
        v27 = 0;
        v26 = v28;
        v28 = from_t0 + _mm_crc32_u32(0, v28);  // 关键步骤
        *v29 = v28;
      }
      xorKey[0] = 0x178DEC4F232DDB6Ei64;
      xorKey[1] = 0xC2AAB7D6D2A167C3ui64;
      xorKey[2] = 0xF1AB91F72761A80Fui64;
      xorKey[3] = 0x3DCEDC28076C41Ai64;
      for ( ii = 0; v44 != ii; ++ii )
        *((_BYTE *)v45 + ii) ^= *((_BYTE *)xorKey + ii);// 再次异或
      compare[0] = 0x3EC81D9432CEF584i64;
      compare[1] = 0xB649A4DCD6BD24FEui64;
      compare[2] = 0xC5927F0B767A787Dui64;
      compare[3] = 0x1F245B7F751BB52Ei64;
      v24 = FlagInData;
      v23 = compare;
      v22 = v8;
      for ( jj = 0; ; ++jj )
      {
        if ( v22 == jj )                        // 循环遍历flaglen次
        {
          v1 = 0;
          goto LABEL_47;
        }
        v20 = *((_BYTE *)v24 + jj) - *((_BYTE *)v23 + jj);// 将compare数组的值和输入的值进行比较
        if ( v20 )
          break;
      }
      v1 = v20;
LABEL_47:
      if ( v1 )
      {
        strcpy((char *)&v4, "wrong\n");         // 等价于printf("wrong\n");
        v14 = &v4;
        v13 = 6i64;
        for ( kk = 0; v13 != kk; ++kk )
        {
          v11 = *((_BYTE *)v14 + kk);
          v10 = v11;
          __outbyte(1u, v11);
        }
      }
      else
      {
        strcpy((char *)&v4 + 7, "correct\n");   // 等价与printf("correct\n");
        v19 = (__int64)&v4 + 7;
        v18 = 8i64;
        for ( mm = 0; v18 != mm; ++mm )
        {
          v16 = *(_BYTE *)(mm + v19);
          v15 = v16;
          __outbyte(1u, v16);
        }
      }
    }
    else
    {
      strcpy(v5, "wrong\n");                    // printf("wrong\n");
      v50 = v5;
      v49 = 6i64;
      for ( nn = 0; v49 != nn; ++nn )
      {
        v47 = v50[nn];
        v46 = v47;
        __outbyte(1u, v47);
      }
    }
  }
  else
  {                                             // printf("wrong\n");
    *(_DWORD *)&v5[7] = 'norw';
    *(_WORD *)&v5[11] = '\ng';
    v5[13] = 0;
    v57 = &v5[7];
    v56 = 6i64;
    for ( i1 = 0; v56 != i1; ++i1 )
    {
      v54 = v57[i1];
      v53 = v54;
      __outbyte(1u, v54);
    }
  }
  __halt();
}

关键:

 

这里是对生成的随机数然后/ 0xE10ui64进行检验

 

图片描述

 

这里等价于printf("input flag:\n");

 

图片描述
这里等价于scanf("%s",flag);
图片描述

 

这里通过先设置一个值,然后每次读取都会触发内存读的回调函数(changeKey),temp[0] = 0x756E69636F726E03LL * temp[0] + 0xBADC0DEC001CAFELL,最后和flag进行第一次异或

 

图片描述

 

之后就是四个字节的取,_mm_crc32_u32之后加上一个from_t0值,这个值就是from_t0 = time0_1 / 0xE10;
图片描述
最后再将flag和一些值进行异或,之后比较
图片描述
爆破思路:
图片描述

 

①v28 = from_t0 + _mm_crc32_u32(0, v28); // 关键步骤

 

生成的v28就是最后会和那些已知的值进行异或的,from_to是随机数/0xE10生成的,_mm_crc32_u32里的v28是之前flag在上面进行的②((_BYTE *)flag_ptr + i_0) ^= (_BYTE)data1 + (_BYTE)v35;得到的,而(_BYTE)data1 + (_BYTE)v35这些我们可以通过它本身的代码运算得到。

 

假如现在我们有flag的前四个字节,有已知的四种格式:qwb{,QWB{,flag{,FLAG{

 

倒推的话,我们将最后比较的值和那些已知的值再次异或,即可得到①式生成的v28,然后现在我们正向推导过去,我们先计算出第一次和flag进行异或的那些值,即(_BYTE)data1 + (_BYTE)v35,可以通过它给的代码和changekey这个读内存的回调函数计算出来,之后将我们猜测的几种flag的前四个字节和这些值异或,异或之后传入_mm_crc32_u32函数即可,那么现在显然我们就只有from_t0一个未知量,可以计算得出它的四种可能,然后前面不是有个对生成的随机数进行了验证的代码片段 ,可以通过那个判断出哪个是正确的,然后我们便可以逆推回去了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <iostream>
#include "ida.h"
#include <x86intrin.h>
 
static uint64  fs_0;
 
uint64 getFS0() {                 //每次读取这个内存都会触发的回调函数
    // v7[0] = 8461816625668189699LL * v7[0] + 841540768324766462LL;
    fs_0 = 0x756E69636F726E03 * fs_0 + 0xBADC0DEC001CAFE;
    return fs_0;
}
 
void setFSO(int64_t val) {        //设置值
    fs_0 = val;
}
 
uint64 test_time(uint64 time) {       //检验生成的随机数是否正确的代码
    uint64  v35;
    setFSO(0x7177625F32303231);
 
    uint64 v2 = time ;
    uint64  data0 = time ;
    uint64 d1, d2,v62, v60;
 
    for (int i = 0; i != 256; ++i )
    {
        d1 = 0;
        d1 = getFS0();
        v62 = d1;
        d2 = getFS0();
        v60 = d2;
        data0 = __ROL8__((data0 ^ d1) + d2 + 33 * data0 + 1, 13);
        if ( (i & 1) != 0 )
            data0 = v60 ^ (v62 + data0);
        if ( (i & 2) != 0 )
            data0 ^= v62 + v60;
        if ( (i & 4) != 0 )
            data0 ^= v60 ^ v62;
        v2 = i & 8;
        if ( (i & 8) != 0 )
        {
            v2 = data0 + v62 + v60;
            data0 = v2;
        }
    }
    printf("%p ==\n", data0);
    return data0;
}
 
int main() {
    unsigned __int64 compare[4];
    unsigned __int64 xorKey[4];
    unsigned int flags[] = {0x67616c66, 0x47414c46, 0x7b627771, 0x7b425751};   //四种flag的前四个字节格式
    unsigned char xorkey0[32] = {0};
    uint32  * xorkey0_4 = (uint32  *)xorkey0;
    compare[0] = 0x3EC81D9432CEF584; // flag, FLAG, qwb{ ,QWB{
    compare[1] = 0xB649A4DCD6BD24FE;
    compare[2] = 0xC5927F0B767A787D;
    compare[3] = 0x1F245B7F751BB52E;
    xorKey[0] = 0x178DEC4F232DDB6E;
    xorKey[1] = 0xC2AAB7D6D2A167C3;
    xorKey[2] = 0xF1AB91F72761A80F;
    xorKey[3] = 0x3DCEDC28076C41A;
 
    unsigned int * compare_4 = (unsigned int *)compare;
 
    unsigned int fs;
    uint64 v35, v36, v33,v32, v31, v30;                  //生成第一次和flag进行异或的值的代码
    setFSO(0x5249415452455451);
    for (int i_0 = 0; 32 != i_0; ++i_0 )
    {
        uint64 data0 = getFS0();               // 0x5249415452455451
        v35 = i_0;
        for (int m = 0; m != 256; ++m )
        {
            uint64 data1 = getFS0();
            uint64 data2 = getFS0();
            v35 = (v35 ^ data1) + data2 + 0x21 * v35 + 1;
 
            v35 = __ROL8__(v35, 13);
            if ( (m & 1) != 0 )
                v35 = data2 ^ (data1 + v35);
            if ( (m & 2) != 0 )
                v35 ^= data2 + data1;
            if ( (m & 4) != 0 )
                v35 ^= data2 ^ data1;
            if ( (m & 8) != 0 )
                v35 += data2 + data1;
        }
        xorkey0[i_0] =  (_BYTE)data0 + (_BYTE)v35;                  //将第一次要和flag进行异或的值存到数组中
    }
 
    for(int k = 0; k < 4; k++) {
        unsigned char * data = (unsigned  char *)&flags[k];         //进行flag的第一次异或
        for (int i = 0 ; i < 4; i++) {
            data[i] ^= xorkey0[i];
        }
       // printf("%x\n", flags[k]);
    }
 
    for (int ii = 0; 32 != ii; ++ii )
        *((_BYTE *)compare + ii) ^= *((_BYTE *)xorKey + ii);        //逆向flag的最后的异或那一步
 
    uint64 targetTT = 0;
    for (int i = 0; i < 4; i++)
    {
        // v27 = from_t0 + _mm_crc32_u32(0, v27);
      //  unsigned int from_t0 = compare_4[0] - _mm_crc32_u32(0, flags[i]);
        uint64 tt = compare_4[0] - _mm_crc32_u32(0, flags[i]);
        uint64 rr = test_time(tt);
        if (rr == 0x1c986c3b22ea63e5) {
            targetTT = tt;
            printf("val:%p\n", tt);
        }
    }
 
    uint32 flag_arr[8];
    for (int i = 0; i < 8; ++i) { // 4 * 8
        for (uint32 val = 0; val != 0xffffffff; ++val) {
            if (compare_4[i] - targetTT == _mm_crc32_u32(0, val)) {           //爆破flag第一次异或之后的值
                flag_arr[i] = val;
                break;
            }
        }
    }
    for (int i = 0; i < 8; ++i) {
        flag_arr[i] ^= xorkey0_4[i];                                        //逆向第一步异或
    }
    printf("%s", (char *)flag_arr);
 
    return 0;
}

参考:
https://panda0s.top/2021/06/14/%E5%BC%BA%E7%BD%91%E6%9D%AF-unicorn-like-a-pro/#强网杯-unicorn-like-a-pro


[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

最后于 2021-6-18 12:32 被SYJ-Re编辑 ,原因:
上传的附件:
收藏
点赞3
打赏
分享
最新回复 (12)
雪    币: 1
活跃值: 活跃值 (123)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_吃胖困难户 活跃值 2021-6-18 10:37
2
1
貌似少了一个图![图片描述](upload/tmp/9 ![图片描述]
雪    币: 5241
活跃值: 活跃值 (4542)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
SYJ-Re 活跃值 2 2021-6-18 12:31
3
0
感谢提醒
雪    币: 2627
活跃值: 活跃值 (1764)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
YenKoc 活跃值 2021-6-18 23:56
4
0
太强了
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
大史 4.0 活跃值 2021-6-21 09:10
5
0
想问下code.bin是怎么得到的呢?
雪    币: 5241
活跃值: 活跃值 (4542)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
SYJ-Re 活跃值 2 2021-6-22 10:30
6
0

内存里面的,我们把它导出成一个code.bin

最后于 2021-6-22 10:33 被SYJ-Re编辑 ,原因:
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
大史 4.0 活跃值 2021-6-22 15:10
7
0
SYJ-Re 内存里面的,我们把它导出成一个code.bin
最有的exp脚本是用g++编译吧,但是ida.h的头文件是从哪里得到的呢?
雪    币: 209
活跃值: 活跃值 (163)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SmallDolphin 活跃值 2021-6-22 15:53
8
2
师傅厉害了
雪    币: 5241
活跃值: 活跃值 (4542)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
SYJ-Re 活跃值 2 2021-6-22 17:35
9
0
ida.h网上搜一下会有的,这里给你个链接:https://pan.baidu.com/s/1Twp4mrf_gIvCx_D6cWNPsg 
提取码:0syj 
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
大史 4.0 活跃值 2021-6-22 20:49
10
0
SYJ-Re ida.h网上搜一下会有的,这里给你个链接:https://pan.baidu.com/s/1Twp4mrf_gIvCx_D6cWNPsg 提取码:0syj
网上找了很久都没找到,在cryptopp包中有名字一样的但是明显不通用
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_zemoepmq 活跃值 2021-6-23 16:02
11
0
next_rip = rip + blockSize - 2,师傅这里为什么要减个2呢
雪    币: 5241
活跃值: 活跃值 (4542)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
SYJ-Re 活跃值 2 2021-6-23 16:29
12
0

你仔细想一下,每一个区块最后结尾是以什么为标志触发uc_hook_add注册的那个ControlFlow1回调的呢,你连续调试,会发现区块结尾都是0x3F0F,占用两个字节

最后于 2021-6-23 16:29 被SYJ-Re编辑 ,原因:
雪    币: 249
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
@=llfly 活跃值 2021-7-19 16:34
13
0
学习
游客
登录 | 注册 方可回帖
返回