Skip to content

Commit

Permalink
Add last pseudo instructions to pickle ##arch
Browse files Browse the repository at this point in the history
  • Loading branch information
dennis-doyensec authored and trufae committed Jan 14, 2025
1 parent a7e958f commit bf6227e
Show file tree
Hide file tree
Showing 3 changed files with 334 additions and 221 deletions.
167 changes: 167 additions & 0 deletions libr/arch/p/pickle/dis_helper.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
enum opcode {
OP_MARK = '(',
OP_STOP = '.',
OP_POP = '0',
OP_POP_MARK = '1',
OP_DUP = '2',
OP_FLOAT = 'F',
OP_INT = 'I',
OP_BININT = 'J',
OP_BININT1 = 'K',
OP_LONG = 'L',
OP_BININT2 = 'M',
OP_NONE = 'N',
OP_PERSID = 'P',
OP_BINPERSID = 'Q',
OP_REDUCE = 'R',
OP_STRING = 'S',
OP_BINSTRING = 'T',
OP_SHORT_BINSTRING = 'U',
OP_UNICODE = 'V',
OP_BINUNICODE = 'X',
OP_APPEND = 'a',
OP_BUILD = 'b',
OP_GLOBAL = 'c',
OP_DICT = 'd',
OP_EMPTY_DICT = '}',
OP_APPENDS = 'e',
OP_GET = 'g',
OP_BINGET = 'h',
OP_INST = 'i',
OP_LONG_BINGET = 'j',
OP_LIST = 'l',
OP_EMPTY_LIST = ']',
OP_OBJ = 'o',
OP_PUT = 'p',
OP_BINPUT = 'q',
OP_LONG_BINPUT = 'r',
OP_SETITEM = 's',
OP_TUPLE = 't',
OP_EMPTY_TUPLE = ')',
OP_SETITEMS = 'u',
OP_BINFLOAT = 'G',

// Protocol 2.
OP_PROTO = '\x80',
OP_NEWOBJ = '\x81',
OP_EXT1 = '\x82',
OP_EXT2 = '\x83',
OP_EXT4 = '\x84',
OP_TUPLE1 = '\x85',
OP_TUPLE2 = '\x86',
OP_TUPLE3 = '\x87',
OP_NEWTRUE = '\x88',
OP_NEWFALSE = '\x89',
OP_LONG1 = '\x8a',
OP_LONG4 = '\x8b',

// Protocol 3 (Python 3.x)
OP_BINBYTES = 'B',
OP_SHORT_BINBYTES = 'C',

// Protocol 4
OP_SHORT_BINUNICODE = '\x8c',
OP_BINUNICODE8 = '\x8d',
OP_BINBYTES8 = '\x8e',
OP_EMPTY_SET = '\x8f',
OP_ADDITEMS = '\x90',
OP_FROZENSET = '\x91',
OP_NEWOBJ_EX = '\x92',
OP_STACK_GLOBAL = '\x93',
OP_MEMOIZE = '\x94',
OP_FRAME = '\x95',

// Protocol 5
OP_BYTEARRAY8 = '\x96',
OP_NEXT_BUFFER = '\x97',
OP_READONLY_BUFFER = '\x98',

// not a real pickle opcode, indicates failure in parsing
OP_FAILURE = '\xff'
};

struct opmap {
const char *const name;
char op;
};

