ryan_knight_12吧 关注:46,986贴子:2,769,991

回复:【伪技术贴】从零开始的SIRE学习日记

只看楼主收藏回复

【第五弹】一起做SIRE 1.29吧(兼CE教学)
在这一弹中,我们一起来做SIRE的新君主技(名字我还不知道叫啥):所属势力内政设施行动力-1。在RK的设计中,君主技和本身特技是不冲突、可以并存的,但是我们这次简单一点,就用君主本身的技能判定。我们的目标效果姑且设置成,如果君主的技能是“能吏”,则所有行动力-1。这一弹的性质以教学为主,我不会把整个特技做出来,只会给大家讲一下最核心的思路,顺便介绍一下CE。(因为RK说他已经在做了)
为了实现这个效果,首先我们找和行动力有关的函数。RK的资料显示,4A1820是军团消耗行动力(势力本身也是一个军团)。在IDA中搜索所有的XREF(引用),其中有-20行动力大概有一页那么多。
我们当然可以一个一个点进去,逐个阅读每一个调用了减行动力的函数都是干什么的。然而,这实在是太复杂了,毕竟静态就意味着无法调试,只能肉眼反汇编,效率极低。
所以我们这一次引入CheatEngine(简称CE),一个为桌面游戏设计的、基于内存的动态调试。动态调试与之前的exe修改不同的是,之前我们需要手动写机器码、然后用Hex workshop导入,虽然有一些trick可以使整个过程更加简单(比如先在IDA里边改,确保结果正确),但是毕竟还是有些复杂了。使用CE,我们直接修改内存,就算修改崩了也大不了重启一下游戏。
在开始修改之前,要明确的是,我们修改的目标是【脱壳版三国志11威力加强版1.1】的exe,是一个修改日期为2014/06/01,文件大小约156MB的exe,如果使用未脱壳版的exe,可能出现CE跳出等问题。
下面就开始吧。CE最大的好处在于,它可以动态设置断点。达到和主流正向编译器差不多的效果。在游戏中,任何内政指令都一定会调用行动力减少的函数,在行动力减少的函数执行完毕后,会返回到之前调用的下一条指令。因此,我们只要将断点设置到行动力函数减少的函数中,然后看一下是谁调用了这个函数(专业术语:查看调用堆栈),我们就可以知道每个函数都是干什么的了。
完整步骤如下:
①打开311pk脱壳版主程序,载入游戏。【将分辨率设置为窗口模式】(否则停在断点之后还要切出去,很麻烦)。
②打开CE,点击左上角闪烁的图标,选择已经打开的311主程序(可能是乱码,因为311主程序采用的是繁体版的BIG5编码,在Windows下兼容性不好)。

③点击CE上的”Memory View”,进入内存查看区域。右键点击”jump to address”,输入已知的减行动力代码段地址:4A1820,在跳转后选中代码,使用快捷键F5设置断点。设置断点后,该行代码将变为红色。
如果我们要设置断点,就需要把CE自带的调试器连接到程序上,如果弹出“是否连接调试器”的弹窗,记得点“是”。
这一步中,我们并不关心在4A1820段发生了什么,只关心它会退出到哪里。因此,我们可以直接找到这个函数的ret指令,设置断点,这样就避免每次还需要手动完成整个函数体的执行过程。

④切回游戏。假设我们想知道巡查的函数位于哪个位置,我们就进行一次巡查。如果上述操作正确,CE的Memory View弹窗的标题会提示,现在已经停在了某个断点。我们接下来使用快捷键F8进行单步执行。(注意:F7 F8都是单步执行,区别在于,如果一行代码调用了一个函数,F7会进入这个函数,F8会直接等待函数执行完毕进入下一行。如果需要查看函数调用的子函数的执行过程,请使用F7。)
⑤在执行完ret后,函数会回到上一层调用的函数中,如果到了哪一层时,函数不一样了,就说明这一层是因行动而已的调用函数了。我们接下来就可以针对性的分析这一段代码,这样就节省了大量的精力。
贴一下我找到的各个行动指令调用行动力的位置:
军团改变行动力:004A1820
军团行动(会调用上一个函数消耗行动力):005B9340
巡查:5CBF95
市场等内政建设:5BC4C1
商人:5CAD1B
征兵:5C3CAB
生产兵装:5C67B3
研究技巧:5D8F68
吸收合并:5D758B
在这些函数中,会先push入一个值(比如20)作为函数参数,然后执行消耗行动力的函数。我们只需要先判断君主有没有这个技能,然后针对性的给每一个-1即可。加入这些逻辑,我们需要在额外代码段设置代码,然后跳转过去。这一部分的操作方法在上一弹中已经介绍的比较详细了,留给诸位作为练习~
顺便讲一下RK的君主技是怎么实现的吧。这一部分不是我做的,是RK和我讲的。在RK的整理资料中,我们会发现每个武将实际上有0x190个字节的信息,包括了五维、性格、亲爱武将等信息,集中储存在程序7200000左右的区域。在C语言中,这实际上就是一个struct。在这0x190个字节中,有一部分是空白的,也就是说,并没有被用上,被统一置为全0。我们可以利用这一部分空白信息加入君主技的相关信息,然后编写相关函数读写信息,完成君主技的系统设计。
至于这一部分,希望RK多多[url]http://发 表[/url]勤政,早日放出SIRE 1.30。
下一弹,我们讲多人搜索的实现(which我还没完全理清头绪,所以我会一边做一边写一边发)


