-
-
[翻译][原创]IDC脚本系列 - IDC : 变量
-
发表于:
2017-7-6 16:55
3654
-
[翻译][原创]IDC脚本系列 - IDC : 变量
在IDC脚本语言中,存在两种变量:
局部变量:这类变量在函数开头的时候声明创建,在函数退出的时候销毁
全局变量:这类变量在脚本编译期创建,在IDA分析数据库关闭的时候销毁(译者注:全局变量的创建和销毁原文描述的其实不是太清晰,经过我的测试,全局变量是在脚本加载进来的时候就被创建,然后当你关闭当前IDA分析的文件的时候,IDA也会清理你加载过的IDC脚本,其实可以理解为IDC脚本清理的时候销毁)
变量可以保存哪些数据类型:
LONG:32位有符号整形(如果是64位的IDA, 则表示64位有符号整形)
INT64:64位有符号整形
STR:字符串
FLOAT:浮点数据(高精度数据,最高支持25位小数)
OBJECT:一种很类似C++对象的数据类型,具有 方法 和 属性的集合
REF:其他变量的引用
FUNC:函数引用
局部变量怎么声明
下面我给出声明一个局部变量的例子,大概是这样的:
auto var1;
auto var2 = expr;
全局变量怎么声明
同样的,我也给出一个全局变量的例子,大概是这样的:
extern var;
需要特别说明的是,全局变量可以声明很多次。但是IDA只保留第一次声明的那个,后续的所有同名的全局变量都自动忽略。在IDC脚本中,全局变量和C语言中的使用还有一个很大的不同点,那就是不能在声明的时候进行初始化赋值。
在给变量命名的时候要注意,所有的C C++的关键词和保留字都不能作为变量的名称,其他就没有什么特别的限制了
虽然IDC脚本允许你在函数体内的任意一个地方声明一个变量,但是所有你声明的函数内临时变量都只会在函数的开始位置初始化一次,然后在函数退出的时候销毁。举个例子,如果你在一个循环体内声明了一个变量,这个变量也只会初始化一次,除非你在某个位置对这个变量进行赋值,不然这个变量的值就一直保持那个最初的初始化值。
如果你在IDC脚本内声明的变量或者函数IDA无法找到相应的声明,那么IDA会尝试从当前打开的分析文件中的符号进行匹配,如果能够匹配成功,这个无法识别的变量或者函数就使用这个匹配出来的符号来代替,还是举个具体的例子来说明:
上面这个例子中,Message调用将会输出 413060, 也就是_errtabled的地址,如果IDA匹配出来的符号是一个结构体,还可以进一步访问结构体的成员变量,比如上面的 errTable就是一个结构体,可以进一步这样使用结构体的成员:Message("address is: %x\n", _errtable.errnocode); 这句调用将打印 413064 这个结果。从上面的这两个例子可以看出来,IDA对符号的处理过程中,只会返回结构体的地址而不是值,如果你想要获取具体的值可以使用 get_field_ea 这个函数来进行。
注意:
如果当前IDA的调试器处于激活状态,也就是说你正在使用IDA调试一个程序,那么你就可以在IDC脚本中使用处理器的寄存器了,你可以使用寄存器名称直接进行寄存器读写。还有一个必须明确,寄存器的读写动作必须要在被调试进程处于暂停状态下进行
你可以使用array函数来枚举获取全局空间的变量或者用array函数创建全局的常驻内存的数组
.data:00413060 errtable dd 1 ; oscode
.data:00413060 dd 16h ; errnocodeMessage("address is: %x\n", _errtable);
在IDC脚本语言中,存在两种变量:
局部变量:这类变量在函数开头的时候声明创建,在函数退出的时候销毁
全局变量:这类变量在脚本编译期创建,在IDA分析数据库关闭的时候销毁(译者注:全局变量的创建和销毁原文描述的其实不是太清晰,经过我的测试,全局变量是在脚本加载进来的时候就被创建,然后当你关闭当前IDA分析的文件的时候,IDA也会清理你加载过的IDC脚本,其实可以理解为IDC脚本清理的时候销毁)
变量可以保存哪些数据类型:
LONG:32位有符号整形(如果是64位的IDA, 则表示64位有符号整形)
INT64:64位有符号整形
STR:字符串
FLOAT:浮点数据(高精度数据,最高支持25位小数)
OBJECT:一种很类似C++对象的数据类型,具有 方法 和 属性的集合
REF:其他变量的引用
FUNC:函数引用
局部变量怎么声明
下面我给出声明一个局部变量的例子,大概是这样的:
auto var1;
auto var2 = expr;
全局变量怎么声明
需要特别说明的是,全局变量可以声明很多次。但是IDA只保留第一次声明的那个,后续的所有同名的全局变量都自动忽略。在IDC脚本中,全局变量和C语言中的使用还有一个很大的不同点,那就是不能在声明的时候进行初始化赋值。
在给变量命名的时候要注意,所有的C C++的关键词和保留字都不能作为变量的名称,其他就没有什么特别的限制了
虽然IDC脚本允许你在函数体内的任意一个地方声明一个变量,但是所有你声明的函数内临时变量都只会在函数的开始位置初始化一次,然后在函数退出的时候销毁。举个例子,如果你在一个循环体内声明了一个变量,这个变量也只会初始化一次,除非你在某个位置对这个变量进行赋值,不然这个变量的值就一直保持那个最初的初始化值。
-
如果你在IDC脚本内声明的变量或者函数IDA无法找到相应的声明,那么IDA会尝试从当前打开的分析文件中的符号进行匹配,如果能够匹配成功,这个无法识别的变量或者函数就使用这个匹配出来的符号来代替,还是举个具体的例子来说明:
.data:00413060 errtable dd 1 ; oscode
.data:00413060 dd 16h ; errnocodeMessage("address is: %x\n", _errtable);
上面这个例子中,Message调用将会输出 413060, 也就是_errtabled的地址,如果IDA匹配出来的符号是一个结构体,还可以进一步访问结构体的成员变量,比如上面的 errTable就是一个结构体,可以进一步这样使用结构体的成员:Message("address is: %x\n", _errtable.errnocode); 这句调用将打印 413064 这个结果。从上面的这两个例子可以看出来,IDA对符号的处理过程中,只会返回结构体的地址而不是值,如果你想要获取具体的值可以使用 get_field_ea 这个函数来进行。
注意:
如果当前IDA的调试器处于激活状态,也就是说你正在使用IDA调试一个程序,那么你就可以在IDC脚本中使用处理器的寄存器了,你可以使用寄存器名称直接进行寄存器读写。还有一个必须明确,寄存器的读写动作必须要在被调试进程处于暂停状态下进行
你可以使用array函数来枚举获取全局空间的变量或者用array函数创建全局的常驻内存的数组
下面我给出声明一个局部变量的例子,大概是这样的:
auto var1;
auto var2 = expr;
局部变量:这类变量在函数开头的时候声明创建,在函数退出的时候销毁
全局变量:这类变量在脚本编译期创建,在IDA分析数据库关闭的时候销毁(译者注:全局变量的创建和销毁原文描述的其实不是太清晰,经过我的测试,全局变量是在脚本加载进来的时候就被创建,然后当你关闭当前IDA分析的文件的时候,IDA也会清理你加载过的IDC脚本,其实可以理解为IDC脚本清理的时候销毁)
LONG:32位有符号整形(如果是64位的IDA, 则表示64位有符号整形)
INT64:64位有符号整形
STR:字符串
FLOAT:浮点数据(高精度数据,最高支持25位小数)
OBJECT:一种很类似C++对象的数据类型,具有 方法 和 属性的集合
REF:其他变量的引用
FUNC:函数引用
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课