前几天我看到廖传政又在修改游戏,于是就给他较劲,故意编个游戏来让他修改不了。据他说,假如要让血槽不动,一般是找到内存变化的地方,然后锁定就是了。从这一点出发,我想到如果表示内存变化的那个地方完全没的规律,那么就比较难以查找了。
我的想法是,真实的数据不能直接放在内存中,而是代之以一个神秘的数值,这个神秘的数值也完全零乱,也就是说血条上升或下降时,这个值会变化,但不一定也是上升或是下降,也是就他们之间不存在简单的线性关系,更进一步说,如果把这个神秘数与真实数的对应关系是一个函数的话,那这个函数是非线性的,其实光线性还不够,而且要是找不出单调的区间。但是它们之间又要可逆,就是要找出一个可逆的非单调函数。
我的基本思想是,假如要加密的是0到100之间的整数,那么就先生成把0到100随机存放到一个encode数组,作为加密的数组,例如一个真实数56,它所对应的加密数就是encode[56],然后产生一个解密数组,分别存放0到100在encode数组中的索引,也就是for any i in 0..100,encode[decode[i]]=i。如果把encode看成是一个函数,那它的逆函数就是decode。
真正在内存里保存的数都是那个“神秘数”,而真实数都得通过decode数组才能读出,通过encode来写,由于加密和解密的部分都只是几次寻址操作,所以效率并不低,而且我们只对关键的数值进行加密。其它不管。
这个算法我给他做了以后,他算是半个成功了,因为找到了那个显示血槽对象的相关内存,但是真正存放数据的地方却没有找到。本来游戏是用Irrlicht写的3D,很占内存和CPU,下面是我用SDL改写的,完全只保留了最基本的演示:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <time.h>
-
-
#include <SDL/SDL.h>
-
-
SDL_Surface *screen = NULL;
-
int blood;
-
-
int *encode;
-
int *decode;
-
-
int index_of(int array[],size_t size,int value){
-
int index;
-
for(index=0;index<size;index++){
-
if(array[index]==value)
-
return index;
-
}
-
return -1;
-
}
-
-
-
void begin_game(){
-
srand(time(NULL));
-
encode=(int *)malloc(1024*sizeof(int));
-
decode=(int *)malloc(1024*sizeof(int));
-
-
int i,r;
-
for(i=0;i<101;i++){
-
r=rand()%101;
-
if(index_of(encode,i,r)==-1)
-
encode[i]=r;
-
else{
-
i--;
-
continue;
-
}
-
}
-
-
for(i=0;i<101;i++){
-
decode[i]=index_of(encode,101,i);
-
}
-
-
blood=encode[100];
-
}
-
-
void end_game(){
-
free(encode);
-
free(decode);
-
}
-
-
void draw (){
-
-
Uint32 color;
-
color=SDL_MapRGB(screen->format,0,0,0);
-
SDL_FillRect (screen, NULL, color);
-
color = SDL_MapRGB (screen->format, 0xFF, 0, 0);
-
-
SDL_Rect *rect=(SDL_Rect *)malloc(sizeof(SDL_Rect));
-
rect->w = decode[blood]*5;
-
rect->h = 20;
-
rect->x = 100;
-
rect->y = 100;
-
SDL_FillRect (screen, rect, color);
-
free(rect);
-
-
SDL_Flip (screen);
-
SDL_Delay (10);
-
}
-
-
-
-
-
int main (int argc, char *argv[]){
-
char *msg;
-
int done;
-
-
SDL_Init (SDL_INIT_VIDEO);
-
atexit (SDL_Quit);
-
-
screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);
-
SDL_WM_SetCaption ("SDL MultiMedia Application", NULL);
-
begin_game();
-
-
-
done = 0;
-
SDL_Event event;
-
-
while (!done){
-
SDL_WaitEvent (&event);
-
switch (event.type){
-
case SDL_KEYDOWN:{
-
switch(event.key.keysym.sym){
-
case SDLK_UP:blood = decode[blood]+10>100 ? blood : encode[decode[blood]+10];break;
-
case SDLK_DOWN:blood = decode[blood]-10<0 ? blood : encode[decode[blood]-10];break;
-
}
-
}
-
break;
-
case SDL_QUIT:
-
done = 1;
-
break;
-
default:
-
break;
-
}
-
draw ();
-
}
-
-
end_game();
-
-
return 0;
-
}
-
2010年1月30日 04:09
游戏中的每个数值都有个对应的内存地址 遇到可以锁定内存地址的修改猛药 比如CE 那该怎么办?