static const struct opmap op_name_map[] = {
{ "mark", '(' },
{ "stop", '.' },
{ "pop", '0' },
{ "pop_mark", '1' },
{ "dup", '2' },
{ "float", 'F' },
{ "int", 'I' },
{ "binint", 'J' },
{ "binint1", 'K' },
{ "long", 'L' },
{ "binint2", 'M' },
{ "none", 'N' },
{ "persid", 'P' },
{ "binpersid", 'Q' },
{ "reduce", 'R' },
{ "string", 'S' },
{ "binstring", 'T' },
{ "short_binstring", 'U' },
{ "unicode", 'V' },
{ "binunicode", 'X' },
{ "append", 'a' },
{ "build", 'b' },
{ "global", 'c' },
{ "dict", 'd' },
{ "empty_dict", '}' },
{ "appends", 'e' },
{ "get", 'g' },
{ "binget", 'h' },
{ "inst", 'i' },
{ "long_binget", 'j' },
{ "list", 'l' },
{ "empty_list", ']' },
{ "obj", 'o' },
{ "put", 'p' },
{ "binput", 'q' },
{ "long_binput", 'r' },
{ "setitem", 's' },
{ "tuple", 't' },
{ "empty_tuple", ')' },
{ "setitems", 'u' },
{ "binfloat", 'G' },
{ "proto", '\x80' },
{ "newobj", '\x81' },
{ "ext1", '\x82' },
{ "ext2", '\x83' },
{ "ext4", '\x84' },
{ "tuple1", '\x85' },
{ "tuple2", '\x86' },
{ "tuple3", '\x87' },
{ "newtrue", '\x88' },
{ "newfalse", '\x89' },
{ "long1", '\x8a' },
{ "long4", '\x8b' },
{ "binbytes", 'B' },
{ "short_binbytes", 'C' },
{ "short_binunicode", '\x8c' },
{ "binunicode8", '\x8d' },
{ "binbytes8", '\x8e' },
{ "empty_set", '\x8f' },
{ "additems", '\x90' },
{ "frozenset", '\x91' },
{ "newobj_ex", '\x92' },
{ "stack_global", '\x93' },
{ "memoize", '\x94' },
{ "frame", '\x95' },
{ "bytearray8", '\x96' },
{ "next_buffer", '\x97' },
{ "readonly_buffer", '\x98' }
};

static inline int name_to_op(const char *opstr) {
size_t i;
for (i = 0; i < R_ARRAY_SIZE (op_name_map); i++) {
if (!r_str_casecmp (opstr, op_name_map[i].name)) {
return op_name_map[i].op;
}
}
return OP_FAILURE;
}
177 changes: 9 additions & 168 deletions libr/arch/p/pickle/plugin.c
Original file line number Diff line number Diff line change
@@ -1,164 +1,10 @@
/* radare2 - LGPL - Copyright 2022-2024 - bemodtwz */

#include <r_anal.h>
#include "dis_helper.inc"

#define MAXSTRLEN 128

struct opmap {
const char * const name;
const char op;
};

enum opcode {
OP_MARK = '(',
OP_STOP = '.',
OP_POP = '0',
OP_POP_MARK = '1',
OP_DUP = '2',
OP_FLOAT = 'F',
OP_INT = 'I',
OP_BININT = 'J',
OP_BININT1 = 'K',
OP_LONG = 'L',
OP_BININT2 = 'M',
OP_NONE = 'N',
OP_PERSID = 'P',
OP_BINPERSID = 'Q',
OP_REDUCE = 'R',
OP_STRING = 'S',
OP_BINSTRING = 'T',
OP_SHORT_BINSTRING = 'U',
OP_UNICODE = 'V',
OP_BINUNICODE = 'X',
OP_APPEND = 'a',
OP_BUILD = 'b',
OP_GLOBAL = 'c',
OP_DICT = 'd',
OP_EMPTY_DICT = '}',
OP_APPENDS = 'e',
OP_GET = 'g',
OP_BINGET = 'h',
OP_INST = 'i',
OP_LONG_BINGET = 'j',
OP_LIST = 'l',
OP_EMPTY_LIST = ']',
OP_OBJ = 'o',
OP_PUT = 'p',
OP_BINPUT = 'q',
OP_LONG_BINPUT = 'r',
OP_SETITEM = 's',
OP_TUPLE = 't',
OP_EMPTY_TUPLE = ')',
OP_SETITEMS = 'u',
OP_BINFLOAT = 'G',

// Protocol 2.
OP_PROTO = '\x80',
OP_NEWOBJ = '\x81',
OP_EXT1 = '\x82',
OP_EXT2 = '\x83',
OP_EXT4 = '\x84',
OP_TUPLE1 = '\x85',
OP_TUPLE2 = '\x86',
OP_TUPLE3 = '\x87',
OP_NEWTRUE = '\x88',
OP_NEWFALSE = '\x89',
OP_LONG1 = '\x8a',
OP_LONG4 = '\x8b',

// Protocol 3 (Python 3.x)
OP_BINBYTES = 'B',
OP_SHORT_BINBYTES = 'C',

// Protocol 4
OP_SHORT_BINUNICODE = '\x8c',
OP_BINUNICODE8 = '\x8d',
OP_BINBYTES8 = '\x8e',
OP_EMPTY_SET = '\x8f',
OP_ADDITEMS = '\x90',
OP_FROZENSET = '\x91',
OP_NEWOBJ_EX = '\x92',
OP_STACK_GLOBAL = '\x93',
OP_MEMOIZE = '\x94',
OP_FRAME = '\x95',

// Protocol 5
OP_BYTEARRAY8 = '\x96',
OP_NEXT_BUFFER = '\x97',
OP_READONLY_BUFFER = '\x98'
};

