吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7769|回复: 17
收起左侧

[Android 原创] Android反编译(MAC下)+为apk添加button+二次打包 (菜鸟级)

  [复制链接]
蓝渊智海 发表于 2018-4-15 18:41
本帖最后由 蓝渊智海 于 2018-4-16 20:45 编辑


反编译一般apk并添加控件(新手)

最近了解了一下逆向,想实现如题的效果,但是从网上搜了半天,没有找到详细的教程,最后只好参考一些相关博客来实现自己的目标,功夫不负有心人,有了一点的收获。本人接触Android时间不长,如有一些东西讲的不对,望各位大佬指点。同时,非喜勿喷O(∩_∩)O
  在这里不得不吐槽一下网上许多的博客都一样,有些博客又大同小异,查找起来真心累。
  • 基本知识和准备:
    1.懂得一点Android的基础知识。
    2.Android Studio的简单操作。
    3.使用的工具是:
    apktool, https://ibotpeaches.github.io/Apktool/install/
    dex2jar,  https://sourceforge.net/projects/dex2jar/files/
    jd-gui   ,http://jd.benow.ca/
    (⊙o⊙)…有点奇怪,怎么文字链接保存后就没有了。。。。
所用的工具上面都有下载链接。本人是在Mac下进行的开发,为了大家开发方便我也上传了
https://download.csdn.net/download/qq_36462112/10350760

  • 工具的环境搭建
    apktool的配置
    (1).将wrapper script的内容拷贝下来,并将文件命名为apktool。(或者将光标移到wrapper script上右键—链接另存为—文件名apktool)
    (2).将apktool2.3.1.jar下载下来并命名为apktool.jar
    (3).将apktool 和apktool.jar 移到/usr/local/bin (要打开隐藏文件,否则看不到user)
    apktool的位置




(4).为apktool添加权限chmod +x apktool
在lib的文件夹(也就是apktool 的父级文件夹,后面就不在细说了)下右键—新建位于文件夹位置的终端窗口(没有就去服务设置里面进行设置),输入命令chmod +x apktool
(也就是通过终端到该文件的父级目录,然后执行命令。由于mac支持在任何文件夹下都可以打开终端,而Ubuntu14.04不行,在这里说明下。没有打开终端的选项,就直接通过cd 命令到达该目录就行了。)



  • 勾选新建位于文件夹位置的终端窗口
    dex2jar-2.0配置:
    (1).下载并解压dex2jar-2.0
    (2). 为dex2jar-2.0添加权限chmod -R 777 dex2jar-2.0
    同样也是在dex2jar-2.0文件夹的父级文件夹下 右键—新建位于文件夹位置的终端窗口,输入命令chmod -R 777 dex2jar-2.0
jd-gui 没有什么配置,直接点击图标后打开使用即可。反编译
反编译市场上的一些apk有点不好,所以我这里准备了一个appText.apk 来进行演示。
1.将apk文件放入一个文件夹中,如我这里的reverse。打开终端



2.在终端下输入命令 apktool d appText.apk
执行成功后出现了一个appText的文件夹 第一次如果有wrong:/Users/lj/Library/apktool/framework/
可以在资源,也就是Library中新建一个apktool文件夹,再在里面新建framework文件夹就行了



(3 )将appText.app的后缀改为.zip 使用解压工具解压(系统自带的有可能解压不了), 将解压后的class.dex拷贝到dex2jar-2.0文件夹下
(4)在dex2jar-2.0文件夹下打开终端,执行命令sh d2j-dex2jar.sh classes.dex得到classes-dex2jar.jar



以上就是反编译的过程,查看源代码的话,就直接使用jd-gui 打开classes-dex2jar.jar就可以了注入代码,添加button
这里只是主要讲一下怎么实现在主activity中加入一个弹框,其他的一些知识就顺便提下,如有兴趣可以自己百度。我后期会出相关笔记博客。
首先在反编译出来的appText文件夹中找到activity_main.xml 在appText —res—layout—activity_main.xml 打开后在布局文件中加入如下代码:
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
<!--   添加的代码 -->
    <Button
        android:id="@+id/text_btn"
        android:text="反编译"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>



之后再到values文件夹中找到public.xml 打开后将 <public type="id" name="text_btn" id="0x7f07007d" />加入。 ps: id值根据自己情况填写
public.xml 包含了所有的资源文件,所以在这里加入我们自己添加的id。 name是你上面自己定义的id名字,id的值根据前一个加1,如我的是0x7f07007c 加1 0x7f07007d 就是 注意资源文件是16进制递增的。一般在最后一个的基础上加1,就行了。不过有些可能不是顺序的,那就在同一个type中,即id 找到一个最大的加1就行。



