• 在工作中,有些第三方JAR...使用反编译工具JD-GUI)打开要修改的jar包(如beforeModify.jar),找到jar包中要修改的class文件(如A.class) 打开Eclipse新建一个Java工程,并添加一个类(如A.java:该类名与A.class

    在工作中,有些第三方JAR不能满足我们的特殊需求,所以经常会有需要修改JAR的情况,这里给出基本的修改思路,然后再辅以实例。

    思路

    • 使用反编译工具JD-GUI)打开要修改的jar包(如beforeModify.jar),找到jar包中要修改的class文件(如A.class)

    • 打开Eclipse新建一个Java工程,并添加一个类(如A.java:该类名与A.class文件中的类名一致,所在包结构与A.class文件中的类所在的包结构一致),复制A.class文件里的全部内容到A.java,对A.java做你要的修改保存即可。补充一点,有些类通过JD-GUI查看会导致莫名的乱码或者错误,这个时候最保险的方法是通过Google Git找出相应的源码,然后复制到Eclipse中的A.java中去。

    • 使用WinRAR解压工具打开如beforeModify.jar,找到A.class选中右键点击删除

    • 把如beforeModify.jar导入到项目中,把项目中需要的jar包导入,导入的目的是保证项目没有报错,可以正常编译。

    • 右键项目导出jar包(如afterModify.jar),然后用WinRAR打开afterModify.jar,找到重新编译好的A.class

    • 用WinRAR打开beforeModify.jar,找到原来A.class文件存放的目录,把重新编译后的A.class文件拖进目录覆盖即可。


    展开全文
  • 本文我们将来探讨关于Android反编译。通常来说,我们在开发过程中的apk出于DEBUG状态,我们并没有给予APK一个特定的签名,而是编译系统默认给apk一个签名。在发布到应用商城时,我们会用自己的签名文件来签名apk,...

      本文我们将来探讨关于Android的反编译。通常来说,我们在开发过程中的apk出于DEBUG状态,我们并没有给予APK一个特定的签名,而是编译系统默认给apk一个签名。在发布到应用商城时,我们会用自己的签名文件来签名apk,以防止被其他人恶意篡改apk。当然,我们也会利用Android的混淆技术或者一些加固技术来防止apk被反编译造成源码泄漏。

      所以,本文只能针对于没有被签名、混淆、加固过的apk,对于绝大多数市面上的apk来说,如果你想要通过反编译得到里面的重要源码,那是行不通的。如果apk用了加固技术,那根本要反编译都很困难。

      我先列举一下我们将会用到的几个工具:
    apktool.jar:查看apk包下的AndroidManifest.xml和res文件夹内容。
    dex2jar.jar:把apk中的classes.dex转为一个jar包
    jdgui:通过上面获得的jar包,利用这个工具打开
    baksmali.jar:把apk中的classes.dex转为为smali源码
    smali:把smali文件编译打包成classes.dex的工具
    signapk.jar 把我们重新生成的apk重新签名

    以上的所有工具打包下载链接:http://download.csdn.net/download/lc_miao/9966230

      废话少说,我们来自己写个Demo,编译出一个apk,这个apk很简单,我们在AActivity输入密码:123456之后才能启动到BActivity,否则提示密码错误。
    源码如下:

    public class AActivity extends ActionBarActivity {
    
        Button btn;
        EditText et;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn = (Button) findViewById(R.id.bt);
            et = (EditText) findViewById(R.id.et);
            btn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    String pwd = et.getText().toString();
                    if("123456".equals(pwd)){
                        startActivity(new Intent(AActivity.this,BActivity.class));
                        Toast.makeText(AActivity.this, "登录成功", Toast.LENGTH_LONG).show();
                    }else{
                        Toast.makeText(AActivity.this, "密码错误", Toast.LENGTH_LONG).show();
                    }
                }
            });
    
        }

      我们的运行截图是这样:

    error
    成功

    好的,接下来我们来尝试解开apk里面的内容。把apk文件的后缀名改成.zip的压缩格式,打开:
    zip

      从apk的目录来看:

      res:我们的资源目录
      META-INF:一些信息配置,这里我们可以不关心。
      resources.arsc:编译资源时生成的文件,资源能根据配置索引到相应的资源就是依赖了它。
      classes.dex:源码编译打包后的文件。
      AndroidManifest.xml:大家都知道了

      首先,我们来看下如何查看apk的源码,我们提取出classes.dex,把classes.dex放到dex2jar的文件夹里面,然后打开cmd,cd进入dex2jar的文件目录,输入命令:dex2jar.bat classes.dex

    dex
      可以发现文件夹里面生成了一个classes_dex2jar.jar,我们把这个jar包提取出来,用jd-gui这个工具来打开,可以直接将jar包拖曳到jd-gui上打开,如下:

    反编译

      到此,我们就完成了反编译的源码查看。

      而apk里面的res目录一些xml文件和AndroidManifest.xml,由于已经被编译成二进制文件,我们无法直接打开查看。可以由apktool.jar这个工具来反编译还原成我们能打开查看的文件。

      同样在cmd里面 cd进入apktool.jar所在的文件夹,把我们的apk放进来,后缀名可以是被我们改成的zip后缀,或者是原先的.apk后缀。
    敲入命令:apktool d Demo.zip

    res

      在文件夹中生成了一个文件夹,里面所有的xml文件我们就可以打开查看了,
    比如查看AndroidManifest.xml:
    mani

      到这里我们已经学会了反编译查看apk源码。接下来我们再来看看如何修改apk进行二次打包。

      在上面我们写的apk中,需要输入123456才能登录进第二个界面,。并且会弹出Toast提示。
      我们来修改成输入123即可进入第二个界面。

      首先,我们需要把classex.dex转为smali文件,利用baksmali.jar这个工具,如下:

      我们把classex.dex复制到baksmali.jar所在的文件夹,然后cd进入这个文件夹之后,敲入命令: java -jar baksmali-2.0.3.jar -x classes.dex
    baks

      可以发现目录生成了个out文件夹,里面存放的就是我们的源码,不过是smali格式的,如果想要深层次的去修改源码则需要先学习smali的语法构造。这里我们简单的修改几个数值,进入out文件中,依次点开文件夹可以发现好几个smali文件,我们发现AActivity的有AActivity.smali文件和AActivity1.smali,AActivity1.smali是和匿名内部类有关,这跟我们在开发中打开出匿名内部类的类名是一样的。由于这里我们只是用到了点击事件,所以这个AActivity$1.smali就是点击事件的匿名内部类的实现了,我们打开这个文件。
      打开后发现都是我们不熟悉的语法,
    首先:

    .class Lcom/example/demo/AActivity$1; 我们定义的类
    .super Ljava/lang/Object; 继承的超类,默认是Object
    .source “AActivity.java” 对应的源文件

    .# interfaces
    .implements Landroid/view/View$OnClickListener;
    这个是实现的接口

    下面的# instance fields、# direct methods、# virtual methods则是这个类定义的字段、方法了。
    我们重点来看onClick方法:

    # virtual methods
    .method public onClick(Landroid/view/View;)V
        .registers 8
        .param p1, "v"    # Landroid/view/View;
    
        .prologue
        const/4 v5, 0x1
    
        .line 27
        iget-object v1, p0, Lcom/example/demo/AActivity$1;->this$0:Lcom/example/demo/AActivity;
    
        iget-object v1, v1, Lcom/example/demo/AActivity;->et:Landroid/widget/EditText;
    
        invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
    
        move-result-object v1
    
        invoke-interface {v1}, Landroid/text/Editable;->toString()Ljava/lang/String;
    
        move-result-object v0
    
        .line 28
        .local v0, "pwd":Ljava/lang/String;
        const-string v1, "123456"
    
        invoke-virtual {v1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
    
        move-result v1
    
        if-eqz v1, :cond_2f
    
        .line 29
        iget-object v1, p0, Lcom/example/demo/AActivity$1;->this$0:Lcom/example/demo/AActivity;
    
        new-instance v2, Landroid/content/Intent;
    
        iget-object v3, p0, Lcom/example/demo/AActivity$1;->this$0:Lcom/example/demo/AActivity;
    
        const-class v4, Lcom/example/demo/BActivity;
    
        invoke-direct {v2, v3, v4}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
    
        invoke-virtual {v1, v2}, Lcom/example/demo/AActivity;->startActivity(Landroid/content/Intent;)V
    
        .line 30
        iget-object v1, p0, Lcom/example/demo/AActivity$1;->this$0:Lcom/example/demo/AActivity;
    
        const-string v2, "\u767b\u5f55\u6210\u529f"
    
        invoke-static {v1, v2, v5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    
        move-result-object v1
    
        invoke-virtual {v1}, Landroid/widget/Toast;->show()V
    
        .line 34
        :goto_2e
        return-void
    
        .line 32
        :cond_2f
        iget-object v1, p0, Lcom/example/demo/AActivity$1;->this$0:Lcom/example/demo/AActivity;
    
        const-string v2, "\u5bc6\u7801\u9519\u8bef"
    
        invoke-static {v1, v2, v5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    
        move-result-object v1
    
        invoke-virtual {v1}, Landroid/widget/Toast;->show()V
    
        goto :goto_2e
    .end method

    再配合我们在jd-gui中打开查看到的源码。

     .line 27
        iget-object v1, p0, Lcom/example/demo/AActivity$1;->this$0:Lcom/example/demo/AActivity;
    
        iget-object v1, v1, Lcom/example/demo/AActivity;->et:Landroid/widget/EditText;
    
        invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;
    
        move-result-object v1
    
        invoke-interface {v1}, Landroid/text/Editable;->toString()Ljava/lang/String;
    
        move-result-object v0

      首先onClick的这部分代码,可以对应我们查看到的源码这行:
    “123456”.equals(AActivity.this.et.getText().toString())

      可以看出上面几句smali源码是这句代码的一个执行顺序,首先是有这个AActivity对象,然后得到EditText对象,然后执行getText后执行toString

    其后:

       .line 28
        .local v0, "pwd":Ljava/lang/String;
        const-string v1, "123456"
    
        invoke-virtual {v1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

      发现载入了一个pwd变量,赋值为v0,v0实际上就是上面 move-result-object v0得到的。然后再有一个字符串常量为123456,到此我们就可以把123456修改成123了。

      接着执行了equals后,注意到:

    move-result v1
    
    if-eqz v1, :cond_2f

      把结果move到v1,又判断v1,如果v1是0的话跳到cond_2f,
    不是0则继续下面,下面的代码也可以看出加载顺序就是intent启动的加载顺序了,
      直到最后弹出了Toast提示,我们可以发现到

    const-string v2, "\u767b\u5f55\u6210\u529f"

      正是Toast弹出提示的内容,也可以进行修改。

    最后面:

     :cond_2f
        iget-object v1, p0, Lcom/example/demo/AActivity$1;->this$0:Lcom/example/demo/AActivity;
    
        const-string v2, "\u5bc6\u7801\u9519\u8bef"
    
        invoke-static {v1, v2, v5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    
        move-result-object v1
    
        invoke-virtual {v1}, Landroid/widget/Toast;->show()V

      则是上面的if eqz v1后为0跳到这里来,实际上就是密码匹配123456不对后跳到这里来提示了密码错误。

      上面的源码我们可以修改很多东西,比如修改if条件,加入其他方法执行,但注意不能加入新定义的方法。

      这里我们简单就修改了密码为123后保存文件

      然后重新转为classex.dex,利用smali.jar工具打包,同样进入文件夹,敲入命令:

    java -jar smali-2.0.3.jar -o classes.dex out

      后生成了一个新的classex.dex,我们把它替换到apk中去,
    然后重新签名,利用signapk.jar工具签名,同样cd到signapk.jar目录下,敲入命令:

    java -jar signapk.jar platform.x509.pem platform.pk8 Demo.apk DemoSigned.apk

      得到了一个DemoSigned.apk,我们把DemoSigned.apk转载到模拟器上看,输入命令:

    adb uninstall com.example.demo

    先卸载掉原先的apk,再输入命令安装:

    adb install DemoSigned.apk

    我们来看看运行:

    打包

      可以发现我们成功修改了apk,现在输入123456是密码错误了,因为密码验证被我们改成了123.

      到此就结束了,后面有机会我再写一些关于smali语法和逆向分析的博文。

    展开全文
  • 一、工具准备:apktool , dex2jar , jd-gui 二、使用dex2jar + jd-gui 得到apk的java源码 1.用解压工具从 apk包中取出 classes....2.用jd-gui反编译工具将得到.jar文件反编译成.java文件 三、使用apktool得到a

    一、工具准备:apktool , dex2jar , jd-gui

    二、使用dex2jar + jd-gui 得到apk的java源码
    1.用解压工具从 apk包中取出 classes.dex 文件
    用命令(dex2jar.bat classes.dex)得到一个 jar文件
    2.用jd-gui反编译工具将得到.jar文件反编译成.java文件

    三、使用apktool得到apk的xml文件
    1.用命令(apktool d xxx.apk xxx_xml)反编译xxx.apk包
    2.从 xxx_xml 文件夹得到xml文件

     

    四、第二步 得到的程序源代码 和 第三步 得到的xml文件组合下,即可得到完整的apk源码。

     

    五、应用: 汉化/去广告,加 values-zh-rCN, values-zh-rTW, values-de, values-fr

    1.在步骤三的文件夹xxx_xml/res/ 下, 建文件夹: values-zh-rCN,values-zh-rTW

    2.1复制values\strings.xml 到   values-zh-rCN 并翻译.

    2.2 去广告见;

    3.重建APK,用命令(apktool b xxx) ,输出到ABC/dist/out.apk

       或命令( apktool b xxx out.apk)

     

    六、重新打包 和 签名

    ======================================================


    1) 汉化apk应用程序

           汉化apk就是 把 反编译之后apk 下的res/values文件夹内string.xml文件的内容 汉化(注意:我们的例子里 只有一个string.xml,有时候 可能 不止 一个 *xml 文件,那么 我们 需要把 相应的 位置 都汉化)。

            一个apk应用在汉化后应该能在英文和中文系统下都能使用。/values目录下的是英文语言包。为了建一个中文语言包,与/values并行创建一个子文件夹:/values-zh-rCN(必须用这个文件名!)。这里values-zh是中国地区语言包(包含港澳台及内地),values-zh-rCN是中文简体语言包(只包含内地),values-zh-rTW是中文繁体语言包(港澳台)。
    把/values文件夹里的strings.xml等语言文件复制进/values-zh-rCN。在我们的例子中,只有strings.xml一个文件。
    进入/values-zh-rCN,用文本编辑器打开strings.xml,然后你就翻译吧,把英文描述译成相应的中文。


    高级内容:以上的汉化是修改string.xml,把英文译成相应的中文就好了,然后打包和签名。但是,在有些apk文件里,所显示的字符文字并不都在xml文件里。apk原作者把某些字符写在代码中。反编译后,存放在/smali文件夹里。一层一层地找下去,最后你会看到一大堆Dalvik码文件,都是以.smali为文件扩展名。举一个例子,用文本编辑器打开某个.smali文件,看到:
    const-string v5, "ServiceMode"
    “ServiceMode”会在apk执行时显示为英文。因此,需要汉化。在I897 ROM里,用工程模式特殊代码看到的多半属于这一类。汉译起来非常花时间。我们要把ServiceMode译成“服务模式”。怎么处理呢?你不能把const-string v5, "ServiceMode"直接改成const-string v5, "服务模式"。打包会失败的。正确的做法是把相应的中文字符用16进制的unicode来表示。例如:把“服务模式”用16进制的unicode表示就是\u670d\u52a1\u6a21\u5f0f 。每一个汉字用4个字符表示,\u表示为16进制的unicode码。好了,正确的汉译是:
    const-string v5, "\u670d\u52a1\u6a21\u5f0f "
    网上有中文字符与16进制unicode码的对照表或转换工具。


    2) 修改图标标签

    每一个apk文件都有一个“图标标签”。将apk程序安装进手机后,在图标下面显示图标标签文字。这个图标标签的内容是可以修改的。\res\values下找到strings.xml,修改其中的一行:
    <string name="app_name">图标标签</string>
    例如:<string name="app_name">静音启动</string>
    同理,如果是窗口小插件,要修改widget_name。


    3) 去掉apk中的广告

    有很多apk应用都带有广告。为了去掉程序中的广告,要修改main.xml文件与广告有关的内容。在/res目录下找到文件main.xml。通常在/layout目录下,有时也被放在其它目录下。甚至,有时不存在main.xml文件,广告行被放在其它xml文件内。只能细心逐个文件进行查找。无论哪一种情况,查看其内容,你会看到有一项类似的命令如下。这就是广告显示。
    <com.admob.android.ads.AdView android:id=”@id/ad” android:layout_width=”fill_parent” android:layout_height=”wrap_content” admobsdk:backgroundColor=”#ff000000″ admobsdk:textColor=”#ffffffff” admobsdk:keywords=”Android application” />
    将其改为:
    <com.admob.android.ads.AdView android:id=”@id/ad” android:layout_width=”0.0dip” android:layout_height=”0.0dip” admobsdk:backgroundColor=”#ff000000″ admobsdk:textColor=”#ffffffff” admobsdk:keywords=”Android application” />
    可以看到,关键是要把fill_parent改为0.0dip,把wrap_content改为0.0dip,其它内容保持不变即可。这种改法就是不给广告显示空间,当然你就看不到广告了。




    展开全文
  • 今天百度搜索“Android反编译”搜索出来的结果大多数都是比较传统的教程。刚接触反编译的时候,我也是从这些教程慢慢学起的。在后来的学习过程中,我接触到比较方便操作的Android反编译。在这,我将使用的过程写下来...

     今天百度搜索“Android反编译”搜索出来的结果大多数都是比较传统的教程。刚接触反编译的时候,我也是从这些教程慢慢学起的。在后来的学习过程中,我接触到比较方便操作的Android反编译。在这,我将使用的过程写下来,贡献给有需的朋友,为国内Android的事业作出一点点贡献。

    首先今天百度搜索“Android反编译”搜索出来的结果大多数都是比较传统的教程。刚接触反编译的时候,我也是从这些教程慢慢学起的。在后来的学习过程中,我接触到比较方便操作的Android反编译。在这,我将使用的过程写下来,贡献给有需的朋友,为国内Android的事业作出一点点贡献。,我们先看一Android界有名的大神写关于Android反编译的博客:

    (郭大侠)http://blog.csdn.net/guolin_blog/article/details/49738023

    (鸿洋大神)http://blog.csdn.net/lmj623565791/article/details/23564065

    (主席大神)http://blog.csdn.net/singwhatiwanna/article/details/18797493

    我推荐大家使用的Android反编译的软件是Android Killer。(这启动界面Cool爆了)

    image

    其实这个软件就是对以上博客提到的操作进行一系列的封装。打开这个软件你就可以发现这些熟悉的反编译工具。

    image

    接着,打开待反编译的apk。(在这示范反编译美柚)

    软件清晰地展示了美柚的信息。(是反编译的不错选择)

    image

    切换到工程管理器,可以查看反编译的资源和smail代码等。

    image

    image

    image

    接下来,查看smali代码,找到你需要查看的文件,点击下图的这个图标

    image 

    看到熟悉的界面了吧。。。

    image

     

    --------------------------------接下来我们修改apk,然后重新打包--不要干坏事-----------------------------

    下面演示修改一个apk的名称

    切换到工程搜索,输入app_name,点击下面搜索到的内容,修改为美柚a。

    image

    接下来,编译打包。

    切换到Android,点击编译。菜单栏还有好多关于Android功能。

    image

    从日志输出的信息可以看到,已经编译打包好了。

    image

    最后,我们安装编译好的apk。

    image

    这软件还有好多功能,在这不一一列出了,有兴趣的朋友自己慢慢摸索。

    在些,我不是在为这个软件做广告,只是推荐大家使用。

    展开全文
  • 我们都知道,Android程序打完包之后得到的是一个APK文件,这个文件是可以直接安装到任何Android手机上的,我们反编译其实也就是对这个APK文件进行反编译Android反编译主要又分为两个部分,一个是对代码的反编译...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/49738023
    之前一直有犹豫过要不要写这篇文章,毕竟去反编译人家的程序并不是什么值得骄傲的事情。不过单纯从技术角度上来讲,掌握反编译功能确实是一项非常有用的技能,可能平常不太会用得到,但是一旦真的需要用到的了,而你却不会的话,那就非常头疼了。另外既然别人可以反编译程序,我们当然有理由应该对程序进行一定程度的保护,因此代码混淆也是我们必须要掌握的一项技术。那么最近的两篇文章我们就围绕反编译和混淆这两个主题来进行一次完全解析。


    反编译

    我们都知道,Android程序打完包之后得到的是一个APK文件,这个文件是可以直接安装到任何Android手机上的,我们反编译其实也就是对这个APK文件进行反编译。Android的反编译主要又分为两个部分,一个是对代码的反编译,一个是对资源的反编译,我们马上来逐个学习一下。
    在开始学习之前,首先我们需要准备一个APK文件,为了尊重所有开发者,我就不拿任何一个市面上的软件来演示了,而是自己写一个Demo用来测试。
    这里我希望代码越简单越好,因此我们建立一个新项目,在Activity里加入一个按钮,当点击按钮时弹出一个Toast,就这么简单,代码如下所示:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(MainActivity.this, "you clicked button", Toast.LENGTH_SHORT).show();
                }
            });
        }
    
    }

    activity_main.xml中的资源如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin">
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"/>
    
    </RelativeLayout>

    然后我们将代码打成一个APK包,并命名成Demo.apk,再把它安装到手机上,结果如下所示:


    好的,到这里准备工作就已经基本完成了,接下来就让我们开始对这个Demo程序进行反编译吧。

    反编译代码

    要想将APK文件中的代码反编译出来,我们需要用到以下两款工具:

    将这两个工具都下载好并解压,然后我们就开始对Demo程序进行反编译。解压dex2jar压缩包后,你会发现有很多个文件,如下图所示:


    其中我们要用到的是d2j-dex2jar.bat这个文件,当然如果你是linux或mac系统的话就要用d2j-dex2jar.sh这个文件。
    然后我们将Demo.apk文件也进行解压,如果不知道怎么直接解压的可以先将文件重命名成Demo.zip,然后用解压软件打开。解压之后你会发现里面有一个classes.dex文件,如下图所示:

    这个classes.dex文件就是存放所有java代码的地方了,我们将它拷贝到dex2jar解压后的目录下,并在cmd中也进入到同样的目录,然后执行:

    d2j-dex2jar classes.dex

    执行结果如下图所示:


    没有报任何错误,这就说明我们已经转换成功了。现在观察dex2jar目录,你会发现多了一个文件,如下图所示:

    可以看到,classes-dex2jar.jar这个文件就是我们借助工具之后成功转换出来的jar文件了。但是对于我们而言,jar文件也不是可读的,因此这里还需要再借助一下jd-gui这个工具来将jar文件转换成java代码。
    下面就很简单了,使用jd-gui工具打开classes-dex2jar.jar这个文件,结果如下图所示:

    OK,由此可见,我们的代码反编译工作已经成功了,MainActivity中的代码非常清晰,基本已经做到了90%以上的还原工作。但是如果想要做到100%的代码还原还是非常有难度的,因为像setContentView()方法传入的参数,其实就是一个资源的id值而已,那么这里反编译也就只能将相应的id值进行还原,而无法变成像R.layout.activity_main这样直观的代码展示。
    另外,除了MainActivity之外,还有很多其它的代码也被反编译出来了,因为当前项目有引用support-v4和support-v7的包,这些引用的library也会作为代码的一部分被打包到classes.dex文件当中,因此反编译的时候这些代码也会一起被还原。
    好的,学完了反编译代码,接下来我们看一下如何反编译资源。

    反编译资源

    其实细心的朋友可能已经观察到了,刚才Demo.apk的解压目录当中不是已经有资源文件了吗,有AndroidManifest.xml文件,也有res目录。进入res目录当中,内容如下图所示:


    这不是所有资源文件都在这里了么?其实这些资源文件都是在打包的时候被编译过了,我们直接打开的话是看不到明文的,不信的话我们打开AndroidManifest.xml文件来瞧一瞧,内容如下图所示:

    可以看到,这代码是完全没法阅读的。当然如果你去打开activity_main.xml看看,结果也不会好到哪儿去:

    由此可见,直接对APK包进行解压是无法得到它的原始资源文件的,因此我们还需要对资源进行反编译才行。
    要想将APK文件中的资源反编译出来,又要用到另外一个工具了:

    关于这个工具的下载我还要再补充几句,我们需要的就是apktool.bat和apktool.jar这两个文件。目前apktool.jar的最新版本是2.0.3,这里我就下载最新的了,然后将apktool_2.0.3.jar重命名成apktool.jar,并将它们放到同一个文件夹下就可以了,如下图所示:


    接下来的工作就很简单了,我们将Demo.apk拷贝到和这两个文件同样的目录当中,然后cmd也进入到这个目录下,并在cmd中执行如下命令:

    apktool d Demo.apk

    其中d是decode的意思,表示我们要对Demo.apk这个文件进行解码。那除了这个基本用法之外,我们还可以再加上一些附加参数来控制decode的更多行为:

    • -f 如果目标文件夹已存在,则强制删除现有文件夹(默认如果目标文件夹已存在,则解码失败)。
    • -o 指定解码目标文件夹的名称(默认使用APK文件的名字来命名目标文件夹)。
    • -s 不反编译dex文件,也就是说classes.dex文件会被保留(默认会将dex文件解码成smali文件)。
    • -r 不反编译资源文件,也就是说resources.arsc文件会被保留(默认会将resources.arsc解码成具体的资源文件)。

    常用用法就这么多了,那么上述命令的执行结果如下图所示:


    这就说明反编译资源已经成功了。
    当然即使你在和我执行一模一样的操作,也有可能会在这里反编译失败,比如说会报如下错误:
    这里写图片描述

    出现这个错误的原因很有可能是你之前使用过apktool的老版本进行过反编译操作,然后apktool就会在你系统的C:\Users\Administrator\apktool\framework这个目录下生成一个名字为1.apk的缓存文件,将这个缓存文件删除掉,然后再重新执行反编译命令应该就可以成功了。
    现在你会发现在当前目录下多了一个Demo文件夹,这个文件夹中存放的就是反编译的结果了。我们可以打开AndroidManifest.xml来瞧一瞧,如下图所示:

    怎么样?这样就完全能看得懂了吧,然后可以再到res/layout中看一下activity_main.xml文件,如下图所示:

    可以看到,activity_main.xml中的内容基本和源代码中的内容是一致的,外层是一个RelativeLayout,里面则是一个Button。你可以再到其它目录中去看一看别的资源,基本上都是可以正常还原的,这样我们就把反编译资源的方法也已经掌握了。

    重新打包

    那么对于反编译出来的文件夹,我们能不能重新把它打包成APK文件呢?答案是肯定的,只不过我实在想不出有什么义正言辞的理由可以让我们这么做。有的人会说汉化,没错,汉化的方式确实就是将一个APK进行反编译,然后翻译其中的资源再重新打包,但是不管怎么说这仍然是将别人的程序进行破解,所以我并不认为这是什么光荣的事情。那么我们就不去讨论本身这件事情的对或错,这里只是站在技术的角度来学习一下重新打包的相关知识。
    首先我们来看一下通过apktool反编译后的包目录情况,如下图所示:


    其中,original文件夹下存放的是未经反编译过、原始的AndroidManifest.xml文件,res文件夹下存放的是反编译出来的所有资源,smali文件夹下存放的是反编译出来的所有代码,AndroidManifest.xml则是经过反编译还原后的manifest文件。这里值得一提的是smali文件夹,如果你进入到这个文件夹中你会发现它的目录结构和我们源码中src的目录结构是几乎一样的,主要的区别就是所有的java文件都变成了smali文件。smali文件其实也是真正的源代码,只不过它的语法和java完全不同,它有点类似于汇编的语法,是Android虚拟机所使用的寄存器语言,语法结构大概如下所示:

    看上去有点晕头转向是吗?但是如果你一旦能够看得懂smali文件的话,那么你就可以做很恐怖的事情了——你可以随意修改应用程序内的逻辑,将其进行破解!
    不过我对这种黑技术并没有什么太大的兴趣,因此我也没有去做具体研究,但即使是这样,也已经可以对程序的逻辑做一定程度的修改了。比如说当我们点击按钮时会弹出you clicked button这样一句Toast,逻辑是写在MainActivity按钮点击事件的匿名类当中的,因此这段代码反编译之后一定就会在MainActivity$1.smali这个文件当中,让我们打开瞧一瞧,部分代码如下所示:

    虽说多数的代码我是看不懂的,但其中第47行实在太明显了,Toast显示的内容不就是在这里定义的么,那么如果我们想把Demo程序hack掉,就可以将这段字符串给改掉,比如说我把它改成Your app is been hacked
    关于smali的语法,网上的资料也非常多,如果你对这门技术十分感兴趣的话可以直接上网去搜,这里我只是简单介绍一下,就不再深入讲解相关知识了。
    改了一处代码后我们再来改一处资源吧,比如这里想要把Demo的应用图标给换掉,那么首先我们要准备好一张新的图片,如下图所示:

    然后从AndroidManifest.xml文件中可以看出,应用图标使用的是ic_launcher.png这张图片,那么我们将上面篮球这张图片命名成ic_launcher.png,然后拷贝到所有以res/mipmap开头的文件夹当中完成替换操作。
    在做了两处改动之后,我们现在来把反编译后的Demo文件夹重新打包成APK吧,其实非常简单,只需要在cmd中执行如下命令:

    apktool b Demo -o New_Demo.apk

    其中b是build的意思,表示我们要将Demo文件夹打包成APK文件,-o用于指定新生成的APK文件名,这里新的文件叫作New_Demo.apk。执行结果如下图所示:


    现在你会发现在同级目录下面生成了一个新的APK文件:

    不过不要高兴得太早了,目前这个New_Demo.apk还是不能安装的,因为它还没有进行签名。那么如果这是别人的程序的话,我们从哪儿能拿到它原来的签名文件呢?很显然,这是根本没有办法拿到的,因此我们只能拿自己的签名文件来对这个APK文件重新进行签名,但同时也表明我们重新打包出来的软件就是个十足的盗版软件。这里大家学学技术就好了,希望不要有任何人去做什么坏事情。
    那么这里我就用一个之前生成好的签名文件了,使用Android Studio或者Eclipse都可以非常简单地生成一个签名文件。
    有了签名文件之后在cmd中执行签名命令就可以进行签名了,命令格式如下:

    jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore 签名文件名 -storepass 签名密码 待签名的APK文件名 签名的别名

    其中jarsigner命令文件是存放在jdk的bin目录下的,需要将bin目录配置在系统的环境变量当中才可以在任何位置执行此命令。
    签名之后的APK文件现在已经可以安装到手机上了,不过在此之前Android还极度建议我们对签名后的APK文件进行一次对齐操作,因为这样可以使得我们的程序在Android系统中运行得更快。对齐操作使用的是zipalign工具,该工具存放于<Android SDK>/build-tools/<version>目录下,将这个目录配置到系统环境变量当中就可以在任何位置执行此命令了。命令格式如下:

    zipalign 4 New_Demo.apk New_Demo_aligned.apk

    其中4是固定值不能改变,后面指定待对齐的APK文件名和对齐后的APK文件名。运行这段命令之后就会生成一个New_Demo_aligned.apk文件,如下所示:


    这个New_Demo_aligned.apk就是我们重新打包签名对齐后的文件了,现在把它安装到手机上,效果如下图所示:

    可以看到,应用图标已经成功改成了篮球,另外点击按钮后弹出的Toast的提示也变成了我们修改后的文字,说明重新打包操作确实已经成功了。


    好的,我们把反编译代码、反编译资源、重新打包这三大主题的内容都已经掌握了,关于反编译相关的内容就到这里,下篇文章会介绍Android代码混淆方面的相关技术,感兴趣的朋友请继续阅读: Android安全攻防战,反编译与混淆技术完全解析(下)

    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • 我们知道,Android的程序打包后会生成一个APK文件,这个文件可以直接安装到任何Android手机上,因此,反编译就是对这个APK进行反编译Android反编译分成两个部分:一个是对代码反编译,也就是java文件的反编译。...
  • android开发中经常会遇到需要反编译竞品的需求,题主也就针对反编译apk后替换sdk后重新打包的场景进行试验,下面一步一步来说明Android如何反编译后重新打包。 一个典型apk包中包含的内容 我们知道android项目...
  • 今天就来总结一下Android反编译和二次打包的一些知识。首先声明本文的目的是为了通过例子讲解反编译和二次打包的原理和方法,继而作为后续讲解防止二次打包和App安全的依据,并不是鼓励大家去重新打包别人的App,...
  • 本文由我的微信公众号:鸿洋(hongyangAndroid)原创首发。...一、概述最近和朋友聊天,发现一些灰色产业链通过批量反编译市场上的apk,然后进行注入广告,再重新打包上渠道。我想大家都不希望自己家的产品或者自
  • 在上一篇文章当中,我们学习了Android程序反编译方面的知识,包括反编译代码、反编译资源、以及重新打包等内容。通过这些内容我们也能看出来,其实我们的程序并没有那么的安全。可能资源被反编译影响还不是很大,而...
  • 反编译Apk,修改文件重新打包APk。 修改资源文件重新打包。 1、使用apktool直接反编译apk  1.1配置apktool环境:  1.1.1打开apktool官网 https://ibotpeaches.github.io/Apktool/install/    ...
  • Android初探反编译

    2019-03-26 15:50:23
    Android初探反编译 本文记述反编译的初级手段。(其余的属于专业的逆向开发人员)   反编译属于逆向工程中的一种,其有很多高级的手段和工具。当我们对别人开发好的应用感兴趣时,我们就可以通过这种技术手段将...
  • 一、前言 今天介绍一个非常好用的反编译的工具 jadx 。...这些优点都让 jadx 成为我反编译的第一选择,它可以处理大部分反编译的需求,基本上是我反编译工具的首选。 接下来我们就来看看,jadx 如何使用吧。 ...
  • android 反编译jar包

    2019-10-26 09:08:17
    最近开发过程中尝试了下jar包的反编译,记录一下~~~~ 用到的工具:fernflower.jar 下载链接: https://pan.baidu.com/s/1Nt0Eb7HS2sT18KbmoYIqkw 提取码: m757 下载好fernflower.jar后,输入命令 我这里是...
  • Android反编译技术

    2018-01-08 15:03:49
    我们都知道,Android程序打完包之后得到的是一个APK文件,这个文件是可以直接安装到任何Android手机上的,我们反编译其实也就是对这个APK文件进行反编译Android反编译主要又分为两个部分,一个是对代码的反编译...
  • 反编译代码 要想将APK文件中的代码反编译出来,我们需要用到以下两款工具:dex2jar 和 jd-gui,可以在网上自行下载,这里分享下网盘下载链接:dex2jar-2.0.zip 和 jd-gui-windows-1.4.0.zip dex2jar这个工具用于将...
  • 记录一次Android反编译过程(修改代码后重新打包)
  • 我推荐大家使用的Android反编译的软件是Android Killer。(这启动界面Cool爆了) 其实这个软件就是对以上博客提到的操作进行一系列的封装。打开这个软件你就可以发现这些熟悉的反编译工具。 接着,打开待反...
  • Android的apk文件反编译后,甚多的资源和java文件无法对应,java文件中引用的资源id变成十进制数字。本文将反编译apk的java文件和资源文件重新关联引用对应,使得java文件能准确无误地重新引用资源文件。 (1)将...
  • 今天百度搜索“Android反编译”搜索出来的结果大多数都是比较传统的教程。刚接触反编译的时候,我也是从这些教程慢慢学起的。在后来的学习过程中,我接触到比较方便操作的Android反编译。在这,我将使用的过程写下来...
1 2 3 4 5 ... 20
收藏数 26,641
精华内容 10,656