Add chip8 disassembler and partial analyzer

This commit is contained in:
Maijin 2017-12-07 15:25:27 +01:00
parent a16d88aa3a
commit fa44625c5a
9 changed files with 556 additions and 2 deletions

View File

@ -265,7 +265,7 @@ force_tab_after_define = false
align_keep_tabs = false
align_with_tabs = true
align_on_tabstop = true
align_number_left = false
align_keep_extra_space = false
align_func_params = false
align_same_func_call_params = false

181
libr/anal/p/anal_chip8.c Normal file
View File

@ -0,0 +1,181 @@
/* radare - LGPL3 - Copyright 2017 - maijin */
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include <r_anal.h>
static int chip8_anop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
memset (op, '\0', sizeof (RAnalOp));
ut16 opcode = r_read_be16 (data);
uint8_t x = (opcode >> 8) & 0x0F;
uint8_t y = (opcode >> 4) & 0x0F;
uint8_t nibble = opcode & 0x0F;
uint16_t nnn = opcode & 0x0FFF;
uint8_t kk = opcode & 0xFF;
op->size = 2;
op->addr = addr;
switch (opcode & 0xF000) {
case 0x0000:
if (opcode == 0x00E0) {
op->type = R_ANAL_OP_TYPE_UNK;
} else if (opcode == 0x00EE) {
op->type = R_ANAL_OP_TYPE_UNK;
} else if (opcode == 0x00C0) {
op->type = R_ANAL_OP_TYPE_UNK;
} else if (opcode == 0x00FB) {
op->type = R_ANAL_OP_TYPE_UNK;
} else if (opcode == 0x00FC) {
op->type = R_ANAL_OP_TYPE_UNK;
} else if (opcode == 0x00FD) {
op->type = R_ANAL_OP_TYPE_UNK;
} else if (opcode == 0x00FE) {
op->type = R_ANAL_OP_TYPE_UNK;
} else if (opcode == 0x00FF) {
op->type = R_ANAL_OP_TYPE_UNK;
}
break;
case 0x1000:
op->type = R_ANAL_OP_TYPE_JMP;
op->jump = nnn;
op->fail = addr + op->size;
break;
case 0x2000:
op->type = R_ANAL_OP_TYPE_CALL;
op->jump = nnn;
op->fail = addr + op->size;
break;
case 0x3000:
r_meta_set_string (anal, R_META_TYPE_COMMENT, addr, "KEYPAD");
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x4000:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x5000:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x6000:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x7000:
op->type = R_ANAL_OP_TYPE_ADD;
break;
case 0x8000: {
switch (nibble) {
case 0x0:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x1:
op->type = R_ANAL_OP_TYPE_OR;
break;
case 0x2:
op->type = R_ANAL_OP_TYPE_AND;
break;
case 0x3:
op->type = R_ANAL_OP_TYPE_XOR;
break;
case 0x4:
op->type = R_ANAL_OP_TYPE_ADD;
break;
case 0x5:
op->type = R_ANAL_OP_TYPE_SUB;
break;
case 0x6:
op->type = R_ANAL_OP_TYPE_SHR;
break;
case 0x7:
op->type = R_ANAL_OP_TYPE_SUB;
break;
case 0xE:
op->type = R_ANAL_OP_TYPE_SHL;
break;
}
} break;
case 0x9000:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0xA000:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0xB000:
op->type = R_ANAL_OP_TYPE_JMP;
op->jump = nnn;
op->fail = addr + op->size;
break;
case 0xC000:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0xD000:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0xE000: {
if (kk == 0x9E) {
op->type = R_ANAL_OP_TYPE_UNK;
break;
} else if (kk == 0xA1) {
op->type = R_ANAL_OP_TYPE_UNK;
break;
}
} break;
case 0xF000: {
switch (kk) {
case 0x07:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x0A:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x15:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x18:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x1E:
op->type = R_ANAL_OP_TYPE_ADD;
break;
case 0x29:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x33:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x55:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x65:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x30:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x75:
op->type = R_ANAL_OP_TYPE_UNK;
break;
case 0x85:
op->type = R_ANAL_OP_TYPE_UNK;
break;
}
} break;
}
return op->size;
}
RAnalPlugin r_anal_plugin_chip8 = {
.name = "chip8",
.desc = "CHIP8 analysis plugin",
.license = "LGPL3",
.arch = "chip8",
.bits = 32,
.op = &chip8_anop,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_chip8,
.version = R2_VERSION
};
#endif

