cpp反汇编之const分析

先来分析一个简单的例子。(注意容易出错)

代码非常简单

#include<iostream>
#include<cstdio>
using namespace std;
int main(){
	const int a = 1;
	int* b = (int*)&a;
	*b = 2;
	cout << a << endl << *b << endl;
	return 0;
}

反汇编分析  重点之处有注释

1:    #include<iostream>
2:    #include<cstdio>
3:    using namespace std;
4:    int main(){
00401560   push        ebp
00401561   mov         ebp,esp
00401563   sub         esp,48h
00401566   push        ebx
00401567   push        esi
00401568   push        edi
00401569   lea         edi,[ebp-48h]
0040156C   mov         ecx,12h
00401571   mov         eax,0CCCCCCCCh
00401576   rep stos    dword ptr [edi]
5:        const int a = 1;
00401578   mov         dword ptr [ebp-4],1
6:        int* b = (int*)&a;
0040157F   lea         eax,[ebp-4]
00401582   mov         dword ptr [ebp-8],eax
7:        *b = 2;
00401585   mov         ecx,dword ptr [ebp-8]  ecx即是指针b的值
00401588   mov         dword ptr [ecx],2
8:        cout<<a<<endl<<*b<<endl;
0040158E   push        offset @ILT+195(std::endl) (004010c8)
00401593   mov         edx,dword ptr [ebp-8]
00401596   mov         eax,dword ptr [edx]
00401598   push        eax	//此处使用eax存储
00401599   push        offset @ILT+195(std::endl) (004010c8)
0040159E   push        1	//此处即是常量a
004015A0   mov         ecx,offset std::cout (0047be90)
004015A5   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
004015AA   mov         ecx,eax
004015AC   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
004015B1   mov         ecx,eax
004015B3   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
004015B8   mov         ecx,eax
004015BA   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
9:        return 0;
004015BF   xor         eax,eax
10:   }
004015C1   pop         edi
004015C2   pop         esi
004015C3   pop         ebx
004015C4   add         esp,48h
004015C7   cmp         ebp,esp
004015C9   call        __chkesp (00420550)
004015CE   mov         esp,ebp
004015D0   pop         ebp
004015D1   ret

输出:
1
2

内存寄存器分析
执行00401578   mov         dword ptr [ebp-4],1 之前
0018FF33  CC CC CC CC CC CC CC  烫烫烫.
0018FF3A  CC CC CC CC CC CC CC  烫烫烫.
0018FF41  CC CC CC CC CC CC CC  烫烫烫.
0018FF48  88 FF 18 00 29 1A 42  ....).B
0018FF4F  00 01 00 00 00 98 17  .......

执行00401578   mov         dword ptr [ebp-4],1 之后
0018FF33  CC CC CC CC CC CC CC  烫烫烫.
0018FF3A  CC CC CC CC CC CC CC  烫烫烫.
0018FF41  CC CC CC 01 00 00 00  烫.....  此处1即为a
0018FF48  88 FF 18 00 29 1A 42  ....).B

0040157F   lea         eax,[ebp-4]
00401582   mov         dword ptr [ebp-8],eax
 EAX = 0018FF44 EBX = 7EFDE000
 ECX = 00000000 EDX = 003C1810
 ESI = 00000000 EDI = 0018FF48
 EIP = 00401585 ESP = 0018FEF4
 EBP = 0018FF48 EFL = 00000206
0018FF33  CC CC CC CC CC CC CC  烫烫烫.
0018FF3A  CC CC CC CC CC CC 44  烫烫烫D
0018FF41  FF 18 00 01 00 00 00  .......
0018FF48  88 FF 18 00 29 1A 42  ....).B

00401585   mov         ecx,dword ptr [ebp-8]
00401588   mov         dword ptr [ecx],2
 EAX = 0018FF44 EBX = 7EFDE000
 ECX = 0018FF44 EDX = 003C1810
 ESI = 00000000 EDI = 0018FF48
 EIP = 0040158E ESP = 0018FEF4
 EBP = 0018FF48 EFL = 00000206
