mirror of
https://github.com/cemu-project/idapython.git
synced 2024-12-26 17:51:54 +01:00
IDAPython 1.5.1
- Introduced the CLI '?' pseudo-command to retrieve doc strings - Introduced the CLI '!' pseudo-command to shell execute a command - Added IDP/assemble notification event - bugfix: High 64 bit addresses were not parsed correctly in IDA64 - bugfix: AskUsingForm() C function was not wrapped by SWIG - NextHead()/PrevHead() have optional 2nd parameter now
This commit is contained in:
parent
58a002ce5b
commit
8375368d6d
10
CHANGES.txt
10
CHANGES.txt
@ -1,6 +1,15 @@
|
||||
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
|
||||
|
||||
|
||||
Changes from version 1.5.0 to 1.5.1
|
||||
------------------------------------
|
||||
- Introduced the CLI '?' pseudo-command to retrieve doc strings
|
||||
- Introduced the CLI '!' pseudo-command to shell execute a command
|
||||
- bugfix: High 64 bit addresses were not parsed correctly in IDA64
|
||||
- Added IDP/assemble notification event
|
||||
- bugfix: AskUsingForm() C function was not wrapped by SWIG
|
||||
- NextHead()/PrevHead() have optional 2nd parameter now
|
||||
|
||||
Changes from version 1.4.3 to 1.5.0
|
||||
------------------------------------
|
||||
- IDA Pro 6.1 support
|
||||
@ -17,6 +26,7 @@ Changes from version 1.4.3 to 1.5.0
|
||||
- bugfix: processor_t.id constants were incorrect
|
||||
- bugfix: get_debug_names() was broken with IDA64
|
||||
- Various bugfixes
|
||||
- Added Scripts folder containing various IDAPython scripts
|
||||
|
||||
Changes from version 1.4.2 to 1.4.3
|
||||
------------------------------------
|
||||
|
2
build.py
2
build.py
@ -36,7 +36,7 @@ else:
|
||||
# IDAPython version
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 5
|
||||
VERSION_PATCH = 0
|
||||
VERSION_PATCH = 1
|
||||
|
||||
# Determine Python version
|
||||
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
|
||||
|
@ -118,8 +118,8 @@ The end!
|
||||
def OnFormChange(self, fid):
|
||||
if fid == self.iButton1.id:
|
||||
print("Button1 fchg;inv=%s" % self.invert)
|
||||
self.SetFocusedField(self.rNormal.id)
|
||||
self.EnableField(self.rError.id, self.invert)
|
||||
self.SetFocusedField(self.rNormal)
|
||||
self.EnableField(self.rError, self.invert)
|
||||
self.invert = not self.invert
|
||||
elif fid == self.iButton2.id:
|
||||
g1 = self.GetControlValue(self.cGroup1)
|
||||
@ -134,6 +134,8 @@ The end!
|
||||
print(">>fid:%d" % fid)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def stdalone_main():
|
||||
f = MyForm()
|
||||
@ -165,7 +167,8 @@ def ida_main():
|
||||
f.rWarnings.checked = True
|
||||
f.rGreen.selected = True
|
||||
f.iStr1.value = "Hello"
|
||||
|
||||
f.iFileSave.value = "*.*"
|
||||
f.iFileOpen.value = "*.*"
|
||||
# Execute the form
|
||||
ok = f.Execute()
|
||||
print("r=%d" % ok)
|
||||
@ -188,6 +191,7 @@ def ida_main():
|
||||
print("No selection")
|
||||
else:
|
||||
print("Selection: %s" % sel)
|
||||
|
||||
# Dispose the form
|
||||
f.Free()
|
||||
|
||||
|
18
python.cpp
18
python.cpp
@ -1139,6 +1139,24 @@ bool idaapi IDAPython_cli_execute_line(const char *line)
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Pseudo commands
|
||||
//
|
||||
qstring s;
|
||||
do
|
||||
{
|
||||
// Help command?
|
||||
if ( line[0] == '?' )
|
||||
s.sprnt("help(%s)", line+1);
|
||||
// Shell command?
|
||||
else if ( line[0] == '!' )
|
||||
s.sprnt("idaapi.IDAPython_ExecSystem(r'%s')", line+1);
|
||||
else
|
||||
break;
|
||||
// Patch the command line pointer
|
||||
line = s.c_str();
|
||||
} while (false);
|
||||
|
||||
begin_execution();
|
||||
PythonEvalOrExec(line);
|
||||
end_execution();
|
||||
|
@ -1644,12 +1644,9 @@ def GetInputMD5():
|
||||
|
||||
@return: MD5 string or None on error
|
||||
"""
|
||||
ua=idaapi.uchar_array(16)
|
||||
ua = idaapi.uchar_array(16)
|
||||
if idaapi.retrieve_input_file_md5(ua.cast()):
|
||||
md5str=""
|
||||
for i in range(16):
|
||||
md5str += "%02x" % ua[i]
|
||||
return md5str
|
||||
return "".join(["%02X" % ua[i] for i in xrange(16)])
|
||||
else:
|
||||
return None
|
||||
|
||||
|
@ -2072,6 +2072,21 @@ def struct_unpack(buffer, signed = False, offs = 0):
|
||||
# Unpack
|
||||
return struct.unpack_from(__struct_unpack_table[n][signed], buffer, offs)[0]
|
||||
|
||||
|
||||
# ------------------------------------------------------------
|
||||
def IDAPython_ExecSystem(cmd):
|
||||
"""
|
||||
Executes a command with popen().
|
||||
"""
|
||||
try:
|
||||
f = os.popen(cmd, "r")
|
||||
s = ''.join(f.readlines())
|
||||
f.close()
|
||||
return s
|
||||
except Exception, e:
|
||||
return str(e)
|
||||
|
||||
|
||||
# ------------------------------------------------------------
|
||||
def IDAPython_ExecScript(script, g):
|
||||
"""
|
||||
@ -2175,10 +2190,10 @@ class __IDAPython_Completion_Util(object):
|
||||
s = self.completion[n]
|
||||
try:
|
||||
attr = getattr(self.lastmodule, s)
|
||||
# is it callable?
|
||||
# Is it callable?
|
||||
if callable(attr):
|
||||
return s + "("
|
||||
# is it iterable?
|
||||
return s + ("" if line.startswith("?") else "(")
|
||||
# Is it iterable?
|
||||
elif isinstance(attr, basestring) or getattr(attr, '__iter__', False):
|
||||
return s + "["
|
||||
except:
|
||||
|
106
swig/idp.i
106
swig/idp.i
@ -65,7 +65,12 @@ def AssembleLine(ea, cs, ip, use32, line):
|
||||
pass
|
||||
#</pydoc>
|
||||
*/
|
||||
static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
|
||||
static PyObject *AssembleLine(
|
||||
ea_t ea,
|
||||
ea_t cs,
|
||||
ea_t ip,
|
||||
bool use32,
|
||||
const char *line)
|
||||
{
|
||||
int inslen;
|
||||
char buf[MAXSTR];
|
||||
@ -93,7 +98,12 @@ def assemble(ea, cs, ip, use32, line):
|
||||
"""
|
||||
#</pydoc>
|
||||
*/
|
||||
bool assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
|
||||
bool assemble(
|
||||
ea_t ea,
|
||||
ea_t cs,
|
||||
ea_t ip,
|
||||
bool use32,
|
||||
const char *line)
|
||||
{
|
||||
int inslen;
|
||||
char buf[MAXSTR];
|
||||
@ -391,6 +401,7 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def unhook(self):
|
||||
"""
|
||||
Removes the IDP hook
|
||||
@ -398,6 +409,7 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def custom_ana(self):
|
||||
"""
|
||||
Analyzes and decodes an instruction at idaapi.cmd.ea
|
||||
@ -410,6 +422,7 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def custom_out(self):
|
||||
"""
|
||||
Outputs the instruction defined in idaapi.cmd
|
||||
@ -418,6 +431,7 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def custom_emu(self):
|
||||
"""
|
||||
Emulate instruction, create cross-references, plan to analyze
|
||||
@ -428,6 +442,7 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def custom_outop(self, op):
|
||||
"""
|
||||
Notification to generate operand text.
|
||||
@ -438,6 +453,7 @@ class IDP_Hooks(object):
|
||||
|
||||
@return: Boolean (whether the operand has been outputted or not)
|
||||
"""
|
||||
pass
|
||||
|
||||
def custom_mnem(self):
|
||||
"""
|
||||
@ -447,6 +463,8 @@ class IDP_Hooks(object):
|
||||
- None: No mnemonic. IDA will use the default mnemonic value if present
|
||||
- String: The desired mnemonic string
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def is_sane_insn(self, no_crefs):
|
||||
"""
|
||||
@ -463,6 +481,7 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def may_be_func(self, no_crefs):
|
||||
"""
|
||||
Can a function start here?
|
||||
@ -474,18 +493,21 @@ class IDP_Hooks(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def closebase(self):
|
||||
"""
|
||||
The database will be closed now
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def savebase(self):
|
||||
"""
|
||||
The database is being saved. Processor module should
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def rename(self, ea, new_name):
|
||||
"""
|
||||
The kernel is going to rename a byte.
|
||||
@ -497,6 +519,8 @@ class IDP_Hooks(object):
|
||||
- If returns value <=0, then the kernel should
|
||||
not rename it. See also the 'renamed' event
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def renamed(self, ea, new_name, local_name):
|
||||
"""
|
||||
@ -508,6 +532,8 @@ class IDP_Hooks(object):
|
||||
|
||||
@return: Ignored
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def undefine(self, ea):
|
||||
"""
|
||||
@ -519,6 +545,8 @@ class IDP_Hooks(object):
|
||||
bit0 - ignored
|
||||
bit1 - do not delete srareas at the item end
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def make_code(self, ea, size):
|
||||
"""
|
||||
@ -527,6 +555,8 @@ class IDP_Hooks(object):
|
||||
@param size: Instruction size
|
||||
@return: 1-ok, <=0-the kernel should stop
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def make_code(self, ea, size):
|
||||
"""
|
||||
@ -535,7 +565,9 @@ class IDP_Hooks(object):
|
||||
@param size: Instruction size
|
||||
@return: 1-ok, <=0-the kernel should stop
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def make_data(self, ea, flags, tid, len):
|
||||
"""
|
||||
A data item is being created
|
||||
@ -545,14 +577,18 @@ class IDP_Hooks(object):
|
||||
@param len: data item size
|
||||
@return: 1-ok, <=0-the kernel should stop
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def load_idasgn(self, short_sig_name):
|
||||
"""
|
||||
FLIRT signature have been loaded for normal processing
|
||||
FLIRT signature have been loaded for normal processing
|
||||
(not for recognition of startup sequences)
|
||||
@param short_sig_name: signature name
|
||||
@return: Ignored
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def add_func(self, func):
|
||||
"""
|
||||
@ -560,6 +596,8 @@ class IDP_Hooks(object):
|
||||
@param func: the func_t instance
|
||||
@return: Ignored
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def del_func(self, func):
|
||||
"""
|
||||
@ -567,6 +605,8 @@ class IDP_Hooks(object):
|
||||
@param func: the func_t instance
|
||||
@return: 1-ok,<=0-do not delete
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def is_call_insn(self, ea, func_name):
|
||||
"""
|
||||
@ -575,6 +615,8 @@ class IDP_Hooks(object):
|
||||
@param ea: instruction address
|
||||
@return: 1-unknown, 0-no, 2-yes
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def is_ret_insn(self, ea, func_name):
|
||||
"""
|
||||
@ -585,6 +627,23 @@ class IDP_Hooks(object):
|
||||
False: include instructions like "leave" which begins the function epilog
|
||||
@return: 1-unknown, 0-no, 2-yes
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def assemble(self, ea, cs, ip, use32, line):
|
||||
"""
|
||||
Assembles an instruction
|
||||
|
||||
@param ea: linear address of instruction
|
||||
@param cs: cs of instruction
|
||||
@param ip: ip of instruction
|
||||
@param use32: is 32bit segment?
|
||||
@param line: line to assemble
|
||||
|
||||
@return: - None to let the underlying processor module assemble the line
|
||||
- or a string containing the assembled buffer
|
||||
"""
|
||||
pass
|
||||
|
||||
#</pydoc>
|
||||
*/
|
||||
@ -700,6 +759,15 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual PyObject *assemble(
|
||||
ea_t ea,
|
||||
ea_t cs,
|
||||
ea_t ip,
|
||||
bool use32,
|
||||
const char *line)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@ -912,8 +980,36 @@ int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
|
||||
ret = proxy->is_ret_insn(ea, strict);
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::assemble:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
ea_t cs = va_arg(va, ea_t);
|
||||
ea_t ip = va_arg(va, ea_t);
|
||||
bool use32 = va_argi(va, bool);
|
||||
const char *line = va_arg(va, const char *);
|
||||
// Extract user buffer (we hardcode the MAXSTR size limit)
|
||||
uchar *bin = va_arg(va, uchar *);
|
||||
// Call python
|
||||
PyObject *py_buffer = proxy->assemble(ea, cs, ip, use32, line);
|
||||
if ( py_buffer != NULL && PyString_Check(py_buffer) )
|
||||
{
|
||||
char *s;
|
||||
Py_ssize_t len;
|
||||
if ( PyString_AsStringAndSize(py_buffer, &s, &len) != -1 )
|
||||
{
|
||||
if ( len > MAXSTR )
|
||||
len = MAXSTR;
|
||||
memcpy(bin, s, len);
|
||||
ret = len;
|
||||
}
|
||||
}
|
||||
// ret = 0 otherwise
|
||||
Py_XDECREF(py_buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Swig::DirectorException &)
|
||||
{
|
||||
msg("Exception in IDP Hook function:\n");
|
||||
|
@ -700,6 +700,12 @@ static bool formchgcbfa_set_field_value(
|
||||
}
|
||||
|
||||
#undef DECLARE_FORM_ACTIONS
|
||||
|
||||
static size_t py_get_AskUsingForm()
|
||||
{
|
||||
return (size_t)AskUsingForm_c;
|
||||
}
|
||||
|
||||
//</inline(py_kernwin)>
|
||||
%}
|
||||
|
||||
@ -1681,10 +1687,6 @@ PyObject *choose2_find(const char *title)
|
||||
}
|
||||
|
||||
|
||||
static size_t py_get_AskUsingForm()
|
||||
{
|
||||
return (size_t)AskUsingForm_c;
|
||||
}
|
||||
//</code(py_kernwin)>
|
||||
|
||||
%}
|
||||
@ -3409,7 +3411,7 @@ class Choose2(object):
|
||||
# Disable the timeout
|
||||
old = idaapi.set_script_timeout(0)
|
||||
n = _idaapi.choose2_create(self, False)
|
||||
idaapi.set_script_timeout(old)
|
||||
_idaapi.set_script_timeout(old)
|
||||
|
||||
# Delete the modal chooser instance
|
||||
self.Close()
|
||||
@ -3729,7 +3731,7 @@ class Form(object):
|
||||
"""
|
||||
Free the control
|
||||
"""
|
||||
# Release parent form reference
|
||||
# Release the parent form reference
|
||||
self.form = None
|
||||
|
||||
|
||||
@ -4201,7 +4203,9 @@ class Form(object):
|
||||
"""
|
||||
self._reset()
|
||||
self.form = form
|
||||
"""Form string"""
|
||||
self.controls = controls
|
||||
"""Dictionary of controls"""
|
||||
self.__args = None
|
||||
|
||||
self.title = None
|
||||
@ -4215,6 +4219,7 @@ class Form(object):
|
||||
"""
|
||||
for ctrl in self.__controls.values():
|
||||
ctrl.free()
|
||||
|
||||
# Reset the controls
|
||||
# (Note that we are not removing the form control attributes, no need)
|
||||
self._reset()
|
||||
@ -4444,12 +4449,21 @@ class Form(object):
|
||||
return (self, self.__args)
|
||||
|
||||
|
||||
def Compiled(self):
|
||||
"""
|
||||
Checks if the form has already been compiled
|
||||
|
||||
@return: Boolean
|
||||
"""
|
||||
return self.__args is not None
|
||||
|
||||
|
||||
def Execute(self):
|
||||
"""
|
||||
Displays a compiled form.
|
||||
@return: 1 - ok ; 0 - cancel
|
||||
"""
|
||||
if self.__args is None:
|
||||
if not self.Compiled():
|
||||
raise SyntaxError("Form is not compiled")
|
||||
|
||||
# Call AskUsingForm()
|
||||
|
Loading…
Reference in New Issue
Block a user