ida-IDC脚本剖析
IDC
IDA中支持進行腳本運行,可以通過編寫腳本通過腳本對文件進行處理,甚至可以通過編寫IDC腳本編寫自動化漏洞審計的腳本。
IDC是ida中支持的一門與C語言類似的語言,但是它是解釋型的,并不是編譯型的,于此同時IDC還融合了一些python中的元素以方便一些內容的處理。
執行腳本
執行IDC腳本一共有三種方式
- idc命令行(菜單欄file->idc command)
- 腳本文件 (菜單欄file->script file)
- python命令行(菜單欄file->python command)
ida語言基礎
注釋
idc中使用C++風格的“//”進行單行注釋;
采用c風格的“/* */”進行多行注釋。
幫助系統
ida為用戶提供了一個很完備的幫助系統,可以使用F1快捷鍵打開幫助系統,其中點擊“index of idc functions”可以看到對應一些idc的函數列表。
idc變量
idc在一個語句中可以生命多個變量,但是idc不支持c語言風格的數組、指針、結構體、聯合等復雜的數據結構。
idc是一種松散的語言,變量沒有明確的類型,其主要使用三種數據類型:整形(long)、字符串型、浮點值。
idc支持全局變量和局部變量:
There are two kinds of variables in IDC:
- local variables: they are created at the function entryand destroyed at the exit- global variables: they are created at the compilation timeand destroyed when the database is closedA 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 referenceA local variable is declared this way:
auto var1;auto var2 = <expr>;Global variables are declared like this:
extern var;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:
.data:00413060 errtable dd 1 ; oscode.data:00413060 dd 16h ; errnocodemsg("address is: %x\n", _errtable);will print 413060. If the label denotes a structure, it is possible to refer to its fields:
msg("address is: %x\n", _errtable.errnocode);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.
idc函數
idc中也可以自定義函數,其聲明方式為:
static func(arg1,arg2,arg3){statements ...}用戶定義函數不需要進行指定特定的參數類型,因為在需要的時候程序會自動進行轉化。如果需要函數返回指定的值需要使用return進行指定,否則默認不顯示返回一個值的函數都將返回零值。
An IDC function always returns a value. There are 2 kinds of functions:
- built-in functions- user-defined functionsA 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:
- objects are always passed by reference- functions are always passed by reference- it is possible to pass a variable by reference using the & operatorIf 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.
idc語句
idc中支持C中的語句,除了switch。
expression; (expression-statement)if (expression) statementif (expression) statement else statementfor ( expr1; expr2; expr3 ) statementwhile (expression) statementdo statement while (expression);break;continue;return <expr>;return; the same as 'return 0;'{ statements... }try statement catch ( var ) statementthrow <expr>;; (empty statement)In IDC there are the following statements:
expression; (expression-statement)if (expression) statementif (expression) statement else statementfor ( expr1; expr2; expr3 ) statementwhile (expression) statementdo statement while (expression);break;continue;return <expr>;return; the same as 'return 0;'{ statements... }try statement catch ( var ) statementthrow <expr>;; (empty statement)Please note that the ‘switch’ statement is not supported.
idc表達式
idc幾乎都能支持C語言中的操作運算表達(加減乘除、判等家族),但是明確說明不支持+=。
在進行操作運算的時候,只有操作中存在64bit的操作,那么其他操作也會編程64bit的。
IDC: Expressions
In the IDC expressions you can use almost all C operations except:
complex assignment operations as '+='Constants are defined more or less like in C, with some minor differences.
There are four type conversion operations:
long(expr) floating point numbers are truncated during conversionchar(expr)float(expr)__int64(expr)However, explicit type conversions are rarely required because all type conversions are made automatically:
- addition:if both operands are strings,string addition is performed (strings are concatenated);if both operands are objects,object combination is performed (a new object is created)if floating point operand exists,both operands are converted to floats;otherwiseboth operands are converted to longs;- subtraction/multiplication/division:if floating point operand exists,both operands are converted to floats;if both operands are objects and the operation is subtraction,object subtraction is performed (a new object is created)otherwiseboth operands are converted to longs;- comparisons (==,!=, etc):if both operands are strings, string comparison is performed;if floating point operand exists,both operands are converted to floats;otherwiseboth operands are converted to numbers;- all other operations:operand(s) are converted to longs;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:
auto x, r;r = &x;r = 1; // x is equal to 1 nowReferences to references are immediately resolved:
auto x, r1, r2;r1 = &x;r2 = &r1; // r2 points to xSince all non-object arguments are passed to functions by value, references are a good way to pass arguments by reference.
idc預定義符號
idc有一些符號是提前定義好了的,其內容和含義如下。
_NT_ IDA is running under MS Windows_LINUX_ IDA is running under Linux_MAC_ IDA is running under Mac OS X_UNIX_ IDA is running under Unix (linux or mac)_EA64_ 64-bit version IDA_QT_ GUI version of IDA (Qt)_GUI GUI version of IDA_TXT_ Text version of IDA_IDA_VERSION_ The current IDA version. For example: "7.5"_IDAVER_ The current, numerical IDA version. For example: "750" means v7.5idc字符串操作(切片)
idc中對于字符串的操作應該是借鑒了python,其string類型的操作支持切片操作(slices)。
str[i1:i2] - substring from i1 to i2. i2 is excluded,If i1 >= i2, empty string is returned.str[idx] - one character substring at 'idx'.this is equivalent to str[idx:idx+1]str[:idx] - substring from the beginning of the string to idxthis is equivalent to str[0:idx]str[idx:] - substring from idx to the end of the stringthis is equivalent to str[idx:0x7fffffff]IDC: Slices
The slice operator can be applied IDC objects are strings.
For strings, the slice operator denotes a substring:
str[i1:i2] - substring from i1 to i2. i2 is excludedstr[idx] - one character substring at 'idx'.this is equivalent to str[idx:idx+1]str[:idx] - substring from the beginning of the string to idxthis is equivalent to str[0:idx]str[idx:] - substring from idx to the end of the stringthis is equivalent to str[idx:0x7fffffff]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:
str[0:2] = "abc";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:
auto x = object();x[0] = value1;x[1] = "value2";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.
idc異常處理
idc異常處理中,可以使用的表達語句:
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}throw xx; #拋出IDC: Exceptions
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:
throw 5;will throw value ‘5’.
idc程序
如果只是需要進行簡單的查詢或者查看,可以直接編寫個別行的函數完成編寫,但是如果一個腳本應用需要執行大量的IDC程序,并且還可能會在很多場景下需要重復使用,那么我們可能需要創建一個獨立的IDC程序文件。
IDC程序文件要求用戶使用用戶定義的函數,并且至少定義一個沒有參數的main函數,此外主程序文件中必須包含idc.idc頭文件。
#idc程序文件基本結構 #Include <idc.idc> static main(){Message("this is a IDC scipt file"); }IDC支持如下C預處理指令:
#include <文件> ;將指定的文件包含在當前文件中
#define <宏名稱>[可選項] ;創建宏,可以選擇給宏分配指定的值
#ifdef <名稱>; 測試指定的宏是否存在
#else 與ifdef一起使用
#endif 通過ifdef指定定義終止符
#undef <名稱> ;刪除指定的宏
常用idc函數
ida中對于idc函數的命名都很有規律,以下列舉了一些特定用途的函數,但是這些并不是全部dic中的函數,還有更多的可以前往ida幫助文檔查找。
讀取和修改數據的函數
用戶交互函數
idc腳本沒有任何調試工具,所以可以依靠輸出函數實現調試。
字符串操縱函數
數據庫名稱操縱函數
處理函數的函數
代碼交叉引用函數
數據交叉引用函數
數據庫操縱函數
數據庫搜索函數
反匯編行組件
IDC腳本示例
示例來自《解密家用路由器0day漏洞挖掘技術》
//枚舉危險函數 scanvuln.idc #include <idc.idc> static flagCalls(fname) //定義了一個函數 {auto count=0;auto func,xref;func =LocByName(fname);if(func!=BADADDR){ for(xref=RfirstB(func);xref!=BADADDR;xref=RnextB(func,xref)) //使用代碼交叉方式遍歷危險函數 {Message("%x,%x\n",xref,func);if(XrefType()==fl_CN || XrefType()==fl_CF) //該判斷語句判定,RfirstB或RnextB返回的交叉引用類型是近調用還是遠調用{MakeComm(xref,"*** AUDIT HERE ***");Message('Function%d:0x%x==>%s\n',++count,xref,fname);}} /* //使用數據交叉引用的方式去搜索危險函數for(xref=DfirstB(func);xref!=BADADDR;xref=DnextB(func,xref)){if(XrefType()==dr_O){MakeComm(xref,"*** AUDIT HERE ***");Message("Function%d:0x%x==> %s\n",++count,xref,fname);}} */} }static main() {Message("---------------------\n");flagCalls("strcpy");flagCalls("sprintf");Message("---------------------\n"); }總結
以上是生活随笔為你收集整理的ida-IDC脚本剖析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 官宣!麻省理工学院官方线上课程之机器学习
- 下一篇: 【Pytorch】常用函数功能介绍和注意