4
0
mirror of https://github.com/QuasarApp/pe-parse.git synced 2025-05-10 10:29:32 +00:00

Implement imports and exports.

Might as well do some general cleanup too:

Rename the len attribute of a section to length.

The section, import and export callbacks return 0 on success and anything else
on failure.

Whitespace fixes.

Fix a bunch of copy/paste mistakes in the test script.
This commit is contained in:
Wesley Shields 2013-11-30 21:36:05 -05:00
parent 2083f6f358
commit 7abab7bd2e
2 changed files with 326 additions and 24 deletions

@ -46,7 +46,7 @@ typedef struct {
PyObject_HEAD
PyObject *name;
PyObject *base;
PyObject *len;
PyObject *length;
PyObject *virtaddr;
PyObject *virtsize;
PyObject *numrelocs;
@ -54,6 +54,196 @@ typedef struct {
PyObject *characteristics;
} pepy_section;
typedef struct {
PyObject_HEAD
PyObject *name;
PyObject *sym;
PyObject *addr;
} pepy_import;
typedef struct {
PyObject_HEAD
PyObject *mod;
PyObject *func;
PyObject *addr;
} pepy_export;
/* None of the attributes in these objects are writable. */
static int pepy_attr_not_writable(PyObject *self, PyObject *value, void *closure) {
PyErr_SetString(PyExc_TypeError, "Attribute not writable");
return -1;
}
static PyObject *pepy_import_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
pepy_import *self;
self = (pepy_import *) type->tp_alloc(type, 0);
return (PyObject *) self;
}
static int pepy_import_init(pepy_import *self, PyObject *args, PyObject *kwds) {
if (!PyArg_ParseTuple(args, "OOO:pepy_import_init", &self->name, &self->sym, &self->addr))
return -1;
return 0;
}
static void pepy_import_dealloc(pepy_import *self) {
Py_XDECREF(self->name);
Py_XDECREF(self->sym);
Py_XDECREF(self->addr);
self->ob_type->tp_free((PyObject *) self);
}
#define PEPY_IMPORT_GET(ATTR) \
static PyObject *pepy_import_get_##ATTR(PyObject *self, void *closure) { \
Py_INCREF(((pepy_import *) self)->ATTR); \
return ((pepy_import *) self)->ATTR; \
}
PEPY_IMPORT_GET(name)
PEPY_IMPORT_GET(sym)
PEPY_IMPORT_GET(addr)
#define MAKEIMPORTGETSET(GS, DOC) \
{ (char *) #GS, (getter) pepy_import_get_##GS, \
(setter) pepy_attr_not_writable, \
(char *) #DOC, NULL }
static PyGetSetDef pepy_import_getseters[] = {
MAKEIMPORTGETSET(name, "Name"),
MAKEIMPORTGETSET(sym, "Symbol"),
MAKEIMPORTGETSET(addr, "Address"),
{ NULL }
};
static PyTypeObject pepy_import_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"pepy.import", /* tp_name */
sizeof(pepy_import), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) pepy_import_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"pepy import object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
pepy_import_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) pepy_import_init, /* tp_init */
0, /* tp_alloc */
pepy_import_new /* tp_new */
};
static PyObject *pepy_export_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
pepy_export *self;
self = (pepy_export *) type->tp_alloc(type, 0);
return (PyObject *) self;
}
static int pepy_export_init(pepy_export *self, PyObject *args, PyObject *kwds) {
if (!PyArg_ParseTuple(args, "OOO:pepy_export_init", &self->mod, &self->func, &self->addr))
return -1;
return 0;
}
static void pepy_export_dealloc(pepy_export *self) {
Py_XDECREF(self->mod);
Py_XDECREF(self->func);
Py_XDECREF(self->addr);
self->ob_type->tp_free((PyObject *) self);
}
#define PEPY_EXPORT_GET(ATTR) \
static PyObject *pepy_export_get_##ATTR(PyObject *self, void *closure) { \
Py_INCREF(((pepy_export *) self)->ATTR); \
return ((pepy_export *) self)->ATTR; \
}
PEPY_EXPORT_GET(mod)
PEPY_EXPORT_GET(func)
PEPY_EXPORT_GET(addr)
#define MAKEEXPORTGETSET(GS, DOC) \
{ (char *) #GS, (getter) pepy_export_get_##GS, \
(setter) pepy_attr_not_writable, \
(char *) #DOC, NULL }
static PyGetSetDef pepy_export_getseters[] = {
MAKEEXPORTGETSET(mod, "Module"),
MAKEEXPORTGETSET(func, "Function"),
MAKEEXPORTGETSET(addr, "Address"),
{ NULL }
};
static PyTypeObject pepy_export_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"pepy.export", /* tp_name */
sizeof(pepy_export), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) pepy_export_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"pepy export object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
pepy_export_getseters, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) pepy_export_init, /* tp_init */
0, /* tp_alloc */
pepy_export_new /* tp_new */
};
static PyObject *pepy_section_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
pepy_section *self;
@ -63,7 +253,7 @@ static PyObject *pepy_section_new(PyTypeObject *type, PyObject *args, PyObject *
}
static int pepy_section_init(pepy_section *self, PyObject *args, PyObject *kwds) {
if (!PyArg_ParseTuple(args, "OOOOOOOO:pepy_section_init", &self->name, &self->base, &self->len, &self->virtaddr, &self->virtsize, &self->numrelocs, &self->numlinenums, &self->characteristics))
if (!PyArg_ParseTuple(args, "OOOOOOOO:pepy_section_init", &self->name, &self->base, &self->length, &self->virtaddr, &self->virtsize, &self->numrelocs, &self->numlinenums, &self->characteristics))
return -1;
return 0;
}
@ -71,7 +261,7 @@ static int pepy_section_init(pepy_section *self, PyObject *args, PyObject *kwds)
static void pepy_section_dealloc(pepy_section *self) {
Py_XDECREF(self->name);
Py_XDECREF(self->base);
Py_XDECREF(self->len);
Py_XDECREF(self->length);
Py_XDECREF(self->virtaddr);
Py_XDECREF(self->virtsize);
Py_XDECREF(self->numrelocs);
@ -88,18 +278,13 @@ static PyObject *pepy_section_get_##ATTR(PyObject *self, void *closure) { \
PEPY_SECTION_GET(name)
PEPY_SECTION_GET(base)
PEPY_SECTION_GET(len)
PEPY_SECTION_GET(length)
PEPY_SECTION_GET(virtaddr)
PEPY_SECTION_GET(virtsize)
PEPY_SECTION_GET(numrelocs)
PEPY_SECTION_GET(numlinenums)
PEPY_SECTION_GET(characteristics)
static int pepy_attr_not_writable(PyObject *self, PyObject *value, void *closure) {
PyErr_SetString(PyExc_TypeError, "Attribute not writable");
return -1;
}
#define MAKESECTIONGETSET(GS, DOC) \
{ (char *) #GS, (getter) pepy_section_get_##GS, \
(setter) pepy_attr_not_writable, \
@ -108,7 +293,7 @@ static int pepy_attr_not_writable(PyObject *self, PyObject *value, void *closure
static PyGetSetDef pepy_section_getseters[] = {
MAKESECTIONGETSET(name, "Name"),
MAKESECTIONGETSET(base, "Base address"),
MAKESECTIONGETSET(len, "Length"),
MAKESECTIONGETSET(length, "Length"),
MAKESECTIONGETSET(virtaddr, "Virtual address"),
MAKESECTIONGETSET(virtsize, "Virtual size"),
MAKESECTIONGETSET(numrelocs, "Number of relocations"),
@ -250,22 +435,23 @@ int section_callback(void *cbd, VA base, std::string &name, image_section_header
s.NumberOfRelocations, s.NumberOfLinenumbers,
s.Characteristics);
if (!tuple)
return 0;
return 1;
sect = pepy_section_new(&pepy_section_type, NULL, NULL);
if (!sect) {
Py_DECREF(tuple);
return 0;
return 1;
}
if (pepy_section_init((pepy_section *) sect, tuple, NULL) == -1) {
PyErr_SetString(pepy_error, "Unable to init new section");
return 0;
return 1;
}
if (PyList_Append(list, sect) == -1) {
Py_DECREF(tuple);
Py_DECREF(sect);
return 1;
}
return 0;
@ -278,7 +464,101 @@ static PyObject *pepy_parsed_get_sections(PyObject *self, PyObject *args) {
return NULL;
}
IterSec(((pepy_parsed *)self)->pe, section_callback, ret);
IterSec(((pepy_parsed *) self)->pe, section_callback, ret);
return ret;
}
int import_callback(void *cbd, VA addr, std::string &name, std::string &sym) {
PyObject *imp;
PyObject *tuple;
PyObject *list = (PyObject *) cbd;
/*
* The tuple item order is important here. It is passed into the
* import type initialization and parsed there.
*/
tuple = Py_BuildValue("ssI", name.c_str(), sym.c_str(), addr);
if (!tuple)
return 1;
imp = pepy_import_new(&pepy_import_type, NULL, NULL);
if (!imp) {
Py_DECREF(tuple);
return 1;
}
if (pepy_import_init((pepy_import *) imp, tuple, NULL) == -1) {
PyErr_SetString(pepy_error, "Unable to init new section");
return 1;
}
if (PyList_Append(list, imp) == -1) {
Py_DECREF(tuple);
Py_DECREF(imp);
return 1;
}
return 0;
}
static PyObject *pepy_parsed_get_imports(PyObject *self, PyObject *args) {
PyObject *ret = PyList_New(0);
if (!ret) {
PyErr_SetString(pepy_error, "Unable to create new list.");
return NULL;
}
IterImpVAString(((pepy_parsed *) self)->pe, import_callback, ret);
return ret;
}
int export_callback(void *cbd, VA addr, std::string &mod, std::string &func) {
PyObject *exp;
PyObject *tuple;
PyObject *list = (PyObject *) cbd;
/*
* The tuple item order is important here. It is passed into the
* export type initialization and parsed there.
*/
tuple = Py_BuildValue("ssI", mod.c_str(), func.c_str(), addr);
if (!tuple)
return 1;
exp = pepy_export_new(&pepy_export_type, NULL, NULL);
if (!exp) {
Py_DECREF(tuple);
return 1;
}
if (pepy_export_init((pepy_export *) exp, tuple, NULL) == -1) {
PyErr_SetString(pepy_error, "Unable to init new section");
return 1;
}
if (PyList_Append(list, exp) == -1) {
Py_DECREF(tuple);
Py_DECREF(exp);
return 1;
}
return 0;
}
static PyObject *pepy_parsed_get_exports(PyObject *self, PyObject *args) {
PyObject *ret = PyList_New(0);
if (!ret) {
PyErr_SetString(pepy_error, "Unable to create new list.");
return NULL;
}
/*
* This could use the same callback and object as imports but the names
* of the attributes would be slightly off.
*/
IterExpVA(((pepy_parsed *) self)->pe, export_callback, ret);
return ret;
}
@ -319,7 +599,11 @@ static PyMethodDef pepy_parsed_methods[] = {
{ "get_bytes", pepy_parsed_get_bytes, METH_VARARGS,
"Return the first N bytes at a given address." },
{ "get_sections", pepy_parsed_get_sections, METH_NOARGS,
"Return a list of dictionaries describing the sections." },
"Return a list of section objects." },
{ "get_imports", pepy_parsed_get_imports, METH_NOARGS,
"Return a list of import objects." },
{ "get_exports", pepy_parsed_get_exports, METH_NOARGS,
"Return a list of export objects." },
{ NULL }
};
@ -395,7 +679,10 @@ static PyMethodDef pepy_methods[] = {
PyMODINIT_FUNC initpepy(void) {
PyObject *m;
if (PyType_Ready(&pepy_parsed_type) < 0 || PyType_Ready(&pepy_section_type) < 0)
if (PyType_Ready(&pepy_parsed_type) < 0 ||
PyType_Ready(&pepy_section_type) < 0 ||
PyType_Ready(&pepy_import_type) < 0 ||
PyType_Ready(&pepy_export_type) < 0)
return;
m = Py_InitModule3("pepy", pepy_methods, "Python interface to pe-parse.");
@ -412,6 +699,12 @@ PyMODINIT_FUNC initpepy(void) {
Py_INCREF(&pepy_section_type);
PyModule_AddObject(m, "pepy_section", (PyObject *) &pepy_section_type);
Py_INCREF(&pepy_import_type);
PyModule_AddObject(m, "pepy_import", (PyObject *) &pepy_import_type);
Py_INCREF(&pepy_export_type);
PyModule_AddObject(m, "pepy_export", (PyObject *) &pepy_export_type);
PyModule_AddStringMacro(m, PEPY_VERSION);
PyModule_AddIntMacro(m, MZ_MAGIC);

@ -14,13 +14,22 @@ print "Number of symbols: %s" % p.numberofsymbols
print "Characteristics: %s" % hex(p.characteristics)
print "Timedatestamp: %s" % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(p.timedatestamp))
print "Bytes at 0x%x: %s" % (ep, byts)
print "Sections:"
for sect in p.get_sections():
sections = p.get_sections()
print "Sections: (%i)" % len(sections)
for sect in sections:
print "[+] %s" % sect.name
print "\tBase: %s" % hex(sect.base)
print "\tLength: %s" % sect.base
print "\tVirtual address: %s" % hex(sect.base)
print "\tVirtual size: %s" % sect.base
print "\tNumber of Relocations: %s" % sect.base
print "\tNumber of Line Numbers: %i" % sect.base
print "\tCharacteristics: %s" % hex(sect.base)
print "\tLength: %s" % sect.length
print "\tVirtual address: %s" % hex(sect.virtaddr)
print "\tVirtual size: %i" % sect.virtsize
print "\tNumber of Relocations: %i" % sect.numrelocs
print "\tNumber of Line Numbers: %i" % sect.numlinenums
print "\tCharacteristics: %s" % hex(sect.characteristics)
imports = p.get_imports()
print "Imports: (%i)" % len(imports)
for imp in imports:
print "[+] Symbol: %s (%s %s)" % (imp.sym, imp.name, hex(imp.addr))
exports = p.get_exports()
print "Exports: (%i)" % len(exports)
for exp in exports:
print "[+] Module: %s (%s %s)" % (exp.mod, exp.func, hex(exp.addr))