Plugin assists in creation classes/structures and detection virtual tables. Best to use with Class Informer plugin, because it helps to automatically get original classes names. Also see slides from ZeroNights 2016.
Just copy HexRaysPyTools.py
file and HexRaysPyTools
directory to Ida plugins directory
Shows relationship between structures.
Also: dark green node is union, light green - enum.
Usage:
- Open Local Types
- Select interesting structures and right click -> "Show Graph" (Hotkey G)
- Plugin creates a graph of all structures that have relationship with selected items.
- Double clicking on node recalculates graph for it
- Every node have a hint message that shows C-like typedef
Usage:
- In Pseudocode viewer ight click on number -> "Structures with this size". (hotkey W)
- Select library in which find structures
- Select structure. Number will become
sizeof(Structure Name)
and type will be imported to Local Types
Helps to find suitable structure by information gleaned from pseudocode after variable scanning.
Usage:
- Method 1
- Right click on variable with LEGAL_TYPE (See structure builder) -> Select "Recognize Shape".
- Select structure.
- Type of variable will be changed automatically.
- Method 2
- Clear Structure Builder if it's currently used.
- Right click on variables supposed to be the same -> "Scan Variable".
- Edit types (will be implemented later), disable or remove uninteresting fields and click button "Recognize Shape".
- You can selected several fields and try to recognize shape for them. If found and selected, they will be replaced by new structure.
- After final structure selection, types of all scanned variables will be changed automatically.
Helps to find containing structure and makes code look pretty by replacing pointers with CONTAINING_RECORD macro
Before:
After:
Usage:
If variable is a structure pointer and is used to address outside of its boundaries than:
- Right click -> Select Containing Structure
- Select Type Library
- Select appropriate Structure and Offset
- If result is disappointing then Right Click -> Reset Containing Structure and go to step 1
The place where all collected information about scanned variables can be viewed and modified
Two ways to collect information:
- Right Click on variable -> Scan Variable. Recognizes fields usage in current function
- Right Click on variable -> Deep Scan Variable. First recursively touches functions to make Ida recognize proper arguments (this happens only once for each function during session). Than recursively applies scanner to variables and functions that get our structure pointer as argument.
- Types with BOLD font are virtual tables. Double click opens list with all virtual functions that helps to visit them. Visited functions are marked with cross and color.
-
Types with ITALIC font have been found as
void *
arguments and are not used in shape recognition. -
Double click on Field's names to edit
-
Double click on offset opens window with every places where this type has been extracted. Click "Ok" button to open selected place in pseudocode window.
Finalize - opens window with editable C-like declaration and assigns new type to all scanned variables.
Disable, Enable - are used for collision resolution.
Origin - switches base from which offset to produce new fields to structure (this value will be added to every offset of new scanned variable).
Array - makes selected field as array, the size of which is calculated automatically.
Pack - creates and substitutes substructure for selected items (collisions for this items should be resolved).
Remove - removes information about selected fields.
Clear - clears everything.
Scanned Variables - do nothing.
Recognize Shape - looks for appropriate structure for selected fields.
LEGAL_TYPES = { DWORD, QWORD, DWORD *, QWORD *, void * } - if variable's type is one of this types or is derivate from them, then it can be scanned by Right-Click-> Scan Variable.
Abbreviations:
- var - variable
- obj - any object, including Virtual Table, that will be handled specially
- x - offset
- TYPE - simple (char, byte, float, ...) or complicated type not from LEGAL_TYPES
- XWORD - DWORD or QWORD
- PXWORD - DWORD * or QWORD *
- PVOID - void *, PVOID
Variable type | Situation | Type | Offset |
---|---|---|---|
XWORD |
*(XWORD *) (var + x) = obj |
typeof(obj) * |
x |
XWORD |
*(XWORD *) (var + x) = &obj |
typeof(obj) * |
x |
XWORD |
*(TYPE *) (var + x) |
TYPE |
x |
XWORD |
function(... , (LEGAL_TYPE) (var + x), ...) |
BYTE[] and recursion started for this function and argument index | x |
XWORD |
function(... , (TYPE) (var + x), ...) |
argument's type | x |
XWORD |
function(... , var + x, ...) |
argument's type | x |
XWORD * , PVOID |
*var = obj |
typeof(obj) * |
0 |
XWORD * , PVOID |
*var = &obj |
typeof(obj) * |
0 |
XWORD * , PVOID |
*var = ??? |
XWORD |
0 |
XWORD * |
var[idx] = obj |
typeof(obj) * |
idx * sizeof(XWORD) |
XWORD * |
var[idx] = &obj |
typeof(obj) * |
idx * sizeof(XWORD) |
XWORD * |
var[idx] = ??? |
XWORD |
idx * sizeof(XWORD) |
XWORD * , PVOID |
*((TYPE *) var + x) |
TYPE |
x * sizeof(TYPE) |
XWORD * , PVOID |
function(... , (LEGAL_TYPE) (var + x), ...) |
BYTE[] and recursion started for this function and argument index | x * sizeof(XWORD) |
XWORD * , PVOID |
function(... , (TYPE) (var + x), ...) |
argument's type | x * sizeof(XWORD) |
PVOID |
function(... , (TYPE *)var + x, ...) |
argument's type | x * sizeof(TYPE) |
PVOID |
function(... , (TYPE)var + x, ...) |
argument's type | x |
PVOID |
(TYPE *) ((char *)var + x) |
TYPE | x |
Also can be found at View->Open Subview->Classes. Helps to manage classes (structures with virtual tables).
!! Better to rename all functions before debugging because Ida can mess up with default names and information in virtual tables will be inconsistent
Class, virtual table and functions names are editable. Also function's declaration can be edited. After edit, altered items change font to italic. Right click opens following menu options:
- Expand All / Collapse All
- Refresh - clear all and rescan local types for information again
- Rollback - undo changes
- Commit - apply changes. Functions will be renamed and recasted both in virtual tables in Local Types and disassembly code.
- Set First Argument type - allows selecting first argument for function among all classes. If right click was used on class name, than its type will be automatically applied to virtual table at offset 0
You can also filter classes using Regexp either by class_name or by existence of specific functions. Just input expression in line edit for filtering by class_name or prepend it with "!" to filter by function name.
- Right click on first line -> "Remove Return" converts return type to void
- Right click on argument -> "Remove Argument" disposes of this argument
- Right click on convention -> "Convert to __usercall" switches to __usercall or __userpurge (same as __usercall but the callee cleans the stack)
Expressions from the table can be quickly modified. Select cast item or variable and press hotkey or select from Right-Click Menu Recast Variable, Return or Argument. It can be applied to both local and global variables.
Original | Shift+L | Shift+R |
---|---|---|
var = (TYPE) expr | var type -> TYPE | |
exp = (TYPE) var | var type -> TYPE | |
function(..., (TYPE) var, ...) | functions' argument -> TYPE | var type -> TYPE |
(TYPE) function(...) | functions' return type -> TYPE | |
return (TYPE) var | functions' return type -> TYPE | var type -> TYPE |
struct.field = (TYPE) var | type(field) -> TYPE | |
pstruct->field = (TYPE) var | type(field) -> TYPE |
When you have an expression like function(..., some_good_name, ...)
, you can rename function argument.
When you have an expression like function(..., v12, ...)
and function has a nice name of the argument. You can quickly apply this name to the variable.
Automatically applies following transformations:
Before:
...
if (condition) {
statement_1;
statement_2;
...
return another_value;
}
return value;
After:
...
if (opposite_condition) {
return value;
}
statement_1;
statement_2;
...
return another_value; // if 'then' branch have no return, than `return value;`