Capstone反汇编(二)

编程之家收集整理的这篇文章主要介绍了Capstone反汇编(二)编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。


前言

Capstone反汇编(一)
上篇文章只是简单分析了官方给出的一个案例用到的API,接下来分析其它的API数据结构

一 cs_option API 分析

1.1 cs_option

反编译引擎的运行时选项

cs_option(csh ud, cs_opt_type type, size_t value)

1.2 cs_opt_type

type是cs_option函数的第二个参数,是反汇编引擎运行时枚举选项

// 反汇编引擎的运行时选项
typedef enum cs_opt_type {
	CS_OPT_INVALID = 0,	// <未指定选项
	CS_OPT_Syntax,	// 汇编输出语法
	CS_OPT_DETAIL,	// 将指令结构分解为细节
	CS_OPT_MODE,	// 在运行时更改引擎的模式
	CS_OPT_MEM,	// 用户自定义动态内存相关函数
	CS_OPT_SKIPDATA, // 反汇编时跳过数据,然后引擎处于 SKIPDATA 模式。
	CS_OPT_SKIPDATA_SETUP, // 为 SKIPDATA 选项设置用户自定义函数
	CS_OPT_MNEMONIC, // 自定义指令助记符
	CS_OPT_UNSIGNED, // 以无符号形式打印立即操作数
} cs_opt_type;

1.3 cs_opt_value

英文很容易理解,这里就不翻译了

/// Runtime option value (associated with option type above)
typedef enum cs_opt_value {
	CS_OPT_OFF = 0,  ///< Turn OFF an option - default for CS_OPT_DETAIL,CS_OPT_SKIPDATA,CS_OPT_UNSIGNED.
	CS_OPT_ON = 3, ///< Turn ON an option (CS_OPT_DETAIL,CS_OPT_SKIPDATA).
	CS_OPT_Syntax_DEFAulT = 0, ///< Default asm Syntax (CS_OPT_Syntax).
	CS_OPT_Syntax_INTEL, ///< X86 Intel asm Syntax - default on X86 (CS_OPT_Syntax).
	CS_OPT_Syntax_ATT,   ///< X86 ATT asm Syntax (CS_OPT_Syntax).
	CS_OPT_Syntax_norEGname, ///< Prints register name with only number (CS_OPT_Syntax)
	CS_OPT_Syntax_MASM, ///< X86 Intel Masm Syntax (CS_OPT_Syntax).
	CS_OPT_Syntax_MOTORolA, ///< MOS65XX use $ as hex prefix
} cs_opt_value;

1.4 例程演示

使用cs_option函数加上反编译引擎的运行时选项,反汇编出来的语法为AT&T语法

  // 以AT&T语法显示
  cs_option(handle, CS_OPT_Syntax, CS_OPT_Syntax_ATT);  
#include <stdio.h>
#include <inttypes.h>

#include <capstone/capstone.h>

#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00"

int main(voID)
{
	csh handle;
	cs_insn *insn;
	size_t count;

	if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK)
		return -1;

    // 以AT&T语法显示
    cs_option(handle, CS_OPT_Syntax_ATT);  
     
	count = cs_disasm(handle, CODE, sizeof(CODE)-1, 0x1000, 0, &insn);
	if (count > 0) {
		size_t j;
		for (j = 0; j < count; j++) {
			printf("0x%"PRIx64":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic,
					insn[j].op_str);
		}

		cs_free(insn, count);
	} else
		printf("ERROR: Failed to disassemble given code!\n");

	cs_close(&handle);

    return 0;
}

看一下结果反汇编出来的语法变成了AT&T语法

在这里插入图片描述

二、 SKIPDATA mode

认情况下,Capstone 在遇到 a broken instruction 时会停止反汇编,大多数时候,原因是这是输入中混合的数据,Capstone 不理解这个“weird” code。
通常,建议您确定下一个代码在哪里,然后从该位置继续反汇编。 但是,在某些情况下,您只想让 Capstone 自动跳过一些数据,直到找到合法指令,然后从那里继续。 因此,为此目的引入了 SKIPDATA 模式。

