Migrate the pyc plugin ##arch

This commit is contained in:
pancake 2023-03-29 16:56:31 +02:00 committed by pancake
parent 1e2c75cf65
commit a8143d8fb2
47 changed files with 77 additions and 99 deletions

View File

@ -44,7 +44,7 @@ arch.pic
anal.ppc_cs anal.ppc_cs
anal.ppc_gnu anal.ppc_gnu
arch.propeller arch.propeller
anal.pyc arch.pyc
arch.riscv_cs arch.riscv_cs
anal.s390_cs anal.s390_cs
anal.s390_gnu anal.s390_gnu

View File

@ -54,7 +54,7 @@ arch.snes
arch.riscv arch.riscv
arch.riscv_cs arch.riscv_cs
arch.pic arch.pic
anal.pyc arch.pyc
arch.propeller arch.propeller
arch.null arch.null
arch.i4004 arch.i4004

View File

@ -42,7 +42,7 @@ arch.6502
arch.snes arch.snes
arch.riscv arch.riscv
arch.pic arch.pic
anal.pyc arch.pyc
arch.propeller arch.propeller
esil.dummy esil.dummy
asm.null asm.null

View File

@ -31,7 +31,7 @@ arch.riscv
arch.riscv_cs arch.riscv_cs
arch.pic arch.pic
arch.wasm arch.wasm
anal.pyc arch.pyc
arch.null arch.null
arch.rsp arch.rsp
arch.i4004 arch.i4004

View File

@ -3,7 +3,7 @@ arch.x86_nz
arch.arm arch.arm
anal.dalvik anal.dalvik
arch.wasm arch.wasm
anal.pyc arch.pyc
anal.bf anal.bf
arch.bpf arch.bpf
arch.riscv arch.riscv

View File

