12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 321|回复: 0

战矛在线外挂制作经验分享(用脚本语言python+lua来节省分析时间)

[复制链接]

312

主题

312

帖子

634

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
634
发表于 2021-7-26 01:28:41 | 显示全部楼层 |阅读模式
本人是一名从事游戏开发的程序猿,平时也喜好玩游戏,好比题目上的这款战矛在线warspear,是一款像素风的mmorpg。
不外有个题目就是这款游戏是真的肝,像我这种天天996的人是没有时间玩的,最终办理这个题目的方法,只能是做外挂了,让计算机自己玩自己{:1_886:}。
这个外挂开发过程中的相关代码,截止到放弃时候完成了,获取怪物信息,打怪,捡物品等功能(之所以放弃因为我发现要想完备做一个外挂,也挺肝的,基本方法学会了,背面就是前面操纵的重复了)。
https://github.com/shanlihou/hack_warspear
当然也要感谢郁金香老师,我也是看了他的视频后学到了许多东西后才开始做的,我这里介绍一些他视频里没有的东西吧。

hack_warspear

0x01:须要工具

1.immunity debugger

之所以选择 immunity 而不用od是因为这个调试器支持python,实现用python来简化一些重复性工作,好比在断点时候打印一些寄存器信息,内存信息等等,虽然od应该也可以做,不外对我这种不太习惯的人来说学习成本有点高。
2.cheat engine

郁金香老师的外挂视频教程中也常常利用的一个查基址,甚至调试的软件。而且我发现ce也支持脚本语言,你是可以通过编写lua脚原来实现许多功能,好比查看堆栈等等
0x02:目次结构

GameData
InjectDll
UpdateBase
hackWarspear
immunity:该目次存放为immunity debugger写的一些python脚本
info:该目次存放一些lua脚本及其他一些调试中心的信息记录
上面前面4个目次是当时写的外挂软件目次,不外本文不涉及
0x03:ce + lua

先给大家分享下ce的lua api网址,内里有ce提供的各种lua接口
https://wiki.cheatengine.org/index.php?title=Lua  
ce通常的利用方法相信应该许多朋友是知道的,好比我想知道怪物的血量信息:
1.找到怪物血量信息在内存中的地址
2.再attach到游戏进程中查看是哪里改写了这个地址
3.然后根据堆栈找到基址
但是我不知道ce当前代码对应的堆栈,所以就必要用到调试器附加到进程加上断点之后再重复上述操纵。  
不外有了ce+lua后,我们就能通过编写lua脚原来直接从ce里获取堆栈,然后就可以直接根据堆栈用ida或其他查看静态汇编的软件来分析了。
function print_stack(ebp, deep)    --deep:堆栈深度    --ebp:栈低寄存器    if deep == 0     then        return ""    end    local ebp_4 = readInteger(ebp + 4) --ebp + 4 就是调用过来时候的eip寄存器存的地址,根据这个就能倒推堆栈    local str_ret = string.format("%x->", ebp_4)    local next_ebp = readInteger(ebp) -- 然后当前ebp内里存的就是上一个栈低的地址,也就是上一个ebp内里存的地址    str_ret = str_ret .. print_stack(next_ebp, deep - 1) --剩下的就是递归调用了,最终会把堆栈保存到str_ret内里    return str_retend上面代码中用到了几个ce提供的lua接口,好比readInteger(addr)就是从传入的addr对应的地址中读出内存中四字节数,其他都是lua语法了.
当然少不了加断点,以及断点主动实行lua脚本的方法了,毕竟ce可是具备了调试器的.
function debugger_onBreakpoint() --通用断点回调,每个断点都会进到这里         local ebp_4 = readInteger(EBP + 4)         if EIP == 0x77E114 -- 根据当前eip地址来做函数分发         then             debugger_0077E114()         else             debugger_784a21()         end  return 1endfunction clear_debug()   local tbl = debug_getBreakpointList() --获取当前加上的所有断点列表  if tbl == nil  then      return  end  for i,v in ipairs(tbl) do      print(string.format("%4d 0x%X",i,v))      debug_removeBreakpoint(v) --根据地址删除断点  endendclear_debug()debug_setBreakpoint(0x77E114) --设置断点到地址0x77E114如上代码展示了ce的断点相关操纵,其实debug_setBreakpoint,我看官方文档最近版本应该是可以指定函数做入参了,之前我写这个脚本时候貌似还没有.
这里只是展示了ce+lua脚本的一小部门功能,还有许多很方便的用法,有兴趣的同学可以试一试.毕竟人生苦短,我用(python or lua or ...),能提高一点效率是一点.
0x04: immunity debugger

