手游安全学习笔记

时间:2024-10-25 12:15:46

学习网站:

一些tips:

查看游戏进程中的内存信息一般只需要查看/proc/pid/maps就可以了
dnspy修改旅行青蛙里面的一个属性,net程序的反编译神器
apktool反编译,直接修改smali代码,然后同apktool进行打包,签名
IDA一旦选择binary file方式加载文件,则需要用户手动填写要加载的段的地址和相对偏移,用这种方式加载文件时,IDA不会自动分析代码,用户根据自己的需求自行反汇编二进制代码
apk文件采用zip压缩算法,可直接解压

游戏的本地验证逻辑越多,就会越致命

 

一些基础知识:

硬件断点:硬断点需要硬件寄存器提供支持,断点的数目受Embedded ICE中的Watchpoint数目的限制,但是可以在任何地方设置断点。
软件断点:软件断点通过在运行起来的程序中设置特征值实现,其数目不受限制,但是一般情况下软件断点只能在可写的存储器的地址中设置(比如:RAM),而不能在ROM(比如:Flash)中设置。 
因为修改的是程序的代码,所以内存断点很容易被程序自身检测到。而硬件断点则很难被发现。
dll注入:apc注入,hook注入,createremotethread,NtCreateThreadEx(利用内核级的函数)
手拖:esp定律(程序调用必须将esp入栈,函数调用结束要将esp弹栈,将esp压栈的位置下上硬件断点,然后再次返回时就是弹栈的操作,弹栈之后壳的操作就结束了,下面的就是用户代码)
1.单步跟踪法
宗旨:向上的跳转不让实现,向下的跳转实现,当发现大跨度跳转时,即会到OEP
定律法
遵循堆栈平衡原理,在壳对程序进行操作加密或者压缩时,会把程序的OEP压入栈中,当壳执行完成后,进行解密或者解压缩,会把真正的OEP从栈中弹出
3.2次内存镜像法
在壳进行解密或解压缩时,最后释放的是资源区段:.rsrc,这个区段被释放完全后,说明整个程序已经被全部解密
操作方法:
载入OllyDbg,ALT+M打开内存窗口,找到第一个资源区段,下断点,Shift+F9或运行,再到内存窗口找到地址为401000的代码区段下断,运行,单步结合单步跟踪法找到OEP

 

一些基本的概念:

手游包括:代码(逻辑),资源(图片,声音)和数据配置(装备属性,战斗属性,商品属性,怪物属性)
    一、静态修改文件:修改资源,替换声音,或者修改代码,修改配置文件,一般配置文件是进行加密的,但是有些的配置文件是xml的,可以直接对xml文件进行更改
    二、动态篡改逻辑(注入或钩子):注入将动态链接库加载到目标进程中(android:1、注入zygote进程渗透到目标游戏进程,2、直接注入目标进程;ios:mobilesubstrate组件将动态链接库注入游戏进程),还可以修改数据:游戏中有些未加密的类成员变量和全局变量,所以通过内存变化规则,可以快速定位到某个数据的内存地址,android就跟linux是一样的,可以根据/proc/pid/maps直接进行修改内存
    三、游戏协议:1、篡改游戏协议,可以对游戏数据包进行拦截,并将其篡改,可能会导致某些校验的结果失效,主要是游戏本身设计的问题
               2、重发游戏协议:枪战类游戏,若通过篡改游戏的伤害值来试图改变对敌方的伤害,则会没有效果,因为服务器默认不相信客户端的伤害值,如果截获这种伤害协议包,然后多发几次同样的,那么就可以实现多次伤害,解决方法就是多为这个协议添加一些字段(包括序号之类的)
