unity3d手游破解(一)

article/2025/10/1 20:15:03

重点知识:

1. \assets\bin\Data\Managed\Assembly-CSharp.dll扔进Reflector+reflexil环境

2.libs\libmono.so的mono_image_open_from_data_with_name函数


MonoImage *mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, const char *name);

转:https://bbs.pediy.com/thread-226135.htm

最近找乐子破解了点手游玩玩,顺便分享一下,目标APK--发条XX。

1、大致分析

拿到APK先看看libs和assets,发现有libmono.so以及\assets\bin\Data\Managed\Assembly-CSharp.dll,可以确定是unity3d手游,可以尝试修改 Assembly-CSharp.dll来破解游戏,不过发条英雄的这个dll加密了,所以需要先解密。

2、解密dll

把 libmono.so扔进ida,找到mono_image_open_from_data_with_name函数,F5查看发现了解密代码:

在这个函数先判断加载的dll是否包含ssem字符串,接着判断前两个字节是否等于82(0x52),77(0x4d),因此可以确定下面的for循环是解密代码,比较简单,抄下来自己写一个解密程序(附件有一份),然后对这个 Assembly-CSharp.dll进行解密。

3、修改dll

把 Assembly-CSharp.dll扔进Reflector+reflexil环境进行修改(不会的同学百度学习一下),找到关键函数get_DamageValue,直接改成返回100W,然后攻击就变成了100W。

不过这个时候怪物攻击也是100W,因此再找到Player的applyDamage函数,修改这个函数直接ret,然后玩家就无敌了。

最后保存为一个新的dll并替换掉之前APK里面的 Assembly-CSharp.dll,解密后的dll头部不等于82(0x52),77(0x4d),因此so可以直接加载。

4、运行

重新签名,打包成新的APK,安装运行,一刀100W。

5、结束语

服务器信赖客户端的计算结果就导致这种情况,不过服务器加强数据校验也能检测出来。有兴趣的同学可以去改改dll实现竞技场百战百胜。

6、附件

decrypt.c

#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>typedef char _BYTE;int main(int argc, const char **argv) {if(argc != 3) {printf("usage:%s <in> <out>\n", argv[0]);return -1;}  FILE *fpDll;  fpDll = fopen(argv[1], "r");  if(fpDll == NULL)  {  printf("open  fail\n");  }  fseek(fpDll, 0, SEEK_END);  int len = ftell(fpDll);  fseek(fpDll, 0, SEEK_SET);  char *data = (char *)malloc(len);  fread(data, 1, len, fpDll);  fclose(fpDll);  signed int v11; // [sp+20h] [bp-18h]@3signed int v12; // [sp+24h] [bp-14h]@3
int v10;
size_t i;v12 = 55;v11 = 89;
char *src = data;
int n = len;if ( *(_BYTE *)src == 82 && *((_BYTE *)src + 1) == 77 ){for ( i = 4; i < n; ++i ){v10 = v12 + v11;v12 = v11;v11 = v10;if ( v10 > 0x10000000 ){v12 = 1;v11 = 1;}*((_BYTE *)src + i) ^= v10;}*(_BYTE *)src = 77;*((_BYTE *)src + 1) = 90;*((_BYTE *)src + 2) = -112;*((_BYTE *)src + 3) = 0;}FILE* pFile = fopen(argv[2],"wb");  fwrite(data,len,1,pFile);  fclose(pFile);     }

 

 

Reflector+Reflexil 相结合实现对DLL文件修改

reflexil

https://github.com/sailro/Reflexil/releases

第一步:

下载Reflector 10和Reflexil 2.2,装好后将Reflexil的插件DLL文件加载到Reflector中

具体操作:Tools->Add-Ins->+->选择Reflexil的DLL文件Reflexil.Reflector.AIO.dll,点击确定加载到Reflector中

第二步:

2.1 Reflector加载需要编译的DLL或exe文件,找到对应的方法。

2.2 打开Tools->Reflexil  你将会看到对应方法的IL代码

选择Reflace all with code 对对应代码进行修改后,点击左下角的 Complie(编译),然后点击“确定”;