@ -77,7 +77,6 @@ r_anal_sources = [
'p/anal_null.c', 'p/anal_null.c',
'p/anal_ppc_cs.c', 'p/anal_ppc_cs.c',
'p/anal_ppc_gnu.c', 'p/anal_ppc_gnu.c',
'p/anal_pyc.c',
'p/anal_s390_cs.c', 'p/anal_s390_cs.c',
'p/anal_s390_gnu.c', 'p/anal_s390_gnu.c',
'../asm/arch/s390/gnu/s390-dis.c', '../asm/arch/s390/gnu/s390-dis.c',
@ -122,11 +121,6 @@ r_anal_sources = [
'../asm/arch/tms320/c55x_plus/decode_funcs.c', '../asm/arch/tms320/c55x_plus/decode_funcs.c',
'../asm/arch/tms320/c55x_plus/hashtable.c', '../asm/arch/tms320/c55x_plus/hashtable.c',
'../asm/arch/tms320/c55x_plus/utils.c', '../asm/arch/tms320/c55x_plus/utils.c',
'../asm/arch/pyc/opcode_all.c',
'../asm/arch/pyc/opcode_anal.c',
'../asm/arch/pyc/opcode_arg_fmt.c',
'../asm/arch/pyc/opcode.c',
'../asm/arch/pyc/pyc_dis.c'
] ]
incdirs = [ incdirs = [
'arch' 'arch'

View File

@ -1,17 +0,0 @@
PYC_ASM_ROOT=../../asm/arch/pyc/
OBJ_PYC=anal_pyc.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode_all.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode_anal.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode_arg_fmt.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode.o
OBJ_PYC+=$(PYC_ASM_ROOT)/pyc_dis.o
STATIC_OBJ+=$(OBJ_PYC)
TARGET_PYC=anal_pyc.$(EXT_SO)
ALL_TARGETS+=$(TARGET_PYC)
PYC_ROOT=../asm/arch/pyc
CFLAGS+=-I$(PYC_ROOT)
$(TARGET_PYC): $(OBJ_PYC)
$(CC) $(call libname,anal_pyc) $(CFLAGS) $(LDFLAGS) -o $(TARGET_PYC) $(OBJ_PYC) -lr_util

View File

@ -85,6 +85,13 @@ r_arch_sources = [
'p/ebc/ebc_disas.c', 'p/ebc/ebc_disas.c',
'p/msp430/plugin.c', 'p/msp430/plugin.c',
'p/msp430/msp430_disas.c', 'p/msp430/msp430_disas.c',
# python
'p/pyc/plugin.c',
'p/pyc/opcode_all.c',
'p/pyc/opcode_anal.c',
'p/pyc/opcode_arg_fmt.c',
'p/pyc/opcode.c',
'p/pyc/pyc_dis.c'
] ]
if arch_plugins.contains('x86_nz') if arch_plugins.contains('x86_nz')

15
libr/arch/p/pyc.mk Normal file
View File

@ -0,0 +1,15 @@
PYC_ROOT=p/pyc
OBJ_PYC=p/pyc/plugin.o
OBJ_PYC+=$(PYC_ROOT)/opcode_all.o
OBJ_PYC+=$(PYC_ROOT)/opcode_anal.o
OBJ_PYC+=$(PYC_ROOT)/opcode_arg_fmt.o
OBJ_PYC+=$(PYC_ROOT)/opcode.o
OBJ_PYC+=$(PYC_ROOT)/pyc_dis.o
STATIC_OBJ+=$(OBJ_PYC)
TARGET_PYC=arch_pyc.$(EXT_SO)
ALL_TARGETS+=$(TARGET_PYC)
$(TARGET_PYC): $(OBJ_PYC)
$(CC) $(call libname,arch_pyc) $(CFLAGS) $(LDFLAGS) -o $(TARGET_PYC) $(OBJ_PYC) -lr_util

View File

@ -1,45 +1,38 @@
/* radare - LGPL3 - Copyright 2016-2022 - FXTi */ /* radare - LGPL3 - Copyright 2016-2023 - FXTi, pancake */
#include <r_lib.h> #include <r_lib.h>
#include <r_anal.h> #include <r_arch.h>
#include "../../asm/arch/pyc/pyc_dis.h" #include "pyc_dis.h"
static R_TH_LOCAL pyc_opcodes *ops = NULL;
static int disassemble(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
RList *shared = NULL;
RBin *bin = a->binb.bin;
static bool disassemble(RArchSession *s, RAnalOp *op, RArchDecodeMask mask) {
RBin *bin = s->arch->binb.bin;
RBinPlugin *plugin = bin && bin->cur && bin->cur->o? bin->cur->o->plugin: NULL; RBinPlugin *plugin = bin && bin->cur && bin->cur->o? bin->cur->o->plugin: NULL;
RList *shared = (plugin && !strcmp (plugin->name, "pyc"))?
if (plugin) { bin->cur->o->bin_obj: NULL;
if (!strcmp (plugin->name, "pyc")) {
shared = bin->cur->o->bin_obj;
}
}
RList *cobjs = NULL; RList *cobjs = NULL;
RList *interned_table = NULL; RList *interned_table = NULL;
if (shared) { if (shared) {
cobjs = r_list_get_n (shared, 0); cobjs = r_list_get_n (shared, 0);
interned_table = r_list_get_n (shared, 1); interned_table = r_list_get_n (shared, 1);
} }
if (!ops || !pyc_opcodes_equal (ops, a->config->cpu)) { pyc_opcodes *ops = s->data;
ops = get_opcode_by_version (a->config->cpu); if (!ops || !pyc_opcodes_equal (ops, s->config->cpu)) {
ops = get_opcode_by_version (s->config->cpu);
if (!ops) { if (!ops) {
ops = get_opcode_by_version ("v3.9.0"); ops = get_opcode_by_version ("v3.9.0");
if (!ops) { if (!ops) {
return 0; return false;
} }
} }
ops->bits = a->config->bits; ops->bits = s->config->bits;
} }
int r = r_pyc_disasm (op, buf, cobjs, interned_table, addr, ops); s->data = ops;
int r = r_pyc_disasm (op, op->bytes, cobjs, interned_table, op->addr, ops);
op->size = r; op->size = r;
return r; return r > 0;
} }
static int archinfo(RAnal *anal, int query) { static int archinfo(RArchSession *anal, ut32 query) {
switch (query) { switch (query) {
case R_ANAL_ARCHINFO_MIN_OP_SIZE: case R_ANAL_ARCHINFO_MIN_OP_SIZE:
return (anal->config->bits == 16)? 1: 2; return (anal->config->bits == 16)? 1: 2;
@ -50,7 +43,7 @@ static int archinfo(RAnal *anal, int query) {
} }
} }
static char *get_reg_profile(RAnal *anal) { static char *regs(RArchSession *as) {
return strdup ( return strdup (
"=PC pc\n" "=PC pc\n"
"=BP bp\n" "=BP bp\n"
@ -71,68 +64,59 @@ static char *get_reg_profile(RAnal *anal) {
); );
} }
static bool set_reg_profile(RAnal *anal) { static RList *get_pyc_code_obj(RArchSession *as) {
char *rp = get_reg_profile (anal); RBin *b = as->arch->binb.bin;
if (rp) {
bool b = r_reg_set_profile_string (anal->reg, rp);
free (rp);
return b;
}
return false;
}
static RList *get_pyc_code_obj(RAnal *anal) {
RBin *b = anal->binb.bin;
RBinPlugin *plugin = b->cur && b->cur->o? b->cur->o->plugin: NULL; RBinPlugin *plugin = b->cur && b->cur->o? b->cur->o->plugin: NULL;
bool is_pyc = (plugin && strcmp (plugin->name, "pyc") == 0); bool is_pyc = (plugin && strcmp (plugin->name, "pyc") == 0);
return is_pyc? b->cur->o->bin_obj: NULL; return is_pyc? b->cur->o->bin_obj: NULL;
} }
static int pyc_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) { static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
RList *pyobj = get_pyc_code_obj (a); RList *pyobj = get_pyc_code_obj (as);
if (!pyobj) { if (!pyobj) {
return -1; return false;
} }
const ut64 addr = op->addr;
const ut8 *data = op->bytes;
RList *cobjs = r_list_get_n (pyobj, 0); RList *cobjs = r_list_get_n (pyobj, 0);
RListIter *iter = NULL; RListIter *iter = NULL;
pyc_code_object *func = NULL, *t = NULL; pyc_code_object *func = NULL, *t = NULL;
r_list_foreach (cobjs, iter, t) { r_list_foreach (cobjs, iter, t) {
if (R_BETWEEN (t->start_offset, addr, t->end_offset - 1)) { // addr in [start_offset, end_offset) if (R_BETWEEN (t->start_offset, addr, t->end_offset - 1)) {
func = t; func = t;
break; break;
} }
} }
if (!func) { if (!func) {
return -1; return false;
} }
if (mask & R_ARCH_OP_MASK_DISASM) { if (mask & R_ARCH_OP_MASK_DISASM) {
disassemble (a, op, addr, data, len); disassemble (as, op, mask);
} }
ut64 func_base = func->start_offset; ut64 func_base = func->start_offset;
ut32 extended_arg = 0, oparg = 0; ut32 extended_arg = 0, oparg = 0;
ut8 op_code = data[0]; ut8 op_code = data[0];
op->addr = addr;
op->sign = true; op->sign = true;
op->type = R_ANAL_OP_TYPE_ILL; op->type = R_ANAL_OP_TYPE_ILL;
op->id = op_code; op->id = op_code;
if (!ops || !pyc_opcodes_equal (ops, a->config->cpu)) { pyc_opcodes *ops = as->data;
if (!(ops = get_opcode_by_version (a->config->cpu))) { if (!ops || !pyc_opcodes_equal (ops, as->config->cpu)) {
return -1; if (!(ops = get_opcode_by_version (as->config->cpu))) {
return false;
} }
} }
int bits = a->config->bits; const int bits = as->config->bits;
bool is_python36 = bits == 8; bool is_python36 = bits == 8;
pyc_opcode_object *op_obj = &ops->opcodes[op_code]; pyc_opcode_object *op_obj = &ops->opcodes[op_code];
if (!op_obj->op_name) { if (!op_obj->op_name) {
op->type = R_ANAL_OP_TYPE_ILL; op->type = R_ANAL_OP_TYPE_ILL;
op->size = 1; op->size = 1;
goto anal_end; goto beach;
} }
op->size = is_python36? 2: ((op_code >= ops->have_argument)? 3: 1); op->size = is_python36? 2: ((op_code >= ops->have_argument)? 3: 1);
if (op_code >= ops->have_argument) { if (op_code >= ops->have_argument) {
if (!is_python36) { if (!is_python36) {
oparg = data[1] + data[2] * 256 + extended_arg; oparg = data[1] + data[2] * 256 + extended_arg;
@ -149,7 +133,7 @@ static int pyc_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RA
op->type = R_ANAL_OP_TYPE_CJMP; op->type = R_ANAL_OP_TYPE_CJMP;
op->fail = addr + ((is_python36)? 2: 3); op->fail = addr + ((is_python36)? 2: 3);
} }
goto anal_end; goto beach;
} }
if (op_obj->type & HASJREL) { if (op_obj->type & HASJREL) {
op->type = R_ANAL_OP_TYPE_JMP; op->type = R_ANAL_OP_TYPE_JMP;
@ -160,47 +144,42 @@ static int pyc_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RA
op->type = R_ANAL_OP_TYPE_CJMP; op->type = R_ANAL_OP_TYPE_CJMP;
//op->fail = addr + ((is_python36)? 2: 3); //op->fail = addr + ((is_python36)? 2: 3);
} }
//goto anal_end;
} }
if (op_obj->type & HASCOMPARE) { if (op_obj->type & HASCOMPARE) {
op->type = R_ANAL_OP_TYPE_CMP; op->type = R_ANAL_OP_TYPE_CMP;
goto anal_end; goto beach;
} }
anal_pyc_op (op, op_obj, oparg); anal_pyc_op (op, op_obj, oparg);
beach:
anal_end: return op->size > 0;
//free_opcode (ops);
return op->size;
} }
static int finish(void *user) { static bool finish(RArchSession *s) {
pyc_opcodes *ops = s->data;
if (ops) { if (ops) {
free_opcode (ops); free_opcode (ops);
ops = NULL; s->data = NULL;
} }
return 0; return true;
} }
RAnalPlugin r_anal_plugin_pyc = { RArchPlugin r_arch_plugin_pyc = {
.name = "pyc", .name = "pyc",
.desc = "Python bytecode analysis plugin", .desc = "Python bytecode analysis plugin",
.license = "LGPL3", .license = "LGPL3",
.arch = "pyc", .arch = "pyc",
.bits = 32, .bits = R_SYS_BITS_PACK1 (32),
.archinfo = archinfo, .info = archinfo,
.get_reg_profile = get_reg_profile, .regs = regs,
.set_reg_profile = &set_reg_profile, .decode = &decode,
.op = &pyc_op,
.esil = false,
.fini = &finish, .fini = &finish,
}; };
#ifndef R2_PLUGIN_INCORE #ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = { R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL, .type = R_LIB_TYPE_ARCH,
.data = &r_anal_plugin_pyc, .data = &r_arch_plugin_pyc,
.version = R2_VERSION .version = R2_VERSION
}; };
#endif #endif