9
libr/anal/p/chip8.mk Normal file
View File

@ -0,0 +1,9 @@
OBJ_CHIP8=anal_chip8.o
STATIC_OBJ+=${OBJ_CHIP8}
TARGET_CHIP8=anal_chip8.${EXT_SO}
ALL_TARGETS+=${TARGET_CHIP8}
${TARGET_CHIP8}: ${OBJ_CHIP8}
${CC} $(call libname,anal_chip8) ${CFLAGS} -o anal_chip8.${EXT_SO} ${OBJ_CHIP8}

101
libr/asm/p/asm_chip8.c Normal file
View File

@ -0,0 +1,101 @@
/* radare - LGPL3 - Copyright 2017 - maijin */
#include <r_asm.h>
#include <r_lib.h>
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *b, int l) {
ut16 opcode = r_read_be16 (b);
uint8_t x = (opcode >> 8) & 0x0F;
uint8_t y = (opcode >> 4) & 0x0F;
uint8_t nibble = opcode & 0x0F;
uint16_t nnn = opcode & 0x0FFF;
uint8_t kk = opcode & 0xFF;
switch (opcode & 0xF000) {
case 0x0000:
if (opcode == 0x00E0) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "cls");
} else if (opcode == 0x00EE) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "ret");
} else if ((opcode & 0xFFF0) == 0x00C0) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "scd 0x%01x", nibble);
} else if (opcode == 0x00FB) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "scr");
} else if (opcode == 0x00FC) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "scl");
} else if (opcode == 0x00FD) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "exit");
} else if (opcode == 0x00FE) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "low");
} else if (opcode == 0x00FF) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "high");
}
break;
case 0x1000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "jp 0x%03x", nnn); break;
case 0x2000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "call 0x%03x", nnn); break;
case 0x3000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "se v%1x, 0x%02x", x, kk); break;
case 0x4000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "sne v%1x, 0x%02x", x, kk); break;
case 0x5000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "se v%1x, v%1x", x, y); break;
case 0x6000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld v%1x, 0x%02x", x, kk); break;
case 0x7000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "add v%1x, 0x%02x", x, kk); break;
case 0x8000: {
switch (nibble) {
case 0x0: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld v%1x, v%1x", x, y); break;
case 0x1: snprintf (op->buf_asm, R_ASM_BUFSIZE, "or v%1x, v%1x", x, y); break;
case 0x2: snprintf (op->buf_asm, R_ASM_BUFSIZE, "and v%1x, v%1x", x, y); break;
case 0x3: snprintf (op->buf_asm, R_ASM_BUFSIZE, "xor v%1x, v%1x", x, y); break;
case 0x4: snprintf (op->buf_asm, R_ASM_BUFSIZE, "add v%1x, v%1x", x, y); break;
case 0x5: snprintf (op->buf_asm, R_ASM_BUFSIZE, "sub v%1x, v%1x", x, y); break;
case 0x6: snprintf (op->buf_asm, R_ASM_BUFSIZE, "shr v%1x, v%1x", x, y); break;
case 0x7: snprintf (op->buf_asm, R_ASM_BUFSIZE, "subn v%1x, v%1x", x, y); break;
case 0xE: snprintf (op->buf_asm, R_ASM_BUFSIZE, "shl v%1x, v%1x", x, y); break;
}
} break;
case 0x9000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "sne v%1x, v%1x", x, y); break;
case 0xA000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld i, 0x%03x", nnn); break;
case 0xB000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "jp v0, 0x%03x", nnn); break;
case 0xC000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "rnd v%1x, 0x%02x", x, kk); break;
case 0xD000: snprintf (op->buf_asm, R_ASM_BUFSIZE, "drw v%1x, v%1x, 0x%01x", x, y, nibble); break;
case 0xE000: {
if (kk == 0x9E) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "skp v%1x", x);
} else if (kk == 0xA1) {
snprintf (op->buf_asm, R_ASM_BUFSIZE, "sknp v%1x", x);
}
} break;
case 0xF000: {
switch (kk) {
case 0x07: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld v%1x, dt", x); break;
case 0x0A: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld v%1x, k", x); break;
case 0x15: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld dt, v%1x", x); break;
case 0x18: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld st, v%1x", x); break;
case 0x1E: snprintf (op->buf_asm, R_ASM_BUFSIZE, "add i, v%1x", x); break;
case 0x29: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld f, v%1x", x); break;
case 0x33: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld b, v%1x", x); break;
case 0x55: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld [i], v%1x", x); break;
case 0x65: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld v%1x, [i]", x); break;
case 0x30: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld hf, v%1x", x); break;
case 0x75: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld r, v%1x", x); break;
case 0x85: snprintf (op->buf_asm, R_ASM_BUFSIZE, "ld v%1x, r", x); break;
}
} break;
}
op->size = 2;
return op->size;
}
RAsmPlugin r_asm_plugin_chip8 = {
.name = "chip8",
.arch = "chip8",
.license = "LGPL3",
.bits = 32,
.desc = "Chip8 disassembler",
.disassemble = &disassemble,
};
#ifndef CORELIB
struct RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_chip8
.version = R2_VERSION
};
#endif

