内存修改作弊是指用户修改内存数据来达到修改分数,金币,生命的作弊手段,这种作弊方法最常见,门槛也最低,只需要简单地掌握CE类修改器的使用方法即可。
#include <iostream> #include <windows.h> #include <conio.h> int score = 0; int main(){ int a,b,c,s; while (true){ a = rand() % 10; b = rand() % 10; c = a + b; system("cls"); printf("当前分数:%d\n",score); printf("请计算:\n"); printf("%d + %d = ?\n",a,b); scanf("%d",&s); if(s == c){ score++; } else if(s < 0){ break; } else{ score--; } } }
程序在屏幕上打印算式,并要求用户计算结果,计算正确加一分,否则扣一分。
使用CE修改器,搜索分数
很快就搜索到了分数的地址
程序被修改
设定另一个变量verify,将verify的值设定为score的10倍,如果发现score和verify对不上,则认定作弊
#include <iostream> #include <windows.h> #include <conio.h> int score = 0; int verify = 0; void AddScore(); void MinusScore(); void CheckCheating(); int main(){ int a,b,c,s; while (true){ a = rand() % 10; b = rand() % 10; c = a + b; system("cls"); printf("当前分数:%d\n",score); printf("请计算:\n"); printf("%d + %d = ?\n",a,b); scanf("%d",&s); if(s == c){ AddScore(); } else if(s < 0){ break; } else{ MinusScore(); } } } void AddScore(){ CheckCheating(); score++; verify = score * 10; } void MinusScore(){ CheckCheating(); score--; verify = score * 10; } void CheckCheating(){ if(score * 10 != verify){ MessageBox(NULL,"禁止作弊!","AntiCheat",MB_OK); exit(0); } }
定义指针p指向分数,每次修改分数时都重新申请内存空间,并释放老的空间,这样会让CE类修改器无法找到分数的地址,自然就无法修改,但是可能会造成系统开销过多,大量使用指针还容易造成内存泄漏
#include <iostream> #include <windows.h> #include <conio.h> int *p; int main(){ p = (int*) malloc(sizeof(int)); *p = 0; int a,b,c,s; int *last; while (true){ a = rand() % 10; b = rand() % 10; c = a + b; system("cls"); printf("当前分数:%d\n",*p); printf("请计算:\n"); printf("%d + %d = ?\n",a,b); scanf("%d",&s); if(s == c){ last = p; p = (int*) malloc(sizeof(int)); *p = *last + 1; } else if(s < 0){ break; } else{ last = p; p = (int*) malloc(sizeof(int)); *p = *last - 1; } free(last); } }
使用不寻常的方式来保存数据,加大作弊难度。
#include <iostream> #include <windows.h> #include <conio.h> int score1 = 0; int score2 = 0; int GetScore(); void SetScore(int score); int main(){ int a,b,c,s; while (true){ a = rand() % 10; b = rand() % 10; c = a + b; system("cls"); printf("当前分数:%d\n",GetScore()); printf("请计算:\n"); printf("%d + %d = ?\n",a,b); scanf("%d",&s); if(s == c){ SetScore(GetScore() + 1); } else if(s < 0){ break; } else{ SetScore(GetScore() - 1); } } } int GetScore(){ return score1 * 10 + score2; } void SetScore(int score){ score1 = score / 10; score2 = score % 10; }
上述代码将分数分成两部分:score1和score2,真实的分数是score1*10+score2,如果作弊者仍然搜索真实分数,就会得到错误的地址。这仅仅是一种简单的示范,实际上我们可以自定义许多复杂的结构,加大破解难度。例如
struct Num{ bool n1:1; bool n2:1; bool n3:1; bool n4:1; bool n5:1; bool n6:1; bool n7:1; bool n8:1; };
C++中的布尔变量占用一个字节,但是实际上的布尔类型仅需要一位,将8个布尔类型变量放在一个结构体里面,这个结构体占一位,此时一般的修改器会将这8个布尔变量误认为是一个数,经过测试,CE修改器成功被骗到,当八个布尔变量都为true时会将Num识别为数字255。
将数据经过处理后保存,这样的处理可以是简单的加减乘除,也可以是复杂的加密
#include <iostream> #include <windows.h> #include <conio.h> int score = 0; int GetScore(); void SetScore(int s); int main(){ int a,b,c,s; while (true){ a = rand() % 10; b = rand() % 10; c = a + b; system("cls"); printf("当前分数:%d\n",GetScore()); printf("请计算:\n"); printf("%d + %d = ?\n",a,b); scanf("%d",&s); if(s == c){ SetScore(GetScore() + 1); } else if(s < 0){ break; } else{ SetScore(GetScore() - 1); } } } int GetScore(){ return -score / 10; } void SetScore(int s){ score = -s * 10; }