Windows 逆向-变量前加星号或地址符的使用

Oyst3r 于 2023-12-30 发布

前言

这一讲的核心概念就是,类型随便转就行,C 语言就是用来玩的,带*类型可以相互转换!(强转)(逆向经常会用到)

课堂

类型转换

这个就像前言中所说的那样,除了一些特别离谱的类型转换不能强转,其他一般都是可以的,这里给个强转的代码例子,不能抱有强转是不对的这样的思想

#include "stdafx.h"
struct Student{
    int x;
    short y;
};
void Test(){
	char* a;   //声明
	int* b;
	short** c;
	Student* s;
	a = (char*)1;   //赋值
	b = (int*)2;
	c = (short**)3;
	s = (Student*)4;

    a = (char*)b;       //int*可以强转成char*
    b = (int*)a;        //char*可以强转成int*
    c = (short**)a;     //int*可以强转成short**
    s = (Student*)b;    //int*可以强转成Student*
    //...
}
int main(int argc,char* argv[]){
   	Test();
	return 0;
}

地址符&

&是地址符,任何类型变量前面加上&,就成了一个新的类型变量,类型是:&后面的类型加上一个*

char a = 10;
short b = 20;
int c = 30;
int* d = (int*)40;
double**** e = (double****)50;

char* pa = &a;    //a是char类型,在前面加上&,&a就变成了char*类型;此时pa中存的就是a变量的地址值

short* pb = &b;   //b是short类型,在前面加上&,&b就变成了short*类型

int* pc = &c;     //c是int类型,在前面加上&,&c就变成了int*类型;此时pc中存的就是c变量的内存地址值

int** pd = &d;    //d是int*类型,在前面加上&,&d就变成了int**类型

double***** pe = &e;    //e是double****类型,在前面加上&,&e就变成了double*****类型

其实本来完整的写法应该是:char* pa = (char*)&a。但是我们知道了这是强转的意思,现在&a 本来就是char*类型,编译器认得出来,所以不用再加这个强转,直接简写就可以

再来看看它的反汇编

所以&就是将变量的地址取出来,光取出来没有意义,我们要把这个值赋给一个容器,用什么类型的容器存储呢?就是这个变量的数据类型加一个*

*类型变量前加*

记住:只能在*类型的变量前面加*,不能在一个普通类型的变量前面加*,不然编译器会报错!

//定义并赋值4个带*类型的变量
int* pa = (int*)1;
char** pa2 = (char**)2;
int*** pa3 = (int***)3;
short**** pa4 = (short****)4;

//接着在这些带*类型变量前加*号:得到的新类型就是原来的类型减一个*
int newpa = *pa;

char* newpa2 = *pa2;   //*pa2的值是一个char*类型的,所以现在把*pa2的值取出来赋给一个char*类型的变量 						  newpa2
int** newpa3 = *pa3;

short*** newpa4 = *pa4;

//不能在普通类型的变量前加*
//int a = 1;   不能出现*a

咱们来看一下*的反汇编

用*来操作数组

  1. *(arr+i) = arr[i](arr 是数组名)

  2. arr = &arr[0]

数组名其实就是一个地址,然后就正常操作就行

char arr[5] = {1,2,3,4,5};
char* pa = &arr[0];    //获取arr数组的首地址,也就是arr数组中第一个元素的首地址,这个值的类型为char*
char* pa2 = arr;    //可以直接简写为arr,同样也是获取arr数组第一个元素的首地址

然后刚刚在上面说了带星号类型可以进行的运算,现在把它们结合一下,那就可以用这个指针去 1 操作数组里面的数据了

int arr[5] = {1,2,3,4,5};
int n0 = *arr;    //arr表示数组第一个元素地址值,那么加一个*号就表示取这个地址中存的值,即数组中第一				     个元素的值1
int n1 = *(arr + 1);   //2   这里其实就是取数组首地址+1*4,取这个新地址中存的数,类型为int*减一个							    *,即int类型。即第二个元素的值
int n2 = *(arr + 2);   //3   首地址+2*4,取这个地址中存的值,即第三个元素的值
int n3 = *(arr + 3);   //4
int n4 = *(arr + 4);   //5

//使用for循环加*号的方式遍历数组中的元素
for(int i = 0;i < 5;i++){
    printf("%d ",*(arr + i));
}

作业

1.前面两个的答案在图片已经给出

2.这里给出我的代码

void reverse_arry()
{
	int arry[5] = {1,2,3,4,5};
	int* p = arry;
	int i = 0;

	for(i ;i < 5/2;i++){
		int a = 4 - i;
		int temp = 0;
		temp = *(p + i);
		*(p + i) = *(p + a);
		*(p + a) = temp;
	}

	for(i = 0;i < 5;i++){

		printf("%d ",arry[i]);
	}
}