指向指针的指针
Posted saintdingspage
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指向指针的指针相关的知识,希望对你有一定的参考价值。
- 占有内存空间就有地址,有地址就可以被指针指向,如果指针作为一个参数,那么改变它就需要指针的地址,指针的指针在这种场景下就应孕而生
注意,命令double *pp = &p;
在c++中编译错误,在c中也会产生警告信息
void main() { int earning = 12000; double *p = &earning; //double *pp = &p;//p的地址为4个字节,pp指向的数据类型double占用8个字节 //pp++执行后前进8个字节 p++前进4个字节,不匹配所以,此行代码非法 printf("p的大小是%d,double类型大小%d ", sizeof(p), sizeof(double)); double**pp = &p;//这样引入了一个崭新的数据类型(double*)double指针类型 printf("p的大小是%d,double* 指针类型大小%d ", sizeof(p), sizeof(double*)); system("pause"); }
一级指针装载变量的地址
二级指针装载指针地址,由此我们可以改变指针的指向,游戏外挂中使用很多。
- 模拟游戏外挂原理
第一步:
准备一段代码模拟苏联图-128截击机的载油情况,这段代码试图捕捉到代码执行过程中各关键变量的地址,然后交给指针的指针修改 #include<stdio.h> #include<stdlib.h> void main() { int fuelindex = 100; int fuelindex_m = 66; int fuelindex_l = 23; printf("fuelindex:%x ",&fuelindex); printf("fuelindex_m:%x ", &fuelindex_m); printf("fuelindex_l:%x ", &fuelindex_l); char fuellevelhigh = ‘h‘, fuellevelmedium=‘m‘, fuellevellow=‘l‘; printf("高级载油量地址为:%x ", &fuellevelhigh); printf("中级载油量地址为:%x ", &fuellevelmedium); printf("低级载油量地址为:%x ", &fuellevellow); char *fuellevel = &fuellevelhigh; system("pause"); }
输出结果:
第二步:编写模块
如果你使用了微软的vs2013集成开发环境,选中解决方案----添加----新建项----visual C++-----常规-----空项目,命名完成后,选中源文件----添加----新建项,开启一个.c文件,我命名为gametrick.c,
然后选中gametrick.c----属性----配置属性----目标文件扩展名选择.dll
往这个文件写入一个函数,在函数体之前添加 _declspec(dllexport);(尽管到目前为止,我也弄不清这是什么,但是就先加上吧)
_declspec(dllexport) void go() { //int *p = 0xcffbcf;//这样还不够,因为仅仅知道表示地址的值0xcffbcf,但并不知道是什么类型 //也就无从知道执行前进操作时,前进几步 //所以 int *p = (int *)0x12ff964; *p = 87; }
写完后在IDE 找到生成--生成,这样就生成了一个动态链接库文件
接下来运行你的主程序,打开DLL注入文件,选中主程序文件对应的那个进程
#include<stdio.h> #include<stdlib.h> #include<Windows.h> void main() { int fuelindex = 100; int fuelindex_m = 66; int fuelindex_l = 23; printf("fuelindex:%x ",&fuelindex); printf("fuelindex_m:%x ", &fuelindex_m); printf("fuelindex_l:%x ", &fuelindex_l); char fuellevelhigh = ‘h‘, fuellevelmedium=‘m‘, fuellevellow=‘l‘; printf("高级载油量地址为:%x ", &fuellevelhigh); printf("中级载油量地址为:%x ", &fuellevelmedium); printf("低级载油量地址为:%x ", &fuellevellow); char *fuellevel = &fuellevelhigh; while (1) { printf(" 载油量是%d,%c", fuelindex, fuellevelhigh); Sleep(3000);//为避免打印过于频繁,需要暂缓执行,引入windows.h函数 } system("pause"); }
注入,生成的模块
看到图中第一行显示的载油量地址为 12ff964,添加到模块文件时,需要改为0x12ff964
通过指针的指针改变值,不知你是否也这样倒霉,弄了一下午,就是改不对
_declspec(dllexport) void cpc() { //char*p = 0xcffbcf;//这样还不够,因为仅仅知道表示地址的值0xcffbcf,但并不知道是什么类型 //也就无从知道执行前进操作时,前进几步 //所以 char **p = (char **)0xeffd47; *p = (char*)0xeffd3b; }
这种改法,感觉很不稳定
总之指针的指针赋值的时候:
类型适配规范:
下列代码侥幸会成功
#include<stdlib.h> void main() { char mark = ‘Z‘; char *tomark = &mark; char **tochar = tomark; printf("%x", tomark); system("pause"); }
而下列代码即使运行时不报错,也一定会导致异常结果
void main() { double mark = 3.1415826; double *tomark = &mark; double *tochar = &tomark; printf("mark大小:%d,tomark大小:%d,tochar大小:%d ", sizeof(double *), sizeof(&mark), sizeof(tomark)); printf("tochar的结果:%lf ",*tochar); getchar(); }
输出结果:
究其原因是一个一级指针A变量,如果存入了另一个一级指针B的地址,那么就意味着给指针A分配了大小为4的空间,但是double类型的长度是8,这就导致了溢出,从而造成实际结果不准确
有影像资料显示,2014年时,vs2013平台上该上机实验会导致报错,现在是2019年可能c语言的标准发生了一些改变,或者微软做了某些优化处理,但类型不匹配导致的数值不准确的风险的确存在!!!
void main() { double mark = 3.1415826; double *tomark = &mark; double *tochar = (double *)tomark;//所以这一步的类型强转必不可少 printf("tochar的结果:%lf ", *tochar); getchar(); }
输出结果:
这种四舍五入是正常的,因为double只能容纳8位
以上是关于指向指针的指针的主要内容,如果未能解决你的问题,请参考以下文章