Rizin
unix-like reverse engineering framework and cli tools
bin_pyc.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016-2020 c0riolis
2 // SPDX-FileCopyrightText: 2016-2020 x0urc3
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_bin.h>
6 #include "../format/pyc/pyc.h"
7 
8 static bool check_buffer(RzBuffer *b) {
9  if (rz_buf_size(b) > 4) {
10  ut32 buf;
11  rz_buf_read_at(b, 0, (ut8 *)&buf, sizeof(buf));
13  return version.magic != -1;
14  }
15  return false;
16 }
17 
18 static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) {
20  if (!ctx) {
21  return false;
22  }
23  ut32 ver;
24  rz_buf_read_at(buf, 0, (ut8 *)&ver, sizeof(ver));
25  ctx->version = get_pyc_version(ver);
26  obj->bin_obj = ctx;
27  return true;
28 }
29 
31  RzBinPycObj *pyc = arch->o->bin_obj;
32  RzBuffer *buf = arch->buf;
33  ut8 b;
34  ut64 result;
35  int addr;
36  for (addr = 0x8; addr <= 0x10; addr += 0x4) {
37  rz_buf_read_at(buf, addr, &b, sizeof(b));
38  if (pyc_is_code(b, pyc->version.magic)) {
39  pyc->code_start_offset = addr;
41  if ((result = get_code_object_addr(pyc, buf, pyc->version.magic)) == 0) {
42  return addr;
43  }
44  return result;
45  }
46  }
47  return 0;
48 }
49 
51  RzBinPycObj *ctx = arch->o->bin_obj;
52  RzBinInfo *ret = RZ_NEW0(RzBinInfo);
53  if (!ret) {
54  return NULL;
55  }
56  ret->file = strdup(arch->file);
57  ret->type = rz_str_newf("Python %s byte-compiled file", ctx->version.version);
58  ret->bclass = strdup("Python byte-compiled file");
59  ret->rclass = strdup("pyc");
60  ret->arch = strdup("pyc");
61  ret->machine = rz_str_newf("Python %s VM (rev %s)", ctx->version.version,
62  ctx->version.revision);
63  ret->os = strdup("any");
64  ret->bits = version2double(ctx->version.version) < 3.6 ? 16 : 8;
65  ret->cpu = strdup(ctx->version.version); // pass version info in cpu, Asm plugin will get it
66  return ret;
67 }
68 
70  RzBinPycObj *ctx = arch->o->bin_obj;
71  return ctx->sections_cache;
72 }
73 
76  if (!entries) {
77  return NULL;
78  }
80  if (!addr) {
82  return NULL;
83  }
84  ut64 entrypoint = get_entrypoint(arch);
85  addr->paddr = entrypoint;
86  addr->vaddr = entrypoint;
87  rz_buf_seek(arch->buf, entrypoint, RZ_IO_SEEK_SET);
89  return entries;
90 }
91 
92 static ut64 baddr(RzBinFile *bf) {
93  return 0;
94 }
95 
97  RzBinPycObj *pyc = arch->o->bin_obj;
99  if (!shared) {
100  return NULL;
101  }
102  RzList *cobjs = rz_list_newf((RzListFree)free);
103  if (!cobjs) {
104  rz_list_free(shared);
105  return NULL;
106  }
108  if (!pyc->interned_table) {
109  rz_list_free(shared);
110  rz_list_free(cobjs);
111  return NULL;
112  }
113  rz_list_append(shared, cobjs);
114  rz_list_append(shared, pyc->interned_table);
115  pyc->shared = shared;
117  if (!sections) {
118  rz_list_free(shared);
119  return NULL;
120  }
122  if (!symbols) {
123  rz_list_free(shared);
125  return NULL;
126  }
127  RzBuffer *buffer = arch->buf;
130  pyc->sections_cache = sections;
131  return symbols;
132 }
133 
134 static void destroy(RzBinFile *bf) {
135  RzBinPycObj *pyc = bf->o->bin_obj;
136  rz_list_free(pyc->shared);
137  RZ_FREE(bf->o->bin_obj);
138 }
139 
141  .name = "pyc",
142  .desc = "Python byte-compiled file plugin",
143  .license = "LGPL3",
144  .info = &info,
145  .load_buffer = &load_buffer,
146  .check_buffer = &check_buffer,
147  .entries = &entries,
148  .sections = &sections,
149  .baddr = &baddr,
150  .symbols = &symbols,
151  .destroy = &destroy
152 };
153 
154 #ifndef RZ_PLUGIN_INCORE
157  .data = &rz_bin_plugin_pyc,
158  .version = RZ_VERSION,
159 };
160 #endif
static RzBinInfo * info(RzBinFile *arch)
Definition: bin_pyc.c:50
static RzList * entries(RzBinFile *arch)
Definition: bin_pyc.c:74
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb)
Definition: bin_pyc.c:18
static RzList * symbols(RzBinFile *arch)
Definition: bin_pyc.c:96
static void destroy(RzBinFile *bf)
Definition: bin_pyc.c:134
RZ_API RzLibStruct rizin_plugin
Definition: bin_pyc.c:155
static bool check_buffer(RzBuffer *b)
Definition: bin_pyc.c:8
static ut64 get_entrypoint(RzBinFile *arch)
Definition: bin_pyc.c:30
static ut64 baddr(RzBinFile *bf)
Definition: bin_pyc.c:92
RzBinPlugin rz_bin_plugin_pyc
Definition: bin_pyc.c:140
static RzList * sections(RzBinFile *arch)
Definition: bin_pyc.c:69
#define RZ_API
#define NULL
Definition: cris-opc.c:27
cs_arch arch
Definition: cstool.c:13
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
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")
ut64 get_code_object_addr(RzBinPycObj *pyc, RzBuffer *buffer, ut32 magic)
Definition: marshal.c:981
bool pyc_is_code(ut8 b, ut32 magic)
Definition: pyc.c:16
bool pyc_get_sections_symbols(RzBinPycObj *pyc, RzList *sections, RzList *symbols, RzList *cobjs, RzBuffer *buf, ut32 magic)
Definition: pyc.c:8
struct pyc_version get_pyc_version(ut32 magic)
Definition: pyc_magic.c:273
double version2double(const char *version)
Definition: pyc_magic.c:316
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
#define RZ_BUF_SET
Definition: rz_buf.h:14
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define RZ_IO_SEEK_SET
Definition: rz_io.h:15
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_VERSION
Definition: rz_version.h:8
#define b(i)
Definition: sha256.c:42
Definition: buffer.h:15
struct pyc_version version
Definition: marshal.h:78
ut64 code_start_offset
Definition: marshal.h:77
RzList * sections_cache
Definition: marshal.h:81
RzList * interned_table
Definition: marshal.h:80
RzList * shared
Definition: marshal.h:82
ut32 magic
Definition: pyc_magic.h:11
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
char * type
Definition: rz_bin.h:211
char * os
Definition: rz_bin.h:219
char * machine
Definition: rz_bin.h:216
char * bclass
Definition: rz_bin.h:212
char * file
Definition: rz_bin.h:210
char * cpu
Definition: rz_bin.h:215
char * rclass
Definition: rz_bin.h:213
char * arch
Definition: rz_bin.h:214
void * bin_obj
Definition: rz_bin.h:293
char * name
Definition: rz_bin.h:509
char * version
Definition: rz_bin.h:512
Definition: sdb.h:63
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58