static const struct opmap op_name_map[] = {
{ "mark", '(' },
{ "stop", '.' },
{ "pop", '0' },
{ "pop_mark", '1' },
{ "dup", '2' },
{ "float", 'F' },
{ "int", 'I' },
{ "binint", 'J' },
{ "binint1", 'K' },
{ "long", 'L' },
{ "binint2", 'M' },
{ "none", 'N' },
{ "persid", 'P' },
{ "binpersid", 'Q' },
{ "reduce", 'R' },
{ "string", 'S' },
{ "binstring", 'T' },
{ "short_binstring", 'U' },
{ "unicode", 'V' },
{ "binunicode", 'X' },
{ "append", 'a' },
{ "build", 'b' },
{ "global", 'c' },
{ "dict", 'd' },
{ "empty_dict", '}' },
{ "appends", 'e' },
{ "get", 'g' },
{ "binget", 'h' },
{ "inst", 'i' },
{ "long_binget", 'j' },
{ "list", 'l' },
{ "empty_list", ']' },
{ "obj", 'o' },
{ "put", 'p' },
{ "binput", 'q' },
{ "long_binput", 'r' },
{ "setitem", 's' },
{ "tuple", 't' },
{ "empty_tuple", ')' },
{ "setitems", 'u' },
{ "binfloat", 'G' },
{ "proto", '\x80' },
{ "newobj", '\x81' },
{ "ext1", '\x82' },
{ "ext2", '\x83' },
{ "ext4", '\x84' },
{ "tuple1", '\x85' },
{ "tuple2", '\x86' },
{ "tuple3", '\x87' },
{ "newtrue", '\x88' },
{ "newfalse", '\x89' },
{ "long1", '\x8a' },
{ "long4", '\x8b' },
{ "binbytes", 'B' },
{ "short_binbytes", 'C' },
{ "short_binunicode", '\x8c' },
{ "binunicode8", '\x8d' },
{ "binbytes8", '\x8e' },
{ "empty_set", '\x8f' },
{ "additems", '\x90' },
{ "frozenset", '\x91' },
{ "newobj_ex", '\x92' },
{ "stack_global", '\x93' },
{ "memoize", '\x94' },
{ "frame", '\x95' },
{ "bytearray8", '\x96' },
{ "next_buffer", '\x97' },
{ "readonly_buffer", '\x98' }
};

static inline bool valid_offset(RArch *a, ut64 addr) {
RBin *bin = R_UNWRAP2 (a, binb.bin);
if (bin) {
Expand Down Expand Up @@ -745,21 +591,12 @@ static inline int assemble_n_str(char *str, ut32 cnt, ut8 *outbuf, int outsz, bo
return len + 1;
}

static inline bool write_op(char *opstr, ut8 *outbuf) {
size_t i;
for (i = 0; i < R_ARRAY_SIZE (op_name_map); i++) {
if (!r_str_casecmp (opstr, op_name_map[i].name)) {
*outbuf = (ut8)op_name_map[i].op;
return true;
}
}
return false;
}

static bool pickle_encode(RArchSession *s, RAnalOp *op, RArchEncodeMask mask) {
const char *str = op->mnemonic;
// some ops can be huge, but they should always be smaller then the mnemonics
int outsz = strlen (str);

// _outbuf is kept for free'ing while outbuff will get ++
ut8 *_outbuf = malloc (outsz);
if (!_outbuf) {
return false;
Expand All @@ -783,8 +620,12 @@ static bool pickle_encode(RArchSession *s, RAnalOp *op, RArchEncodeMask mask) {
arg = "";
}

if (write_op (opstr, outbuf)) {
char ob = (char)*outbuf;
int ob = name_to_op (opstr);
if (ob == OP_FAILURE) {
R_LOG_ERROR ("Unkonwn pickle verb: %s", opstr);
wlen = -1;
} else {
*outbuf = (ut8)ob;
wlen++;
outbuf++;
outsz--;
Expand Down
Loading

0 comments on commit bf6227e

Please sign in to comment.