0018FF33  CC CC CC CC CC CC CC  烫烫烫.
0018FF3A  CC CC CC CC CC CC 44  烫烫烫D
0018FF41  FF 18 00 02 00 00 00  .......  <strong>此处的地址a处被改为2</strong>
0018FF48  88 FF 18 00 29 1A 42  ....).B

0040158E   push        offset @ILT+195(std::endl) (004010c8)
00401593   mov         edx,dword ptr [ebp-8]
00401596   mov         eax,dword ptr [edx]
00401598   push        eax
 EAX = 00000002 EBX = 7EFDE000
 ECX = 0018FF44 EDX = 0018FF44
 ESI = 00000000 EDI = 0018FF48
 EIP = 00401598 ESP = 0018FEF0
 EBP = 0018FF48 EFL = 00000206

稍作修改后

#include<iostream>
#include<cstdio>
using namespace std;
int main(){
	const int a = 1;
	int* b = (int*)&a;
	*b = 2;
	cout << a << endl << *b << endl;
	b = new int(8);
	cout << a << endl << *b << endl;
	return 0;
}

反汇编分析

1:    #include<iostream>
2:    #include<cstdio>
3:    using namespace std;
4:    int main(){
00401560   push        ebp
00401561   mov         ebp,esp
00401563   sub         esp,50h
00401566   push        ebx
00401567   push        esi
00401568   push        edi
00401569   lea         edi,[ebp-50h]
0040156C   mov         ecx,14h
00401571   mov         eax,0CCCCCCCCh
00401576   rep stos    dword ptr [edi]
5:        const int a = 1;
00401578   mov         dword ptr [ebp-4],1
6:        int* b = (int*)&a;
0040157F   lea         eax,[ebp-4]
00401582   mov         dword ptr [ebp-8],eax
7:        *b = 2;
00401585   mov         ecx,dword ptr [ebp-8]
00401588   mov         dword ptr [ecx],2
8:        cout << a << endl << *b << endl;
0040158E   push        offset @ILT+195(std::endl) (004010c8)
00401593   mov         edx,dword ptr [ebp-8]
00401596   mov         eax,dword ptr [edx]
00401598   push        eax
00401599   push        offset @ILT+195(std::endl) (004010c8)
0040159E   push        1
004015A0   mov         ecx,offset std::cout (0047be90)
004015A5   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
004015AA   mov         ecx,eax
004015AC   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
004015B1   mov         ecx,eax
004015B3   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
004015B8   mov         ecx,eax
004015BA   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
9:        b = new int(8);
004015BF   push        4
004015C1   call        operator new (004205d0)
004015C6   add         esp,4
004015C9   mov         dword ptr [ebp-0Ch],eax
004015CC   cmp         dword ptr [ebp-0Ch],0
004015D0   je          main+83h (004015e3)
004015D2   mov         ecx,dword ptr [ebp-0Ch]
004015D5   mov         dword ptr [ecx],8
004015DB   mov         edx,dword ptr [ebp-0Ch]
004015DE   mov         dword ptr [ebp-10h],edx
004015E1   jmp         main+8Ah (004015ea)
004015E3   mov         dword ptr [ebp-10h],0
004015EA   mov         eax,dword ptr [ebp-10h]
004015ED   mov         dword ptr [ebp-8],eax
10:       cout << a << endl << *b << endl;
004015F0   push        offset @ILT+195(std::endl) (004010c8)
004015F5   mov         ecx,dword ptr [ebp-8]
004015F8   mov         edx,dword ptr [ecx]
004015FA   push        edx
004015FB   push        offset @ILT+195(std::endl) (004010c8)
00401600   push        1
00401602   mov         ecx,offset std::cout (0047be90)
00401607   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
0040160C   mov         ecx,eax
0040160E   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
00401613   mov         ecx,eax
00401615   call        @ILT+250(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010ff)
0040161A   mov         ecx,eax
0040161C   call        @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
11:       return 0;
00401621   xor         eax,eax
12:   }
00401623   pop         edi
00401624   pop         esi
00401625   pop         ebx
00401626   add         esp,50h
00401629   cmp         ebp,esp
0040162B   call        __chkesp (004205f0)
00401630   mov         esp,ebp
00401632   pop         ebp
00401633   ret

