C++逆向第十课-----数组与指针的寻址
2017-03-09 10:29
323 查看
好久没写博客了,做人最难的事情就是坚持,不管怎么样,从今天开始重新捡起来,做人还是应该有始有终
数据类型上要有一致性
如何证明:
比例因子寻址,例如:mov reg,[ebp + esi * 4 - 8]
循环迭代
数组的优势就是循环批量的操作
由上面的代码可以看出连续定义相同类型的局部变量和数组赋值顺序是相反的
字符串初始化代码Debug与Release版对比
C++源码
Debug版反汇编
Release版反汇编
对比以上源码可知道,字符串赋值操作都是,将.data数据区的地址给连续的栈空间,相当于给数组赋初值
C++源码
Debug版反汇编
Release版反汇编
C++源码
Debug版反汇编
由以上反汇编代码可以看出指针多了一次间接访问
C++源码
Debug版反汇编
可以看出数组下标寻址公式为
二维数组type nArray[M]
,使用i,j作为下标寻址
Release版反汇编
由以上反汇编可以看出有些许优化,具体优化公式为
0x00 逆向时候判断数组的依据
证明在内存上是连续的,中间不留空数据类型上要有一致性
如何证明:
比例因子寻址,例如:mov reg,[ebp + esi * 4 - 8]
循环迭代
数组的优势就是循环批量的操作
0x01 数组与局部变量赋值的对比
源码:8: int n1 = 1; 00401028 mov dword ptr [ebp-4],1 9: int n2 = 2; 0040102F mov dword ptr [ebp-8],2 10: int n3 = 3; 00401036 mov dword ptr [ebp-0Ch],3 11: int n4 = 4; 0040103D mov dword ptr [ebp-10h],4 12: int n5 = 5; 00401044 mov dword ptr [ebp-14h],5 13: 14: int nArr[5] = {1,2,3,4,5}; 0040104B mov dword ptr [ebp-28h],1 00401052 mov dword ptr [ebp-24h],2 00401059 mov dword ptr [ebp-20h],3 00401060 mov dword ptr [ebp-1Ch],4 00401067 mov dword ptr [ebp-18h],5
由上面的代码可以看出连续定义相同类型的局部变量和数组赋值顺序是相反的
0x02 数组与字符串
在C++中,字符串本身就是数组字符串初始化代码Debug与Release版对比
C++源码
char szHello[] = "Hello World!!!!"; printf("%s\r\n",szHello);
Debug版反汇编
mov eax, dword ptr ds:aHelloWorld ; "Hello World!!!!" mov [ebp+var_38], eax mov ecx, dword ptr ds:aHelloWorld+4 ; "o World!!!!" mov [ebp+var_34], ecx mov edx, dword ptr ds:aHelloWorld+8 ; "rld!!!!" mov [ebp+var_30], edx mov eax, dword ptr ds:aHelloWorld+0Ch ; "!!!" mov [ebp+var_2C], eax lea ecx, [ebp+var_38] push ecx push offset aS_0 ; "%s\r\n" call _printf add esp, 8
Release版反汇编
mov ecx, dword_40603C mov eax, dword_406038 mov edx, dword_406040 mov [esp+10h+var_C], ecx lea ecx, [esp+10h+var_10] mov [esp+10h+var_10], eax mov eax, dword_406044 push ecx push offset aS ; "%s\r\n" mov [esp+18h+var_8], edx mov [esp+18h+var_4], eax call _printf
对比以上源码可知道,字符串赋值操作都是,将.data数据区的地址给连续的栈空间,相当于给数组赋初值
0x03数组字与字符串处理
在Debug版下,将直接调用库函数处理字符串,但是在Release版本下,会采用内联汇编进行优化。但是在高版本的编译器中这些优化又消失了如VS2013,因为这些优化都集成到了硬件当中去了C++源码
char szHello[] = "Hello World!!!!"; printf("%d\r\n",strlen(szHello));
Debug版反汇编
mov eax, dword ptr ds:aHelloWorld ; "Hello World!!!!" mov dword ptr [ebp+Str], eax mov ecx, dword ptr ds:aHelloWorld+4 ; "o World!!!!" mov [ebp+var_C], ecx mov edx, dword ptr ds:aHelloWorld+8 ; "rld!!!!" mov [ebp+var_8], edx mov eax, dword ptr ds:aHelloWorld+0Ch ; "!!!" mov [ebp+var_4], eax lea ecx, [ebp+Str] push ecx ; Str call _strlen
Release版反汇编
mov eax, dword_406038 mov ecx, dword_40603C mov edx, dword_406040 mov [esp+10h+var_10], eax mov eax, dword_406044 push edi mov [esp+14h+var_C], ecx mov [esp+14h+var_4], eax //以下为无分支求字符串长度的汇编代码 lea edi, [esp+14h+var_10] or ecx, 0FFFFFFFFh xor eax, eax mov [esp+14h+var_8], edx repne scasb not ecx dec ecx push ecx push offset aD ; "%d\r\n" call _printf add esp, 8
0x04下标寻址和指针寻址
指针寻址方式不但没有下标寻址方式便利,而且效率也比下标寻址低。这一点我们可以用反汇编证明。C++源码
char szHello[] = "Hello!!"; char * pChar = "Hello!!"; printf("%c\r\n",szHello[0]); printf("%c\r\n",* pChar);
Debug版反汇编
11: char szHello[] = "Hello!!"; 0040B4B8 mov eax,[string "Hello!!" (0041fe58)] 0040B4BD mov dword ptr [ebp-8],eax 0040B4C0 mov ecx,dword ptr [string "Hello World!!!!"+4 (0041fe5c)] 0040B4C6 mov dword ptr [ebp-4],ecx 12: char * pChar = "Hello!!"; 0040B4C9 mov dword ptr [ebp-0Ch],offset string "Hello!!" (0041fe58) 13: printf("%c\r\n",szHello[0]); 0040B4D0 movsx edx,byte ptr [ebp-8] 0040B4D4 push edx 0040B4D5 push offset string "%d\r\n" (0041fe50) 0040B4DA call printf (0040b7b0) 0040B4DF add esp,8 14: printf("%c\r\n",* pChar); 0040B4E2 mov eax,dword ptr [ebp-0Ch] 0040B4E5 movsx ecx,byte ptr [eax] 0040B4E8 push ecx 0040B4E9 push offset string "%d\r\n" (0041fe50) 0040B4EE call printf (0040b7b0) 0040B4F3 add esp,8
由以上反汇编代码可以看出指针多了一次间接访问
0x04多维数组下标寻址
以二位下标为例子C++源码
int ary[3][5] = { {1,2,3,4,5}, {1,2,3,4,5}, {1,2,3,4,5} }; printf("%d\r\n",ary[argc + 1][0]);
Debug版反汇编
17: printf("%d\r\n",ary[argc + 1][0]); 0040B521 mov eax,dword ptr [ebp+8] 0040B524 add eax,1 0040B527 imul eax,eax,14h 0040B52A mov ecx,dword ptr [ebp+eax-3Ch] 0040B52E push ecx 0040B52F push offset string "%d\r\n" (0041fe50) 0040B534 call printf (0040b7b0) 0040B539 add esp,8
可以看出数组下标寻址公式为
二维数组type nArray[M]
,使用i,j作为下标寻址
nArray + i * N * sizeof(type) + j * sizeof(type) = nArray + i * N * sizeof(type) + j*sizeof(type)
Release版反汇编
mov ecx, [esp+eax*4+3Ch+var_28] push ecx push offset aD ; "%d\r\n" call _printf
由以上反汇编可以看出有些许优化,具体优化公式为
nArray + i * N * sizeof(type) + j * sizeof(type) =nArray + sizeof(type)* (i * N + j)
相关文章推荐
- C++反汇编学习笔记7——数组和指针以及他们的寻址
- 基于arm的C++反汇编 数组和指针的寻址
- C/C++数组名与指针区别深层探索
- C/C++中数组和指针类型的关系
- C/C++数组名与指针区别深入探索,流传还挺广的
- C/C++ 多维数组与指针
- C++复习 04 数组和指针
- C/C++中字符指针数组及指向指针的指针的含义
- C++中使用基类指针操作子类数组的分析
- C++ Tips: 指针、数组和结构
- 指针, 指针的指针, 数组, 指针数组, 数组指针, 指针函数, 函数指针 C/C++中函数指针的含义
- [转载]c/c++指针与数组的使用与区别
- [原创] 一劳永逸:关于C/C++中指针、数组与函数复合定义形式的直观解释
- 挑战30天C++入门极限-C/C++中字符指针数组及指向指针的指针的含义
- c++入门学习(内存与指针及数组)
- C/C++数组名与指针区别深入探索
- C/C++中字符指针数组及指向指针的指针的含义
- 挑战30天C++入门极限-C/C++中数组和指针类型的关系
- C/C++数组名与指针区别深入探索
- C/C++数组名与指针区别深入探索