unity3d反编译能提取场景资源吗

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity3d反编译能提取场景资源吗相关的知识,希望对你有一定的参考价值。

  下面我会从头介绍一下提取的全过程:

步骤一:首先下载 DisUnity v0.3.1
我解压到了D:\\disunity_v0.3.1 这个路径 大家根据自己的需求来选择自己的路径吧

步骤二:确保安装了 Java JDK 7
检测是否安装成功 在cmd输入 java -version 可以打印出版本号 说明应该没问题了。如果没有成功这里就不详细介绍了 问下度娘或者google一下(虽然最近google有些杯具了),请大家见谅。

步骤三:获取可以破解的源文件 首先我们需要android的 .apk 或者 ios的 .ipa 或者网页游戏的.unity3d 和 .boundle 文件
Android: 先看看 Android 的 apk 安装包吧,把下好的文件后缀名.apk 直接改成 .rar 解压到单独的文件夹 可以反编译的文件的路径就在:解压后的文件夹\\assets\\bin\\Data
IOS: ios的 ipa的安装包 也是同样的原理 把.ipa 改成 .rar 然后解压到单独的文件夹 可以反编译的文件的路径就在: 解压后的文件夹\\Payload\\godoflight.app\\Data (这里我用的是神之光举例子 所以是 godoflight.app)
网页: 这个我们重点讲一下

下面我讲一下如何提取unity3d做的网页游戏的资源

首先我们先要下载 火狐浏览器 请大家自行下载吧。

然后安装 FireBug 插件 上图了

然后搜索 Firebug 找到后点安装

安装成功后这里会有个虫子的图标

准备工作完成了,下面我们找一个unity3d开发的网页游戏 这里我们用 《冰火破坏神》 来举例,

先登录游戏,然后打开firebug 如图 点 [网络] -> [全部] 如果目前网页中有unity的资源的话 就会在下面的列表里出现

这里我先清理了一下因为里面有很多不是unity的资源文件 列表清空了之后 我点 【进入游戏】 就进入了一个加载界面列表里开始加载新的资源

有.boundle 和 .unity3d 的资源 这就是我们需要的 至于其他的资源 我也是刚刚才尝试出来的估计就这两种有用的文件吧 如果不是还请大家补充 大家共同研究哈。

这里已经加载了不少资源了 然后就是蛋疼的下载 因为一直没有很好的批量下载的方法 我目前还是一个一个的下载 如果大家有好的方法的话 希望可以分享一下 感激不尽。

复制链接 然后我用工具下载下来就可以了(我用的QQ旋风)。

到此需要做的准备基本完成下面我们开始反编译。

步骤四: 打开cmd 进入步骤一中的 D:\\disunity_v0.3.1 文件夹中

下面是disunity_v0.3.1中的目录结构

然后我们可以用命令 disunity extract 需要反编译的文件的路径\\*.* 就可以了
我的反编译文件放在了E:\\Downloads\\szgPJB(jb51.net)\\assets\\bin\\Data 这个文件夹中 用 *.* 就可以把里面的文件全部反编译 当然无法识别的文件是没法反编出来的

从.ipa和.apk中解压出来的资源 貌似只有 .assets 文件可以反编译出来

从网页上下载的.boundle和.unity3d 文件也可以放到一个文件夹 用上面的方法 反编译出来。
当然 单个文件的话 把*.* 替换成想要反编译的文件就可以了
参考技术A unity3d反编译也是能提取场景资源的,这一点毋庸置疑。本回答被提问者采纳

Android反编译和二次打包

参考:APK反编译

一、工具介绍:

1、解压工具

2、JDK

3.apktool: aapt.exe,apktool.bat,apktool.jar;三个在同一目录结合使用,用来反编译apk,反编译生成smali字节码文件,提取apk中的资源文件,apk重新打包

4.dex2jar:该工具作用是将classes.dex文件,翻译出程序的源代码、图片、XML配置、语言资源等文件(如果apk未加固),反编译出文件,使用jd-gui工具进行查看;

5.jarsigner.exe:签名工具,将重新打包的apk进行签名,如果不签名,无法安装使用。

为了尽可能的把问题讲清楚,我们来实现一个很简单的例子。首先创建一个工程DecompileDemo,在MainActivity中定义一个布局,其中包含一个Button,点击会打印一段日志。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(this);
    }
 
    @Override
    public void onClick(View v) {
        Log.d(TAG,"Button is clicked");
    }
}

将这个工程编译生成的apk。

1、反编译apk包。利用apk tool对apk进行反编译。apktool -f [待反编译的apk] -o [反编译之后存放文件夹]  

