昨天忽然对结构体以及指向结构体的指针来了兴趣,就找了个程序逆向了一下,学到一些东西。
这是本菜第一次发帖,希望大家轻拍呀……
不看源程序,反汇编代码,F5后得到这样两条语句:
*(*(Data + 4) + 8 * **(Data + 4) + 4) = v1;
*(*(Data + 4) + 8 * **(Data + 4) + 8) = v2;
其中,Data是指向某个结构体的指针,也即一个32位的地址。
首先要理解的是,Data作为指向结构体的指针,它本身只占4字节内存,即一个32位;而这32位的含义是它所指向的结构体那个类型的一个变量的内存首地址。
呵呵,这句话比较拗口,总之是存了一个变量(假定名字为A)的首地址;而这个变量是个结构体类型——也就是说,这个变量A可能占用4个、8个、12个乃至更多字节的内存,因为结构体内是可能包括很多不同数据类型的变量的。
理解了这一点,就可以看一下 Data + 4,这显然仍然是一个地址,而且正如上面说的,是Data所指向的变量A内部的某个元素(假定为B)的地址。
OK,加个星号,*(Data + 4)取出这个元素B。
由于上面的反汇编中出现了**(Data + 4)这样的代码,所以可以断定元素B存放的也是一个指针,它也指向某个变量(假定为C)的地址(或首地址)。
所以**(Data + 4)取出了C的内容。
C= *(B + 0) = *(*(Data + 4) + 0 )
接下来,变量C乘以了8,这说明了什么呢,说明C这个地址内存放的是某个数组的index值,而这个数组中元素的大小为8字节。而B是指向这个数组(假定为D)首地址的。
之后,这个乘积与B相加,可以看出,结果会是B所指向的这个数组的某个元素的地址。但是为什么后面还要再加一个4呢?
原来是这样的,前面曾经提到,B所指向的内容C并不是一个数组的指针,而只是一个索引值,那么这个数组的地址自然就存到了 B + 4 这个内存中。进一步又说明了B指向的也是一个结构体。这个结构体第一个元素是一个数组的index值,第二个元素是这个数组D的地址,假定为E。
到这里,似乎分析基本已经清楚了。但是仔细看一下会发现第二行代码有一个加8,这是什么情况呢?这里应该有两种可能性,第一种是结构体B还有第三个元素,而且也是一个数组指针;第二种则是数组D的元素也是结构体类型,加8可以看成两个加4,第一个是从B中取得D的内容;第二个则是在D中取一个偏移,获得D的第index个元素的第2个变量的地址。
好了,至此真相大白,最后用一个*号得到内容,直接操作之~
所以其实上面的代码应该是:
*( (*(Data + 4) + 4) + 8 * ( *(*(Data + 4) + 0 ) ) + 0 ) = v1;
*( (*(Data + 4) + 4) + 8 * ( *(*(Data + 4) + 0 ) ) + 4 ) = v2;
真实C语言源代码如下:
Data->Object->Entry[Data->Object->Index].Name =v1;
Data->Object->Entry[Data->Object->Index].Id =v2;
这里Data是指向结构体B的指针A,
Object就是我们分析的结构体B,它自身仅是一个地址。
这个地址处有两个内容:第一个是数组的索引index,刚才我们称之为C,第二个是数组的首地址Entry,刚才称之为D。
数组Entry的元素都是结构体,有两个数据项,Name和Id。
眼花不?呵呵,我一开始也眼花,多看看就好了。做个记录,免得以后忘了。由于本人水平有限,以上分析肯定有很多疏漏之处,望诸位不吝赐教,非常感谢! |