滴水逆向--01-29 C语言05_正向基础
变量的声明
- 声明变量就是告诉计算机,我要用一块内存,你给我留着,宽度和存储格式有数据类型决定。
- 计算机什么时候把这块内存给你,取决于变量的作用范围,如果是全局变量,在程序编译完就已经分配了空间,如果是局部变量,只有所在的程序被调用的时候,才会分配空间。
- 全局变量如果不赋初始值,默认是0,但局部变量在使用前一定要赋初值
类型转换
-
MOVSX先符号扩展,再传送(有符号数用)1
2
3
4MOV AL, 0xFF 1111 1111
MOVSX CX, AL 1111 1111 1111 1111
MOV AL, 80 1000 0000
MOVSX CX, AL 1111 1111 1000 0000 -
MOVZX先零扩展,再传送(无符号数用)1
2
3
4MOV AL, 0xFF 1111 1111
MOVZX CX, AL 0000 0000 1111 1111
MOV AL, 80 1000 0000
MOVZX CX, AL 0000 0000 1000 0000
当表达式中存在不同宽度的变量时,结果将转换为宽度最大的那个。
当表达式中同时存在有符号和无符号数的时候,表达式的结构将转换为无符号数。
课后作业
-
基于缓冲区溢出的 HelloWorld
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void HelloWorld() {
printf("Hello World");
getchar();
}
void Func() {
int arr[5] = {1, 2, 3, 4, 5};
arr[6] = (int)HelloWorld;
}
int main(int argc, char* argv[]) {
Func();
return 0;
}
数组首先开辟了存储 5 个变量的空间,arr[0] 在
[ebp-14h]的位置,那么 arr[6] 就会存在[ebp-14h]+6*4的位置也就是[ebp+4](如图箭头所指),而原本这里是存储函数返回地址的,现在被覆盖成了 HelloWorld 函数的首地址,所以在 Func 执行结束返回时,CPU 就跳去执行 HelloWorld 了。 -
永不停止的 HelloWorld
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Func() {
int i;
int arr[5] = {0};
for (i = 0; i <= 5; i++) {
arr[i] = 0;
printf("Hello World!\n");
}
}
int main(int argc, char* argv[]) {
Func();
return 0;
}

从汇编中可以看出来,arr 数组存在 [ebp-18]~[ebp-8],[ebp-4] 这里存的是 i,问题就在于 for 循环对 arr 数组进行了六次赋值,而第六次赋值时 arr[5] 的地址是 [ebp-4] 也就是 i 的位置,又把 i 变成了 0,导致一直在 for 循环里出不来