游戏插件开发之防插件剥离的简单保护壳工具设计(利用反汇编引擎实现自动化代码保护)下
前言:
感谢:易道云学院 tiger老师指导:
前提:已经做完自动保护工具。主要讲解如何解析生成的保护程序。
分析:
我们已经生成的保护程序,程序末尾首先写入了有多少段要保护的代码,后面是结构体数据,二进制数据如下
02 00 00 00:有两段要保护的代码 50 c7 c8 00:第一段要保护的代码首地址为 C8C750 04 00 :第一段中有4个地方需要做重定位 52 00 : 第一段保护代码大小为 0x52 b0 c7 c8 00 :第二段要保护代码首地址为 C8C7B0 00 00:第二段中没有需要做重定位的 15 00:第二段保护代码带下为 0x15
在这之后写入的是第一段需要重定位地址的相对偏移,后面是第一段要保护的代码,然后是第二段....最后写入的是源程序的大小二进制数据如下:
通过前面得到第一段有四个重定位信息
0B 00 ,25 00,36 00, 3F 00 这四个数据记录的是4个重定位数据所在地址相对于该保护代码起始地址的相对偏移。 56 8B F1 ..... 5E C2 04 00 :第一段代码。 8B 44 24 ..... 01 C2 04 00: 第二段代码。 2B CA 22 01 :记录的源程序大小. 刚好是19057195。
思路:
通过以上分析我们大致知道了生成的保护程序的结构,通过在插件中定义函数进行解析。
定义变量:
LPVOID* _EntryCode; //存放游戏保护代码
char _myFunCode[8]{ (char)0xE8,(char)0x00,(char)0x00,(char)0x00,(char)0x00,(char)0xFF,(char)0xE0,(char)0xCC }; //定义一个构建自己函数和跳转的汇编指令
定义函数:
unsigned getAddress(int _index); //根据分发函数的值获取游戏代码地址 bool InitEntryCode();//解析保护代码
函数:
unsigned _stdcall GetFunctionAddress(int index)
{
return rData->getAddress(index);
}
解析:通过我们定义的汇编会跳转到这里根据参数(push 0 ,push1 ...)计算地址并跳转到指定游戏代码执行
unsigned getAddress(int _index)
{
unsigned result = (unsigned)this->_EntryCode[_index];
return result;
}
解析:根据参数分发地址
bool InitEntryCode()
{
TCHAR fileModule[0x100];
GetModuleFileName(NULL, fileModule, 0x100); //获取游戏名称
auto hFile = CreateFile(fileModule, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)return false;
DWORD dRead;
DWORD fileLen = GetFileSize(hFile, &dRead); //获取文件大小
char* _data = new char[fileLen];
if (ReadFile(hFile, _data, fileLen, &dRead, NULL)) //读取文件到_data
{
char* _dataBegin = (char*)_data;
unsigned* _uRead = (unsigned*)(_data + fileLen - 4);//定义指针指向文件末尾-4的地方,刚好是记录的源文件大小
fileLen = _uRead[0]; //获取源文件大小
_uRead = (unsigned*)(_data + fileLen);//指向源文件末尾,我们保护数据的开始位置
unsigned code_count = _uRead[0]; //获取到有多少段保护代码
_data = _data + fileLen + sizeof(code_count); //把指针往后移动,指向第一个结构体
PCODEConText _conTextArrys = (PCODEConText)_data;
_data = _data + sizeof(CODEConText) * code_count;//把指针继续往后移动,指向重定位偏移的位置
_EntryCode = new LPVOID [code_count];
for (int i = 0; i < code_count; i++) //分别解析这两端保护代码
{
_EntryCode[i] = new char[_conTextArrys[i].len+2];
char* adr = (char*)_EntryCode[i];
adr[0] = 0x9D;
adr[1] = 0x61;
unsigned offset = sizeof(_conTextArrys[i].r_count)* _conTextArrys[i].r_count; //计算记录偏移数据到代码的偏移
memcpy(((char*)_EntryCode[i]+2), _data + offset, _conTextArrys[i].len); //拷贝代码
//修复重定位
unsigned short* rel = (unsigned short*)_data; //定义指针变量指向第一个偏移的数据
for (int x = 0; x < _conTextArrys[i].r_count; x++)
{
unsigned* _callAdr = (unsigned*)(((char*)_EntryCode[i] +2)+ rel[x] + 1); //指向E8 后面的地址
_callAdr[0] = _callAdr[0]-(unsigned)(((char*)_EntryCode[i] + 2) + rel[x])-5; //重定位地址值 E8 XXXX=目标地址-当前地址-5 因为制作保护程序的时候已经计算出了目标地址
}
_data = _data + offset + _conTextArrys[i].len; //把指针移动到下一段保护代码偏移的位置
DWORD dOled;
VirtualProtect(_EntryCode[i], _conTextArrys[i].len+2, PAGE_EXECUTE_READWRITE, &dOled);
}
delete[]_dataBegin;
}
else return false;
//写入分发函数
auto hMod = GetModuleHandle(NULL); //获取游戏地址
unsigned addMod = unsigned(hMod);
unsigned codeAdr = addMod + 0xC2EFFC; //算出我们找到的那块内存的地址
DWORD dOld;
::VirtualProtect((LPVOID)codeAdr, 8, PAGE_EXECUTE_READWRITE, &dOld); //修改内存属性
unsigned* read = (unsigned*)codeAdr; //定义指针指向那块内存的地址
read[0] = (unsigned)this->_myFunCode; //把函数写入该地址
read = (unsigned*)(this->_myFunCode + 1); //把指针指向call后面的地址值
read[0] = (unsigned)GetFunctionAddress - 5 - (unsigned)(this->_myFunCode); //计算好地址写入
return true;
}
解析:该函数是核心解析函数,通过读取文件依次解析出各个数据,并再循环中写入每段保护代码,并重新计算需要重定位的地址。注意要再每段代码前写入 popfd 和popad来恢复寄存器的值。
总结:
通过文件读取来读取我们保护的数据,并通过该数据把保护代码写入到插件中,当游戏执行到保护代码时会先进行寄存器数据的保存,然后跳转到我们指定的地址,进去后执行我们的分发函数,通过参数来跳转到我们插件中保护的代码,进入后首先恢复寄存器的值然后执行游戏代码。
游戏插件开发之防插件剥离的简单保护壳工具设计(利用反汇编引擎实现自动化代码保护)下相关推荐
- 游戏插件开发之防插件剥离的简单保护壳工具设计(利用反汇编引擎实现自动化代码保护)上
前言: 感谢:易道云学院 tiger老师指导: 前提:需要导入小蜜蜂反汇编引擎,不会的可以回复问,这里不做介绍,MFC页面的搭建也不做详细介绍.因为任务量太大本贴只写代码保护工具的制作,后续解析在下个 ...
- Unity游戏Mod/插件制作教程05 - 插件实例2: 简单功能实现
这一次的教程进行一个小小的功能实现,完整的制作一个插件.以Mirror这个游戏为例,插件的目标是当玩家按下空格时,有一定概率为玩家增加金钱,或者扣除玩家金钱.概率.增加的金钱.扣除的金钱都由配置文件决 ...
- FastAdmin插件开发辅助增强插件
本人开发的FastAdmin插件开发辅助增强插件 不改变官方的开发习惯,但更丝滑,尽最大的努力生成你想要的代码 非常重要 非常重要 非常重要 写在最前面是为了不要漏了,导致插件没有正常工作. 编写代码 ...
- idea插件开发--服务-翻译插件
gitee地址:https://gitee.com/jyq_18792721831/studyplugin.git idea插件开发入门 idea插件开发–配置 idea插件开发–服务-翻译插件 id ...
- 游戏开发之U3D插件EasyTouch5.x使用
游戏开发之U3D插件EasyTouch5.x使用 本篇只讲EasyTouch5.x的使用,不讲源码.本来想把EasyTouch5.x的使用手册翻译一遍,想来也是没那个时间. 第一 ...
- 游戏客户端内存防修改浅析
游戏客户端内存防修改浅析 但凡现在有点人气的游戏都可能被hack,而且网上有很多方便的工具可以使用,单就手机端还讲,最常见的内存修改器有八门神器.烧饼修改器.最近针对这两种内存修改器做了些防护处理,简 ...
- 科技计算机玩游戏,迷你世界:插件科技新玩法,一招造出计算机,在游戏内玩游戏...
文/陌瑾 引言:陌瑾出品,争做精品! 游戏加入高科技"插件包"玩法 迷你世界在最近在游戏内新加入了一个插件库的玩法,它相对于之前的另两种游戏道具"微缩道具模型和地形编辑器 ...
- 【Chrome浏览器插件开发】浏览器插件运行机制03之实战使用Vue.js 3 + Vite 2开发出简易的浏览器插件(含源码)
文章目录 知识点: 一.使用 vite 创建项目 1.1 环境搭建 1.2 安装vite工具 1.3 创建vite项目 1.4 进入项目并安装依赖 1.5 修改端口 1.6 运行项目 二.创建项目资源 ...
- 前端自动化工具 grunt 插件 uglify 的简单使用(一)
Grunt 的简介: Grunt 是一套前端自动化工具,是一个基于 node.js 的命令行工具,它一般用于: 1.压缩文件: 2.合并文件: 3.简单的语法检测: 4.监听文件变动: 5.less ...
最新文章
- Maya游戏角色绑定入门学习教程 Game Character Rigging for Beginners in Maya
- python语言使用什么语句实现上下文管理协议_Python 技巧探究:上下文管理器和with语句...
- freemarker写入word【未完,待续】
- 服务器不显示内存条,服务器主机检测不到内存条
- 第十届蓝桥杯省赛JavaC组真题——详细答案对照(完整版-包含打扫机器人的视频全过程讲解与编码内容对照)
- codeforces-1201 C Maximum Median
- 我又来学ElasticSearch了。。。
- Atitit.判断汉字的编码 regedit 注册表里面的reg_sz
- querydsl动态 sql_SpringDataJPA学习记录(四)--使用QueryDSL
- 英雄联盟显示服务器属于高限制,玩英雄联盟出现超出频率限制,该怎么处理?
- 批量重命名图片去掉烦人的括号
- GPIB编程控件指令
- maps-api-v3_利用Google Maps API发挥创意
- qgc地面站飞行模式
- PDF限制编辑怎么解决
- machine learning 四要素
- scrapy框架连接MongoDB数据库
- c语言编程:vc++6.0入门教程及习题_百度文库,C语言编程:vc++6.0入门教程及习题.doc...
- 架构系列之标准Web系统的架构分层
- 一战封神!“中国飞人”苏炳添跑出9秒83到底有多牛?
热门文章
- 用SAX优化读excel文件的内存消耗
- 微信开发者工具出现catch sdkSubPackage: sclEngine error: TypeError: Cannot redefine property:
- DC-DC开关电源电感选型指南
- 5G反开3D-MIMO之负荷均衡优化
- 倒车喇叭语音ic芯片
- EVC创建DLL及调用的基本方法
- 16.深度解密十六:解密投放百度竞价广告效果提升的问题讲解
- 阿里云是什么,与亚马逊的云服务相比较,处于什么位置?
- 单片机节日彩灯实训报告_单片机(节日彩灯控制).doc
- linux rm 文件找回_linux下执行rm -rf命令后如何恢复