更新的防止游戏修改的算法

  上次我把程序发给了另外一个高中同学,他似乎并没有花多少时间就找出来了。但是看他给我的描述,似乎找到不是真正的存放关键数据的内存。还是给廖传政同学修改的差不多,由于要通过画矩形来显示结果,所以必定要提供一个变量来表示真实的数据。如果放在一个函数的局部变量里,由于局部变量是存放在栈中的,只要调用堆栈相同就可以找到。所以放在堆空间更好,但是我却忽略了一点。如下:

  1. void *p=malloc(100);
  2. free(p);
  3. p=malloc(100)

  这个式子中,p在free前后的值很多情况下是相同的,这样,即使在堆空间,也可能完全相同。为了防止这种情况,我又使用了随机得到一个堆内存的方法,为了防止栈空间也相同,我同样使用了随机层次的递归,这样一来,我觉得应该会提高破解的难度。更新的代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. #include <SDL/SDL.h>
  7.  
  8. SDL_Surface *screen = NULL;
  9. int blood;
  10.  
  11. int *encode;
  12. int *decode;
  13. SDL_Rect *rects;
  14.  
  15. int index_of(int array[],size_t size,int value){
  16.     int index;
  17.     for(index=0;index<size;index++){
  18.         if(array[index]==value)
  19.             return index;
  20.     }
  21.     return -1;
  22. }
  23.  
  24.  
  25. void begin_game(){
  26.     srand(time(NULL));
  27.     encode=(int *)malloc(1024*sizeof(int));
  28.     decode=(int *)malloc(1024*sizeof(int));
  29.     rects=(SDL_Rect *)malloc(1024*sizeof(SDL_Rect));
  30.    
  31.     int i,r;
  32.     for(i=0;i<101;i++){
  33.         r=rand()%101;
  34.         if(index_of(encode,i,r)==-1)
  35.             encode[i]=r;
  36.         else{
  37.             i--;
  38.             continue;
  39.         }           
  40.     }
  41.    
  42.     for(i=0;i<101;i++){
  43.         decode[i]=index_of(encode,101,i);
  44.     }   
  45.    
  46.     blood=encode[100];
  47. }
  48.  
  49. void end_game(){
  50.     free(encode);
  51.     free(decode);
  52.     free(rects);
  53. }
  54.  
  55. void draw (int layer){
  56.     if(layer>0)
  57.         return draw(--layer);
  58.    
  59.     Uint32 color;   
  60.     color=SDL_MapRGB(screen->format,0,0,0);
  61.     SDL_FillRect (screen, NULL, color);   
  62.     color = SDL_MapRGB (screen->format, 0xFF, 0, 0);
  63.    
  64.     SDL_Rect *rect=&rects[rand()%1024];
  65.     rect->w = decode[blood]*5;
  66.     rect->h = 20;
  67.     rect->x = 100;
  68.     rect->y = 100;
  69.     SDL_FillRect (screen, rect, color);
  70.  
  71.     SDL_Flip (screen);
  72.     SDL_Delay (10);
  73. }
  74.  
  75.  
  76.  
  77.  
  78. int main (int argc, char *argv[]){
  79.     char *msg;
  80.     int done;
  81.    
  82.     SDL_Init (SDL_INIT_VIDEO);
  83.     atexit (SDL_Quit);
  84.  
  85.     screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);
  86.     SDL_WM_SetCaption ("SDL MultiMedia Application", NULL);
  87.     begin_game();
  88.    
  89.  
  90.     done = 0;
  91.     SDL_Event event;
  92.    
  93.     while (!done){
  94.         SDL_WaitEvent (&event);
  95.         switch (event.type){
  96.             case SDL_KEYDOWN:{
  97.                 switch(event.key.keysym.sym){
  98.                     case SDLK_UP:blood = decode[blood]+10>100 ? blood : encode[decode[blood]+10];break;
  99.                     case SDLK_DOWN:blood = decode[blood]-10<0 ? blood : encode[decode[blood]-10];break;
  100.                 }
  101.             }
  102.                 break;
  103.             case SDL_QUIT:
  104.                 done = 1;
  105.                 break;
  106.             default:
  107.                 break;
  108.         }
  109.         draw (rand()%10);
  110.     }
  111.    
  112.     end_game();
  113.  
  114.     return 0;
  115. }
  116.  