IP属地:北京63楼2018-08-01 15:54
回复
    太难了 看不懂……还是饥荒mod里面那种接近js的易懂好写


    IP属地:黑龙江64楼2018-08-01 16:11
    回复
      2025-07-26 00:53:03
      广告
      不感兴趣
      开通SVIP免广告
      用od会不会方便些,你这样改二进制文件会不会太麻烦了。还有,楼主这是要做教程呢。。那么啰嗦,懂的嫌啰嗦,不懂的看了你这个也不懂


      来自手机贴吧65楼2018-08-01 16:28
      回复(2)
        好棒!


        IP属地:上海66楼2018-08-02 14:01
        回复
          哇 比想象的麻烦多了


          IP属地:上海来自iPhone客户端67楼2018-08-03 02:31
          回复
            加油


            IP属地:上海来自Android客户端68楼2018-08-03 07:03
            回复
              第六弹·多人搜索(1)UI文字修改(兼CE内存搜索I)
              多人搜索是PKME的亮点功能,我们这一整个的目的是把多人搜索整合进SIRE。在第一弹中,我们先进行最简单的UI替换。我们的目标是,把UI中“探索武将”文字改为“多人搜索”,效果如下:

              首先要明确的是,所有的字符串,比如“登庸武将”、“螺旋突刺”等都储存在exe文件中的固定数据段,会随着exe载入内存。因此,我们只要修改内存中相应的数据(而非代码),就可以改变UI中的文字。
              三国志11中用的是【BIG5】编码储存繁体汉字的。BIG5转换器在网上都有,请大家自行寻找。
              下面用CE来搜索替换字符串。首先,假设我们要改变“探索人才”为“多人探索”。首先我们要写出“探索人才”的【繁体字】,这个最蠢的办法就是在word里转换,其他方法大家自行探索。然后在BIG5码查询器中查出对应的BIG5码,按照【小端序】排列。小端序是什么意思呢?就是把所有的字节(2位16进制)按倒序排列就好了。比如,“探索”的小端序为C1AFB4B1,“人才”为F7A748A4。
              接下来,打开CE,在右侧点选“Hex”框(因为是16进制),然后选择4 byte(8位16进制 = 4 byte),点击first scan。如果***作没有错误,左侧的选框会出现大量匹配项。其中的某一个就是我们要找的。在这里有一个小技巧:在这些选项中,有一些是固定的数据区,不会随着操作改变;还有一些只是被加载到内存里的数据。因此,我们可以在游戏里随便干点别的事情,然后再回去,点击“Next Scan”,在刚刚已经筛出的结果中再筛一次,这样就可以筛掉被加载到内存中的部分,留下固定的数据区。
              剩下的中,有一个是UI中的“探索”或者“人才”字符串,我们需要找到它。如果数据不多的话可以一个一个改,然后看看游戏中有没有相应的改变。如果比较多的话可以采用二分搜索的办法,每次改一半,看看结果有没有变,这样每次可以筛掉一半错误选项,算法复杂度下降为logN。
              最终我们会发现,“探索”位于007EB684,“人才”位于007EB688,将这两个数据用CE改成“多人”与“探索”的BIG5编码的小端序,即可完成UI中的替换。
              在这里我没有太过深入的去讲解CE的操作方法,因为类似的教程在网上有很多,甚至CE还自带了一个类似于闯关游戏的教程,推荐大家玩一玩(在菜单Help – Cheat Engine Tutorial中)
              下一弹我们讲如何增加菜单项(在召唤移动搜索登庸褒赏授予没收的基础上,增加一个新的选单),效果如下:


              IP属地:北京69楼2018-08-04 09:11
              收起回复


                IP属地:中国香港来自Android客户端72楼2018-08-07 03:36
                回复
                  2025-07-26 00:47:03
                  广告
                  不感兴趣
                  开通SVIP免广告
                  (最近一直在导师手下做科研,实在没时间写教程、做修改,今天有空写一篇出来)
                  注意:这一篇没有(多余精力去)配图,请大家先学会CE的基本使用后再来观看,否则会出现一脸懵逼的状况。
                  第六弹·多人搜索(2)界面修改(兼CE内存搜索II)
                  这一弹中我们增加选单数。这里的逻辑是怎么实现的呢?在RK的指点下,我们可以去研究一下计略·落雷的显示逻辑——如果部队中有鬼门特技,则落雷和妖术会显现,如果有妖术特技,单独的妖术会显现,而如果都没有,则两种计略连显示都不会显示(而非灰色)。
                  我们推测,应该是有一个专门的显示函数,函数的一个参数就是选项的数量,然后程序一个一个去调用字符串并显示。如果我们能改掉传入的参数数量,那么就可以起到增加/减少显示选单的作用了。(为什么要减少选项呢?比如说我们可以删掉吸收合并的UI显示。)
                  我们采用CE的Next Scan模式来定位传入的选项数量参数。首先,我们点击城市 – 都市,会出现开发、征兵等等选单。维持鼠标位置不要动,直接用Alt + Tab切到CE,设置搜索长度2 byte,用First Scan搜索7,因为都市下有7个选项(从开发到研究技巧)。搜索后,我们得到了一堆结果。
                  切回311,打开军事选单,训练、出征、输送三个选项出现后,维持鼠标位置,切回CE,搜索3,点击Next Scan,意思是在之前搜到的东西里边继续搜3。再切回311,点开人才,再切回CE用Next Scan搜索6...几次之后,我们发现只有三个结果了,它们会随着我们选择的菜单而改变选项数。这三个分别位于0019F318, 0019F334, 0019F42C。0019xxxx是属于游戏运行时的堆栈区域,并不是我们的代码,因此没有办法静态分析,必须动态分析它们是如何压进去的。
                  这三个数据中只有“最早”确定的那个是有用的,因为后两个参数很可能是UI“复制”了第一个参数用于显示。这里有一个重要的小技巧:在汇编语言中,堆栈的push顺序是从高到低的。换言之,假如第一个数据的内存位置在10000,我们再push一个数据,它的位置是9999,之后是9998,以此类推。换言之,【如果几个数据同时存在于栈中,那么地址最高的数据一定是最先入栈的】。因此,0019F42C是最早入栈、最根本的数据。当然,这个方法只适用于堆栈区域,如果是静态代码就没有用了。
                  如果实在不放心这个trick,或者遇到了不一致的情况,另一种比较笨的方法就是查看三个数据的调用堆栈顺序,最顶层的调用者所对应的数据是最根本的数据。如果我们使用这种办法,会发现调用0019F318的堆栈为4DFE26<-4DC47A<-4DC8EA<-59EE9A<-59F204<-59F4C9<-618687<-6187B1(左侧被右侧调用),而最右边的59F204正是0019F42C对应的修改代码段,也印证了0019F42C是最根源的数据。
                  (调用堆栈 其实就是 调用顺序 的意思,汇编中使用call语句调用函数,函数执行结束后,会用ret语句返回调用的地方。我们在函数中设置断点,观察每一次ret后回到的位置,将这些位置穿起来就得到了调用堆栈。比如上边的例子中,6187B1调用了618687,618687又调用了59F4C9,59F4C9调用了59F204...以此类推)
                  我们选中0019F42C的数据,右键点击Find out what writes to this address,监视所有改变这个值的代码。接着我们回到游戏,再随便点一个别的选单,就会发现在监视窗口中,出现了两行代码。第一行代码只被调用了一次,在IDA中反汇编这行代码,发现是将这个值清零。这个是一个初始化清零的指令,我们不用管。第二行代码(0059F281)被调用了n次(n=选项数量),在IDA或CE中查看,会发现这是一行自增指令。
                  因此,代码逻辑很清晰了。每次点击新的菜单时,先将显示的选项数(称为x)清零,接着,进行n次x++操作,达到将n赋给x的效果,其中n是菜单数量。因此,只要我们修改自增指令的调用次数n,就能相应修改显示的菜单数。
                  在CE中观察4DFE26的调用堆栈,理论上,我们要找的东西为一个带break的while循环。Break条件即为循环指定次数。我们沿着上边的调用堆栈一路找过去,发现6185C0函数就是我们要找的:用IDA的F5功能,可以看到函数中出现了这样的语句:
                  while ( 1 )
                  {
                  // call some functions,
                  if ( ++v7 > v11 )
                  {
                  v5 = a2;
                  goto LABEL_11; // 在v7自增到一定值后跳出,等同于break
                  }
                  }
                  用CE设断点调试,我们发现eax与edi寄存器中储存的是【从第一个菜单的第一条选项(即内政中的开发)到当前菜单最后一条的距离】,edx初始存的是“当前菜单栏中第一条的序号”(比如“君主”菜单的第一条·评定的序号为32),每次自增edx,等edx == eax后跳出。最终的效果就是,显示当前菜单从第一条到最后一条的全部内容。而具体eax和edx中的序号和距离,合理推测是从内存中某一段固定数据中提取出来的。
                  分析上下文汇编代码,发现eax与edi中的【总距离】是调用了一个函数后确定的。用CE动态调试,发现函数位于617890,点开之后发现就是非常明了的一个switch-case语句,在代码中写死了每一个菜单(如内政,军事,人才等)中选项卡的个数。我们直接改掉这部分的内存、给人才选项卡多一个选项就ok了。
                  但是这样又会带来新的问题:游戏中所有的字符串是紧密排放的,采用base+offset的方式寻址。换言之,选项单--显示的字符串是一一对应的,如果我们要增加新选单(比如大家心心念念的禅让、答题等等),必然就要覆盖掉已有的另一个旧选单。这使得加入新的菜单比较困难,目前只能做到替换功能,替换后原有功能消失。这一部分是血色工作组仍然没有搞定的技术难点。我和RK的初步共识是可以通过在寻址时新增代码解决,但是目前还没有开始动工


                  IP属地:北京73楼2018-08-15 19:56
                  回复
                    看不懂只管膜拜


                    IP属地:广东来自iPhone客户端74楼2018-08-15 20:33
                    回复
                      这个就厉害了


                      IP属地:上海来自iPhone客户端75楼2018-08-15 20:35
                      回复
                        很多pvp党要的智力差>X必中
                        冲突说明:修改了“虚实”附近的代码段。可能与对特技虚实的改动冲突
                        以下为Auto Assembler脚本,可直接用Cheat Engine的Ctrl+A快捷键粘贴后修改
                        920500:
                        // 判定虚实
                        push 2
                        push 39 // 虚实
                        call 495680
                        cmp eax, edi
                        jg 92051D // 有虚实则跳转至ret
                        // 判定新增的全局特性
                        mov eax, 0
                        mov al, [ecx+C6] // 取不对智力
                        sub eax, 0A // 0A为智力差,可调
                        cmp eax, edi // 比较、返回
                        ret
                        5AEC07: // 以下均为不同计略的位点。修改了虚实,将虚实部分抹去,改为跳转至新函数,一起判断虚实与新特性
                        mov ecx, esi
                        call 920500
                        jg 5AEC38
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        5AEC58:
                        mov ecx, esi
                        call 920500
                        jg 5AEC38
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        5AED39:
                        call 920500
                        jg 5AEC38
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        5AEEBB:
                        call 920500
                        jg 5AEC38
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        5AF00C:
                        mov ecx, esi
                        call 920500
                        jg 5AEC38
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        5AF0C7:
                        call 920500
                        jg 5AEC38
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop
                        5AF227:
                        call 920500
                        jg 5AEC38
                        nop
                        nop
                        nop
                        nop
                        nop
                        nop


                        IP属地:北京77楼2018-08-19 23:28
                        回复
                          **,311要被玩坏了啊


                          来自Android客户端79楼2018-08-19 23:37
                          回复
                            能修改Al吗?


                            IP属地:河北来自Android客户端80楼2018-08-20 07:13
                            回复
                              2025-07-26 00:41:03
                              广告
                              不感兴趣
                              开通SVIP免广告
                              好厉害 加油 支持楼主


                              IP属地:河北81楼2018-08-20 15:57
                              回复