外挂指破坏游戏客户端的正常数据和代码逻辑,或伪造游戏客户端的操作状况的工具:1、辅助版外挂:专用插件(专用于某个游戏,非常灵活),通用工具(内存修改器(修改属性),变速器(改变快慢),按键精灵(相当于重复点点点的脚本),模拟器(在其他的平台上玩不属于这个平台的游戏,基于虚拟机),WPE抓包工具(可以对数据包进行修改))。2、破解版外挂:脱机挂以及修改原客户端的破解版外挂
游戏:mmorpg(梦幻西游(城镇,野外),对玩家作弊的容忍度很低,强服务器逻辑的架构,基本的验证都是在服务器端,在主机端的验证很少,安全性高,打击感差),arpg(强调实时性,不可避免将碰撞检测、血量、伤害等放在本地),FPS(CS等,为了实时性,不可避免的将很多的验证以及逻辑放在本地执行,透视,自瞄等等),卡牌类(操作较少,安全性较高),moba(实时性的要求很高,但是更重要的时公平性,所以必须做成强服务器模式的,否则无论本地保护的多好,都有被攻破的风险),跑酷(一大重点在于角色与障碍物的碰撞,碰撞对实时性的要求较高,碰撞逻辑一般只能放在本地,因此对碰撞的检测需要做一些服务器校验来保证逻辑安全)

 

定制化外挂:

通常通过如下来实现定制化外挂的流程,逆向分析游戏逻辑->验证外挂是否可行->注入游戏进程->枚举游戏进程模块信息->(hook游戏关键函数(劫持函数的调用)| 游戏内存数据修改)->实现外挂功能

 

外挂技术:

注入技术:进程注入技术:

为了对内存中的某个进程进行操作,并获得目标进程的地址空间内的信息,或者修改目标进程的地址空间内的私有信息,在注入成功后便可以访问和篡改目标进程空间内的信息,包括数据,代码等。
    1、ptrace(1、附加到远程进程上。2、读取和写入寄存器的值。3、远程进程的内存读取和写入数据。4、远程调用函数。5、恢复寄存器值。6、detach(分离)进程)
    2、感染ELF文件(通过修改program header table中的依赖库信息,添加自己的库文件,当游戏进程加载主逻辑模块时,也会加载自定义的库文件)
hook技术:

hook是windows消息处理机制的一个平台:在关键函数执行前,先执行预先设置的钩子函数,分为(系统消息hook技术(利用现成的API)和API hook技术(自己实现整个hook)),API hook技术分为两大类(1、基于汇编代码替换的hook方式(inline hook、异常hook)。2、使用hook函数地址替换原始函数的地址(导入表hook,虚表hook))
    1、基于异常hook:利用sigill异常机制可以实现hook操作,可以对想要监控的地址设置一条非法指令,当程序执行到非法指令位置时系统会回调预先设定好的异常处理函数,在异常处理函数中恢复监控地址的原指令,获取上下文环境信息,然后打印寄存器等信息,若想重复持续的进行监控:可以在获取到异常的时候,对目标地址的下一条指令设置异常hook操作,然后在下一个异常触发时,在异常处理函数中回复当前异常指令并重新对目标地址设置非法指令,用于等待下一次目标地址被调用时获得执行时机
    2、inline hook(功能非常强大,执行效率高):inline hook直接修改需要hook的位置的指令代码,并让其跳转到桩函数中。在桩函数中,通常会处理寄存器等信息,并调用自定义的桩函数。在处理完自己的桩函数后,会跳转并执行原指令。(需要注意的点:1、不同的CPU架构等的跳转指令以及桩函数的构建不同,涉及到系统汇编层面。2、执行完桩函数跳转到原指令的时候,如果原指令涉及到类似于PC等相对寻址,需要进行指令修复。3、inline hook的覆盖顺序:最后原指令的覆盖操作时最后执行的,主要是出于一系列跳转要么都成功,要么直接失败(有点像数据库的事务))
    3、导入表hook:属于函数地址替换类型的hook,原理:替换需要hook的导入函数地址,当导入函数调用时,hook函数先获得执行时机,将got表里面的函数地址进行替换(特殊说明:1、通过读取/proc/pid/maps可以获得so文件的绝对路径和加载到内存中的基址信息。2、在修改导入表的函数地址时,需要修改页的权限,增加可写权限。3、导入表hook一般基于注入成功之后的操作,需要提前将so模块代码注入目标程序中)
篡改游戏内容:注入式以及非注入式
    1、非注入式(篡改APK安装包,篡改安装目录文件,修改proc目录文件)
    2、注入式:篡改内存数据(通过汇编,通过系统API函数),篡改逻辑代码(暴力修改游戏代码,或者hook技术实现复杂的外挂功能)