简单点来说就是当输入的二进制代码中有不合法的指令,Capstone遇到这个不合法指令便会停止反汇编,不会继续反汇编后面的数据,所以引入了SKIPDATA 模式,跳过这些不合法的指令,并用一个助记符替代,然后继续反汇编后面的数据。

2.1 数据结构

cs_opt_skipdata

//用户自定义设置 SKIPDATA 选项
typedef struct cs_opt_skipdata {
	// Capstone 将要跳过的数据视为特殊的“指令”
	// 用户可以在这里为该指令的“助记符”指定字符串。
	// 认情况下(如果 @mnemonic 为 NulL),Capstone 使用“.byte”。
	const char *mnemonic;

	// Capstone hits 数据时调用用户自定义回调函数
	// 如果此回调的返回值为正数 (>0),Capstone 将准确跳过该字节数并继续
	// 否则,如果回调返回 0,Capstone 停止反汇编并立即从 cs_disasm() 返回
	// 注意:如果此回调指针为 NulL,Capstone 将根据体系结构跳过一些字节,如下所示:
	/// Arm:     2 bytes (Thumb mode) or 4 bytes.
	/// Arm64:   4 bytes.
	/// Mips:    4 bytes.
	/// M680x:   1 byte.
	/// PowerPC: 4 bytes.
	/// Sparc:   4 bytes.
	/// SystemZ: 2 bytes.
	/// X86:     1 bytes.
	/// xcore:   2 bytes.
	/// EVM:     1 bytes.
	/// RISCV:   4 bytes.
	/// WASM:    1 bytes.
	/// MOS65XX: 1 bytes.
	/// BPF:     8 bytes.
	cs_skipdata_cb_t callback; 	// default value is NulL

	// 用户自定义数据将被传递给callback函数指针
	voID *user_data;
} cs_opt_skipdata;

(2)cs_skipdata_cb_t

/**
	SKIPDATA 选项用户定义回调函数
 @code: 包含要反汇编的代码的输入缓冲区。
        这与传递给 cs_disasm() 的缓冲区相同。
 @code_size: 上述 code 缓冲区的大小(以字节为单位)。
 @offset: 当前检查字节在上述输入缓冲区 code 中的位置。
 @user_data: 用户数据通过 cs_opt_skipdata 结构中的 user_data 字段传递给 cs_option()。

 @return: 返回要跳过的字节数,或 0 立即停止反汇编。
*/
typedef size_t (CAPSTONE_API *cs_skipdata_cb_t)(const uint8_t *code, size_t code_size, size_t offset, voID *user_data);

(3)打开 SKIPDATA mode
要让Capstone跳过一些(未知的)数据量,直到下一个合法指令,只需使用cs_option()打开选项CS_OPT_SKIPDATA(关闭),如下所示:

csh handle;
cs_open(CS_ARCH_X86, &handle);

// turn on SKIPDATA mode
cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);

2.2 例程演示

例程采用官方的例程:
使用SKIPDATA mode 之前:

/* Capstone disassembler Engine */

#include <stdio.h>
#include <stdlib.h>

#include <capstone/platform.h>
#include <capstone/capstone.h>

struct platform {
	cs_arch arch;
	cs_mode mode;
	unsigned char *code;
	size_t size;
	const char *comment;
	cs_opt_type opt_type;
	cs_opt_value opt_value;
	cs_opt_type opt_skipdata;
	size_t skipdata;
};

static voID print_string_hex(unsigned char *str, size_t len)
{
	unsigned char *c;

	printf("Code: ");
	for (c = str; c < str + len; c++) {
		printf("0x%02x ", *c & 0xff);
	}
	printf("\n");
}