相信immunity 的python调试功能许多同学都用过,我在分析这款游戏时候,首先也是用的immunity,不事后来发现ce能支持lua后大部门工作就放在ce上了.两个各有优缺点吧.
immunity:
优点: 调试功能还是比较全的,毕竟是名字里带着debugger的调试器
缺点: 断点之后+python着实优点肿了,许多时候他的断点函数实行会导致进程变的非常缓慢.但是假如你用ce+lua就完全不会,一秒钟进入几十次断点游戏运行速度险些不受影响
ce+lua:
优点: 如上所说,断点调试非常顺滑,甚至调用频率比较高的接口都敢放心加断点.
缺点: lua跟python比提供的功能还是太简单了.而且这个lua的import貌似有题目,import之后的函数还是找不到,所以基本上代码只能写到一个文件中,一些自己封装的接口也没法通用.  
其实大部门功能还是相似的,好比常用的断点实行某个函数等功能,告急区别是因为python的库比较多,可以实现一些自己的小工具等.  
好比根目次下immunity/rec_down.py这个文件是我实现的一个方便查看内存的脚本.不外我也是在网上找了一个现成的别人对递归下降算法的实现,然后改了一下,让他能支持对简单的语法解析,内里内容有点长,这里就不展示了,原理是利用递归下降算法来做语法解析,有兴趣的同学可以相识下.
用法就是在immunity的命令行窗口下
!rec_down [eax]: 这个命令可以用来查看eax寄存器对应地址的内容
!rec_down [ebx + [eax + 4]] 这个命令是先读取eax+4地址对应内容再 加上ebx的值,得到的地址,再从中获取值
!rec_down [ecx+[ebx + [eax+4]]]  哈哈,这个告急就是可以无限嵌套.
immunity 的脚本实行必要通过在命令窗口实行 "!脚本名 脚本参数1 脚本参数2" 以这种方式实行(不带双引号)
在有了这个小工具后,你就可以把他当做一个库来用在其他脚本里了,好比
from immlib import *import rec_down # 引入刚才咱们介绍的小工具import utilsclass HookStack(LogBpHook):    def __init__(self, desp):        LogBpHook.__init__(self)        self.desp = desp    #########################################################################    def run(self, regs):        imm = Debugger()        #ret = rec_down.parse_exprs(imm, regs, '[esp],[esp+8],[esp+12],[esp+16]') 这是之前解释的一个,        data_len = rec_down.parse_expr(imm, regs, '[esp+12]') # 这个就是获取 esp+12 再取地址内容存入data_len        if data_len != 6:            data_addr = rec_down.parse_expr(imm, regs, '[esp+8]')             ret = imm.readMemory(data_addr, data_len) #从地址data_addr 处读取 data_len长度的数据到ret中            ret = list(map(lambda x:ord(x), ret))            imm.log("data_addr:{:x}, len:{}, ret:{}".format(data_addr, data_len, ret))        if data_len == 30:            stacks = imm.callStack() # 假如数据长度等于30的话,就获取堆栈并把堆栈输出到imm的log窗口中            for stack in stacks:                imm.log(str(stack))        # stack_set = imm.getKnowledge('stack')        # if not stack_set:        #     stack_set = set()        # stack_set.add(rec_down.parse_expr(imm, regs, '[esp+4]'))        # imm.addKnowledge('stack', stack_set)    @staticmethod    def cat_stack_set():        imm = Debugger()        ret = imm.getKnowledge('stack') # getKnowledge是获取用户自定义的之前存入stack中的值,相称于一个全局变量        imm.log(str(ret))def main(args): # immunity的可实行脚本都要有main函数,然后参数从这里传入    imm = Debugger()    utils.clear_hooks(imm)    opr = args[0]    if opr == 'hook':         # ---------------------------- send start ------------------------------------        addr = '76C76C19' # bp send        #addr = '008563D1' # 8418a6        #addr = '841871'        # ---------------------------- send end --------------------------------------        #addr = '5a926a' # HookClick        #addr = '5a9210' # click header        h = HookStack(addr) # 这个钩子是我们刚刚定义的,现在把它实例化        ret = h.add(h.desp,  int(addr, 16)) # 这个就是加断点了,当断下来的时候就会回调到我们的钩子函数内里        if ret == -1:            imm.log("hook send failed!")    elif opr == 'cat':        HookStack.cat_stack_set()    elif opr == 'clear':        utils.clear_hooks(imm)    return "ok"上面展示的就是加断点并且附带一个钩子函数,当断点断下来时候会实行成员函数run内里的内容.


如上只是一些个人在调试分析时候的一些经验分享吧.有错误或者有兴趣的朋友欢迎指正或交换,大家一起学习,一起进步.
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-4-25 13:20 , Processed in 0.125000 second(s), 30 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表