【Meの重大突破】中间变量基址与P2的对应关系
ME的最主要优点就是可以方便追踪gdata,cdata,sdata这样的全局数组中任何变量,这个优点要归功于ME已经做好了各个指针间的对应关系。
但是对于非以上各大数组中的变量,在ME已有的构架下似乎无法方便的给出其地址。
最近跟小伙伴们讨论过程中,终于解决了这个难题。现将相关内容整理如下。
[E+ ME已有基本指针关系]
有过因版本更新而自食其力手动调整ME指针的童鞋应该了解,E+的各层指针关系对应如下:
指针地址=>指针对应值
0+修正1=>P1
P1+修正2=>P2
P2+修正3.1=>数组基址CS
P2+修正3.2=>数组基址CA
...
数组基址CS+修正4=>数组CS变量值
修正1-4为各级偏移量(以下用10进制表示),其中,
修正1要通过查找进程名来锁定其大致范围。修正2在主流版本中固定为44,一般不做变动。
而修正3会随着二次加工(反编译+再编译)版本的不同而有所差别,
这就是每次需要玩家逐个表一一手动校对的罪魁祸首。(也就是找到新版本的修正3.1;修正3.2...以此类推)
但是这条也说明数组基址指针的地址,与P2是有固定对应关系的。
修正4其实就是数组中各个变量与该数组基址的偏移量(offset)。对于一个单纯由整型(int)(←ME里大部分都是这样的)变量构成的数组。
每相邻两个变量间地址相差4。因此数组中第k个变量的地址就是(从0开始,k=0代表第一个变量):
数组(k)=数组基址+4*k
一个很重要的发现就是:每个数组本身的地址,除了对应基址指针之外,数组基址偏移-12的地方也会储存着数组的基址。
这个规律不仅适用于数组,同时也适用于中间变量的。(未验证所有数组和中间变量是否全部符合)
同时,中间变量类似数组,也拥有自身的基址指针。
因此,我们想要每次开游戏就找到中间变量的值,只要找到:
P2+修正3=>中间变量基址
中间变量基址=>中间变量值
里面的修正3,就可以说是大功告成。
那么下面以*号锁定目标为例,说明如何找到这一修正值。

在代码中,记录*号目标的,是i@m187这一变量。显然这个变量并不是几个基本数组中的变量。
想要找到其对应的指针,我们需要用CE改变*号目标来锁定。
因为*号目标和cdata角色编号有关。比如0是PC,1-15是队友,16以后是其他冒险者。
大致60以后是该地图其他NPC。
那么只要清楚其编号,自然可以自如改变该变量从而锁定其地址。
一般来说,我们最终会找到两个地址:

这两个值其中一个就是i@m187,另一个是变量tc
因此在*号锁定时,这两个值永远一致。所以我们暂时不去区分,找到其中一个基址指针位置即可。
根据指针储存基址地址的特性。我们用16进制搜索022c4488

可以看到两个结果。其中一个是指针,另一个就是我们提到过的,基址偏移-12所储存的基址地址。
那么显然,16进制的488与16进制的47c相差12,所以第一个是基址偏移-12地址。
而第二个,就是指针的地址。
由此,我们得到了指针的地址,再通过其与P2值的差异,就可以获得 修正3。
为了验证这一概念,我们可以在ME里增加两个基于P2的指针

可以看到现在和上述两个地址是符合的。
如果我们成功,那么重启游戏再次锁定该变量后,ME应该可以自动得到两变量的新地址。
重启游戏,重新锁定,这是新的变量地址:

而ME里给出的地址是:

完全一致,搞定收工~
ME的最主要优点就是可以方便追踪gdata,cdata,sdata这样的全局数组中任何变量,这个优点要归功于ME已经做好了各个指针间的对应关系。
但是对于非以上各大数组中的变量,在ME已有的构架下似乎无法方便的给出其地址。
最近跟小伙伴们讨论过程中,终于解决了这个难题。现将相关内容整理如下。
[E+ ME已有基本指针关系]
有过因版本更新而自食其力手动调整ME指针的童鞋应该了解,E+的各层指针关系对应如下:
指针地址=>指针对应值
0+修正1=>P1
P1+修正2=>P2
P2+修正3.1=>数组基址CS
P2+修正3.2=>数组基址CA
...
数组基址CS+修正4=>数组CS变量值
修正1-4为各级偏移量(以下用10进制表示),其中,
修正1要通过查找进程名来锁定其大致范围。修正2在主流版本中固定为44,一般不做变动。
而修正3会随着二次加工(反编译+再编译)版本的不同而有所差别,
这就是每次需要玩家逐个表一一手动校对的罪魁祸首。(也就是找到新版本的修正3.1;修正3.2...以此类推)
但是这条也说明数组基址指针的地址,与P2是有固定对应关系的。
修正4其实就是数组中各个变量与该数组基址的偏移量(offset)。对于一个单纯由整型(int)(←ME里大部分都是这样的)变量构成的数组。
每相邻两个变量间地址相差4。因此数组中第k个变量的地址就是(从0开始,k=0代表第一个变量):
数组(k)=数组基址+4*k
一个很重要的发现就是:每个数组本身的地址,除了对应基址指针之外,数组基址偏移-12的地方也会储存着数组的基址。
这个规律不仅适用于数组,同时也适用于中间变量的。(未验证所有数组和中间变量是否全部符合)
同时,中间变量类似数组,也拥有自身的基址指针。
因此,我们想要每次开游戏就找到中间变量的值,只要找到:
P2+修正3=>中间变量基址
中间变量基址=>中间变量值
里面的修正3,就可以说是大功告成。
那么下面以*号锁定目标为例,说明如何找到这一修正值。

在代码中,记录*号目标的,是i@m187这一变量。显然这个变量并不是几个基本数组中的变量。
想要找到其对应的指针,我们需要用CE改变*号目标来锁定。
因为*号目标和cdata角色编号有关。比如0是PC,1-15是队友,16以后是其他冒险者。
大致60以后是该地图其他NPC。
那么只要清楚其编号,自然可以自如改变该变量从而锁定其地址。
一般来说,我们最终会找到两个地址:

这两个值其中一个就是i@m187,另一个是变量tc
因此在*号锁定时,这两个值永远一致。所以我们暂时不去区分,找到其中一个基址指针位置即可。
根据指针储存基址地址的特性。我们用16进制搜索022c4488

可以看到两个结果。其中一个是指针,另一个就是我们提到过的,基址偏移-12所储存的基址地址。
那么显然,16进制的488与16进制的47c相差12,所以第一个是基址偏移-12地址。
而第二个,就是指针的地址。
由此,我们得到了指针的地址,再通过其与P2值的差异,就可以获得 修正3。
为了验证这一概念,我们可以在ME里增加两个基于P2的指针

可以看到现在和上述两个地址是符合的。
如果我们成功,那么重启游戏再次锁定该变量后,ME应该可以自动得到两变量的新地址。
重启游戏,重新锁定,这是新的变量地址:

而ME里给出的地址是:

完全一致,搞定收工~