static voID test()
{
#define RANDOM_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"

	struct platform platforms[] = {
		{
			CS_ARCH_X86,
			CS_MODE_64,
			(unsigned char*)RANDOM_CODE,
			sizeof(RANDOM_CODE) - 1,
		},

	};

	csh handle;
	uint64_t address = 0x1000;
	cs_insn *insn;
	cs_err err;
	int i;
	size_t count;

	for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {

		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
		if (err) {
			printf("Failed on cs_open() with error returned: %u\n", err);
			abort();
		}

		if (platforms[i].opt_type)
			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);

		count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, &insn);
		if (count) {
			size_t j;

			print_string_hex(platforms[i].code, platforms[i].size);
			printf("disasm:\n");

			for (j = 0; j < count; j++) {
				printf("0x%" PRIx64 ":\t%s\t\t%s\n",
						insn[j].address, insn[j].op_str);
			}

			// print out the next offset,after the last insn
			printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);

			// free memory allocated by cs_disasm()
			cs_free(insn, count);
		} else {
			printf("****************\n");
			print_string_hex(platforms[i].code, platforms[i].size);
			printf("ERROR: Failed to disasm given code!\n");
			abort();
		}

		printf("\n");

		cs_close(&handle);
	}
}

int main()
{
	test();

	return 0;
}

在这里插入图片描述


Capstone 在遇到 a broken instruction 时会停止反汇编了。

使用SKIPDATA mode 之后:

/* Capstone disassembler Engine */

#include <stdio.h>
#include <stdlib.h>

#include <capstone/platform.h>
#include <capstone/capstone.h>

struct platform {
	cs_arch arch;
	cs_mode mode;
	unsigned char *code;
	size_t size;
	const char *comment;
	cs_opt_type opt_type;
	cs_opt_value opt_value;
	cs_opt_type opt_skipdata;
	size_t skipdata;
};

static voID print_string_hex(unsigned char *str, platforms[i].opt_value);

		// turn on SKIPDATA mode
		cs_option(handle, CS_OPT_ON);
		cs_option(handle, platforms[i].opt_skipdata, platforms[i].skipdata);

		count = cs_disasm(handle, platforms[i].size);
			printf("ERROR: Failed to disasm given code!\n");
			abort();
		}

		printf("\n");

		cs_close(&handle);
	}
}

int main()
{
	test();

	return 0;
}

Capstone 在遇到 a broken instruction 时,自动跳过一些数据,用.byte代替,直到找到合法指令,然后从那里继续反汇编。
Capstone 跳过 1 个字节的数据并继续从输入流中的下一个字节进行反汇编。 在这种情况下,实际上 Capstone 将跳过数据视为指令 ID 为零的特殊指令,助记符为“.byte”,操作数字符串为其跳过的字节序列的十六进制代码

在这里插入图片描述

2.3 改变助记符例程

如上所述,Capstone 认为数据将被跳过具有认助记符“.byte”的指令。 要更改此助记符,请使用带有 CS_OPT_SKIPDATA_SETUP 的 cs_option(),如下所示:

csh handle;
cs_open(CS_ARCH_X86, CS_MODE_32, &handle);

cs_opt_skipdata skipdata = {
    .mnemonic = "db",
};

// customize SKIPDATA mode
cs_option(handle, CS_OPT_SKIPDATA_SETUP, &skipdata);

// Turn on SKIPDATA mode
cs_option(handle, CS_OPT_ON);
/* Capstone disassembler Engine */

#include <stdio.h>
#include <stdlib.h>

#include <capstone/platform.h>
#include <capstone/capstone.h>

struct platform {
	cs_arch arch;
	cs_mode mode;
	unsigned char *code;
	size_t size;
	const char *comment;
	cs_opt_type opt_type;
	cs_opt_value opt_value;
	cs_opt_type opt_skipdata;
	size_t skipdata;
};

static voID print_string_hex(unsigned char *str, *c & 0xff);
	}
	printf("\n");
}


