Windows 逆向-字符数组与字符串

Oyst3r 于 2024-01-17 发布

前言

这个主要还是想说用指针和用数组操作一个字符串的区别在哪里,前面那个字符数组与字符串的话相信大家只要学过 C 语言肯定就知道他俩之间的区别在哪里

课堂

字符数组

char arr[10] = {'A','B','C','D','E','F'};   //编译器默认在结尾添加0x00
char arr[3] = {'A','B','C'}; //但是如果没有留出'\0'的空间,编译器就不会自动添加
char buffer[100] = ""; //定义了一个空字符串,字符串中每个字节默认初始为0x00
char buffer[] = ""; //这个数组长度只有1,且默认初始为0x00

所以我们在定义一个字符数组来表示一个字符串的时候,一定要记得在结尾加’\0’,如果不加的话一定要记得预留出空间,这样的话,编译器也可以帮你加上,否则在%s 输出的时候,这个会默认的把\0 前面的东西全部都输出,这样肯定是不对的

字符串

char names[] = “ABCDE”; //可以省略数组大小,但是此时的数组大小应该 6,因为编译器会自动在末尾加 0x00
char* p = “ABCDE”; //这个是将常量区中存储 ABCDE 字符串的首地址赋给 p,此时 p 的长度是 4 字节,常量区的字符 串虽然后面补 0,但是不能算到字符串的长度中,所以字符串的长度应为 5 字节

上面这两个其实就有点引出今天的重点了,这个会在下面具体讲,大家别急哈

字符串和字符数组的输出

char arr1[6] = {'A','B','C','D','E','\0'};
char arr2[6] = {'A','B','C','D','E',0};  //注意区分这里的0不是'0'
char arr3[6] = {'A','B','C','D','E'};   //只要比5大,数组的长度随便
char names[] = "ABCDE";
printf("%s\n",arr1);
printf("%s\n",arr2);
printf("%s",names);
char word[8];
scanf("%7s", word);//最多读7个字符

上面的结果都是一样的,都打印 ABCDE

字符串数组

这里给出它的两种形式

char a[][10] = {"hello","abcdefg"};
上面这个就相当于把常量区里面的字符串复制出来了一份,这句话你可能现在不理解,往后看就行了,看完这篇文章肯定会明白的,一开始的[]是空的,在这里就是1了,因为根据后面有两个字符串嘛,编译器自动会补的
char *a[] = {"hello","abcdefg"};
应该把这个*号写前面哈,这个就是明天那篇文章要说的指针数组,即是一个数组,但里面的每一个元素都是一个指针,这个就直接指到常量区了

常量区

这块早在一开始逆向的时候就讲过,现在再拿出来说一下,记住常量区里面的数据是可读不可写的,一般字符串等会放到常量区里面

重点—字符串的反汇编

char* x = "china";   //x中存的就是存储在常量区的china字符串的首地址,x指针型变量直接指向常量区中的存储				         china字符串的首地址
char y[] = "china";  //这里也是常量区中的china字符串,但是与指针不同的是,这里会将字符串值复制一份到给y				         字符数组变量分配的内存中(栈)
void Func(){
	y[1] = 'A';    //可以修改
    //*(x + 1) = 'A';  无法修改
}

x 本身是可以再修改的:如x = "abc";,但是 x 指向的字符串”china”是无法修改的!即 x 指向常量区的”china”字符串,现在想用 x 去改变常量区的字符串,也是不可以的。具体原因看下面反汇编!

#include "stdafx.h"
int main(int argc,char* argv[]){
	char* x = "china";
	//char y[] = "china";
    return 0;
}

所以可以发现使用指针类型变量 x 操作字符串其实就是修改常量区中的字符串,那么由于常量区中的数据可读不可写,所以编译器不允许使用*(x + 1) = 'A'

#include "stdafx.h"
int main(int argc,char* argv[]){
	char* x = "china";
	//char y[] = "china";
    return 0;
}

有的人会问,那如果把这个 char y[] = “china”;不放到 main 函数里面呢,事实上它还是会从常量区把字符串复制一份到全局变量区,操纵的依然不是常量区原本的字符串

所以:如果想对字符串做写操作,就定义成:char arr[] = "abc";。如果只做读操作,定义成char* arr = "abc"

作业

无无无,很开心哈哈哈哈