Rizin
unix-like reverse engineering framework and cli tools
analysis_pyc.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016-2020 FXTi <zjxiang1998@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_types.h>
5 #include <rz_lib.h>
6 #include <rz_util.h>
7 #include <rz_asm.h>
8 
9 #include "../../asm/arch/pyc/pyc_dis.h"
10 
11 static int archinfo(RzAnalysis *analysis, int query) {
12  if (!strcmp(analysis->cpu, "x86")) {
13  return -1;
14  }
15 
16  switch (query) {
18  return (analysis->bits == 16) ? 1 : 2;
20  return (analysis->bits == 16) ? 3 : 2;
21  default:
22  return -1;
23  }
24 }
25 
26 static char *get_reg_profile(RzAnalysis *analysis) {
27  return strdup(
28  "=PC pc\n"
29  "=BP bp\n"
30  "=SP sp\n"
31  "=A0 sp\n"
32  "gpr sp .32 0 0\n" // stack pointer
33  "gpr pc .32 4 0\n" // program counter
34  "gpr bp .32 8 0\n" // base pointer // unused
35  );
36 }
37 
38 static RzList *get_pyc_code_obj(RzAnalysis *analysis) {
39  RzBin *b = analysis->binb.bin;
40  RzBinPlugin *plugin = b->cur && b->cur->o ? b->cur->o->plugin : NULL;
41  bool is_pyc = (plugin && strcmp(plugin->name, "pyc") == 0);
42  if (!is_pyc) {
43  return NULL;
44  }
45  return ((RzBinPycObj *)b->cur->o->bin_obj)->shared;
46 }
47 
48 static int pyc_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
49  pyc_opcodes *ops = (pyc_opcodes *)a->plugin_data;
50  RzList *cobjs = rz_list_get_n(get_pyc_code_obj(a), 0);
51  RzListIter *iter = NULL;
52  pyc_code_object *func = NULL, *t = NULL;
53  rz_list_foreach (cobjs, iter, t) {
54  if (RZ_BETWEEN(t->start_offset, addr, t->end_offset - 1)) { // addr in [start_offset, end_offset)
55  func = t;
56  break;
57  }
58  }
59  if (!func) {
60  return -1;
61  }
62 
63  ut64 func_base = func->start_offset;
64  ut32 extended_arg = 0, oparg = 0;
65  ut8 op_code = data[0];
66  op->addr = addr;
67  op->sign = true;
69  op->id = op_code;
70 
71  if (!pyc_opcodes_equal(ops, a->cpu)) {
73  ops = NULL;
74  }
75 
76  if (!ops) {
77  if (!(ops = get_opcode_by_version(a->cpu))) {
78  return -1;
79  }
80  a->plugin_data = ops;
81  }
82  bool is_python36 = a->bits == 8;
83  pyc_opcode_object *op_obj = &ops->opcodes[op_code];
84  if (!op_obj->op_name) {
86  op->size = 1;
87  goto analysis_end;
88  }
89 
90  op->size = is_python36 ? 2 : ((op_code >= ops->have_argument) ? 3 : 1);
91 
92  if (op_code >= ops->have_argument) {
93  if (!is_python36) {
94  oparg = data[1] + data[2] * 256 + extended_arg;
95  } else {
96  oparg = data[1] + extended_arg;
97  }
98  }
99 
100  if (op_obj->type & HASJABS) {
101  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
102  op->jump = func_base + oparg;
103 
104  if (op_obj->type & HASCONDITION) {
106  op->fail = addr + ((is_python36) ? 2 : 3);
107  }
108  goto analysis_end;
109  }
110  if (op_obj->type & HASJREL) {
111  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
112  op->jump = addr + oparg + ((is_python36) ? 2 : 3);
113  op->fail = addr + ((is_python36) ? 2 : 3);
114 
115  if (op_obj->type & HASCONDITION) {
117  // op->fail = addr + ((is_python36)? 2: 3);
118  }
119  // goto analysis_end;
120  }
121 
122  if (op_obj->type & HASCOMPARE) {
123  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
124  goto analysis_end;
125  }
126 
127  analysis_pyc_op(op, op_obj, oparg);
128 
129 analysis_end:
130  return op->size;
131 }
132 
133 static bool finish(void *user) {
134  pyc_opcodes *ops = (user);
135  free_opcode(ops);
136  return true;
137 }
138 
140  .name = "pyc",
141  .desc = "Python bytecode analysis plugin",
142  .license = "LGPL3",
143  .arch = "pyc",
144  .bits = 16 | 8, // Partially agree with this
145  .archinfo = archinfo,
146  .get_reg_profile = get_reg_profile,
147  .op = &pyc_op,
148  .esil = false,
149  .fini = &finish,
150 };
151 
152 #ifndef RZ_PLUGIN_INCORE
155  .data = &rz_analysis_plugin_pyc,
157 };
158 #endif
size_t len
Definition: 6502dis.c:15
static struct @29 ops[]
#define mask()
static char * get_reg_profile(RzAnalysis *analysis)
Definition: analysis_pyc.c:26
static int pyc_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: analysis_pyc.c:48
RzAnalysisPlugin rz_analysis_plugin_pyc
Definition: analysis_pyc.c:139
RZ_API RzLibStruct rizin_plugin
Definition: analysis_pyc.c:153
static RzList * get_pyc_code_obj(RzAnalysis *analysis)
Definition: analysis_pyc.c:38
static bool finish(void *user)
Definition: analysis_pyc.c:133
static int archinfo(RzAnalysis *analysis, int query)
Definition: analysis_pyc.c:11
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
void free_opcode(pyc_opcodes *opcodes)
Definition: opcode.c:217
pyc_opcodes * get_opcode_by_version(char *version)
Definition: opcode.c:169
bool pyc_opcodes_equal(pyc_opcodes *op, const char *version)
Definition: opcode.c:151
void analysis_pyc_op(RzAnalysisOp *op, pyc_opcode_object *op_obj, ut32 oparg)
@ HASCONDITION
Definition: opcode.h:17
@ HASCOMPARE
Definition: opcode.h:16
@ HASJREL
Definition: opcode.h:21
@ HASJABS
Definition: opcode.h:20
#define RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE
Definition: rz_analysis.h:99
RzAnalysisOpMask
Definition: rz_analysis.h:439
#define RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE
Definition: rz_analysis.h:98
@ RZ_ANALYSIS_OP_TYPE_CMP
Definition: rz_analysis.h:399
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_ILL
Definition: rz_analysis.h:387
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
#define RZ_BETWEEN(x, y, z)
#define RZ_VERSION
Definition: rz_version.h:8
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: dis.c:12
st64 start_offset
Definition: marshal.h:72
char * op_name
Definition: opcode.h:38
const char * version
Definition: rz_analysis.h:1239
RzBinBind binb
Definition: rz_analysis.h:579
RzBin * bin
Definition: rz_bin.h:807
char * name
Definition: rz_bin.h:509
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58