I'm trying to extact a global variable from an executable. Basically, I'm tryin to reverse an executable that put some python bytecode in a global variable and I'd like to extract it. I found out that the data is in the .data of the PE File, but I can't find a way to get it in all the data segments. Any ideas?
1 Answers
Since you say you are trying to reverse an executable which stores some python bytecode in a variable, it means probably the executable embeds python. If the code is likely to be executed at some point of time, you can use a debugger.
Set a breakpoint on PyEval_EvalFrameEx .
It has a prototype of PyObject* PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
The first parameter PyFrameObject has the following structure.
typedef struct _frame {
PyObject_VAR_HEAD
struct _frame *f_back; /* previous frame, or NULL */
PyCodeObject *f_code; /* code segment */
PyObject *f_builtins; /* builtin symbol table (PyDictObject) */
PyObject *f_globals; /* global symbol table (PyDictObject) */
PyObject *f_locals; /* local symbol table (any mapping) */
PyObject **f_valuestack; /* points after the last local */
PyObject **f_stacktop;
PyObject *f_trace; /* Trace function */
PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
PyThreadState *f_tstate;
int f_lasti; /* Last instruction if called */
int f_lineno; /* Current line number */
int f_iblock; /* index in f_blockstack */
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
} PyFrameObject;
The third member of PyFrameObject is PyCodeObject.
PyCodeObject has the following structure.
typedef struct {
PyObject_HEAD
int co_argcount; /* #arguments, except *args */
int co_nlocals; /* #local variables */
int co_stacksize; /* #entries needed for evaluation stack */
int co_flags; /* CO_..., see below */
PyObject *co_code; /* instruction opcodes */
PyObject *co_consts; /* list (constants used) */
PyObject *co_names; /* list of strings (names used) */
PyObject *co_varnames; /* tuple of strings (local variable names) */
PyObject *co_freevars; /* tuple of strings (free variable names) */
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
/* The rest doesn't count for hash/cmp */
PyObject *co_filename; /* string (where it was loaded from) */
PyObject *co_name; /* string (name, for reference) */
int co_firstlineno; /* first source line number */
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) */
void *co_zombieframe; /* for optimization only (see frameobject.c) */
} PyCodeObject;
The sixth member of the above structure is co_code . It is basically a PyStringObject.
It has the following structure.
typedef struct {
PyObject_VAR_HEAD
long ob_shash;
int ob_sstate;
char ob_sval[1];
} PyStringObject;
The ob_sval contains the bytecode you are after.
So once you hit PyEval_EvalFrameEx follow the structures in memory to get the bytecode.
Another thing to note is you need to know the layout of PyObject_VAR_HEAD and PyObject_HEAD to get the actual offsets. Refer to the python source for more information.
- 6,090
- 3
- 23
- 33
.datasection that sounds to me like it's an initialized variable. What more than the part in the.datasection do you need then? – 0xC0000022L Jun 30 '14 at 09:16