运行apktool.jar这个jar文件来将apk文件进行反编译,在java中,运行可执行jar包的命令是:

java -jar jar包名.jar

  命令:java -jar apktools.jar d -f -o test_output_dir ****.apk

  此命令将会反编译apk包到test_output_dir文件夹下。文件夹下是反编译出来的各种文件夹。具体参考网上找的图:

  

 2、使用dex2jar反编译apk得到Java源代码。首先将apk包,解压成zip文件。得到其中的classes.dex文件(它就是java文件编译再通过dx工具打包而成的)

  d2j-dex2jar classes.dex

  命令执行完成之后,在当前目录下就可以看到生成的Jar文件了。

   3、可以用jd-gui工具进行查看步骤2内生成的classes_dex2jar.jar。其内容和步骤1内的smali相对应。

  被混淆过的类文件名称以及里面的方法名称都会以a,b,c....之类的样式命名

  

 可以看到反编译的代码和原本的代码差别不大,主要差别是原来的资源引用全都变成了数字。

       下面我们来修改这个apk的内容。

4、在步骤1内生成的文件夹内,找到主要的类MainActivity.smali,文件内容如下:

.class public Lcom/viclee/decompiledemo/MainActivity;
.super Landroid/support/v7/app/AppCompatActivity;
.source "MainActivity.java"
 
# interfaces
.implements Landroid/view/View$OnClickListener;

 
# static fields
.field private static final TAG:Ljava/lang/String; = "MainActivity"
 
 
# instance fields
.field private btn:Landroid/widget/Button;
 
 
# direct methods
.method public constructor <init>()V
    .locals 0
 
    .prologue
    .line 9
    invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V
 
    return-void
.end method
 
 
# virtual methods
.method public onClick(Landroid/view/View;)V
    .locals 2
    .param p1, "v"    # Landroid/view/View;
 
    .prologue
    .line 23
    const-string v0, "MainActivity"
 
    const-string v1, "Button is clicked"
 
    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
 
    .line 24
    return-void
.end method
 
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 1
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;
 
    .prologue
    .line 14
    invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
 
    .line 15
    const v0, 0x7f040019
 
    invoke-virtual {p0, v0}, Lcom/viclee/decompiledemo/MainActivity;->setContentView(I)V
 
    .line 17
    const v0, 0x7f0c0050
 
    invoke-virtual {p0, v0}, Lcom/viclee/decompiledemo/MainActivity;->findViewById(I)Landroid/view/View;
 
    move-result-object v0
 
    check-cast v0, Landroid/widget/Button;
 
    iput-object v0, p0, Lcom/viclee/decompiledemo/MainActivity;->btn:Landroid/widget/Button;
 
    .line 18
    iget-object v0, p0, Lcom/viclee/decompiledemo/MainActivity;->btn:Landroid/widget/Button;
 
    invoke-virtual {v0, p0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
 
    .line 19
    return-void
.end method

其中36-40行是打印日志的位置,文件内容很清晰,每个区域的意义如下:

.class  类名

.super 父类名

.source  文件名

.implements  这个类实现的接口

.field  成员变量

.method 方法

       5、然后新建一个工程,在这个工程中实现想要替换的代码,我们这里是希望将原始工程中打印日志的地方替换为弹出一个Toast。

public class MainActivity extends AppCompatActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        showToast();
    }
 
    public void showToast() {
        Toast.makeText(this,"我是反编译后进行的修改。",Toast.LENGTH_LONG).show();
    }
}

然后像前面一样执行apktool命令,生成的smali文件内容如下:

.class public Lcom/viclee/decompiledemo/MainActivity;
.super Landroid/support/v7/app/AppCompatActivity;
.source "MainActivity.java"
 
 
# direct methods
.method public constructor <init>()V
    .locals 0
 
    .prologue
    .line 7
    invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V
 
    return-void
.end method
 
 
# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 1
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;
 
    .prologue
    .line 10
    invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
 
    .line 11
    const v0, 0x7f040019
 
    invoke-virtual {p0, v0}, Lcom/viclee/decompiledemo/MainActivity;->setContentView(I)V
 
    .line 13
    invoke-virtual {p0}, Lcom/viclee/decompiledemo/MainActivity;->showToast()V
 
    .line 14
    return-void
.end method
 
.method public showToast()V
    .locals 2
    .prologue
    .line 17
    const-string v0, "\\u6211\\u662f\\u53cd\\u7f16\\u8bd1\\u540e\\u8fdb\\u884c\\u7684\\u4fee\\u6539\\u3002"
 
    const/4 v1, 0x1
    invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
 
    move-result-object v0
 
    invoke-virtual {v0}, Landroid/widget/Toast;->show()V
 
    .line 18
    return-void
