일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- python3.11 pip
- python3.11 설치
- GEF
- 임베디드 시스템 해킹
- 공유 라이브러리는 왜 항상 같은 순서로 맵핑 될까?
- VSCode C++ 표준 버전 수정
- vmware 반응 속도
- python
- pwntools
- Seccomp bypass
- c++
- std::cerr
- docker
- DYNAMIC Section
- wsl2 복구
- pwn
- OpenAI 개발
- vhdx 파일 복구
- 지훈현서
- z3 signed 이슈
- tool
- 실시간로깅
- 개발
- Windows 부팅 오류
- GDB
- Recoverit
- Python.h: No such file or directory
- pip 에러 해결
- 리커버릿
- Python3
- Today
- Total
OZ1NG의 뽀나블(Pwnable)
[C/C++] Capstone 라이브러리 (disassembly 라이브러리) 본문
[*] pwntools의 asm(), disasm() 함수처럼 C와 C++ 전용으로 사용 가능한 capstone 라이브러리를 소개한다.
- 공식 사이트 : https://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
- windows의 경우
github에서 바로 릴리즈 버전을 설치하는게 가장 빠르다.
- 릴리즈 버전 (latest) : https://github.com/capstone-engine/capstone/releases/tag/4.0.2
[*] 라이브러리 설치 (구버전)
(주의!) 아래와 같이 apt로 설치하게 되면 구버전(4.0.1) 버전이 설치되어 endbr64와 같은 명령어를 해석하지 못해 제대로된 디스 어셈이 불가능하니 아래의 방법으로 설치는 하지 않는 것을 추천한다.
- Ubuntu의 경우
$ sudo apt install libcapstone-dev
- 참고 : https://www.capstone-engine.org/documentation.html
- 만약 기존에 위와 같은 방법으로 설치한 경우에는 아래의 명령어로 제거 후 위의 신버전 설치 방법으로 재설치 해주면 된다.
$ 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
'Tips' 카테고리의 다른 글
[C++] new operator 정적 할당(된 곳에 변수 할당) (0) | 2022.07.19 |
---|---|
[C/C++] 구조체 bitfield 멤버 변수 선언 ( ':' ) (0) | 2022.07.19 |
[Python3] 인코딩 범위 무시하고 순수 바이트 값으로 디코딩 하기 (bytes.decode(errors="surrogateescape")) (0) | 2022.07.14 |
[Tips] PIE 보호 기법이 걸려 경우 gdb 디버깅 - gef (0) | 2022.07.14 |
[Tips] VSCode Python Module Debugging (0) | 2022.06.29 |