OZ1NG의 뽀나블(Pwnable)

[C/C++] Capstone 라이브러리 (disassembly 라이브러리) 본문

Tips

[C/C++] Capstone 라이브러리 (disassembly 라이브러리)

OZ1NG 2022. 7. 18. 05:56

[*] pwntools의 asm(), disasm() 함수처럼 C와 C++ 전용으로 사용 가능한 capstone 라이브러리를 소개한다.

- 공식 사이트 : https://www.capstone-engine.org/

 

The Ultimate Disassembly Framework

The Ultimate Disassembler

www.capstone-engine.org

[*] 장점

- 당연히 파이썬 기반인 pwntools를 사용하는 것보다 몇십배는 빠른 연산이 가능하다.

- 실제 3바이트 짜리 어셈 코드 테이블을 만드는데 pwntools는 7시간 이상이 걸렸지만 capstone은 20~30초 내로 끝났다...

- 또한 apt에 등록되어있어 매우 간편하게 설치가 가능하다.

 

[*] 라이브러리 설치 (최신 버전 >= 4.0.2)

- *nix (Linux, Unix 등...)의 경우

$ git clone https://github.com/capstone-engine/capstone.git

$ cd capstone

$ ./make.sh

$ sudo ./make.sh install

- 참고 : https://github.com/capstone-engine/capstone/blob/master/COMPILE.TXT

 

GitHub - capstone-engine/capstone: Capstone disassembly/disassembler framework: Core (Arm, Arm64, BPF, EVM, M68K, M680X, MOS65xx

Capstone disassembly/disassembler framework: Core (Arm, Arm64, BPF, EVM, M68K, M680X, MOS65xx, Mips, PPC, RISCV, Sparc, SystemZ, TMS320C64x, Web Assembly, X86, X86_64, XCore) + bindings. - GitHub -...

github.com

 

- windows의 경우

github에서 바로 릴리즈 버전을 설치하는게 가장 빠르다.

- 릴리즈 버전 (latest) : https://github.com/capstone-engine/capstone/releases/tag/4.0.2

 

Release Version 4.0.2 · capstone-engine/capstone

Release 4.0.2 is a stable release version, with bugfixes in the core & some bindings. Core Windows kernel-mode driver support Fix installation path on FreeBSD and DragonFly cstool Add armv8, ppc...

github.com

 

[*] 라이브러리 설치 (구버전)

(주의!) 아래와 같이 apt로 설치하게 되면 구버전(4.0.1) 버전이 설치되어 endbr64와 같은 명령어를 해석하지 못해 제대로된 디스 어셈이 불가능하니 아래의 방법으로 설치는 하지 않는 것을 추천한다.

- Ubuntu의 경우

$ sudo apt install libcapstone-dev

- 참고 : https://www.capstone-engine.org/documentation.html

 

Documentation

The Ultimate Disassembler

www.capstone-engine.org

- 만약 기존에 위와 같은 방법으로 설치한 경우에는 아래의 명령어로 제거 후 위의 신버전 설치 방법으로 재설치 해주면 된다.

$ sudo apt purge libcapstone-dev

 

[*] 사용법 

- 테스트 코드 작성

/* test1.c */

#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) // arch : x86-64, mode : x64 인 환경을 뜻함
		return -1;
	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;

[cs_open]

cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle);

- 아키텍처와 모드(intel의 경우 x86 or x64 등등)를 설정하고 성공한 경우 handle에 필요한 내용을 설정한다.

- cs_arch

// Architecture type
typedef enum cs_arch {
	CS_ARCH_ARM = 0,	// ARM architecture (including Thumb, Thumb-2)
	CS_ARCH_ARM64,		// ARM-64, also called AArch64
	CS_ARCH_MIPS,		// Mips architecture
	CS_ARCH_X86,		// X86 architecture (including x86 & x86-64)
	CS_ARCH_PPC,		// PowerPC architecture
	CS_ARCH_SPARC,		// Sparc architecture
	CS_ARCH_SYSZ,		// SystemZ architecture
	CS_ARCH_XCORE,		// XCore architecture
	CS_ARCH_MAX,
	CS_ARCH_ALL = 0xFFFF, // All architectures - for cs_support()
} cs_arch;

- cs_mode