同样是在values文件夹中找到ids.xml 在最后面加入<item type="id" name="text_btn">false</item>


在appText/smali/com/blue/demo 中找到 R$id.smali 打开后将下面的代码加入进去
.field public static final text_btn:I = 0x7f07007d
text_btn 之前的button的id 0x7f07007d 前面得到数值。





上面将资源部分的添加完了,接下来是代码部分根据appText中的AndroidMainfest.xml 中的 package=”com.blue.demo” 包名使用Android studio新建一个一样的项目
注意一下,我添加的button点击后浏览百度网站,所以要加网络权限。你们在添加时,如果没有就在AndroidMainfest.xml 中加上。



我这里是测试所以xml使用的是一样的,下面是Java代码
[Java] 纯文本查看 复制代码
package com.blue.demo;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setShow();
    }

    private void setShow() {

        Button button = findViewById(R.id.text_btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final Context context = MainActivity.this;
                TextView title = new TextView(context);
                title.setText("提示");
                title.setPadding(10, 10, 10, 10);
                title.setGravity(Gravity.CENTER);
                title.setTextSize(25);
                title.setTextColor(Color.BLACK);
                TextView m = new TextView(context);
                m.setText("如何解决你的问题-->");
                m.setPadding(5, 5, 5, 5);
                m.setGravity(Gravity.CENTER);
                m.setTextColor(Color.BLACK);
                m.setTextSize(20);
                AlertDialog.Builder dialog = new AlertDialog.Builder(context);
                dialog.setCustomTitle(title);
                dialog.setView(m);
                dialog.setPositiveButton("是",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Uri uri = Uri.parse("http://www.baidu.com");
                                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                                startActivity(intent);
                            }
                        });
                dialog.setNegativeButton("否",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                                Uri uri = Uri.parse("https://upload-images.jianshu.io/upload_images/10343318-0e072b630eab8733.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240");
                                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                                startActivity(intent);
                            }
                        });
                dialog.show();
            }
        });

    }


}


