#ifndef __PY_IDA_BYTES__ #define __PY_IDA_BYTES__ // //------------------------------------------------------------------------ static bool idaapi py_testf_cb(flags_t flags, void *ud) { PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t py_flags(PyLong_FromUnsignedLong(flags)); newref_t result(PyObject_CallFunctionObjArgs((PyObject *) ud, py_flags.o, NULL)); return result != NULL && PyObject_IsTrue(result.o); } //------------------------------------------------------------------------ // Wraps the (next|prev)that() static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyCallable_Check(py_callable) ) return BADADDR; else return (next ? nextthat : prevthat)(ea, bound, py_testf_cb, py_callable); } //--------------------------------------------------------------------------- static int idaapi py_visit_patched_bytes_cb( ea_t ea, int32 fpos, uint32 o, uint32 v, void *ud) { PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t py_result( PyObject_CallFunction( (PyObject *)ud, PY_FMT64 "iII", pyul_t(ea), fpos, o, v)); PyW_ShowCbErr("visit_patched_bytes"); return (py_result != NULL && PyInt_Check(py_result.o)) ? PyInt_AsLong(py_result.o) : 0; } // //------------------------------------------------------------------------ // //------------------------------------------------------------------------ /* # def visit_patched_bytes(ea1, ea2, callable): """ Enumerates patched bytes in the given range and invokes a callable @param ea1: start address @param ea2: end address @param callable: a Python callable with the following prototype: callable(ea, fpos, org_val, patch_val). If the callable returns non-zero then that value will be returned to the caller and the enumeration will be interrupted. @return: Zero if the enumeration was successful or the return value of the callback if enumeration was interrupted. """ pass # */ static int py_visit_patched_bytes(ea_t ea1, ea_t ea2, PyObject *py_callable) { PYW_GIL_CHECK_LOCKED_SCOPE(); if ( !PyCallable_Check(py_callable) ) return 0; else return visit_patched_bytes(ea1, ea2, py_visit_patched_bytes_cb, py_callable); } //------------------------------------------------------------------------ /* # def nextthat(ea, maxea, callable): """ Find next address with a flag satisfying the function 'testf'. Start searching from address 'ea'+1 and inspect bytes up to 'maxea'. maxea is not included in the search range. @param callable: a Python callable with the following prototype: callable(flags). Return True to stop enumeration. @return: the found address or BADADDR. """ pass # */ static ea_t py_nextthat(ea_t ea, ea_t maxea, PyObject *callable) { return py_npthat(ea, maxea, callable, true); } //--------------------------------------------------------------------------- static ea_t py_prevthat(ea_t ea, ea_t minea, PyObject *callable) { return py_npthat(ea, minea, callable, false); } //------------------------------------------------------------------------ /* # def get_many_bytes(ea, size): """ Get the specified number of bytes of the program into the buffer. @param ea: program address @param size: number of bytes to return @return: None or the string buffer """ pass # */ static PyObject *py_get_many_bytes(ea_t ea, unsigned int size) { PYW_GIL_CHECK_LOCKED_SCOPE(); do { if ( size <= 0 ) break; // Allocate memory via Python newref_t py_buf(PyString_FromStringAndSize(NULL, Py_ssize_t(size))); if ( py_buf == NULL ) break; // Read bytes if ( !get_many_bytes(ea, PyString_AsString(py_buf.o), size) ) Py_RETURN_NONE; py_buf.incref(); return py_buf.o; } while ( false ); Py_RETURN_NONE; } //--------------------------------------------------------------------------- /* # # Conversion options for get_ascii_contents2(): ACFOPT_ASCII = 0x00000000 # convert Unicode strings to ASCII ACFOPT_UTF16 = 0x00000001 # return UTF-16 (aka wide-char) array for Unicode strings # ignored for non-Unicode strings ACFOPT_UTF8 = 0x00000002 # convert Unicode strings to UTF-8 # ignored for non-Unicode strings ACFOPT_CONVMASK = 0x0000000F ACFOPT_ESCAPE = 0x00000010 # for ACFOPT_ASCII, convert non-printable # characters to C escapes (\n, \xNN, \uNNNN) def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII): """ Get contents of ascii string This function returns the displayed part of the string It works even if the string has not been created in the database yet. @param ea: linear address of the string @param len: length of the string in bytes (including terminating 0) @param type: type of the string @param flags: combination of ACFOPT_... @return: string contents (not including terminating 0) or None """ pass # */ static PyObject *py_get_ascii_contents2( ea_t ea, size_t len, int32 type, int flags = ACFOPT_ASCII) { char *buf = (char *)qalloc(len+1); if ( buf == NULL ) return NULL; size_t used_size; if ( !get_ascii_contents2(ea, len, type, buf, len+1, &used_size) ) { qfree(buf); Py_RETURN_NONE; } if ( type == ASCSTR_C && used_size > 0 && buf[used_size-1] == '\0' ) used_size--; PYW_GIL_CHECK_LOCKED_SCOPE(); newref_t py_buf(PyString_FromStringAndSize((const char *)buf, used_size)); qfree(buf); py_buf.incref(); return py_buf.o; } //--------------------------------------------------------------------------- /* # def get_ascii_contents(ea, len, type): """ Get contents of ascii string This function returns the displayed part of the string It works even if the string has not been created in the database yet. @param ea: linear address of the string @param len: length of the string in bytes (including terminating 0) @param type: type of the string @return: string contents (not including terminating 0) or None """ pass # */ static PyObject *py_get_ascii_contents( ea_t ea, size_t len, int32 type) { return py_get_ascii_contents2(ea, len, type); } // #endif