C语言反汇编_数组和结构体

C语言反汇编_数组与结构体

0 . 说明

​ 看滴水逆向视频总结笔记

​ 编译器VC++6.0

1.数组

1.数组对应堆栈空的分配

​ 数组在汇编中的位置与普通局部变量有一些细节上的差异,一般局部变量都是从栈底依次分配到栈底,数组也不例外,但是,数组内部排序是从上到下的。

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p9zRFdaX-1584113276066)(E:/Typora/image/1584107077486.png)]

  1. 数组在堆栈里从上到下依次存放str[0]到str[n],这一点与单个局部变量在堆栈的存储不同,具体表现为:一大片等宽的堆栈空间。
  2. 还值得注意,堆栈在给数组分配空间时,严格遵循变量的类型宽度,int型数组每个变量站4个字节,char型数组每个变量占一个字节,而当我们定义单个变量时,不管int还是char型,堆栈都会分配4个字节,(__int64型变量会分配8个字节)。
  3. 这是一维数组,而二维、三维数组的本质也是一维数组,所以堆栈空间的分配其实也差不多,只是引用的时候有差异。

2.数组的寻址

1.一维数组

​ 当str[i]中的i为一个固定常量时,如str[1];

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nV5uILmV-1584113276067)(E:/Typora/image/1584108198021.png)]

​ 当str[i]中的i,是一个变量时,比如for循环中的i。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-54VdNaQi-1584113276067)(E:/Typora/image/1584108706234.png)]

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];

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1RYnYS6V-1584113276068)(E:/Typora/image/1584109337049.png)]

​ 本质上和一维数组是一样的。一样是编译器根据变量对应的地址寻址。

​ 当str[i][j]中的i、j,是一个变量时,比如for循环中的i、j。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GCYBl1GP-1584113276068)(E:/Typora/image/1584110115521.png)]

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:           }

  1. 经过上诉语句,明白二维数组(初始化为str[m][n]),求str[i][j]时,对应的地址为==[首地址+i*n+j]==,同时还要考虑数组元素的宽度为int(4)还是char(1)。
  2. 不难发现,其实二维数组的本质也是一位数组。分配的堆栈空间也是大致相同的。
3.三维数组

​ 有了上述二维数组的经验后,再求一个三维数组,先初始化一个

int str[m][n][r];//对数组初始化长度为m*n*r.

那我们要引用数组str[i][j][k]时,那么对应的地址为==[首地址+i * m * r + j * r + k]==,可以下去尝试一下。

3.数组的作为函数参数

​ 当数组作为一个函数的参数时,本质是传入一个地址。

void fun( int str[])
{
	;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2pqPC0X-1584113276068)(E:/Typora/image/1584111271837.png)]

可以发现,传入的参数为数组的首地址,

004010AB   lea         eax,[ebp-14h]
004010AE   push        eax

我们进入函数,看如何调用这个数组参数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EArYVvkA-1584113276069)(E:/Typora/image/1584111403056.png)]

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.结构体

​ 其实,结构体的本质也和数组类似。上面调试了数组,只需再调试一下,看看结构体在堆栈中是怎样分配的,我们便能大概知道怎么引用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c5ig6UIZ-1584113276069)(E:/Typora/image/1584112391014.png)]

  1. 这个结构体每个元素加起来的宽度为0xb(4+2+1+4),而这里开头却分配了0x4c的空间(为局部变量分配了额外的0xc的空间),在下面赋值语句可以发现,stu.c本是char型数据,却占了2个字节宽度的空间,原因呢,是因为:字节对齐(整个结构的空间地址加起来必须要能被4整除)。

  2. 发现,结构体在堆栈中分配空间也和一般的数组相似的,先整体分配一个空间,里面的元素,是从上往下挨个存储的,所以呢,

    当你发现有一段堆栈空间连续存储且等宽,且数据大小还相似,那么极有可能是数组之类的;当你发现有一段堆栈空间连续存储但不等宽,那么极有可能是结构体。

大概知道了结构体的样貌,和数组一对比,其实结构体的寻址、引用都和数组差不多,这里我就不调试了0.0


要是有写错了或写的不好的地方,还请大家多多指正。^ ^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值