输出:
1
2
1
8

执行此句后 9:        b = new int(8);
内存变化
0018FF33  CC CC CC CC CC C8 07  烫烫倘.
0018FF3A  54 00 C8 07 54 00 C8  T...T..
0018FF41  07 54 00 02 00 00 00  .T.....  a地址处还是2  <strong>说明编译器把const变量直接用常数代替,其内存还是可以改的</strong>
0018FF48  88 FF 18 00 A9 1A 42  ......B
0018FF4F  00 01 00 00 00 98 17  .......
0018FF56  54 00 10 18 54 00 00  T...T..
时间: 2024-10-21 10:28:01

cpp反汇编之const分析的相关文章

《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口

<C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户main函数. class COne { public: COne() { printf("COne \r\n"); } ~COne() { printf("~COne \r\n"); } }; COne g_One; int main() { printf("

c++反汇编与逆向分析 小结

第一章  熟悉工作环境和相关工具1.1 熟悉OllyDBG  操作技巧1.2 反汇编静态分析工具 IDA(最专业的逆向工具)    快捷键    功能     Enter     跟进函数实现     Esc       返回跟进处    A         解释光标处的地址为一个字符串的首地址     B         十六进制数与二进制数转换    C         解释光标处的地址为一条指令     D         解释光标处的地址为数据,没按一次将会转换这个地址的数据长度   

第3课 - 进化后的const分析

第3课 - 进化后的const分析 1. C语言中的const (1)const 修饰的变量具有只读属性,本质还是变量,只是告诉编译器该变量不能出现在赋值符号的左边. (2)const 修饰的局部变量在栈上分配空间,修饰的全局变量在只读存储区分配空间. (3)const 只在编译期间有用,在运行期间无用.const 不能定义真正意义上的常量(const英文含义)! (4)C语言中的常量只有枚举这一种类型. 2. C++中的const C++ 在 C 的基础上对 const 进行了进化处理. (1

cpp反汇编分析之构造函数

子类构造函数先调用父类.子类保留父类一块空间. 以一个例子分析: class A { public: A() { } ~A() { cout<<"~A"<<endl; } }; class B:public A { public: B(A &a):_a(a) { } ~B() { cout<<"~B"<<endl; } private: A _a; }; int main(void) { A a; //很简单,

cpp反汇编之类和结构体分析

废话不多说.. #include<stdio.h> class CNumber { public: CNumber() { m_nOne = 1; m_nTwo = 2; } int __stdcall GetNumberOne() { return m_nOne; } int GetNumberTwo() { return m_nTwo; }<pre name="code" class="plain">1: #include<stdi

cpp反汇编之菱形继承

先分析一个例子 #include<stdio.h> class CFurniture { public: CFurniture() { m_nPrice = 0; } virtual ~CFurniture() { printf("virtual ~CFurniture()\n"); } virtual int GetPrice() { return m_nPrice; } public: int m_nPrice; }; class CSofa : virtual pub

cpp反汇编之控制结构

控制结构主要是关于  if/else   switch/case 废话不多说..献上代码及反汇编分析.. #include<stdio.h> int main(int argc , char *argv[]) { int nInt = 9; // if(0 == nInt) __asm { cmp DWORD PTR [EBP - 4h] , 0 ; jle __exit; } // __asm { printf("%d\n" , nInt); /* push DWORD

cpp反汇编之多继承

源码 #include<stdio.h> class CSoft { public: CSoft() { m_nColor = 2; } virtual ~CSoft() { printf("virtual ~CSoft()\n"); } virtual int GetColor() { return m_nColor; } virtual int SitDown() { return printf("Sit down and rest your legs!\n&

cpp反汇编之继承之基类

先分析一个例子. #include<stdio.h> class CBase { public: CBase() { printf("CBase\n"); } ~CBase() { printf("~CBase\n"); } void SetNumber(int nInt) { this->m_nNumber = nInt; } int GetNumber() { return this->m_nNumber; } private: int