变量
局部变量
- 保存在栈上,先声明的变量在高地址,后声明在低地址。
- 局部变量在栈上会内存对齐。
静态局部变量
区分
在tls
环境中,保存着i
是否被初始化的标志,每次进函数的时候,都要进行判断。
通过汇编我们可以看到,静态局部变量的初始标志的检查是无锁的。
但是标志的改写,仍然是需要线程同步的。
堆变量
- 调用
malloc
,但是有可能被静态链接,如果sig
文件未识别的话,往下找可以找到调用系统的API
。
全局变量
- 保存在
.rdata
或者.data
、.bss
,常量区或全局数据区、未初始化区。
有初始值
没有初始值
全局变量的动态初始化
生成汇编:
- 首先生成一个
dynamic initializer for 'g_int'
函数。
- 在入口之前执行动态初始化。
逆向时向上查找全局变量被引用地址,看看是否被动态初始化调用。(通过IDA的绘图向上溯源)
数组
连续的变量如何证明为数组?
- 类型是否一致?
- 是否跟着循环、判断下标等语句?
- 是否有初始化代码?
- 数组寻址公式:
ary + index * sizeof(type)
,或者指针累加。lea eax, ary``mov ary, ary+4
- 数组的初始化通常有
rep
或者memset
,特别是memset
。(debug
会使用rep
),默认值会使用xmm0
寄存器。
数组初始化
不完全初始化
第一种,未初始化的元素个数较少,会使用xmm0
与movups、movaps
等指令处理。
第二种,较多的元素未初始化,会使用memset
将未初始化的元素全部初始化为0
未初始化
并不会使用memset
将元素初始化为0
,而是会使用栈上的残留值。
初始化为0
会使用memset
将数组全部初始化为0
。
全初始化
要么使用xmm0
或者直接优化为多个mov
语句。
数组的遍历
一维数组的遍历,可以找到循环和一次乘法。
二维数组,可以找到两层循环和两个步长
二维数组/多维数组
在内存中,并不存在多维数组,只是步长更精细。
二维数组乘两次、三位乘三次…
务必记得乘法会被优化为移位。