首页 > 其他分享 >基于虚拟机字节码的文本修改思路

基于虚拟机字节码的文本修改思路

时间:2024-02-26 18:44:37浏览次数:16  
标签:字节 instr 虚拟机 VM Hook 指令 字符串 文本

基于虚拟机字节码的文本修改思路

前言

大部分的Gal引擎为了提高运行效率或加密或防止修改等目的都会使用私有的VM,也就是会把明文脚本编译成字节码的脚本,由于是私有的VM所以没有现成的工具来解析,所以为了修改文本,我们不得不分析其VM,而分析VM依据OP数量和结构,工作量会有不同程度的增加,但总的来说分析VM的工作量都比较大,由于我们是为了修改文本数据,所以从文本修改替换的角度来考虑一下这个问题。

结构

依据个人的分析经验,可以总结一下Gal引擎VM架构实现存储文本数据的结构,大概来说可以划分成这两种

  • 指令与数据分离

    那么什么是指令与数据分离?其实就是VM要使用到字符串数据的时候,是用一个偏移来指向字符串数据的,即大多数此类实现的VM的脚本文件会有个区域(通常在脚本文件末尾)来存放字符串,也就是游戏的文本统一存放在一个区域,我们可以称之为字符串区段。一句话总结就是,代码区段使用指向字符串区段的偏移来读取字符串数据

    其抽象结构类似如下:

    .code
    [instr][instr][instr][instr][instr][instr]
    
    .str
    [text][text][text]
    

    从这里就不难发现,如果指令与数据分离了,那么我们就可以很轻松的改变文本长度,因为指令中存储了一个偏移来指向文本,那么我们只需要找到相关指令并修改这个偏移,就可以把文本数据附加到脚本文件的末尾,这样的好处是不会破坏原来的字符串区段,这就使得没有修改的偏移依然指向有效数据,同时新增的字符串也可以随意改变长度

  • 指令与数据混合

    那么什么是指令与数据混合?这就不言而喻了,就是字符串数据紧接在指令后面

    .code
    [instr][text][instr][text][instr][instr][text][instr][instr]
    

    那么也不难发现,如果指令与数据混合了,修改起来会很麻烦,首先就是不能够随便变化文本的长度,缩短文本长度的话,倒是可以,如果增长会造成其后的指令相对脚本文件开头的偏移改变,这时候如果内部有相对或绝对的跳转都又可能会出现问题,然而事实是依据以往的分析经验大多数游戏都会有相对或绝对的跳转,或者脚本文件的结构上还会设计label来标识某个代码块,方便进行跳转,所以基本不能直接增长文本。

    那么直接解析呢?首先如果要直接解析的话,最基本的都得知道op\instr的长度,如果op\instr是定长的,那么倒是简单了一些,但仍然需要知道哪些op是跳转的op,并要分析出其结构,才能够正确的替换文本,如果op\instr是变长的,也就是op\instr的值本身没存储长度信息,也没办法直接从op\instr解析出长度信息,或没有这种结构,每一个op都有不确定的参数个数,也就是有不同的长度,说白了就是每一个op都有自己的结构,这样就没办法确定下一个op在何处开始了,所以就要分析每一个op,至少是要分析出每一个op的长度,才能解析脚本文件,如果要正确替换文本的话,还是得找到跳转相关的指令,这就要解析每一个op的功能了,或者至少也得用取巧的方法分析出跳转相关的指令,反正两种方法都得花费不少的时间来修正跳转的问题,没几个op还好说,要是遇到op有上百个的情况,这种的话工作量会巨大。

当然也不一定是这样的结构,有种是以块来存储数据的,它二进制脚本里的数据,其实并不是真正的VM字节码,而是一种类似序列化后的数据,在加载脚本的时候,再反序列化成内部的对象来执行代码。

讨论

那么有没有方法可以避免指令与数据混合这种结构带来的工作量巨大的分析呢?