第三步:

确定操作完毕后,在左侧DLL或exe文件上右击

Save as 程序集编译成功!

 

Reflector反编译插件Reflexil 图文使用教程

Reflexil 它是Reflector的一个插件,结合Reflector,可以进行DLL代码注入等工作,实践证明完全可用,方便开发人员对.NET程序进行修改;可以作为一个Reflector插件修改程序集的IL并保存到磁盘文件,也可以在自己的.NET程序中调用进行更为灵活的.NET程序集修改。

下载好Reflexil后,在Add-ins 界面,点"+",选择Reflexil.Reflector.AIO.dll,然后Close

现在在Tool中会多一个Reflexil选项

它的界面

用法:

把我刚才写的Hello world拖进Reflector,我们选中程序集,命名空间,类名,方法, Reflexil的界面都是不一样的.

这里可以知道,我们能注入类,接口,枚举,方法,等,也可以重命名,删除.

现在我们来添加一个方法试试,选择Inject method 。 Item Name:Demo(此时只能声明无参,无返回值的方法,后面会讲什么添加这些)

点ok会给出警告

 意思就是,做大改动(注入,删除,重命名)时你是看不见结果,让你保存一次在导入新的dll文件,那就保存一次

保存好后,把新dll拖到Reflector中,就会发现在 Programe中多了一个Dmeo方法.

现在来给Demo 写实现

选择Demo 后右边的界面为:

选择Main:

instructions 中是IL指令, 高级玩家可以直接修改添加指令,但不是高级玩家咋办?

我们选择Replace all with code... 替换所以代码.

不过在这之前 先在Parameters添加一个参数string name,并在Attributes 将Return type设为stirng

我再次点击Replace all with code...  代码已经更新为

修改完成后,点compile 如果没有错误,就会生成IL指令,点ok就行

现在在来修改一下Main方法,调用Demo

代码已经改完,现在保存看看执行效果:

原程序:

修改后程序:

 

https://www.52pojie.cn/thread-271347-1-1.html

Reflector 之reflexil使用