// Mode type
typedef enum cs_mode {
	CS_MODE_LITTLE_ENDIAN = 0,	// little-endian mode (default mode)
	CS_MODE_ARM = 0,	// 32-bit ARM
	CS_MODE_16 = 1 << 1,	// 16-bit mode (X86)
	CS_MODE_32 = 1 << 2,	// 32-bit mode (X86)
	CS_MODE_64 = 1 << 3,	// 64-bit mode (X86, PPC)
	CS_MODE_THUMB = 1 << 4,	// ARM's Thumb mode, including Thumb-2
	CS_MODE_MCLASS = 1 << 5,	// ARM's Cortex-M series
	CS_MODE_V8 = 1 << 6,	// ARMv8 A32 encodings for ARM
	CS_MODE_MICRO = 1 << 4, // MicroMips mode (MIPS)
	CS_MODE_MIPS3 = 1 << 5, // Mips III ISA
	CS_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA
	CS_MODE_MIPSGP64 = 1 << 7, // General Purpose Registers are 64-bit wide (MIPS)
	CS_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc)
	CS_MODE_BIG_ENDIAN = 1 << 31,	// big-endian mode
	CS_MODE_MIPS32 = CS_MODE_32,	// Mips32 ISA (Mips)
	CS_MODE_MIPS64 = CS_MODE_64,	// Mips64 ISA (Mips)
} cs_mode;

[cs_disasm]

size_t CAPSTONE_API cs_disasm(csh handle,
		const uint8_t *code, size_t code_size,
		uint64_t address,
		size_t count,
		cs_insn **insn);

- handle에 설정한 환경 정보를 토대로 code를 disassemble 한다.

- handle : 환경 정보

- code : 바이트 어셈 코드

- code_size : 해석할 바이트 어셈 코드의 길이

- address : 해석 된 어셈 코드의 시작 주소 (뭔 값이든 상관 없음)

- count : 해석할 명령어 개수 (만약 0이라면 전부 해석함)

- insn : 해석된 명령어의 정보를 가지고 있는 instruction info 구조체를 리턴한다.

[struct insn]

// Detail information of disassembled instruction
typedef struct cs_insn {
	// Instruction ID (basically a numeric ID for the instruction mnemonic)
	// Find the instruction id in the '[ARCH]_insn' enum in the header file 
	// of corresponding architecture, such as 'arm_insn' in arm.h for ARM,
	// 'x86_insn' in x86.h for X86, etc...
	// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF
	// NOTE: in Skipdata mode, "data" instruction has 0 for this id field.
	unsigned int id;

	// Address (EIP) of this instruction
	// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF
	uint64_t address;

	// Size of this instruction
	// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF
	uint16_t size;
	// Machine bytes of this instruction, with number of bytes indicated by @size above
	// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF
	uint8_t bytes[16];

	// Ascii text of instruction mnemonic
	// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF
	char mnemonic[32];

	// Ascii text of instruction operands
	// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF
	char op_str[160];

	// Pointer to cs_detail.
	// NOTE: detail pointer is only valid when both requirements below are met:
	// (1) CS_OP_DETAIL = CS_OPT_ON
	// (2) Engine is not in Skipdata mode (CS_OP_SKIPDATA option set to CS_OPT_ON)
	//
	// NOTE 2: when in Skipdata mode, or when detail mode is OFF, even if this pointer
	//     is not NULL, its content is still irrelevant.
	cs_detail *detail;
} cs_insn;

- 명령어의 자세한 정보를 가진 구조체이다.

- id : 어셈 명령줄의 id 값

- address : cs_disasm에서 설정한 address를 기준으로 하는 가상주소

- size : 어셈 명령줄의 길이 (바이트 길이)

- bytes : 어셈 명령줄의 바이트 값

- mnemonic : 어셈 명령줄의 해석된 opcode(명령어) 문자열

- op_str : 어셈 명령줄의 해석된 operand 문자열

 

[cs_free]

void CAPSTONE_API cs_free(cs_insn *insn, size_t count);

- insn 구조체는 명령어 개수(count)만큼 청크가 힙에 할당되는데 그것들을 free 하는 함수

[cs_close]

cs_err CAPSTONE_API cs_close(csh *handle);

- 핸들을 정리한다.

 

- 컴파일

gcc test.c -o test -lcapstone

위와 같이 -lcapstone을 붙여주면 된다.

 

- 참고 : https://www.capstone-engine.org/lang_c.html

 

Programming with C language

The Ultimate Disassembler

www.capstone-engine.org

 

Comments