直接Build–BuildAPK(s) 打包一个debug版本的apk,再使用上面的反编译方法得到app-debug文件夹,
将app-debug/smali/com/blue/demo中的MainActivity.smali 中的下面代码复制到 appText/smali/com/blue/demo的MainActivity.smali 中。
[Asm] 纯文本查看 复制代码
.method private setShow()V
    .locals 2

    .line 27
    const v0, 0x7f07007d   #修改为我们之前定义button时,算出来的id   0x7f07007d 

    invoke-virtual {p0, v0}, Lcom/blue/demo/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    #.line 28
    .local v0, "button":Landroid/widget/Button;
    new-instance v1, Lcom/blue/demo/MainActivity$1;

    invoke-direct {v1, p0}, Lcom/blue/demo/MainActivity$1;-><init>(Lcom/blue/demo/MainActivity;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    #.line 70
    return-void
.end method

// .method      .end method  标志的是函数的开始和结束    放在最后就行了。
// 使用#注释掉.line xx  或者直接删除,这个是起标志执行的步骤(对代码的实际运行不怎么影响)。我们是直接强加的,就不要加这个了。 

    #.line 22
    invoke-direct {p0}, Lcom/blue/demo/MainActivity;->setShow()V
//这句话是调用上面的函数,要放在onCreate()方法里面,同时也要在setContentView()方法之后,


//下面我的appText/smali/com/blue/demo的MainActivity.smali  全部代码(修改后)。给你们参看下,不同的项目是不一样的

.class public Lcom/blue/demo/MainActivity;
.super Landroid/support/v7/app/AppCompatActivity;
.source "MainActivity.java"


# direct methods
.method public constructor <init>()V
    .locals 0

    .prologue
    .line 6
    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, 0x7f09001a

    invoke-virtual {p0, v0}, Lcom/blue/demo/MainActivity;->setContentView(I)V


    invoke-direct {p0}, Lcom/blue/demo/MainActivity;->setShow()V

    .line 12
    return-void
.end method

.method private setShow()V
    .locals 2

    const v0, 0x7f07007d   #修改为我们之前定义button时,算出来的id   0x7f07007d 

    invoke-virtual {p0, v0}, Lcom/blue/demo/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    .local v0, "button":Landroid/widget/Button;
    new-instance v1, Lcom/blue/demo/MainActivity$1;

    invoke-direct {v1, p0}, Lcom/blue/demo/MainActivity$1;-><init>(Lcom/blue/demo/MainActivity;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    return-void
.end method


可以看到在setShow()函数中有一个MainActivity$1我的理解是当前类的实例,每一个button或者其他的监听之类的事件都会有一个MainActivity$ --   与之对应。我之前的项目中没有一个监听,所以没有一个MainActivity$1,可以直接使用MainActivity$1 ,如果你反编译的项目有一个或者多个,在它的基础上加1就行了。如:反编译的项目中有MainActivity$1,MainActivity$2,MainActivity$3那么你就把app&#8722;debug中的文件名改为MainActivity$4 ,其他的是两个也要一起改MainActivity4$1.smali   MainActivity4$2.smali
注意:改了文件名后,这三个文件中的MainActivity$1都要改为MainActivity$5
我的没有所以直接是将app-debug/smali/com/blue/demo中的MainActivity$1.smali    MainActivity1$1.smali   MainActivity1$2.smali中   三个文件直接放到了 appText/smali/com/blue/demo中。

以上所有的代码都改完了,下面二次打包。
在reverse文件下打开终端,输入指令apktool b appText -o text2.apk
得到text2.apk 这个apk还没签名无法安装。首先,签名需要keystore文件,可以使用keytool工具生成,一般Java环境都带有keytool命令,可以在命令行测试。
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
回车之后设置密码
各个参数解释如下:
-genkey 产生证书文件
-alias 产生别名
-keystore 指定密钥库的.keystore文件中
-keyalg 指定密钥的算法,这里指定为RSA(非对称密钥算法)
-validity 为证书有效天数,这里我们写的是40000天输入上述命令后,会有如下的提示:输入keystore密码:
再次输入新密码:
您的名字与姓氏是什么?
[Unknown]: test
您的组织单位名称是什么?
[Unknown]: test
您的组织名称是什么?
[Unknown]:
您所在的城市或区域名称是什么?
[Unknown]:
您所在的州或省份名称是什么?
[Unknown]:
该单位的两字母国家代码是什么
[Unknown]:
CN=test, OU=test, O=Unknown, L=Unknown, ST=Unknown, C=Unknown 正确吗?
[否]: y输入demo.keystore的主密码
(如果和 keystore 密码相同,按回车):执行完后会有一个demo.keystore文件,再使用它对apk进行签名
jarsigner也存在于Java JDK的安装包当中,所以安装好了Java环境的话,可以直接在命令行使用。
jarsigner -verbose -keystore demo.keystore text2.apk demo.keystore
回车之后输入密码
-verbose 指定生成详细输出
-keystore 指定数字证书存储路径这样,就完成了对一个apk的签名过程,然后就可以安装使用了。注意如果你的手机上原来就有这个apk,需要卸载掉。因为新apk的签名已经改变了。


写的有点啰嗦,不喜勿喷哈,也欢迎大佬给予指点
以上就是这次的所有内容,觉得可以评分一下吗 这个送给你们

这个图片有点拉伸的感觉,这里是原博客    https://blog.csdn.net/qq_36462112/article/details/79705178

免费评分

参与人数 4吾爱币 +9 热心值 +4 收起 理由
lzy学霸 + 1 + 1 我很赞同!
qtfreet00 + 6 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Jermic + 1 + 1 Android Crack Tool for Mac https://www.52pojie.cn/thread-452617-1-1.ht
挖地球达人 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 蓝渊智海 发表于 2018-4-16 18:45
evill 发表于 2018-4-16 09:09
有没有可以直接打包的工具,实在不想在mac上再装一个android studio了 ?

我直接使用jdk里面的指令打包的。
如果可以装虚拟机的话,吾爱破解上有很多Windows平台下的打包软件。
Jermic 发表于 2018-4-18 11:52
kanxue2018 发表于 2018-4-15 19:06
木棉拖鞋 发表于 2018-4-15 19:43
怎么没有贴进来啊
mds丶剑仙 发表于 2018-4-15 20:16 来自手机
这不违规吗?不能发网址的!
gunxsword 发表于 2018-4-15 21:03
感谢分享,看一看,学习一下!谢谢!
evill 发表于 2018-4-16 09:09
有没有可以直接打包的工具,实在不想在mac上再装一个android studio了 ?
mrzcpo 发表于 2018-4-16 09:48
感谢分享
挖地球达人 发表于 2018-4-16 09:48
学习一下。
xjh88232259 发表于 2018-4-16 11:05
学习一下。
 楼主| 蓝渊智海 发表于 2018-4-16 18:39
mds丶剑仙 发表于 2018-4-15 20:16
这不违规吗?不能发网址的!

我不是很了解规则,马上改。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 22:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表