Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
There are two kinds of variables in IDC:
A variable can contain:
LONG: a 32-bit signed long integer (64-bit in 64-bit version of IDA)
INT64: a 64-bit signed long integer
STR: a character string
FLOAT: a floating point number (extra precision, up to 25 decimal digits)
OBJECT: an object with attributes and methods (a concept very close to C++ class) more
REF: a reference to another variable
FUNC: a function reference
A local variable is declared this way:
Global variables are declared like this:
Global variables can be redefined many times. IDA will silently ignore subsequent declarations. Please note that global variables cannot be initialized at the declaration time.
All C and C++ keywords are reserved and cannot be used as a variable name.
While it is possible to declare a variable anywhere in the function body, all variables are initialized at the function entry and all of them are destroyed only at the exit. So, a variable declared in a loop body will not be reinitialized at each loop iteration, unless explicitly specified with an assignment operator.
If a variable or function name cannot be recognized, IDA tries to resolve them using the names from the disassembled application. In it succeeds, the name is replaced by its value in the disassembly listing. For example:
will print 413060. If the label denotes a structure, it is possible to refer to its fields:
will print 413064. Please note that IDA does not try to read the data but just returns the address of the structure field. The field address can also be calculated using the get_field_ea function.
NOTE: The processor register names can be used in the IDC scripts when the debugger is active. Reading from such a variable return the corresponding register value. Writing to such a variable modifies the register value in the debugged process. Such variables are accessible only when the application is in the suspended mode.
NOTE: another way to emulate global scope variables is to use array functions and create global persistent arrays.
In IDC there are the following statements: expression; (expression-statement) if (expression) statement if (expression) statement else statement for ( expr1; expr2; expr3 ) statement while (expression) statement do statement while (expression); break; continue; return <expr>; return; the same as 'return 0;' { statements... } try statement catch ( var ) statement throw <expr>; ; (empty statement) Please note that the 'switch' statement is not supported.
IDC language is a C-like language. It has the same lexical tokens as C does: character set, constants, identifiers, keywords, etc. However, since it is a scripting language, there are no pointers, and all variable types can be handled by the interpreter. Any variable may hold any value; variables are declared without specifying their type;
auto myvar;
An IDC program consists of function declarations. By default, execution starts from a function named 'main'.
Select a topic to read:
Classes can be declared the following way:
Inside the class, method functions are declared without the 'static' keyword. The method with the name of the class is the class constructor. For example:
Inside the class methods, the 'this' variable can be used to refer to the current object.
Only one constructor per class is allowed.
Class instances are created like this:
And object attributes (or fields) are accessed like this:
A new attribute is created upon assigning to it:
Accessing an unexisting attribute generates an exception, which can be caught.
The following special method names exist:
Simple class inheritance is support. Derived classed are declared like this:
Here we declare the 'derived' class that is derived from the 'base' class. For derived classes, the base class constructor can be called explicitly:
If the base class constructor is not called explicitly, IDA will call it implicitly, without any arguments.
It is possible to call base class methods using full names:
The 'this' argument must be passed explicitly in this case.
When there are no more references to an object, it is automatically destroyed. We use a simple reference count algorithm to track the object use. Circularly dependent objects are not detected: they are never destroyed.
The following built-in object classes exist:
Human readable form of the typeinfo can be obtained by calling the print() method. The type size can be calculated using the size() method.
loader_input_t: class to read files.
The following symbols are predefined in the IDC preprocessor:
These symbols are also defined when parsing C header files.
In the IDC expressions you can use almost all C operations except:
Constants are defined more or less like in C, with some minor differences.
There are four type conversion operations:
However, explicit type conversions are rarely required because all type conversions are made automatically:
If any of the long operands is 64bit, the other operand is converted to 64bit too.
There is one notable exception concerning type conversions: if one operand is a string and the other is zero (0), then a string operation is performed. Zero is converted to an empty string in this case.
The & operator is used to take a reference to a variable. References themselves cannot be modified once created. Any assignment to them will modify the target variable. For example:
References to references are immediately resolved:
Since all non-object arguments are passed to functions by value, references are a good way to pass arguments by reference.
Any runtime error generates an exception. Exceptions terminate the execution. It is possible to catch an exception instead of terminating the execution: auto e; try { ... some statements that cause a runtime error... } catch ( e ) { // e holds the exception information // it is an instance of the exception class } The try/catch blocks can be nested. If the current function has no try/catch blocks, the calling function will be examined, and so on, until we find a try/catch block or exit the main function. If no try/catch block is found, an unhandled exception is reported.
It is also possible to throw an exception explicitly. Any object can be thrown. For example:
will throw value '5'.
An IDC function always returns a value. There are 2 kinds of functions:
built-in functions
user-defined functions A user-defined function is declared this way: static func(arg1,arg2,arg3) { statements ... } It is not necessary to specify the parameter types because all necessary type conversions are performed automatically.
By default all function arguments are passed by value, except:
If the function to call does not exist, IDA tries to resolve the name using the debugged program labels. If it succeeds, an dbg_appcall is performed.
The following constants can be used in IDC:
The loader_input_t class can read from input files. It has the following methods:
Instances of this class can be created by calling the open_loader_input function.
See other IDC classes.
The slice operator can be applied IDC objects are strings.
For strings, the slice operator denotes a substring:
Any indexes that are out of bounds are silently adjusted to correct values. If i1 >= i2, empty string is returned. Negative indexes are used to denote positions counting from the end of the string.
String slices can be used on the right side of an assignment. For example:
will replace 2 characters at the beginning of the string by "abc".
For objects, the slice operator denotes a subset of attributes. It can be used to emulate arrays:
x[i1:i2] denotes all attributes with numeric values between i1 and i2 (i2 is excluded).
Any non-numeric attributes are ignored by the slice operator.