Android进阶知识树——应用安全基础篇

1、Smile语法入门

Smali是Java虚拟机中的一种.dex格式文件汇编器,它采用一种宽松式的Jasmin/dedexer的语法,表达了.dex格式所有功能和信息,如果了解Smali语言基础,在我们反编译程序时就可以看出程序的大致代码,这对于分析竞品可能有所帮助,下面一起学习下Smali基础知识

  • 原始类型映射关系:这里的映射关系和JNI中一致
  1. v :void ()
  2. Z:boolean
  3. B:byte
  4. S:short
  5. C:char
  6. I:int
  7. J:long
  8. F:float
  9. D:double
  • 类的表示:smile中采用全路径的方式进行展示,如:Ljava/lang/String;
  1. L:表明此处表示类
  2. java/lang/String:类的全路径名称
  3. ;:类声明结束符号
  • 数组表示:数组采用[+元素类型的方式,如[I 、[Ljava/lang/String
  1. [:表示声明数组
  2. I:表示数组的类型
  3. [[I:表示二维数组
  • 对象的表示:对象的表示分为两部分,一部分是持有此对象类型的表示,第二部分是变量展示即变量名+变量类型,如: Ljava/lang/String; ——> FieldName : Ljava/lang/String;
  1. Ljava/lang/String;:类的全路径
  2. FieldName:对象名称
  3. Ljava/lang/String;:对象类型
  • 方法表示:使用方法的所在类、方法名、方法签名表示,如 Ljava/lang/String; ——> method(III)V
  1. Ljava/lang/String;:类的全路径
  2. method:方法名称
  3. III:方法的传参类型,传入3个Int类型数据
  4. V :方法返回类型
  • 方法参数:.param p1, “savedInstanceState” # Landroid/os/Bundle;
  1. .param:表示参数
  2. p1:寄存器
  3. “savedInstanceState":参数名称
  4. # Landroid/os/Bundle;:参数类型
  • 寄存器:表示此方法在执行中需要的存储空间个位置
  1. 方法中声明使用寄存器个数
    .registers 指令指定了方法中寄存器的总数
    .locals 指令表明了方法中非参寄存器的总数,出现在方法中的第一行
  2. 方法的参数被放在最后几个寄存器中
1.1、Smile实战示例
public class MainActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      TextView textView = findViewById(R.id.textView);
   }
   @Subscribe
   public void action(TypeEvent event) {
   }
   @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
   public void actionTwo(TypeEvent event) {
   }
}
  1. 查看生成的smali代码
.class public Lcom/alex/kotlin/jniapplication/MainActivity;  //表明类文件的路径和名称
.super Landroid/support/v7/app/AppCompatActivity;  //继承的父类
.source "MainActivity.java" //当前类的名称
# direct methods //声明方法开始
.method public constructor <init>()V  //构造函数
    .locals 0 
    .line 10  //代码行数
    invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V
    return-void
.end method  //声明方法结束
# virtual methods
.method public action(Lcom/alex/kotlin/jniapplication/TypeEvent;)V //action()标明了方法名、参数、返回类型
    .locals 0
    .param p1, "event"    # Lcom/alex/kotlin/jniapplication/TypeEvent; //参数 
    .annotation runtime Lorg/greenrobot/eventbus/Subscribe;  //方法注解
    .end annotation
    .line 22
    return-void
.end method
.method public actionTwo(Lcom/alex/kotlin/jniapplication/TypeEvent;)V //actionTwo()
    .locals 0
    .param p1, "event"    # Lcom/alex/kotlin/jniapplication/TypeEvent;
    .annotation runtime Lorg/greenrobot/eventbus/Subscribe;
        sticky = true
        threadMode = .enum Lorg/greenrobot/eventbus/ThreadMode;->MAIN:Lorg/greenrobot/eventbus/ThreadMode;
    .end annotation
    .line 27
    return-void
.end method
.method protected onCreate(Landroid/os/Bundle;)V  //create()
    .locals 1  //声明寄存器个数
    .param p1, "savedInstanceState"    # Landroid/os/Bundle; //声明参数
    .line 14
    invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V //代码语句
    .line 15
    const v0, 0x7f09001c
    invoke-virtual {p0, v0}, Lcom/alex/kotlin/jniapplication/MainActivity;->setContentView(I)V //代码语句
    .line 16
    const v0, 0x7f070087
    invoke-virtual {p0, v0}, Lcom/alex/kotlin/jniapplication/MainActivity;->findViewById(I)Landroid/view/View;//代码语句
    move-result-object v0
    .line 17
    .local v0, "textView":Landroid/widget/TextView;
    return-void
.end method

从上面示例编译后的smile语言中,根据smile的语句特性可以清晰阅读到整个代码的内容,相比之下还是很清晰的,具体细节见代码注释;

2、ApkTool反编译

  • 反编译APK

在开发中使用发编译的场景不多,但如果想查看某些产品的实现和代码,就要先将产品反编译出来,反编译的过程也很简单,下面一起使用ApkTool反编译一个apk,直接命令行工具反编译现有的apk

apktool d app-debug.apk   //编译解析出资源文件,但会将Class文件解析成smali文件
apktool d -s app.apk  //编译解析出资源文件,但会将Class文件解析成dex文件
  1. 编译结果——smile语言
    Android进阶知识树——应用安全基础篇_第1张图片
  2. 反编译dex语言
    Android进阶知识树——应用安全基础篇_第2张图片
  • 将dex编译为Jar包
  1. 将上面编译的classes.dex文件复制到dexjar文件夹下,执行命令语句
sh d2j-dex2jar.sh classes.dex
sudo chmod +x d2j_invoke.sh //处理文件权限
  1. 文件夹下会自动生成classes-dex2jar.jar
  • JD-GUI查看生成的代码
  1. 打开GUI将第二部生成的classes-dex2jar.jar包拖入即可查看生成对应的Java代码
    Android进阶知识树——应用安全基础篇_第3张图片

3、Jadx反编译

  • 配置导入工具
git clone https://github.com/skylot/jadx.git  //先下载jadx文件
cd jadx
./gradlew dist //编译
  • jadx使用
  1. 双击bin/jadx-gui运行程序,此时会启动操作界面和terminal(显示操作日志)
  2. 将要反编译的APK拖进窗口即可自动编译
  3. 反编译的代码可以在Java 和 Smali之间切换
    Android进阶知识树——应用安全基础篇_第4张图片
  • 代码搜索功能
  1. Navigation -> Text Search 或者 Navigation -> Class Search启动代码搜索功能
  2. jadx支持 Class、Method、Field、Code四个维度的搜索
  3. 在代码中可以直接右键 -> Find Usage 查找代码
    Android进阶知识树——应用安全基础篇_第5张图片
  • deobfuscation
  1. 对于代码混淆的APK,点击 “ 工具 -> 反混淆 “会自动为每个类创建别名方便查看和查找
    Android进阶知识树——应用安全基础篇_第6张图片Android进阶知识树——应用安全基础篇_第7张图片
  • 导出Gradle工程
  1. 点击“File -> 导出Gradle工程 “
  • 反编译出现卡顿
  1. 针对出现的卡顿修改并发线程:File -> 首选项 ->. 并行线程数 (默认为4)
    Android进阶知识树——应用安全基础篇_第8张图片

4、二次打包

关于二次打包主要是修改编译后smaile代码,然后重新打包签名即可,这里就是要看懂smile代码,另外保证修改后的smile代码不冲突即可,详细参见Android反编译和二次打包实战

你可能感兴趣的:(APK,反编译,二次打包,Android高级进阶之旅)