Windows 逆向-带星号的类型

Oyst3r 于 2023-12-25 发布

前言

这里真的是一种不一样的理解思维,建议大家反复食用,但归根到底就是这几个问题—带星号的数据宽度,它的运算(比如加几减几),与&的联动,每&一次数据类型加一颗*,每*一次数据类型减一颗星,加星减星,指针不一定非要指向什么类型或者什么东西,我们想让它指啥就指啥,因为指针只是用来操作数据的工具

课堂

带*类型的宽度

永远记住的话,*类型的变量宽度永远是 4 字节、无论类型是什么,无论有几个*,咱们下面来探测一下,就用函数那里学的局部变量的知识,虽然堆栈提升是按照本机的尺寸,但使用的时候还是按照本身变量的宽度

#include "stdafx.h"
struct Student{
	int a;
    short b;
    char c;
};

int main(){
    char* x;   //4字节宽度
	int* y;	   //4字节宽度
	Student* s;  //4字节宽度

	x = (char*)1;
	y = (int*)1;
	s = (Student*)4;
}

通过反汇编分析:char 后面跟了后变成带类型,此时通过 dword 可以判断 char数据类型的宽度为 4 字节;同理 int宽度也为 4 字节;而结构体类型后面跟那么此时的新类型的变量是可以直接赋值的,但是要告诉 4 应该被当做 Student类型看待,可以发现,此时的 Student*也同样为 4 字节

如果给这些类型加上两个*或者多个*呢?结果都是一样的,下面看验证的图片

#include "stdafx.h"
struct Student{
	int a;
    short b;
    char c;
};

int main(){
    char**** x;   //4字节宽度
	int*** y;	   //4字节宽度
	Student** s;  //4字节宽度

	x = (char****)1;
	y = (int***)1;
	s = (Student**)4;
}

同样宽度还是 4 字节

声明带*类型变量

在我们现在所学过的任何数据类型的后面加*就是变成了一个新的类型(指针类型!)

char* x;  //char *x是同一个意思,但是按照海哥的讲解,写成char* x更好理解
short* y;
int* z;
float* f;
double* d;
Student* st;

带*类型的变量赋值

先看看我们之前学过的给变量赋值,其实都是简化的赋值,实际上我们给一个变量赋值,应该要说明这个值应该是什么类型,即告诉编译器如何看待这数值;但是之所以可以用简化的写法,是因为编译器现在都很智能,可以通过变量定义时的数据类型来自己将后面赋的值看待成什么类型

char x;
short y;
int z;
x = (char)'c';
y = (short)12;
z = (int)2;

那么用同样的方法也可以给带*类型变量赋值,同样也是要告诉编译器这个值应该当成什么类型看待,因为带*类型编译器是无法自动解析的,所以*类型的变量赋值时只能使用“完整写法”

char*** x;
short* y;
int** z;
x = (char***)'c';
y = (short*)12;
z = (int**)2;

指针的算数特征

带*类型变量做++或者–

我们知道不带*号类型的变量,++或者–,都是加 1 或者减 1,*类型的变量,++ 或者 – 新增(减少)的数量是去掉一个*后变量的宽度

这里还是举例子吧

#include "stdafx.h"
int main(){
    char* x;
	short* y;
	int* z;

	x = (char*)100;
	y = (short*)100;
	z = (int*)100;
	x++;           //得到的结果依然是原来的带*类型
	y++;
	z++;

	printf("%d %d %d",x,y,z); //101 102 104
	return 0;
}

char*去掉*此时类型为 char,所以 x++即 100 + 1
short*去掉*此时类型为 short,所以 y++即 100 + 2
int*去掉*此时类型为 int,所以 z++即 100 + 4

如果带两个*号变量++(或者–),同样先去掉一个*号,然后加上或者减去此时类型的宽度

#include "stdafx.h"
int main(){
    char** x;
	short** y;
	int** z;

	x = (char**)100;
	y = (short**)100;
	z = (int**)100;
	x++;
	y++;
	z++;

	printf("%d %d %d",x,y,z);
	return 0;
}

char*去掉一个此时类型为 char,所以 x++即 100 + 4(我们全面学过任何类型加了不管多少个的变量宽度都是 4 字节)
short*去掉一个此时类型为 short*,所以 y++即 100 + 4
int*去掉一个此时类型为 int*,所以 z++即 100 + 4

带*类型变量加或减一个整数

这个就和上面那个++和–没什么区别,在之后在乘上这个整数即可

#include "stdafx.h"
int main(){
    char** a ;
	short*** b ;
	int**** c ;

	a = (char**)100;
	b = (short***)100;
	c = (int****)100;

	a = a - 4;
	b = b - 4;
	c = c - 4;
	printf("%d %d %d",a,b,c);  //84 84 84
    return 0;
}

char**去掉一个*char*,即宽度为 4 字节,所以 a - 4 = 100 - 4 * 4
下面同理,b - 4 = b - 4 * 4;c - 4 = c - 4 * 4

两个带*类型变量求差值

#include "stdafx.h"
int main(){
    char* a ;
	char* b ;
	a = (char*)200;
	b = (char*)100;
	int x = a - b;  //两个带*号类型必须相同!减完的结果是int类型!
	printf("%d\n",x);   //(200-100)/1 = 100
    return 0;
}

两个带*类型做大小比较

*的变量,如果类型相同,可以做大小的比较,比如

#include "stdafx.h"
int main(){
	char**** a;
    char**** b;
    a = (char****)200;
    b = (char****)100;
    if(a>b){
        printf("1");  //1
    }
    else{
        printf("2");
    }
    return 0;
}

作业

答案当时都写上了,就不多说了