【移动安全基础篇】——14、创建破解代码库

1. smali  代码插入

用 smali 代码编写程序与用 java 代码编写程序一样,在原理上是可行的,不过前提是对smali 语法足够熟悉。以插入打印 log 代码为例,原理就是通过直接插入有效的 smali 代码,从而输出程序的数据内容。更为复杂一点的则可以直接修改整个程序的执行流程。

2. smali  代码编写

一个静态返回 HelloWorld 的方法:
1) .class public Lf8/helloworld/helloStr; #类声明
    .super Ljava/lang/Object; #父类声明

    .method public static retHello()Ljava/lang/String; #函数声明
    .locals 1 #寄存器数量
     const-string v0, “Hello World from StaticMethod” #新建字符串
     return-object v0 #返回 Object 类型
    .end method #方法结束
2) 返回静态 field 的方法
    .field public static final hStr:Ljava/lang/String; = “Hello World from static field”
    #field 声明与初始化
   .method public static retHello2()Ljava/lang/String;
   .local 1
    sget-object v0, Lf8/helloworld/helloStr;->hStr:Ljava/lang/String #获取 filed
    return-object v0
   .end method
3) 普通的函数
.method public constructor <init>()V
              .locals 0
               invoke-direct {p0}, Ljava/lang/Object;-><init>()V
               return-void
.end method

.method public retHello3()Ljava/lang/String;
.locals 1
const-string v0, “Hello World from Method”
return-object v0
.end method

4) 普通的 field 与函数

.field public hStr2:Ljava/lang/String;
.method public constructor <init>()V
.locals 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
const-string v0, “Hello field” #初始化非静态 field
input-object v0, p0, Lf8/helloworld/helloStr;->hStr2:Ljava/lang/String;
return-void
.end method

.method public retHello4()Ljava/lang/String;
.locals 1
iget-object v0, p0, Lf8/helloworld/helloStr;->hStr2:Ljava/lang/String;
return-object v0
.end method

调用的时候需要先初始化一个实例

new-instance v1, Lf8/helloworld/helloStr;
invoke-direct{v1}, Lf8/helloworld/helloStr;-><init>()V
invoke-virtual{v1}, Lf8/helloworld/helloStr;->retHello4()Ljava/lang/String;
move-result-object v1

3. Android Log
来自于 android/util/Log 包
方法为 d(String, String)l, e, i, v 等
调用方法为
invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
Android Killer 中自带

4. LoadLibrary
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

5. stackTrace
打印当前函数堆栈,方法为 Thread.dumpStack();
invoke-static {}, Ljava/lang/Thread;->dumpStack()V

6. Method Trace
函数跟踪
invoke-static {}, Landroid/os/Debug;->startMethodTracing()V #函数头部
invoke-static {}, Landroid/os/Debug;->stopMethodTracing()V #函数尾部
添加权限

保存的 trace 文件,可以 dump 出来用 monitor 打开
adb pull /storage/sdcard/dmtrace.trace 本地路径 #dump 指令

7.  字符串处理
新建字符串:
const-string v1, “%d”
字符串格式化:
const-string v1, “%d” #格式化描述符
const/4 v2, 0x1 #数组长度
new-array v2, v2, [Ljava/lang/Object; #创建 Object 数组
aput-object v3, v2, v4 #填充数组

invoke-static {v1, v2}, Ljava/lang/String;->format(Ljava/lang/String;[Ljava/lang/Object;)
Ljava/lang/String; #格式化字符串
字符串替换:
invoke-virtual {v0, v1, v2},
Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/
String;
invoke-virtual {v0, v1, v2},
Ljava/lang/String;->replaceAll(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

8. waitForDebugger

调试
invoke-static{}, Landroid/os/Debug;->waitForDebugger()V

9. Demo  实例
1)  字符串搜索

2)  插入 dump 堆栈的方法

3)  对付签名验证
搜索目标字符串

找到代码中对字符串的调用

执行 jeb 中重命名脚本应对混淆

找到对应的 java 代码

可以直接修改 DOWNLOAD 和 EXIT 相关的代码
通过交叉引用查找实现签名验证的代码

交叉引用无法使用,然后插入堆栈跟踪代码

根据 dump 出的堆栈信息分析函数调用

找到签名验证的方法

分析方法 p()

对函数和变量进行重命名

该 app 是对 packageName 信息进行 MD5 运算后 post 到在线网站中进行验证

对 app 发送的签名数据包进行抓包操作

找到发送的 MD5 值

未选中的数字为 JSON 格式的数值
将抓取的 MD5 值写进程序中

最后 app 运行无签名提示

总会有不期而遇的温暖. 和生生不息的希望。
原文地址:https://www.cnblogs.com/devi1/p/13486452.html