11
libr/asm/p/chip8.mk Normal file
View File

@ -0,0 +1,11 @@
OBJ_CHIP8=asm_chip8.o
STATIC_OBJ+=${OBJ_CHIP8}
TARGET_CHIP8=asm_chip8.${EXT_SO}
ifeq ($(WITHPIC),1)
ALL_TARGETS+=${TARGET_CHIP8}
${TARGET_CHIP8}: ${OBJ_CHIP8}
${CC} ${call libname,asm_chip8} ${CFLAGS} -o ${TARGET_CHIP8} ${OBJ_CHIP8}
endif

View File

@ -586,7 +586,7 @@ typedef struct r_anal_options_t {
int hpskip; // skip `mov reg,reg` and `lea reg,[reg]`
int jmptbl; // analyze jump tables
bool pushret; // analyze push+ret as jmp
bool armthumb; //
bool armthumb; //
} RAnalOptions;
typedef struct r_anal_t {
@ -1668,6 +1668,7 @@ extern RAnalPlugin r_anal_plugin_sparc_cs;
extern RAnalPlugin r_anal_plugin_xcore_cs;
extern RAnalPlugin r_anal_plugin_propeller;
extern RAnalPlugin r_anal_plugin_msp430;
extern RAnalPlugin r_anal_plugin_chip8;
extern RAnalPlugin r_anal_plugin_cris;
extern RAnalPlugin r_anal_plugin_v810;
extern RAnalPlugin r_anal_plugin_6502;

View File

@ -228,6 +228,7 @@ extern RAsmPlugin r_asm_plugin_malbolge;
extern RAsmPlugin r_asm_plugin_ws;
extern RAsmPlugin r_asm_plugin_6502;
extern RAsmPlugin r_asm_plugin_h8300;
extern RAsmPlugin r_asm_plugin_chip8;
extern RAsmPlugin r_asm_plugin_cr16;
extern RAsmPlugin r_asm_plugin_v850;
extern RAsmPlugin r_asm_plugin_sysz;

248
plugins.cfg Normal file
View File

@ -0,0 +1,248 @@
STATIC="anal.8051
anal.arc
anal.arm_cs
anal.arm_gnu
anal.avr
anal.i4004
anal.bf
anal.chip8
anal.cr16
anal.cris
anal.dalvik
anal.ebc
anal.gb
anal.h8300
anal.i8080
anal.java
anal.m68k_cs
anal.xtensa
anal.malbolge
anal.mips_cs
anal.mips_gnu
anal.msp430
anal.nios2
anal.null
anal.ppc_cs
anal.ppc_gnu
anal.sh
anal.sparc_cs
anal.sparc_gnu
anal.sysz
anal.tms320
anal.v850
anal.ws
anal.xap
anal.x86_cs
anal.x86_udis
anal.xcore_cs
anal.z80
anal.v810
anal.vax
anal.6502
anal.snes
anal.riscv
anal.pic18c
anal.rsp
asm.6502
asm.8051
asm.arc
asm.arm_cs
asm.arm_gnu
asm.arm_winedbg
asm.avr
asm.bf
asm.chip8
asm.cr16
asm.cris_gnu
asm.dalvik
asm.dcpu16
asm.hexagon_gnu
asm.ebc
asm.gb
asm.h8300
asm.hppa_gnu
asm.i4004
asm.i8080
asm.java
asm.lm32
asm.tricore
asm.xtensa
asm.m68k_cs
asm.malbolge
asm.mips_cs
asm.mips_gnu
asm.msp430
asm.nios2
asm.ppc_cs
asm.ppc_gnu
asm.propeller
asm.riscv
asm.rsp
asm.lanai_gnu
asm.sh
asm.snes
asm.sparc_cs
asm.sparc_gnu
asm.spc700
asm.sysz
asm.tms320
asm.v850
asm.ws
asm.xap
asm.arm_as
asm.wasm
asm.x86_as
asm.x86_cs
asm.x86_nz
asm.x86_udis
asm.x86_nasm
asm.xcore_cs
asm.z80
asm.lh5801
asm.v810
asm.vax
asm.mcs96
asm.pic18c
bin.any
bin.wasm
bin.nro
bin.nso
bin.art
bin.bf
bin.bflt
bin.bios
bin.bootimg
bin.cgc
bin.coff
bin.dex
bin.dol
bin.elf
bin.elf64
bin.fs
bin.java
bin.menuet
bin.mach0
bin.mach064
bin.mbn
bin.mdmp
bin.mz
bin.nes
bin.nin3ds
bin.ninds
bin.ningb
bin.ningba
bin.omf
bin.p9
bin.pe
bin.pe64
bin.pebble
bin.smd
bin.sms
bin.avr
bin.sfc
bin.spc700
bin.te
bin.vsf
bin.xbe
bin.dyldcache
bin_xtr.xtr_dyldcache
bin_xtr.fatmach0
bin.zimg
bin.psxexe
bp.arm
bp.bf
bp.mips
bp.ppc
bp.x86
core.anal
core.java
crypto.aes
crypto.des
crypto.rc4
crypto.cps2
crypto.xor
crypto.blowfish
crypto.rc2
crypto.rot
crypto.rol
crypto.ror
crypto.base64
crypto.base91
crypto.aes_cbc
crypto.punycode
crypto.rc6
crypto.serpent
debug.bf
debug.io
debug.esil
debug.gdb
debug.qnx
debug.native
debug.rap
debug.windbg
debug.bochs
debug.null
egg.exec
egg.xor
fs.io
fs.r2
fs.ext2
fs.fat
fs.fb
fs.hfs
fs.hfsplus
fs.iso9660
fs.jfs
fs.minix
fs.ntfs
fs.posix
fs.reiserfs
fs.sfs
fs.tar
fs.udf
fs.ufs
fs.xfs
io.null
io.bfdbg
io.bochs
io.debug
io.default
io.gdb
io.qnx
io.r2pipe
io.gzip
io.http
io.tcp
io.r2web
io.ihex
io.mach
io.malloc
io.sparse
io.mmap
io.procpid
io.ptrace
io.rap
io.self
io.shm
io.w32
io.w32dbg
io.windbg
io.winedbg
io.zip
io.r2k
io.ar
io.rbuf
lang.vala
parse.6502_pseudo
parse.arm_pseudo
parse.att2intel
parse.dalvik_pseudo
parse.m68k_pseudo
parse.mips_pseudo
parse.mreplace
parse.ppc_pseudo
parse.sh_pseudo
parse.avr_pseudo
parse.x86_pseudo
parse.z80_pseudo"
SHARED="io.shm"

View File

@ -5,6 +5,7 @@ anal.arm_gnu
anal.avr
anal.i4004
anal.bf
anal.chip8
anal.cr16
anal.cris
anal.dalvik
@ -50,6 +51,7 @@ asm.arm_gnu
asm.arm_winedbg
asm.avr
asm.bf
asm.chip8
asm.cr16
asm.cris_gnu
asm.dalvik