答案是肯定的,在此我们从直观的思路出发,递进简略讨论这个问题,以不同的实现难度给出三种方法,并主观讨论其实现的效果和优劣以及改进的方案。(以下讨论的方法其实也适用指令与数据分离的结构,只不过这种结构很少需要走到这一步)

  • 利用字符串搜索定位文本读取的位置实现动态替换

    动态替换也是有部分汉化补丁使用的,有点类似VNR的内嵌功能的味道,或者说找H-Code的意思,好像是这个说法来着。

    如果说我们基本没去逆VM,或者说不具备这样的能力的话,那么其实可以用搜索的功能,搜索当前游戏显示的字符串,找存储字符串的buffer,或者找读取字符串的位置,有点类似于那种拿CE搜所谓"基址"的操作,找到后写个替换就结束了,不过可能由于信息不足,你只能选择遍历相同的字符串来替换。这种我个人是不推荐的,首先,如果你没找到足够的信息来定位唯一的字符串,就只能选择遍历匹配原文字符串的方法,这就会带来性能上的问题。其次由于是随便找,碰运气到位置,运气不佳,没搞清楚这地方的作用,可能会出现问题,导致整个实现稳定性堪忧,因为这种实现出问题的其实我也见过好几个(。

  • Hook VM

    这个的话有点接近我们的最终答案,在我们对VM有一点了解之后,我们可以Hook VM的dispatch或具体OP的处理函数或位置,来实时获取VM的状态数据(哪个是PC哪个是Code指针哪个是需要的指令),从而达到更加精准的字符串替换。或说通俗一点我们可以Hook VM中处理文本渲染,压入文本数据的OP,同时配合VM的状态数据来达到精准的替换。

    这个是我比较认可的方法,这种实现的效果肯定是更好的(相比胡乱搜内存找一个位置,或者从系统API来替换文本而言),首先就可以消除搜索字符串的操作,因为如果你要搜索字符串第一个是性能问题,第二个可能会有不同位置但原文字符串相同,但译文不一样的情况,第三是可能还涉及到字符串过滤的问题,因为有些字符串并不是文本的字符串,可能是一些文件名之类的。

    当然再稍微深入一点,还有种方法是可以构造我们自己的OP,来实现出一个类似 指令与数据分离 的结构。

    总而言之,如果你对VM结构有一点了解,就可以达到这种比较精准和高效的替换了。不过这显然还是需要写Hook代码,不同游戏还要找位置,搜特征,也涉及到代码注入等问题,通用性比较差,但是对于有一点了解的人来说,这种方法确实是方便(从逆向分析的工作量上来看)又高效(从文本替换的角度上看)。

  • 利用VM指令构造VM下的Inline Hook

    这个是我认知里能提供的一个比较好的方案,前提是要大概分析一遍VM,也就是说你要对VM有一定程度的了解。

    从上面的Hook VM的思想上再深入一点,Hook VM其实就是Hook Native代码,也就是本机代码,更具体一点,其实就是修改x86汇编,从另一个角度来看,VM也可以看作一种类似x86 cpu的东西,而里面跑的字节码其实就可以比作是x86汇编代码,那么从这个角度上来说,能不能构造一个在VM下的Hook,也就是利用VM的字节码写一个Hook,而不修改任何x86汇编代码?

    显然是可以的,这个的关键就是找到VM的Jmp指令,就和x86下写一个 Inline Hook 一样通过Jmp指令跳转到目标代码块,执行完毕后跳转回去,当然x86下很方便,因为指令都是已知的,也有方便的调试工具和各种库来实现这种功能,而Gal引擎的VM显然大多数都是闭源,特别是Gal引擎基本都是会采用自己写的VM,所以基本是不可能直接找到工具来编辑脚本中的指令的,也找不到指令功能的说明文档,除非有人逆了,所以这就要求对VM要有一定的了解,目的其实就是找到那个Jmp指令。

    当然Jmp指令可不是随便一个都行,首先这个指令要能够修改VM的PC,不然怎么Jmp?其次这个指令不能造成副作用,或者说副作用可以被抵消,因为不像x86汇编我们可以使用pushad之类的指令来保存环境,一个私有的VM连有什么指令都不清楚,哪来的保存环境?如果真有的话也需要分析找到这种指令,所以找到这样的指令是前提,当然一般来说VM都有这种指令,因为Gal脚本通常都会有GOTO之类的写法来跳转和切换不同的场景,选择分支之等。

    不过类似的指令其实会有很多,比如Call指令其实也需要修改PC,也有一种类似Jmp的效果,特别是Gal引擎还会有一种脚本文件之间的Call指令,当然还有什么Label_Call之类的,各种各样的,你看着像是修改了PC,但有很多副作用,或者说没办法方便传递跳转偏移等一系列问题。

    所以关键是能不能够找到一个副作用可以抵消或者没有副作用的单纯的跳转指令,就像是x86下的Jmp指令一样,如果你找到的是类似x86下的Call指令,又没找到Ret指令,显然会出问题,所以这又要求要准确把握指令的含义及其操作了VM中的什么数据。

    找到这样的指令后,就可以在文本数据之前或者文本数据的位置,写上这个指令,跳转到脚本文件末尾,然后在末尾写上Push Str的OP指令和数据,然后再跳转回之前指令的结尾,这就有点类似于在x86下Inline Hook的意思了,只不过这是利用VM自身的指令来实现的。

    所以,通过这种方法就可以避免Hook动态替换文本,或者工作量巨大的VM指令完全解析和分析外加写编译反编译工具,而且这种方法就和完全反编译和重新编译脚本一样,可以通用同一个引擎不同的游戏而无需写Hook,DLL注入之类的。

    关于这个思路具体实现,可以查看以下项目

    这两个引擎都是指令和数据混合的架构,实现替换文本的思路相同,都是借助VM的类Jmp指令,从Push Str的位置跳出来,在脚本末尾写上Push Str,然后再跳回原来指令的结束位置,以此来替换文本,从而避免去完整解析脚本和使用Hook的方法动态替换。

感悟

写完这篇文章记录一下自己的感悟吧,2024年2月26日03点41分。

这些思路也是一步步从实际出发自然而然地往下思考的,说实话,看着很简单,其实一开始还真想不到,或者一开始也没能力做这个,有时候没思路了,就把电脑关了,其实关了还是心心念念,或者说在那死磕,搞了半天也没看出什么名堂。

写这文章也是,一口气写了好几个小时,其实后面思路就有点混乱了,或者说已经开始有点表达不出想要的意思了,但还是刻意去改来改去,所以花了更多时间,但又时不时会做出这种行为。

其实有些时候并不需要刻意去想脑子里就会自然浮现出一些想法,然后再考虑这些到底合不合理,有没有可行性,反正就有种自然而然的感觉,特别是一个人安静的时候,脑子里就会在琢磨一些事情,这种时候比较放松,思路就会更清晰一点,确实很神奇,只不过相比问别人答案,过程确实比较长,当然也得有人问才是(

所以其实相比问别人我还是喜欢自己考虑问题,有些时候虽然有的东西理解起来很简单,其实仔细想想可能并没完全理解到精髓上,只是把别人说的话记在脑子里而已,没准过几天就忘了。

逆引擎的VM其实是我一直比较感兴趣的,但奈何网上资料,不能说少吧,那基本是没有,当然像是那种打CTF的玩具VM那规模和复杂度基本没啥参考价值,Github有一些开源编译反编译工具,但也看不到他们分析的内部结构和过程,只有分析后写的工具,说实话这样的参考价值就低了很多。

咱也没什么人脉,还是只能靠自己慢慢磨了,说实话分析VM真的是非常烦人,不过像是现在这种VM遍地走的时代,没办法,还是得硬着头皮上啊,不然很多编译的脚本文本替换不了也白搭,当然我也不是什么汉化组的没这个急切的需求,主要还是想锻炼一下自己分析的能力,加强对基础的认识。

反正就是悟了亿段时间有点体会了,如果是汉化的话,主要也是这个目的,为什么不写具体例子呢?,其实我认为思路还是比较重要的,有思路才有方向嘛,好嘛,主要是我菜,而且完全解析VM工作量也很大,要写成文章就更费时间了,以后可能会写吧。

标签:字节,instr,虚拟机,VM,Hook,指令,字符串,文本
From: https://www.cnblogs.com/Dir-A/p/18034944

相关文章

  • PDFUtils (解析PDF 中的文本 和 图片 PDF 转 HTML HTML 转 PDF)
    引入pdfbox依赖<dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.19</version></dependency>packagecom.icil.swif......
  • Java - 将TXT文本文件转换为PDF文件
    与TXT文本文件,PDF文件更加专业也更适合传输,常用于正式报告、简历、合同等场合。项目中如果有使用Java将TXT文本文件转为PDF文件的需求,可以查看本文中介绍的免费实现方法。 免费JavaPDF库本文介绍的方法需要用到FreeSpire.PDFforJava,该免费库支持多种操作、转换PDF文档的功......
  • vue3+vite使用vue-pdf-embed或者pdf-vue3预览 PDF 文件(能躲避 XSS 攻击,需要 pdf 文件
    1.使用vue-pdf-embed1.npm安装所需插件[email protected]@0.1.62.封装组件(创建pdfPriview.index文件)<template><divclass="pdf-preview"> <vue-pdf-embed :source="state.source" v-for="pageinstate......
  • 一个支持Sora模型文本生成视频的Web客户端
    大家好,我是Java陈序员。最近OpenAI又火了一把,其新推出的文本生成视频模型——Sora,引起了巨大的关注。Sora目前仅仅只是发布预告视频,还未开放出具体的API.今天,给大家推荐一个最近十分火热的开源项目,一个支持使用Sora模型将文本生成视频的Web客户端。关注微信公众......
  • 如何把电脑文件传到虚拟机
    如何把电脑文件传到虚拟机方法一:VMWareTools安装VMWaretools,点击上方虚拟机->安装VMwaretools安装成功后,即可通过复制粘贴文件,将文件复制到虚拟机中安装成功后,会显示如下内容安装成功后,可以直接拖动文件,或者通过ctrl+Cctrl+V复制粘贴。若发现不能直接拖动,可以在拖......
  • 【办公自动化】批量将Markdown文件转换为纯文本文件
    本文介绍如何将Markdown文件转换为纯文本文件。Markdown是一种轻量级的标记语言,用于编写格式简单的文档。但是,有时候我们需要将Markdown文件转换为纯文本文件,以便进行其他处理或直接在浏览器中查看。下面介绍一种简单的方法来实现这个功能。转成html要将Markdown文件转换为......
  • SharePoint Online 启用文档库多行文本的富文本属性
    前言相信大家都知道我们可以在列表中快速创建支持富文本的多行文本字段,但是,文档库中不行。正文1.这是列表中的多行文本字段,可以点击编辑图标,如下图:2.然后,会弹出一个富文本编辑框,支持富文本,如下图:3.但是,在文档库中新建多行文本的时候,少了一些属性,如......
  • 【转】【福利】无需注册登录 免费传输文件和文本
    来源:https://zhuanlan.zhihu.com/p/598829318 01几个分享文本的网站一:网络剪切板(https://netcut.cn)   ①域名比较好记,net,网络;cut,剪切;cn,中国地区②原理:相当于创建一个网络房间,在不同的浏览器上输入相同的网址可进入同一个房间,可设置密码,房间有效期最长可设置为三年......
  • VMware Workstation 安装Ubuntu虚拟机 屏幕窗口分辨率 自动调整大小 自动适应客户机
    Ubuntu18.04.5LTSVMwareWorkstation16Pro 首先排查了vmwaretools的安装问题首先尝试通过这样安装 点击安装后,好像是有个cd挂载上,复制这个文件到桌面解压这个压缩包,在文件夹打开终端sudo./vmware-install.pl全按回车应该就可以其间Theinstallerhasdetect......
  • Linux文本三剑客超详细教程---grep、sed、awk
    Linux文本三剑客超详细教程---grep、sed、awk羽林君 2023-10-1223:51 广东文章来源:https://www.cnblogs.com/along21/p/10366886.html awk、grep、sed是linux操作文本的三大利器,合称文本三剑客,也是必须掌握的linux命令之一。三者的功能都是处理文本,但侧重点各不相......