潜水潜了那么久,上来换口气..
昨天和小伙伴一起玩一个CrackMe(C#),打算一起来写KeyGen,他用的是爆破的方法,我修复程序后发现里面常量各种溢出...无奈,只能用reflexil注入方法,然后写出KeyGen.
分享下使用reflexil常用的几个方法..

Reflector 之reflexil使用

先写个简单的控制台程序

工具,添加插件.

选中reflexil 1.6 (1.7从来没附加成功过.不知道为啥..)

一 直接修改操作数

可以直接编辑IL

Update 后

在程序集中右键

另存程序.

执行刚保存的程序

还可以直接添加IL 接着让后面继续输出

二 直接注入IL

右键,新建(new Create),填写对应的操作码,选择类型,

值得注意的是右边的按钮,append(添加),接着是插入在选择之前,然后是插入在选择之后;别选错了.

注意    注入的时候操作数的类型别选错了.

然后继续参照上面的,将程序另存一次.

三 替换代码

如果不想折腾IL,直接选择 替换所有代码.

不过这意味着你要重写所有代码(大多数时,我都会用在重写某个方法上)…然后提交一下,他会自动编译, 然后继续参照上面的,将程序另存一次.

提交完成后会自动编译,并且再右侧区域会生成对应的IL.

然后继续参照上面的,将程序另存一次.

执行下…

四  注入方法

别选错地方了.是你要将方法注入到某个类中,不是注入class所以,一定是在类上右键

暂时只能注入返回值为void的方法

对了,点击OK后会有个该死的提示,这提示的大致意思是:

当你在执行,增加,删除,重命名,等动作时,你不会直接看见相应的操作,他们是不同步的.

你必须要重新加载程序集才可以看见.

当然,你还需要将程序另存一次.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

然后你需要关闭程序集,接着重新打开刚才另存的 

现在方法已经注入进去了.

然后我需要给它添加点内容..

让方法输出个InjectedMethod字符串

在方法中添加IL

接着修改Main方法,并且调用刚才注入的方法.

另存下..

执行结果.

Ps:   如果是替换代码的话,先更改injectmethod时不用实现main方法,只需要修改injectmethod()方法,然后再去修改Main方法.调用时因为injectmethod方法不是static所以需要实例化Program

接下来说说添加有参数,有返回值的方法:

先在参数(parameter)标签,中添加一个参数.

然后在属性标签中修改返回值为string.

接着使用替换代码的功能

可以看见方法已经带有参数并且有返回值.

修改下这个方法

打印下传进来的名字,并且打印当前时间

修改主函数调用

编译,然后不要忘记另存….

Good Job .

Have Fun .

By McevilRock

9-7/2014


http://chatgpt.dhexx.cn/article/LBukZ5rd.shtml

相关文章

【Unity3D】初学加密技巧(反破解)

参考文章&#xff1a; Unity3D研究院之Android加密DLL与破解DLL .SO&#xff08;八十一&#xff09; | 雨松MOMO程序研究院 Unity3D研究院之Android二次加密.so二次加密DLL&#xff08;八十二&#xff09; | 雨松MOMO程序研究院 Unity 2019.4.0 Mono 编译以及加密 windows版…

2021Unity教程:Unity官方中文版免费下载方法(黑皮肤可选)无需破解!

首先科普两个知识点&#xff1a; 1. Unity官方支持个人免费版&#xff0c;新的学习者和初创公司员工&#xff08;公司财务规模低于10万美元一年&#xff09;均可以使用。黑皮肤免费&#xff08;Unity2019.3以上的版本&#xff09;&#xff0c;基本功能齐全&#xff0c;无需破解…

Unity官方支持中文版啦!!!附教程——无需破解!

Chinar blog &#xff1a;www.chinar.xin Unity安装官方中文版教程 本文提供全流程&#xff0c;中文翻译。 Chinar 坚持将简单的生活方式&#xff0c;带给世人&#xff01;&#xff08;拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例&#xff09; Chinar —…

Unity游戏逆向及破解方法介绍

背景介绍 随着手游的发展&#xff0c;Unity3D引擎逐渐成为主流的游戏开发解决方案&#xff0c;传统cocos的2D游戏逐渐被取代&#xff0c;一些公司在Unity3D游戏方面的产出也越来越多&#xff0c;如天天飞车&#xff0c;天天来战&#xff0c;全民破坏神&#xff0c;全民偶像&am…

java之成员变量(实例成员变量和静态成员变量)

类的成员 类的成员可以包含以下&#xff1a;字段、方法、代码块、内部类和接口等。此处我们重点介绍字段. 1.1字段/属性/成员变量 在类中, 但是方法外部定义的变量. 这样的变量我们称为 "字段" 或 "属性" 或 "成员变量"(三种称呼都可以, 一般…

java成员变量的调用_java中对象调用成员变量与成员的方法介绍

java中对象调用成员变量与成员的方法介绍 发布时间&#xff1a;2020-05-06 10:03:53 来源&#xff1a;亿速云 阅读&#xff1a;838 作者&#xff1a;小新 今天小编给大家分享的是java中对象调用成员变量与成员的方法介绍&#xff0c;相信很多人都不太了解&#xff0c;为了让大家…

局部变量和成员变量

局部变量和成员变量的区别&#xff1a; 定义的位置不一样【重点】 局部变量&#xff1a;在方法的内部 成员变量&#xff1a;在方法的外部&#xff0c;直接写在类当中作用范围不一样【重点】 局部变量&#xff1a;只有在方法当中才可以使用&#xff0c;出了方法就不能再用了 成…

C++之静态成员变量

一、静态成员变量 1&#xff09;static修饰的静态成员 静态成员变量、静态成员函数 静态成员变量&#xff1a; 1、static声明为静态的&#xff0c;称为静态成员&#xff0c;不管这个类创建了多少对象&#xff0c;静态成员只有一个拷贝&#xff0c;但是类的其他所有成员共享…

静态成员-静态成员变量

静态成员 静态成员都是用static修饰&#xff0c;它的特点是不论创建多少个对象&#xff0c;程序都只创建一个静态成员。 最主要的特点&#xff1a;共享 什么是共享呢&#xff1f; 例如&#xff1a;统计超市中所有商品数量的总和&#xff0c;商品数量的总和是随着每一个数量…

成员变量和成员方法

成员变量 1、成员变量的分类 实例变量&#xff1a;没有static修饰&#xff0c;也叫对象属性&#xff08;实例变量&#xff09;&#xff0c;属于某个对象的&#xff0c;通过对象来使用 类变量&#xff1a;有static修饰&#xff0c;也叫类变量&#xff0c;属于整个类的&#x…

Python——成员变量和类变量

类中的变量分为两种类型:一种是成员变量(实例属性),另一种是类变量(类属性)。 成员变量是在构造方法__init__()中定义的,通过 self 参数引用; 类变量是在类中方法之外定义的变量。 在类的外部,成员变量属于对象,只能通过对象名访问; 类变量属于类,既可以通过类名访问,又可以…

成员变量[详解]

我是认为"成员变量包含实例变量和静态变量(静态变量也是类变量)",但学习过程中遇到说"成员变量仅仅指实例变量",所以下面具体研究一下成员变量的定义、包含关系 1、认同"成员变量包含实例变量和静态变量"的说法汇总 说法一 java中,成员变量是指…

基于MediaPlayer实现视频播放

一、概述 一个简单的视频播放器&#xff0c;满足一般的需求。使用原生的 MediaPlayer 和 TextureView来实现。 功能点&#xff1a; 获取视频的首帧进行展示&#xff0c;网络视频的首帧会缓存视频播放&#xff0c;本地视频或者网络视频感知生命周期&#xff0c;页面不可见自动…

玩转 Android MediaPlayer之Media Proxy

本文来自http://blog.csdn.net/hellogv/ &#xff0c;引用必须注明出处&#xff01; 本文是在《Android MediaPlayer与Http Proxy结合之提高篇》基础上&#xff0c;进一步优化代理服务器&#xff0c;支持了Http的302、301重定向&#xff0c;获取Http Request和Http Response的文…

MediaPlayer播放assets文件夹下的音频

一、先放张图&#xff0c;MediaPlayer的生命周期图如下&#xff1a; 二、mediaPlayer方法 setDataSource() //设置要播放的音频文件的位置 prepare() //在开始播放之前调用这个方法完成准备工作 start() //开始或继续播放音频 pause() //暂停播放音频 reset() //将MediaPlayer…

Android openGL+MediaPlayer播放视频

在Android平台折腾了好多次openGL MediaPlayer播放视频的事情&#xff0c;openGL本身是套API规范&#xff0c;其身后的计算机图形学还是比较难缠&#xff0c;但只是播放视频用不了太多东西&#xff0c;没有过多的坐标转换、简单2D纹理展示&#xff0c;实现起来还是比较简单&am…

Android-MediaPlayer播放网络音频

官方文档&#xff1a;https://developer.android.google.cn/reference/android/media/MediaPlayer 运行截图&#xff1a; 主布局文件&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.a…

深入Android MediaPlayer的使用方法详解

1&#xff09;如何获得MediaPlayer实例&#xff1a; 可以使用直接new的方式&#xff1a; MediaPlayer mp new MediaPlayer(); 也可以使用create的方式&#xff0c;如&#xff1a; MediaPlayer mp MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了 2) 如…

Android MediaPlayer状态机

翻译Android Reference Manual的MediaPlayer的状态机 对播放音频/视频文件和流的控制是通过一个状态机来管理的。下图显示一个MediaPlayer对象被支持的播放控制操作驱动的生命周期和状态。椭圆代表MediaPlayer对象可能驻留的状态。弧线表示驱动MediaPlayer在各个状态之间迁移的…

Android提高第二十一篇之MediaPlayer播放网络视频

本文来自http://blog.csdn.net/hellogv/ &#xff0c;引用必须注明出处&#xff01; 上次讲解了MediaPlayer播放网络音频&#xff0c;介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法&#xff0c;这次再讲解MediaPlayer播放网络视频。播放网络视频比播放网络音频多需要…