反编译基础知识

article/2025/9/11 20:53:42

!!! 严正声明

本文相关反编译技术仅限于技术研究使用,不能用于非法目的,否则后果自负.

1. apktool 逆向APK文件的工具

官方网站

apktool主要用于逆向apk文件,可以将资源解码,并在修改之后可以重新构建它们.它还可以用来重新构建apk.

1.1 功能

  • 将资源解码成近乎原始的形式(包括resources.arsc, classes.dex, 9.png. 和 XMLs)
  • 将解码的资源重新打包成apk/jar
  • 组织和处理依赖于框架资源的APK
  • Smali调试
  • 执行自动化任务

安装教程

1.2 使用

  • 逆向apk文件: apktool d xx.apk,逆向之后只能看到代码的smali格式文件,需要学习smali语法才能看懂.
  • 重新打包: apktool b xx,打包出来的是没有签名的apk,需要签名才能安装

1.3 smali 语法

smali是Dalvik虚拟机指令语言. 当使用apktool反编译apk文件之后,会生成一个smali文件夹,里面是虚拟机需要执行的smali代码.smali语言的一些基本语法还是不复杂,可以简单了解下.万一需要看一下别人实现的炫酷的UI效果呢…顺手偷一段别人的代码,哈哈…不对,读书人的事情怎么能算偷呢?

下面是用apktool反编译之后的smali目录:

smali

为了学习它的语法结构,先随便写一个Activity,代码如下:

public class SmaliActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_smail);initView();}private void initView() {int num = 2 + 3;String name = "zhangsan";Log.w("xfhy666", "initView: num = " + num + "  name = " + name);}@Overrideprotected void onDestroy() {super.onDestroy();}
}

来看下它的smali代码如下:

