C语言代码逆向基础-变量在内存中的位置和访问方式

C语言代码逆向基础-变量在内存中的位置和访问方式

在程序中,包含全局变量、局部变量和静态变量。全局变量和局部变量的最大区别是生命周期不同,

全局变量和局部变量的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<stdio.h>

int a=0;
int b=1;

int main()
{
int c=3;
int d=4;
scanf("%d,%d",&c,&d);
printf("%d %d\r\n",c,d);
scanf("%d,%d",&a,&b);
printf("%d %d\r\n",a,b);
}

反汇编关键代码:

可以观察得到,全局变量和局部变量的特征:

全局变量

  • 所在地址为数据区,生命周期与所在模块一致
  • 使用立即数间接访问
  • 先定义变量在低地址,后定义变量在高地址

局部变量

  • 所在地区为栈区,生命周期与 所在函数作用域一致
  • 使用ebp或者esp间接访问
  • 先定义变量在低地址,后定义变量在高地址

局部静态变量

局部静态变量和全局变量都保存在执行文件中的数据区中,且生命周期都相同。如果函数被频繁调用,由于C++语法规定局部静态变量指被初始化一次,那么如何保证编译器每次进入函数体中赋值操作只执行一次?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>

void showStatic( int number)
{
static int a=number;
printf("%d \r\n",a);
}

int main()
{
for(int i=0;i<5;i++)
{
showStatic(i);//循环调用局部静态变量,每次传入不同值
}
return 0;
}

运行程序发现每次输出都为0

关键反汇编代码如下:

1
xor     eax, eax

对eax进行异或指令,eax清空。

1
mov     al, byte_42AE5C

取地址42AE5C处1字节数据到al中

1
2
and     eax, 1
test eax, eax

将eax与数值1做位与运算,eax最终结果只能是0或1

1
2
3
4
5
6
jnz     short loc_40104E
mov cl, byte_42AE5C
or cl, 1
mov byte_42AE5C, cl
mov edx, [ebp+arg_0]
mov dword_42AE60, edx

比较eax,不等于0则执行跳转,等于0则跳转40104E处;通过位运算将标志中的以为数据置1,以此来判断是否已经被初始化。

堆变量

使用malloc与new实现堆空间的申请,返回的数据便是申请的堆堆空间地址,使用free和delete完成堆空间的释放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
#include<stdlib.h>


int main()
{
char * pCharMalloc = (char*)malloc(10);
char * pCharNew = new char[10];

if(pCharMalloc != NULL)
{
delete [] pCharNew;
pCharNew = NULL;
}
if(pCharMalloc != NULL)
{
free(pCharMalloc);
pCharMalloc = NULL;
}
return 0;
}

申请内存空间反汇编关键代码如下:

1
2
3
.text:00401028                 push    0Ah             ; Size
.text:0040102A call _malloc
.text:0040102F add esp, 4

先使用push指令开辟0Ah字节(10字节),然后调用Malloc函数,在平衡esp指针;new指令也是先使用push指令申请空间,然后再调用函数,最后平衡指针。

释放内存空间反汇编代码如下:

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信