.end method

上面代码中,33、39-56行就是弹出Toast的代码部分。将上面整个showToast方法拷贝到原始工程的smali文件中,这里要特别注意修改行号,这个行号表示的是代码在原始Java文件中的行号,需要参考两个smali文件的行号来修改。我认为只要保证方法内的行号不乱序,并且方法之间的行号不冲突就可以。然后,需要将原始工程中打印日志的代码替换为显示Toast的代码,也就是将原始smali文件中36-40行修改为新建工程中33、39-56行的内容。修改后的内容如下,主要关注下面内容中36行、75-91行与原始smali文件的差异。

.class public Lcom/viclee/decompiledemo/MainActivity;
.super Landroid/support/v7/app/AppCompatActivity;
.source "MainActivity.java"
 
# interfaces
.implements Landroid/view/View$OnClickListener;
 
 
# static fields
.field private static final TAG:Ljava/lang/String; = "MainActivity"
 
 
# instance fields
.field private btn:Landroid/widget/Button;
 
 
# direct methods
.method public constructor <init>()V
    .locals 0
 
    .prologue
    .line 9
    invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V
 
    return-void
.end method
 
 
# virtual methods
.method public onClick(Landroid/view/View;)V
    .locals 2
    .param p1, "v"    # Landroid/view/View;
 
    .prologue
    .line 23
    invoke-virtual {p0}, Lcom/viclee/decompiledemo/MainActivity;->showToast()V
 
    .line 24
    return-void
.end method
 
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 1
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;
 
    .prologue
    .line 14
    invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
 
    .line 15
    const v0, 0x7f040019
 
    invoke-virtual {p0, v0}, Lcom/viclee/decompiledemo/MainActivity;->setContentView(I)V
 
    .line 17
    const v0, 0x7f0c0050
 
    invoke-virtual {p0, v0}, Lcom/viclee/decompiledemo/MainActivity;->findViewById(I)Landroid/view/View;
 
    move-result-object v0
 
    check-cast v0, Landroid/widget/Button;
 
    iput-object v0, p0, Lcom/viclee/decompiledemo/MainActivity;->btn:Landroid/widget/Button;
 
    .line 18
    iget-object v0, p0, Lcom/viclee/decompiledemo/MainActivity;->btn:Landroid/widget/Button;
 
    invoke-virtual {v0, p0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
 
    .line 19
    return-void
.end method
 
.method public showToast()V
    .locals 2
 
    .prologue
    .line 27
    const-string v0, "\\u6211\\u662f\\u53cd\\u7f16\\u8bd1\\u540e\\u8fdb\\u884c\\u7684\\u4fee\\u6539\\u3002"
 
    const/4 v1, 0x1
 
    invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
 
    move-result-object v0
 
    invoke-virtual {v0}, Landroid/widget/Toast;->show()V
 
    .line 28
    return-void

然后我们需要将修改后的文件目录重新打包,执行命令 apktool   b  app-release,就会在app-releae目录下生成两个文件夹:build 文件夹里面是一些中间文件(classes.dex等内容),dist 文件夹里面存放着重新打包出来的apk文件。

       6、最后还要记得对生成的apk进行签名,否则安装时会报错。执行下面的命令行:

jarsigner -verbose -keystore viclee.keystore -signedjar app-release-signed.apk app-release.apk viclee.keystore 

-verbose 输出签名详细信息 
-keystore 指定密钥对的存储路径 
-signedjar 后面三个参数分别是签名后的apk、未签名的apk和密钥对的别名

       安装签名后的apk,点击按钮,确实弹出了Toast,内容和我们所设置的一致,说明我们的修改成功了。

我们注意到,修改smali文件的时候并不是直接在文件上进行修改,毕竟smali文件的可读性差,直接修改是十分困难的。我们的解决办法是新建一个工程将需要增加的代码实现,最好抽成一个单独的方法(方便替换),然后将新工程打包产生的apk反编译,得到对应的smali文件,再用其中的内容对原始smali文件进行替换。这样的修改方式降低了修改的难度也减小了犯错误的风险。

  

以上是关于unity3d反编译能提取场景资源吗的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D代码加密防止反编译及资源加密

如何防止Unity3D代码被反编译

如何防止Unity3D代码被反编译

Unity3D对apk反编译重编译重签名

如何防止Unity3D代码被反编译

如何防止Unity3D代码被反编译