某游戏map内存数据的逆向

个人觉得逆向游戏,比一般程序要来的简单,一个特定的操作就能实现一个特定的功能.
这样很容易定位到目标函数,然后进行逆向.
随笔,备忘.

 int _my_x = my_x >> 5; //右移5位,等于除以32,说明实际地图数据为显示的X,Y除以32
 int _my_y = my_y >> 5;
后面的代码用到得都是_my_x, _my_y,这可以解释为MAP数据的精度和游戏内显示的不同,游戏显示坐标/32

 

 //比较X,Y是否超出最大值
 if ((_my_x >> 6) < 0)
 {
  return FALSE;
 }
 if ((_my_x >> 6) > map_info.maxX || (_my_x >> 6) == map_info.maxX)  
 //map_info.maxX = [map_info + 180],因为每次都是和x坐标位右移 11位后做比较,所以取这个名字
 {
  return FALSE; 
 }

my_x >> 11 后每次都是和map_info.maxX比较,大于等于就返回.可以暂时把map_info.maxX推测为my_x >> 11的最大值.
my_y做和my_x同样的处理.

 

//推测 map_info + 188,以后存着小块地图的信息,块大小为 2048*2048
 int _ecx = (_my_x >>6) << 6 + _my_y >> 6;
 _ecx = [map_info + 188 + _ecx * 4];     
 if(_ecx == 0)
 {
  return FALSE;
 }

看[map_info + 188 + _ecx * 4], _ecx*4 这是一个最常见的数组;
分析这句 int _ecx = (_my_x >>6) << 6 + _my_y >> 6 , 0-5位保存my_y >> 11, 6-11位保存 my_x >> 11.
从上两条分析可以看出这是用1个数组来保存2维信息.

 int call_1_arg1 = _my_x & 0x8000003F;     //保留最高位和低6位
 int call_2_arg2 = _my_y & 0x8000003F;
 int _eax = call_1(call_1_arg1, call_1_arg2, _ecx);  //_ecx用ecx传递参数  _eax = _ecx + ((x << 6) + y) * 12;
 if (_eax == 0)
 {
  return result;
 }

从 int call_1_arg1 = _my_x & 0x8000003F 可以看出, 这个运算就是保留符号位和低6位.

 

接着看call_1函数的运算
int call_1(call_1_arg1, call_1_arg2, _ecx)
{
 _ecx = [_ecx + 1c];
 int _eax = ((call_1_arg1 << 6) + call_1_arg2) + ((call_1_arg1 << 6) + call_1_arg2)*2;
 int _eax = _ecx + _eax *4;
 return _eax;

 //上面是直接翻译.下面为推测
 //(call_1_arg1 << 6) + call_1_arg2) + ((call_1_arg1 << 6) + call_1_arg2)*2;
 //可以简化为 ((call_1_arg1 << 6) + call_1_arg2) * 3;
 //_ecx + _eax *4;则为简化为 _ecx + ((call_1_arg1 << 6) + call_1_arg2) * 12;
 /*
 以下为[_ecx + 1c]指向的内容,貌似是12字节为一个元素
  01A6309C  40 20 7E 00 00 00 E5 41 08 98 78 01 80 40 7E 00  @ ~...錋榵€@~.
  01A630AC  00 00 E5 41 10 43 7A 01 C0 60 7E 00 00 00 E5 41  ..錋Cz繾~...錋
  01A630BC  7C FF 78 01 40 20 7E 00 00 00 E5 41 94 4E 78 01  |x@ ~...錋擭x
  01A630CC  00 00 7E 00 00 00 E5 41 94 42 7B 01 00 00 7E 00  ..~...錋擝{..~.
  01A630DC  00 00 E5 41 9C 37 7B 01 40 20 7E 00 00 00 E5 41  ..錋?{@ ~...錋
  01A630EC  D4 90 7A 01 C0 60 7E 00 00 00 E5 41 4C 69 7B 01  詯z繾~...錋Li{
  01A630FC  C0 61 7E 00 00 00 E5 41 28 57 78 01 C0 61 7E 00  繿~...錋(Wx繿~.
  01A6310C  00 00 E5 41 54 AC 78 01 80 41 7E 00 00 00 E5 41  ..錋T瑇€A~...錋
  01A6311C  7C 94 7A 01 80 41 7E 00 00 00 E5 41 74 1F 79 01  |攝€A~...錋ty
  01A6312C  40 21 7E 00 00 00 E5 41 CC CD 78 01 40 21 7E 00  @!~...錋掏x@!~.
  01A6313C  00 00 E5 41 60 B2 78 01 80 41 7E 00 00 00 E5 41  ..錋`瞲€A~...錋
  01A6314C  34 F0 78 01 80 41 7E 00 00 00 E5 41 B0 23 7B 01  4饃€A~...錋?{

  40 20 7E 00 00 00 E5 41 08 98 78 01  size = 0xC
  80 40 7E 00 00 00 E5 41 10 43 7A 01
  C0 60 7E 00 00 00 E5 41 7C FF 78 01
  .....
 */

}

看 _ecx + ((call_1_arg1 << 6) + call_1_arg2) * 12 , 很明显这也是一个数组,元素的长度为12字节.

((call_1_arg1 << 6) + call_1_arg2)从这里可以看出,和上面一样,也是低0-5位存y信息,6-11存x信息.也是一个用数组存储2维信息.

以上是内存分布和算法.可以做以下总结.
1.把完整地图划分为N块小地图存储.
2.小地图的大小为 2048*2048.
3.算法,都是用数组存储2维信息.

模拟读取X,Y点的信息:
先看X.Y属于哪块小地图,读取小地图指针,然后在小快地图信息里,读取X.Y坐标的信息.

根据信息成像就比较简单了.位图,表述各个点的信息就OK.

 

 

 

 

posted @ 2009-05-30 13:41  鸿鹄  阅读(778)  评论(0)    收藏  举报