# 这里简单介绍了类的名称,父类是谁
.class public Lcom/xfhy/allinone/smali/SmaliActivity;
.super Landroidx/appcompat/app/AppCompatActivity;
.source "SmaliActivity.java"# direct methods 从这里开始的都是在当前类定义的方法
# .method 表示这是一个方法
# 这里定义的是当前类的不带参数缺省的构造方法,末尾的V表示方法返回类型是void
.method public constructor <init>()V# .locals 表示当前方法需要申请多少个寄存器.locals 0.line 16invoke-direct {p0}, Landroidx/appcompat/app/AppCompatActivity;-><init>()Vreturn-void
.end method.method private initView()V.locals 4.line 27const/4 v0, 0x5.line 28.local v0, "num":Iconst-string v1, "lisi".line 29.local v1, "name":Ljava/lang/String;new-instance v2, Ljava/lang/StringBuilder;invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()Vconst-string v3, "initView: num = "invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;const-string v3, "  name = "invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;invoke-virtual {v2, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;move-result-object v2const-string v3, "xfhy666"invoke-static {v3, v2}, Landroid/util/Log;->w(Ljava/lang/String;Ljava/lang/String;)I.line 30return-void
.end method# virtual methods  从这里开始的都是覆写父类的方法
.method protected onCreate(Landroid/os/Bundle;)V.locals 1.param p1, "savedInstanceState"    # Landroid/os/Bundle;.line 20invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V.line 21const v0, 0x7f0b001finvoke-virtual {p0, v0}, Lcom/xfhy/allinone/smali/SmaliActivity;->setContentView(I)V.line 23invoke-direct {p0}, Lcom/xfhy/allinone/smali/SmaliActivity;->initView()V.line 24return-void
.end method.method protected onDestroy()V.locals 0.line 35invoke-super {p0}, Landroidx/appcompat/app/AppCompatActivity;->onDestroy()V.line 36return-void
.end method

可以看到,其实大部分smali语法我们是能够看懂的,外加一些猜测的话,能看懂60%左右.上面的这份smali代码就比Java代码多了一个缺省的构造方法.然后每个方法的开始是以.method开始的,以.end method结束.

smali语法简单过一下:

官方文档

Davlik字节码中,寄存器是32位,一般的类型用一个寄存器就够存了.只有64位类型的需要2个寄存器来存储,Long和Double就是64位类型的.

原始数据类型

类型表示原始类型
vvoid
Zboolean
Bbyte
Sshort
Cchar
Iint
Jlong (64位)
Ffloat
Ddouble (64位)

对象类型

类型表示Java中的类型
Ljava/lang/String;String
Landroid/os/Bundle;Bundle
  • 对象类型的前面会加一个L
  • 末尾会加一个;
  • 包名全路径,中间以/分隔

数组

类型表示Java中的类型
[Iint[]
[[Iint[][]
[Ljava/lang/String;String[]

方法定义

类型表示Java中的表示
public getDouble()Dpublic double getDouble()
public getNum(ILjava/lang/String;Z)Ljava/lang/String;public String getNum(int a,String b,boolean c)

eg:

.method public getDouble()D.locals 2.line 45const-wide/16 v0, 0x0return-wide v0
.end method

字段定义

类型表示Java中的表示
.field private num:Iprivate int num
.field public text:Ljava/lang/String;public String text
.field private tvName:Landroid/widget/TextView;private TextView tvName

可以看到在字段定义的前面会加一个关键字.field,然后修饰符+名称+:+类型.

指定方法寄存器个数

一个方法中需要多少个寄存器是需要指定好的.有2种方式

  • .registers 指定方法寄存器总数
  • .locals 表名方法中非参寄存器的总数,一般在方法的第一行

eg:

.method public getNum(ILjava/lang/String;Z)Ljava/lang/String;.registers 6.param p1, "a"    # I.param p2, "b"    # Ljava/lang/String;.param p3, "c"    # Z.prologue.line 40const/4 v0, 0x2.line 41.local v0, "num":Iconst-string v1, ""return-object v1
.end method.method public getNum(ILjava/lang/String;Z)Ljava/lang/String;.locals 2.param p1, "a"    # I.param p2, "b"    # Ljava/lang/String;.param p3, "c"    # Z.line 40const/4 v0, 0x2.line 41.local v0, "num":Iconst-string v1, ""return-object v1
.end method

方法传参

方法的形参也会被存储于寄存器中,形参一般被放置于该方法的最后N个寄存器中(eg:形参是2个,那么该方法的最后2个寄存器就是拿来存储形参的). 值得注意的是,非静态方法隐含有一个this参数.

寄存器命名方式

命名方式有2种,v命名法(v0,v1…)和p命名法(p0,p1…)

来看一段smali代码加深一下印象

.method public getNum(ILjava/lang/String;Z)Ljava/lang/String;.locals 2.param p1, "a"    # I.param p2, "b"    # Ljava/lang/String;.param p3, "c"    # Z.line 40const/4 v0, 0x2.line 41.local v0, "num":Iconst-string v1, ""return-object v1
.end method
  • 首先通过.locals 2表明该方法内有2个v寄存器.
  • 然后定义了p1,p2,p3这3个寄存器,其实还有一个p0寄存器,p0表示this(即本身的引用,this指针).
  • 这个方法里面既有v命名的,也有p命名的
  • 只有v命名的寄存器需要在.locals处声明个数,而p命名的不需要

标记

标记含义
# static fields定义静态变量
# instance fields定义实例变量
# direct methods定义静态方法
# virtual methods定义非静态方法

控制条件

语句含义
if-eq vA, vB, :cond_**如果vA等于vB则跳转到:cond_**
if-nevA, vB, :cond_**如果vA不等于vB则跳转到:cond_**
if-ltvA, vB, :cond_**如果vA小于vB则跳转到:cond_**
if-gevA, vB, :cond_**如果vA大于等于vB则跳转到:cond_**
if-gtvA, vB, :cond_**如果vA大于vB则跳转到:cond_**
if-levA, vB, :cond_**如果vA小于等于vB则跳转到:cond_**
if-eqz vA, :cond_**如果vA等于0则跳转到:cond_**
if-nezvA, :cond_**如果vA不等于0则跳转到:cond_**
if-ltzvA, :cond_**如果vA小于0则跳转到:cond_**
if-gezvA, :cond_**如果vA大于等于0则跳转到:cond_**
if-gtzvA, :cond_**如果vA大于0则跳转到:cond_**
if-lezvA, :cond_**如果vA小于等于0则跳转到:cond_**

这个很难记忆,建议需要用到的时候再回来查.

这里的z表示zero,可以是0,也可以是null,或者是false,具体看上下文环境.

1.4 Smali插桩(代码注入)

通过smali插桩,我们可以修改原有代码的走向,比如修改某个逻辑或者是修改某个app的展示文本,汉化等等.

简单举个例子让大家感受一下:

showText函数中有一个形参isVip,如果是true则跳过广告,如果是false,则观看广告.我现在想把这个isVip永远的改成true,那么我就永远跳过广告,哈哈…仅测试用…

private void showText(boolean isVip) {if (isVip) {Toast.makeText(this, "Skip ad", Toast.LENGTH_SHORT).show();} else {Toast.makeText(this, "Watch ad", Toast.LENGTH_SHORT).show();}
}

上面的java代码对应的smali代码如下:

.method private showText(Z)V.locals 2.param p1, "isVip"    # Z.line 38const/4 v0, 0x0if-eqz p1, :cond_0  # 如果p1是true,那么跳过cond_0.line 39const-string v1, "Skip ad"invoke-static {p0, v1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;move-result-object v0invoke-virtual {v0}, Landroid/widget/Toast;->show()Vgoto :goto_0.line 41:cond_0const-string v1, "Watch ad"invoke-static {p0, v1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;move-result-object v0invoke-virtual {v0}, Landroid/widget/Toast;->show()V.line 43:goto_0return-void
.end method

上面的代码比较简单,我直接在if-eqz判断的前面将isVip改成true不就ok了么.

.method private showText(Z)V.locals 2.param p1, "isVip"    # Zconst/4 p1, 0x1.line 38const/4 v0, 0x0if-eqz p1, :cond_0  ......
.end method

smali代码改好之后保存,然后用apktool工具,打包成apk : apktool b apkFileName.

打包完成之后,是不能立即在Android手机上进行安装的,还需要签名.得去下载一个autosign,给这个apk签名,命令是java -jar signapk.jar testkey.x509.pem testkey.pk8 update.apk update_signed.apk. 打包好之后,运行到手机上,完美,toast输出的是Skip ad.插桩成功.

可以下载一个Android逆向助手,里面有autosign工具包. 下载地址如下:

链接:https://pan.baidu.com/s/1NW9PAyuar1dWeUfQBQEftg 密码:8nb7

2.dex2jar

一个将dex转换成jar的工具,下载下来之后是一个压缩包,里面有很多工具.

dex2jar

这些工具一看名字就知道是干啥的.

使用方式也比较简单,随便举个例子,命令行进入解压之后的文件夹,将待转成jar的dex(假设为classes.dex,拷贝到当前文件夹)准备好.让这些文件全部有执行权限,chmod +x *(Windows不需要).然后执行./d2j-dex2jar.sh classes.dex即可将dex转成jar(转出来的jar包名字是classes-dex2jar.jar),然后用jd-gui工具即可查看该jar中的class对应的java源码(和原始的源码不太一样哈).

下载地址: https://sourceforge.net/projects/dex2jar/

3. jd-gui

jd-gui是一款反编译软件,可以将查看jar中的class对应的java代码.使用方式: 直接将jar文件拖入jd-gui即可,查看里面的class对应的java代码.

jd-gui

jd-gui github : https://github.com/java-decompiler/jd-gui

4. jadx

jadx github : https://github.com/skylot/jadx

需要下载jadx的直接到GitHub页面下载最新的Relase包.

jadx就更厉害了,直接将apk文件将其拖入.可得到如下信息:

  • 签名的详细信息(类型,版本,主题,签名算法,MD5,SHA-1,SHA-256等等)
  • 所有资源文件(比如layout布局文件都是反编译了的,可以直接查看)
  • 所有class对应的java代码(未加壳的才行),java代码对应的smali代码也能看.
  • so文件

jadx界面

据说,jadx是史上最好用的反编译软件,从使用上来看,确实是这样,操作简单.除了上面提到的功能点外,还有些你可能更喜欢的,比如:

  • 导出Gradle工程
  • 反混淆
  • 代码跳转(Ctrl+鼠标左键)
  • 全局搜索文本

有了jadx我感觉其实可以不用上面的那些工具了,这个已经有上面的那些工具的功能了.

5. 脱壳

说到脱壳,这里简单介绍几个工具

  • Xposed 框架
  • VirtualXposed
  • FDex2

如果手机已经root,则选择Xposed框架+FDex2.
如果手机没有root,则选择VirtualXposed+FDex2.

5.1 Xposed 框架

首先我们得知道什么是Xposed框架?

维基百科: Xposed框架(Xposed framework)是一套开放源代码的、在Android高权限模式下运行的框架服务,可以在不修改APK文件的情况下修改程序的运行(修改系统),基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。这套框架需要设备解锁了Bootloader方可安装使用(root为解锁Bootloader的充分不必要条件,而xposed安装仅需通过TWRP等第三方Recovery卡刷安装包而不需要设备拥有完整的root权限)。

Xposed框架非常非常牛皮,可以安装各种插件(xposed插件,这里有很多 https://www.xda.im/),比如自动抢红包、防撤回、步数修改等等各种骚操作.就是Xpose框架的安装非常麻烦.安装教程这里就不说了,每个手机可能不太一样.我记得我的手机当时解锁BootLoader,刷机啥的,麻烦.

传统的Xposed框架只支持到Android N,后续的Android版本可以使用EdXposed替代.

5.2 VirtualXposed

官网: https://vxposed.com/

VirtualXposed也非常牛逼,它看起来提供了一个虚拟的安卓环境,但它其实是一个app.它提供Xposed框架环境,而不需要将手机root,不需要解锁BootLoader,也不需要刷机.Xposed模块提供了超多应用、游戏的辅助,但是苦于Xposed框架安装的麻烦很多用户只能放弃,VirtualXposed最新版让用户可以非常方便地使用各种Xposed模块.

5.3 FDex2

FDex2是Xposed的一个插件,用来从运行中的app中导出dex文件的工具.

使用:首先安装FDex2这个apk,然后在Xposed框架中勾选这个插件,然后手机重启.进入FDex2,点击需要脱壳的应用,然后FDex2会展示该app脱壳之后的dex输出目录.然后去运行那个需要脱壳的app,就可以获得该app对应的dex.然后导出dex到电脑上,用jadx查看反编译的代码.

当然,FDex2不一定能成功.

6. 开发者助手

这个工具特别厉害,但是大部分功能是需要root权限才能使用的.主要功能如下:

  • 实时查看任何应用数据库和SP
  • 网络请求信息
  • log输出
  • 当前Activity或者Fragment
  • 界面资源分析(可以查看那个控件是什么做的)

apk酷安下载地址: https://www.coolapk.com/apk/com.toshiba_dealin.developerhelper

从应用详情里面看到,开发者助手还有电脑版本,功能也不少

  • 支持了大部分手机版开发者助手的功能
  • 支持截图到电脑
  • 支持全局debug开启 (动态调试用)
  • 支持进程优先级查看
  • 更稳定的当前包名/activity名/fragment名获取

开发者助手电脑版下载链接:https://pan.baidu.com/s/1MFagBWVbR1xNDMakWUlv5g
提取码:l4hv

7. 其他

大概的工具就是上面这些了,勉强够用了.还有些其他的工具我也一并放入下面的下载链接里面了.

链接:https://pan.baidu.com/s/1kuoJ83vob13SM971mIwrmw 密码:lc6p

这里有一个库,里面关于安卓应用的安全讲解的很全面,喜欢的可以去看看. https://github.com/crifan/android_app_security_crack

参考资料

  • ApkTool官网
  • Smali–Dalvik虚拟机指令语言–>【android_smali语法学习一】
  • 关于smali插桩
  • 安卓从开发到逆向(四),smali插桩
  • android逆向分析之smali语法
  • Xposed框架-维基百科

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

相关文章

Android安全攻防战,反编译与混淆技术完全解析(上)

转载请注明出处&#xff1a;http://blog.csdn.net/guolin_blog/article/details/49738023 之前一直有犹豫过要不要写这篇文章&#xff0c;毕竟去反编译人家的程序并不是什么值得骄傲的事情。不过单纯从技术角度上来讲&#xff0c;掌握反编译功能确实是一项非常有用的技能&…

通知(Notifications)

通知(Notifications) 如需转载&#xff0c;请注明地址http://blog.csdn.net/carrey1989/article/details/9027585 我们可以通过notification来在应用UI之外的地方来向用户展示信息。当你告诉系统来发布一个notification的时候&#xff0c;系统会首先在notification area里展示一…

解读Notification

综述 status bar notification添加一个图标(和一条可选的ticker-text消息)到系统的status bar(状态条)&#xff0c;并且显示一个notification message(通知消息)在系统的notifications window(消息窗口)中。当用户选择了消息窗口中的一条消息&#xff0c;Android系统就发出一个…

Android-自定义Notification

Android-自定义Notification 2014年4月26日 消息栏的消息&#xff0c;想必各位Android发烧友很清楚知道是什么&#xff0c;比如我们下载了一个应用&#xff0c;它可能会定时推送些消息到我们的手机中&#xff0c;比如微信消息送达的时候&#xff0c;可能会在通知栏显示。本博文…

notification新旧用法 notification builder

api 11 版本之前&#xff1a; //显示通知信息protected void showNotification() {NotificationManager notificationManager (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // Notification notification new Notification(this,R.drawable.ic_launche…

Android Notification 详解

下图是我对 Notification 做的思维导图&#xff0c;也是本文的主要逻辑。&#xfffc; 本文主要讲述 Notification 的基本操作部分&#xff0c;进阶部分的内容还在学习ing~ Notification 概述 Notification&#xff0c;是一种具有全局效果的通知&#xff0c;可以在系统的通知栏…

Android Notification

日记月累第四天。发现做事情坚持真的很重要&#xff0c;其实我今天都有点凌乱了&#xff0c;不想记录了&#xff0c;在坚持一下吧&#xff0c;毕竟才第四天。今天对昨天同事所说的Notification进行了一下温故今天主要是拿来主意&#xff0c;明天代码实践。今天公司又有同事分享…

HTML5 桌面通知:Notification API

Notification API 是 HTML5 新增的桌面通知 API&#xff0c;用于向用户显示通知信息。该通知是脱离浏览器的&#xff0c;即使用户没有停留在当前标签页&#xff0c;甚至最小化了浏览器&#xff0c;该通知信息也一样会置顶显示出来。 用户权限 想要向用户显示通知消息&#xf…

Android自定义Notification

Notification是一种让你的应用程序在不使用Activity的情况下警示用户&#xff0c;Notification是看不见的程序组件警示用户有需要注意的事件发生的最好途径。 作为UI部分&#xff0c;Notification对移动设备来说是最适合不过的了。用户可能随时都带着手机在身边。一般来说&…

Notification-通知

Notification-通知 通知是一种消息&#xff0c;这种消息呈现在应用UI之外&#xff0c;通过通知可以对用户进行提醒、可以和其他用户收发信息等。通过点击通知&#xff0c;可以唤起app页面或者直接在通知上执行一些操作。下面介绍通知的一些常用用法。 展示一条普通通知 先来…

全面解析Notification

Notification在Android中使用的频率可以说是非常高的,本篇博客,我将围绕着Notification的各方面进行解析,使大家对Notification有更好的认识。 Notification的使用步骤 1.获取NotificationManager NotificationManager mNotificationManager = (NotificationManager) get…

Android Notification使用

Android 通知栏适配 前言正文一、Android中通知的变化1. Android 4.1&#xff0c;API 162. Android 4.4&#xff0c;API 19 和 203. Android 5.0&#xff0c;API 214. Android 7.0&#xff0c;API 245. Android 8.0&#xff0c;API 266. Android 12.0&#xff0c;API 31 二、创…

Android之Notification的多种用法

我们在用手机的时候&#xff0c;如果来了短信&#xff0c;而我们没有点击查看的话&#xff0c;是不是在手机的最上边的状态栏里有一个短信的小图标提示啊&#xff1f;你是不是也想实现这种功能呢&#xff1f;今天的Notification就是解决这个问题的。 我们也知道Android系统也是…

Android--通知之Notification

前言 之前一篇博客讲了Android下使用Toast的方式提示消息。这篇博客讲解一下在Android中使用Notification提示消息给用户&#xff0c;Notification是一种具有全局效果的通知&#xff0c;程序一般通过NotificationManager服务来发送Notification。在本篇博客中&#xff0c;将介绍…

Android通知Notification使用全解析,看这篇就够了

1、效果 2、简介 通知是 Android 在您的应用 UI 之外显示的消息&#xff0c;用于向用户提供提醒、来自其他人的通信或来自您的应用的其他及时信息。用户可以点击通知打开您的应用或直接从通知中执行操作。 2.1、展示 通知以不同的位置和格式向用户显示&#xff0c;例如状态栏…

php cacti,cacti搭建遇到的那些事

最近闲的无聊&#xff0c;亲手操刀了一把整个生产环境cacti的搭建&#xff0c;时间消耗了3-4天&#xff0c;这里主要感谢网友老李、不想扮演逃兵、jiam的指导和帮助。下面就说说我搭建这个遇到的一些棘手的问题吧&#xff01; 搭建完成的界面如下图&#xff1a; 系统环境&#…

cacti mysql_cacti监控mysql

1.MySQL stats模板 功能&#xff1a;用来监控MySQL状态&#xff0c;其中包括索引使用情况、查询、排序、锁定情况等。 1).将mysql_stats.php 和 dumpMemcachedStats.php脚本放到cacti脚本目录下(/usr/local/apache/htdocs/cacti/.s/)&#xff0c;导入模板时注意选择cacti_host_…

cacti mysql 详解,cacti详解和基本配置

cacti简介&#xff1a; cacti是用php语言实现的一个软件&#xff0c;它的主要功能是用snmp服务获取数据&#xff0c;然后用rrdtool存储和更新数据&#xff0c;当用户需要查看数据的时候就用rrdtool生成图表呈现给用户。snmp抓到的数据不是存储在mysql中&#xff0c;而是存在rrd…

cacti安装

1、搭建LNMP环境 http://blog.csdn.net/yang_xu_1987/article/details/77292340 #下面是按照源码搭建LNMP的方式&#xff0c;主要是路径不一样 2、安装rrd-tool、snmp相关包 yum install -y rrdtool net-snmp net-snmp-utils 3、安装cacti 下载cacti&#xff1a;http://down…

java cacti_开源的企业级监控系统 Cacti 简介

Cacti是一款网络流量监测图形分析工具&#xff0c;把LAMP的功能都结合起来&#xff0c;用于网络流量监控&#xff0c;操作起来非常方便&#xff01;让我们认识下Cacti简介及工作流程。 一、Cacti简介 1. cacti是用php语言实现的一个软件&#xff0c;它的主要功能是用snmp服务获…