某游戏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.

浙公网安备 33010602011771号