static voID test()
{
#define RANDOM_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"


	cs_opt_skipdata skipdata = {
		// rename default "data" instruction from ".byte" to "db"
		"db",
	};


	struct platform platforms[] = {
		{
			CS_ARCH_X86,
			"X86 64 (Intel Syntax) - Skip data",
		{
			CS_ARCH_X86,
			"X86 64 (Intel Syntax) - Skip data with custom mnemonic",
			CS_OPT_INVALID,
			CS_OPT_OFF,
			CS_OPT_SKIPDATA_SETUP,
			(size_t) &skipdata,

	};

	csh handle;
	uint64_t address = 0x1000;
	cs_insn *insn;
	cs_err err;
	int i;
	size_t count;

	for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
		printf("****************\n");
		printf("Platform: %s\n", platforms[i].comment);
		err = cs_open(platforms[i].arch, platforms[i].skipdata);

		// turn off SKIPDATA mode
		//cs_option(handle,CS_OPT_OFF);

		count = cs_disasm(handle, count);
		} else {
			printf("****************\n");
			printf("Platform: %s\n", platforms[i].comment);
			print_string_hex(platforms[i].code, platforms[i].size);
			printf("ERROR: Failed to disasm given code!\n");
			abort();
		}

		printf("\n");

		cs_close(&handle);
	}
}

int main()
{
	test();

	return 0;
}


在这里插入图片描述

从结果可以看到助记符由.byte变成db了。

总结

文章主要讲解了cs_option函数和Capstone的SKIPDATA mode。

参考资料

https://xz.aliyun.com/t/5772
https://xz.aliyun.com/t/5753
http://www.capstone-engine.org/skipdata.html

解锁查看全部内容

付费后查看完整内容
限时 微信扫码支付 ¥9.9 19.9

总结

以上是编程之家为你收集整理的Capstone反汇编(二)全部内容,希望文章能够帮你解决Capstone反汇编(二)所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。

Android相关文章

优化输出文章对你有所帮助的话,欢迎给个赞或者 star,你的支持是对作者最大的鼓励,不足之处可以在评论区多多指正,交流学习
作者:半身风雪上篇:ThreadLocal进阶解析系列文章简介:什么叫做CAS呢?CAS 本名叫做:Compare And Swap。本文将通过CAS 的实现,JDK中相关的原子操作,及原子操作的三大问题,来全面的解析CAS。CAS 原理解析一、什么是原子操作?如何实现原子操作?二、CAS 实现原子操作的三大问题2.1、ABA 问题2.2、开销问题2.3、只能保证一个共享变量的原子操作。三、Jdk 中相关原子操作类的使用3.1、AtomicInteger3.2、AtomicIntegerArra.
Java 内存模型即 Java Memory Model,简称JMM。JMM 定义了Java 虚拟机 (JVM)在计算机内存(RAM)中的工作方式。JVM 是整个计算机虚拟模型,所以 JMM 是隶属于 JVM 的。Java1.5 版本对其进行了重构,现在的 Java 仍沿用了 Java1.5 的版本。Jmm 遇到的问题与现代计算机中遇到的问题是差不多的。 物理计算机中的并发问题,物理机遇到的并发问题与虚拟机中的情况有不少 相似之处,物理机对并发的处理方案对于虚拟机的实现也有相当大的参考意义。
这是小空坚持写的Android新手向系列,欢迎品尝。大佬(√)新手(√√√)先说结论使用系统的CalendarView基本上就是自找麻烦,适宜的应用场景少之又少。还是建议使用三方封装的吧,截至2022年3月9日。https://github.com/huanghaibin-dev/CalendarView Star数8.1Khttps://github.com/prolificinteractive/material-calendarview Star数5.8Khttps://github.com/ki
Android 眼睛 显示隐藏密码(ImageView)在前端中我们知道用javascript就可以可以很容易实现,那么在Android中怎么实现这个功能呢?
Capstone反汇编的使用
JAVA开发中经常会遇到不方便使用数据库,但又要进行结构化数据计算的场景。JAVA早期没有提供相关类库,即使排序、分组这种基本计算也要硬写代码,开发效率很低。后来JAVA8推出了Stream库,凭借Lambda表达式、链式编程风格、集合函数,才终于解决了结构化数据计算类库从无到有的问题。比如排序:上面代码中的sorted是集合函数,可方便地进行排序。"(参数)->函数体"的写法即Lambda表达式,可以简化匿名函数的定义。两个sorted函数连在一起用属于链式编程风格,可以使多步骤计算变得直观。仍然以上面
用swing技术实现编写一个贪吃蛇大作战小游戏,项目供大家参考学习交流。
微信公众号搜索 “ 程序精选 ” ,选择关注!
微信公众号搜 "程序精选"关注