Algorithm Comments(0) 2008年4月25日 11:32

防止游戏修改的一个小算法

  前几天我看到廖传政又在修改游戏,于是就给他较劲,故意编个游戏来让他修改不了。据他说,假如要让血槽不动,一般是找到内存变化的地方,然后锁定就是了。从这一点出发,我想到如果表示内存变化的那个地方完全没的规律,那么就比较难以查找了。
  我的想法是,真实的数据不能直接放在内存中,而是代之以一个神秘的数值,这个神秘的数值也完全零乱,也就是说血条上升或下降时,这个值会变化,但不一定也是上升或是下降,也是就他们之间不存在简单的线性关系,更进一步说,如果把这个神秘数与真实数的对应关系是一个函数的话,那这个函数是非线性的,其实光线性还不够,而且要是找不出单调的区间。但是它们之间又要可逆,就是要找出一个可逆的非单调函数
  我的基本思想是,假如要加密的是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改写的,完全只保留了最基本的演示:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. #include <SDL/SDL.h>
  7.  
  8. SDL_Surface *screen = NULL;
  9. int blood;
  10.  
  11. int *encode;
  12. int *decode;
  13.  
  14. int index_of(int array[],size_t size,int value){
  15.     int index;
  16.     for(index=0;index<size;index++){
  17.         if(array[index]==value)
  18.             return index;
  19.     }
  20.     return -1;
  21. }
  22.  
  23.  
  24. void begin_game(){
  25.     srand(time(NULL));
  26.     encode=(int *)malloc(1024*sizeof(int));
  27.     decode=(int *)malloc(1024*sizeof(int));
  28.    
  29.     int i,r;
  30.     for(i=0;i<101;i++){
  31.         r=rand()%101;
  32.         if(index_of(encode,i,r)==-1)
  33.             encode[i]=r;
  34.         else{
  35.             i--;
  36.             continue;
  37.         }           
  38.     }
  39.    
  40.     for(i=0;i<101;i++){
  41.         decode[i]=index_of(encode,101,i);
  42.     }   
  43.    
  44.     blood=encode[100];
  45. }
  46.  
  47. void end_game(){
  48.     free(encode);
  49.     free(decode);
  50. }
  51.  
  52. void draw (){
  53.    
  54.     Uint32 color;   
  55.     color=SDL_MapRGB(screen->format,0,0,0);
  56.     SDL_FillRect (screen, NULL, color);   
  57.     color = SDL_MapRGB (screen->format, 0xFF, 0, 0);
  58.    
  59.     SDL_Rect *rect=(SDL_Rect *)malloc(sizeof(SDL_Rect));
  60.     rect->w = decode[blood]*5;
  61.     rect->h = 20;
  62.     rect->x = 100;
  63.     rect->y = 100;
  64.     SDL_FillRect (screen, rect, color);
  65.     free(rect);
  66.  
  67.     SDL_Flip (screen);
  68.     SDL_Delay (10);
  69. }
  70.  
  71.  
  72.  
  73.  
  74. int main (int argc, char *argv[]){
  75.     char *msg;
  76.     int done;
  77.    
  78.     SDL_Init (SDL_INIT_VIDEO);
  79.     atexit (SDL_Quit);
  80.  
  81.     screen = SDL_SetVideoMode (640, 480, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);
  82.     SDL_WM_SetCaption ("SDL MultiMedia Application", NULL);
  83.     begin_game();
  84.    
  85.  
  86.     done = 0;
  87.     SDL_Event event;
  88.    
  89.     while (!done){
  90.         SDL_WaitEvent (&event);
  91.         switch (event.type){
  92.             case SDL_KEYDOWN:{
  93.                 switch(event.key.keysym.sym){
  94.                     case SDLK_UP:blood = decode[blood]+10>100 ? blood : encode[decode[blood]+10];break;
  95.                     case SDLK_DOWN:blood = decode[blood]-10<0 ? blood : encode[decode[blood]-10];break;
  96.                 }
  97.             }
  98.                 break;
  99.             case SDL_QUIT:
  100.                 done = 1;
  101.                 break;
  102.             default:
  103.                 break;
  104.         }
  105.         draw ();
  106.     }
  107.    
  108.     end_game();
  109.  
  110.     return 0;
  111. }
  112.  

Algorithm Comments(1) 2008年4月19日 17:39