c语言函数调用的机制

visio大法好啊,以前都是用word手动绘图的(o(╯□╰)o

调试的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#define N 20
struct user
{
char number[N];
char password[N];
};
struct user log_In(struct user u)
{
int i = 0;
printf("请输入用户名:\n");
gets(u.number);
printf("请输入密码:\n");
while ( u.password[i] = getch() )
{
if ( u.password[i] == 13 )
{
break;
}
else if ( u.password[i] != '\b' )
{
printf("*");
i++;
}
else
{
printf("\b \b");
i--;
}
}
u.password[i] = '\0';
printf("\n");
return u;
}
int compare(struct user u)
{
FILE *fp;
char file_str[2*N+1];
char *number, *password;
fp = fopen("F:\\data.txt", "r");
if (!fp)
{
printf("error!\n");
exit(2);
}
while ( fgets(file_str, sizeof(file_str), fp) )
{
number = strtok(file_str, " ");
password = strtok(NULL, "\n");
if ( strcmp(u.number, number) == 0 && strcmp(u.password, password) == 0 )
{
fclose(fp);
return 1;
}
}
fclose(fp);
return 0;
}
int main()
{
struct user u;
printf("--------------------------------\n");
printf("| 用户登录 |\n");
printf("--------------------------------\n");
u = log_In(u);
if ( compare(u) == 1 )
printf("登录成功!\n");
else
printf("登录失败!\n");
return 0;
}

说明

上面的代码模拟的是一个登录系统,是网络对抗老师作为破解密码的例子。
我们可以在debug的时候通过单步调试,可以看到c++语言对应的汇编语言的指令。

若仅仅通过汇编语言就能明白程序的意思,这个过程叫做逆向。

这篇文章的重点是说明函数的调用机制

先贴上自己画的原理图:



所要做的几点说明:

  1. 函数内存的调用就是一个栈的模型。
  2. 我们知道调用两个函数的时候,中间会留下一部分的空间来保存函数的返回时的信息那么黑客就可以改变指针的方向,改变指针以达到窃取信息的目的。

补充

代码中有这样的一段:

1
2
3
FILE *fp;
char file_str[2*N+1];
char *number, *password;

并不是严格的按照栈的规则来存的。



可是老师课上演示的完全就是栈来存的呀。可能不同的软件分配内存的方式也是不同的吧emmmm,也有可能我使用的是c++?
对了,就连函数调用完的指示地址的指针,它的地址也是倒着存的

内存的分配机制

分配的区域的划分:

  1. .就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
  2. ,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete.如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
  3. 自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
  4. 全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
  5. 常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改.

然而我也不是很懂啊,一遇到汇编语言就傻。
内存分配

几种寄存器的简单的介绍

寄存器就是能够记忆保存数据的装置。
寄存器的种类:

  1. EIP:程序所执行到的位置指示
  2. ECP:一种计数(count)的寄存器
  3. EBP:内存栈的栈底(bottom)
  4. ESP:内存栈的栈顶(superficial?)

还有什么EAX,EDI,不是很懂。

操作的指令

  1. sub esp, 28h:将一个esp寄存器减去28h(16进制)
  2. mov ecx, 0Ah:将0Ah传输到ecx寄存器
  3. lea esi, [ebp-28h]:[ ]中采用相对基址变址的寻址方式表达存储单元,然后传入esi
  4. rep: 重复一个指令

还有很多的汇编指令,然而还不是很懂,菜菜的。

未解决的问题

文章目录
  1. 1. 调试的代码
    1. 1.1. 说明
    2. 1.2. 补充
    3. 1.3. 内存的分配机制
    4. 1.4. 几种寄存器的简单的介绍
  2. 2. 未解决的问题
{{ live2d() }}