C语言反汇编_数组与结构体
0 . 说明
看滴水逆向视频总结笔记
编译器VC++6.0
1.数组
1.数组对应堆栈空的分配
数组在汇编中的位置与普通局部变量有一些细节上的差异,一般局部变量都是从栈底依次分配到栈底,数组也不例外,但是,数组内部排序是从上到下的。
- 数组在堆栈里从上到下依次存放str[0]到str[n],这一点与单个局部变量在堆栈的存储不同,具体表现为:一大片等宽的堆栈空间。
- 还值得注意,堆栈在给数组分配空间时,严格遵循变量的类型宽度,int型数组每个变量站4个字节,char型数组每个变量占一个字节,而当我们定义单个变量时,不管int还是char型,堆栈都会分配4个字节,(__int64型变量会分配8个字节)。
- 这是一维数组,而二维、三维数组的本质也是一维数组,所以堆栈空间的分配其实也差不多,只是引用的时候有差异。
2.数组的寻址
1.一维数组
当str[i]中的i为一个固定常量时,如str[1];
当str[i]中的i,是一个变量时,比如for循环中的i。
0040D513 mov ecx,dword ptr [ebp-18h]
//将局部变量i的中放入ecx
0040D516 mov dword ptr [ebp+ecx*4-14h],0
//[ebp-0x14]为数组的首地址,[首地址+ecx*4]代表偏移。(4代表int型数据的宽度,char型数据为1,short型数据为2)
2.二维数组
当str[i][j]
中的i、j为一个固定常量时,如str[1][2]
;
本质上和一维数组是一样的。一样是编译器根据变量对应的地址寻址。
当str[i][j]
中的i、j,是一个变量时,比如for循环中的i、j。
4: str1[i][j] = 0;
0040D530 mov eax,dword ptr [ebp-1Ch]
//将i的值取出来放于eax中
0040D533 imul eax,eax,0Ch//有符号乘法
//将i的中乘以0xc,结果放入eax中,
//这里的0xC可以理解为3*4,3就是str[2][3]中的3,每个int型数据占4个字节
0040D536 lea ecx,[ebp+eax-18h]
//把这个地址放于ecx中,这个地址相当于str[i][]中对应i的偏移量
0040D53A mov edx,dword ptr [ebp-20h]
//把j的值放于edx中
0040D53D mov dword ptr [ecx+edx*4],0
//在str[i][]的基础上在偏移一个j (edx*4)
15: }
- 经过上诉语句,明白二维数组(初始化为
str[m][n]
),求str[i][j]
时,对应的地址为==[首地址+i*n+j]==,同时还要考虑数组元素的宽度为int(4)还是char(1)。 - 不难发现,其实二维数组的本质也是一位数组。分配的堆栈空间也是大致相同的。
3.三维数组
有了上述二维数组的经验后,再求一个三维数组,先初始化一个
int str[m][n][r];//对数组初始化长度为m*n*r.
那我们要引用数组str[i][j][k]
时,那么对应的地址为==[首地址+i * m * r + j * r + k]==,可以下去尝试一下。
3.数组的作为函数参数
当数组作为一个函数的参数时,本质是传入一个地址。
void fun( int str[])
{
;
}
可以发现,传入的参数为数组的首地址,
004010AB lea eax,[ebp-14h]
004010AE push eax
我们进入函数,看如何调用这个数组参数。
0040D4FB mov eax,dword ptr [ebp+8]
//把参数(传入的数组参数)首地址放入eax
0040D4FE mov ecx,dword ptr [ebp-10h]
//把局部变量str1[1]放入ecx
0040D501 mov dword ptr [eax+4],ecx
//[exa+4]代表对eax的偏移,而eax就是数组参数的首地址
看来,一样是通过偏移来引用这些数组数据。
2.结构体
其实,结构体的本质也和数组类似。上面调试了数组,只需再调试一下,看看结构体在堆栈中是怎样分配的,我们便能大概知道怎么引用。
-
这个结构体每个元素加起来的宽度为0xb(4+2+1+4),而这里开头却分配了0x4c的空间(为局部变量分配了额外的0xc的空间),在下面赋值语句可以发现,stu.c本是char型数据,却占了2个字节宽度的空间,原因呢,是因为:字节对齐(整个结构的空间地址加起来必须要能被4整除)。
-
发现,结构体在堆栈中分配空间也和一般的数组相似的,先整体分配一个空间,里面的元素,是从上往下挨个存储的,所以呢,
当你发现有一段堆栈空间连续存储且等宽,且数据大小还相似,那么极有可能是数组之类的;当你发现有一段堆栈空间连续存储但不等宽,那么极有可能是结构体。
大概知道了结构体的样貌,和数组一对比,其实结构体的寻址、引用都和数组差不多,这里我就不调试了0.0
要是有写错了或写的不好的地方,还请大家多多指正。^ ^