反调试技术:
    1、self-debugging反调试(父进程创建子进程,子进程调试父进程,阻止调试器对程序进行调试),
    2、轮询(判断进程是否正在被调试(读取进程的/proc/pid/status,查看status文件里的字段tracerpid字段的值判断当前进程是否正在被调试),如果字段值为0,说明程序没有在被调试,如果非0,则说明程序在被调试)
    3、java层的反调试技术(主要针对于JDWP协议的java代码调试器,想要调试,必须在文件的application标签中设置android:debuggable的属性为true,还有isDebuggerConnected的方法可以看)

 

基本arm指令:

    1、跳转:B/BL Cond表示这条指令会在什么条件下执行,其实每个条件都会给B指令加上后缀,比如“BNE/BEQ/BGT”等等,BL相对于B来说,L位表示是否需要保存当前指令的下一条指令至LR寄存器(BL指令一般用于跳转到函数内部,其中的LR用于保存返回地址)
    2、LDR/STR指令:用于向内存中读、写数据,LDR为读,STR为写
    3、函数传参:不同的编译方式对函数传参的做法不同,比较常见的是将前四个参数放到r0~3,把剩下的参数放到栈中,把函数的返回值放在r0中, 

 

游戏漏洞:
    1、文本校验类风险:刷屏,空昵称,重名角色,脏词敏感词风险,(出现原因:对文本没有做校验或校验强度不高,或者校验只放在本地客户端,有些游戏虽然做了服务器校验,但是校验强度不高)(主要是修改文字包的包内容)
    2、弹框类风险:在高操作游戏中突然弹窗,影响正常游戏(出现原因:攻击者截获数据包进行重放攻击,如果游戏做了重放校验,导致了我们利用工具重发失败。一般情况下需要分析协议中是否含有类似与验证token,一般这个token属于一次性的,服务器校验通过则会使协议生效,而过每次重放,每次的token都相同,服务器自然会主动丢弃,这时候就需要向逻辑层去看了,定位到游戏逻辑层的对应代码,进行远程调用这个函数,并填写参数为对应玩家的ID,进行多次调用,因为此时游戏执行还未到组包函数,所以调用对应函数会按照游戏自身逻辑组包,可绕过大多数协议重放的检测)                                                                       3、强制交互风险:强制对方进行交易或者订婚之类的(可以进行重发协议:分析协议含义及交互过程,确定协议中玩家ID并修改为攻击对象,确定协议中交互flag字段并修改,观察服务器反馈)                    4、收费特权风险:特权协议分为两类:一类是直接复用了正常的协议,仅仅改变了其中的部分字段,一类是单独存在的仅仅在触发特权上执行,如果特权为单独的协议,可通过购买道具,支付游戏币等正常操作去感知协议,有协议工具进行拦截并重发,如果特权协议复用了普通协议,只需要将数据包进行拦截,将其中的普通权限ID改为特权ID就好了
    5、任务类风险:从执行效果上看,主要风险分为(1、极大降低任务完成时间。2、非法获取或重复获取任务的最大奖励,提升收益。3、极大促进游戏工作室游戏内刷任务等非法行为),出现这种情况的原因是服务器的校验疏忽,只单单对任务最终结果做了校验,进而导致任务的前置条件和执行过程出现了各种被绕过,被多次利用的可能
    6、信息泄露:自瞄,透视,竞猜玩法直接获得胜利,用户个人信息的泄露,产生原因:服务器客户端交互过程中,为了同步状态进行判断,将本该隐藏的信息明文下发到了客户端,导致了玩家可以感知和利用        
    7、突破限制:包括地图的限制等等,产生原因:限制突破类风险存在的根本原因是因为游戏将限制的逻辑放在了客户端,而服务端有没有校验或校验不严格,导致限制可以被轻而易举绕过
    8、时间竞争:就是不恰当的执行顺序导致了非预期的执行结果,产生原因:1、操作指令不止一条,或指令数不止一个。2、操作指令执行时间出现异常
    9、边界条件风险:比如dnf背包格子满了,开一个罐,靶向药开出的东西放在格子里,如果开出来叠加,开不出来想要的会因为格子满了提示失败,产生原因:需要游戏内达到一些边界条件,服务器没有进行校验
    10、外挂
协议漏洞的话主要是对协议内容或者具体的场景或者说时序(重发)来进行修改