View File

@ -1594,7 +1594,6 @@ extern RAnalPlugin r_anal_plugin_x86_im;
extern RAnalPlugin r_anal_plugin_x86_simple; extern RAnalPlugin r_anal_plugin_x86_simple;
extern RAnalPlugin r_anal_plugin_x86_udis; extern RAnalPlugin r_anal_plugin_x86_udis;
extern RAnalPlugin r_anal_plugin_xcore_cs; extern RAnalPlugin r_anal_plugin_xcore_cs;
extern RAnalPlugin r_anal_plugin_pyc;
extern RAnalPlugin r_anal_plugin_pickle; extern RAnalPlugin r_anal_plugin_pickle;
extern RAnalPlugin r_anal_plugin_evm_cs; extern RAnalPlugin r_anal_plugin_evm_cs;
extern RAnalPlugin r_anal_plugin_hppa_gnu; extern RAnalPlugin r_anal_plugin_hppa_gnu;

View File

@ -325,6 +325,7 @@ extern RArchPlugin r_arch_plugin_pdp11;
extern RArchPlugin r_arch_plugin_lh5801; extern RArchPlugin r_arch_plugin_lh5801;
extern RArchPlugin r_arch_plugin_ebc; extern RArchPlugin r_arch_plugin_ebc;
extern RArchPlugin r_arch_plugin_msp430; extern RArchPlugin r_arch_plugin_msp430;
extern RArchPlugin r_arch_plugin_pyc;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -7,6 +7,7 @@ asm_plugins = [ 'null' ]
anal_plugins = [ 'null' ] anal_plugins = [ 'null' ]
arch_plugins = [ 'null', arch_plugins = [ 'null',
# 'arc', # 'arc',
'pyc',
'lh5801', 'lh5801',
'ebc', 'ebc',
'msp430', 'msp430',
@ -152,7 +153,6 @@ endif
# else # else
if no_user_plugins if no_user_plugins
# TODO: add the pyc plugin for meson builds too
anal_plugins += [ anal_plugins += [
'6502_cs', '6502_cs',
'8051', '8051',