欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[分享]发几个Android静态和动态分析的小技巧

[分享]发几个Android静态和动态分析的小技巧

没有好的调试工具下
对dex后的smali的技巧。
一、常用插代码
(如果怕影响寄存器值,可以将.locals xxx改多几个或者合适的地方,如返回前添加)
1、

const-string v7, "log.v(xx, yy);"

invoke-static {v7, v7}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I

2、
const-string v0, "Must ensure vx is Context class, then Toast.makeText(vx, xxx, 1).show();" # CharSequence对象类型

const/4 v1, 0x1 # I int类型

invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; # p0 是一个Context

move-result-object v0

invoke-virtual {v0}, Landroid/widget/Toast;->show()V

二.调用回溯
1、静态方法搜索需要扩展到父类的方法搜索,如Sublime Text 3下结果
.class public Lcom/dataviz/dxtg/common/android/launcher/TabbedLauncherActivity;

.super Lcom/dataviz/dxtg/common/android/ApplicationActivity;

# interfaces

.implements Landroid/view/GestureDetector$OnGestureListener;

.implements Lcom/dataviz/dxtg/common/android/ar;

.implements Lcom/dataviz/dxtg/common/android/bt;

.implements Lcom/dataviz/dxtg/common/android/cs;

.implements Lcom/dataviz/dxtg/common/android/dv;

.implements Lcom/dataviz/dxtg/common/android/iap/d;

.implements Lcom/dataviz/dxtg/common/android/iap/z;

.method public c()V

.end method

搜索方法
Lcom/dataviz/dxtg/common/android/launcher/TabbedLauncherActivity;->c()V
也许搜索没有结果,就有可能是父类或 接口。
这里是Lcom/dataviz/dxtg/common/android/dv;->c()V
.class public interface abstract Lcom/dataviz/dxtg/common/android/dv;

.super Ljava/lang/Object;

# virtual methods

.method public abstract a(Ljava/lang/String;)V

.end method

.method public abstract a(Z)V

.end method

.method public abstract c()V

.end method

结果
Searching 7287 files for "Lcom/dataviz/dxtg/common/android/dv;->c()V"

 

D:\com.dataviz.docstogo\smali\com\dataviz\dxtg\common\android\do.smali:

   91:     invoke-interface {v0}, Lcom/dataviz/dxtg/common/android/dv;->c()V

  289:     invoke-interface {v0}, Lcom/dataviz/dxtg/common/android/dv;->c()V

 

2 matches in 1 file

 然后看看调用这个方法的所在方法有没有判断跳转语句,如果没有可能还要继续查看谁调用。
2. 动态/运行时查看
制造异常查看函数调用堆栈
 在查看方法调用时,制造空指针异常。回溯方法调用堆栈
.method public c()V

    .locals 1 ## .locals 1 romove desktop tab 

    const/4 v0, 0x0

    #new-instance v0, Lcom/dataviz/dxtg/common/android/bl;

    #invoke-direct {v0}, Lcom/dataviz/dxtg/common/android/bl;-><init>()V

    invoke-direct {p0, v0}, Lcom/dataviz/dxtg/common/android/launcher/TabbedLauncherActivity;->a(Landroid/support/v4/app/Fragment;)Z

    return-void

.end method

堆栈截图


三、smali修改代码出错举例1
●
  • 1. 入参类型

  • 当smali修改代码出错举例1,log如下:
    虚拟机层次:
    1.本身做出了预测,寄存器v2是符合要求入参,暗示你这个也许是你想要的。VFY: register1 v2 type 17, wanted ref
    2.下一句:报参数1不对,应该是String类型。 VFY: bad arg 1 (into Ljava/lang/String;)
    3.第三行,拒绝调用初始化。VFY:  rejecting call to Ljava/lang/StringBuilder;.<init> (Ljava/lang/String;)V
    4. 拒绝调用代码和偏移量。VFY:  rejecting opcode 0x70 at 0x031f
    5. 函数调用堆栈。VFY:  rejected Lcom/dataviz/dxtg/common/android/AboutScreenActivity;.onCreate (Landroid/os/Bundle;)V
    6.出错类,全路径。Verifier rejected class Lcom/dataviz/dxtg/common/android/AboutScreenActivity;
    7.出错详细描述。Class init failed in newInstance call (Lcom/dataviz/dxtg/common/android/AboutScreenActivity;)
    Android运行时日志:
    略。



    ●
  • 2. 字段赋值
  • 	const-string/jumbo v0, "4.001"
    
    	const v1, 666666
    
    	# # VFY: invalid reg type 1073801336 on iput instr (need 12)
    
    	# # VFY:  rejecting opcode 0x59 at 0x001d
    
    	# # 0x59 表示 iput vx,vy, field_id, 0x001d应该是 方法里偏移量,两字节一个偏移量
    
            iput v0, v4, Lxx/yy/clazz;->field:I

    偏移量可正可负,它从指令开始字节计算的。偏移量按字(2字节1个偏移),从中可以看出偏移量大小。
    原文:
    The offset can be positive or negative and it is calculated from the offset of the starting byte of the instruction. The offset is always interpreted in words (2 bytes per 1 offset value increment/decrement). Negative offset is stored in two's complement format. The current position is the offset of the starting byte of the instruction.


    四、代码混乱的替换
    举例:
    Lcom/dataviz/dxtg/common/d/j;单个类域替换,包括成员;
    Lcom/dataviz/dxtg/common/d/j/此对应文件夹及其子文件夹下所有类都替换,最后斜杠。
    可以保存脚本,替换回来。
    用于向处理http的线程,比如,假设Lcom/dataviz/dxtg/common/d/j是线程Thread或Runnable的儿子、孙子或重孙子...类,可以替换为Lcom/dataviz/dxtg/common/d/HttpThread_j等有意义的类名。

    保存脚本内容可能这样:
    <?xml version="1.0" encoding="utf-8"?>
    
    <fs_sr_script>
    
        <fs_sr_options/>
    
        <fs_sr_info case_sensitive="0">
    
            <search_string>Lcom/dataviz/dxtg/common/d/j/</search_string>
    
            <replace_string>Lcom/dataviz/dxtg/common/d/HttpThread_j</replace_string>
    
        </fs_sr_info>
    
        <fs_file_list_info>
    
            <mask>*</mask>
    
            <path>D:\d</path>
    
        </fs_file_list_info>
    
    </fs_sr_script>

    貌似这里已经有了:
    https://code.google.com/p/dex2jar/wiki/DeObfuscateJarWithDexTool
    主要就是:
    ●
  • 要点

  • 混淆代码处理有现成的东西:DeObfuscateJarWithDexTool
    1、自动收集建议的配置文件,也许像这样
    #generate a 'suggest' config for rename
    
    d2j-init-deobf -f -o init.txt a.jar
    
    -o 输出配置文件,这里为init.txt
    
    -f 如果存在重写文件
    
    a.jar 待修改的文件

    2、替换的命令也许这样:
    d2j-jar-remap -f -c init.txt -o a-deobf.jar a.jar
    
    -c 替换的配置文件
    
    -o 输出文件
    
    -f 如果存在重写文件
    
    a.jar 待修改的文件

    3、配置文件格式:
    ##  file UTF-8
    
    # format : ? x=y
    
    #?为大写貌似是静态吗,因为在public class InitOut里方法private void doMethod(String owner, ClassInfo.MemberInfo member, int x)有句sb.append(AccUtils.isStatic(member.access) ? "M" : "m");
    
    #重命名包a为pa
    
    p a=pa
    
    #重命名类a为C000_a
    
    c a/a=C000_a
    
    #重命名方法名a为Ma
    
    m a/a.a()=Ma
    
    #重命名字段名a为Fa
    
    f a/a.a=Fa
    
    

    ##  file UTF-8
    
    ##  format : pqx=y
    
    ##  
    
    ##  p is as follow:
    
    ##  a comment line config starts with '#';
    
    ##  a field or method line config starts with 'F', 'M', 'f',or 'm';
    
    ##  a class line config starts with 'C',or 'c';
    
    ##  a package line config starts with 'P',or 'p';
    
    ##  a @ line config starts with '@';
    
    ##  
    
    ##  q ?, but a space is ok


    如果打不开,下面是拷贝过来的。
    ●
  • Introduction

  • dex-tool-0.0.9.8 add support to DeObfuscate a jar

    ●
  • Details

  • ●
  • The Problem

  • for a Obfuscated jar like this

    package a;
    public class a
    {
    static String a = "Hello";
    static void a() {
    System.out.println(a);
    }
    public static void main(String[] args) {
    a();
    }
    }

    all package,class,field,method names are 'a', which is difficult to read.

    ●
  • DeObfuscate It

  • run the following command
    #generate a 'suggest' config for rename
    d2j-init-deobf -f -o init.txt a.jar

    we got a init.txt

    p a=pa
    c a/a=C000_a
    m a/a.a()=Ma
    m a/a.a=Fa

    which means
    #rename package a to pa
    p a=pa
    #rename class a to C000_a
    c a/a=C000_a
    #rename method a to Ma
    m a/a.a()=Ma
    #rename field a to Fa
    m a/a.a=Fa

    modify init.txt to
    #rename package a to hello
    p a=hello
    #rename class a to World
    c a/a=World
    #rename method a to say
    m a/a.a()=say
    #rename field a to message
    m a/a.a=message

    and run
    d2j-jar-remap -f -c init.txt -o a-deobf.jar a.jar
    now we get the comfortable source
    package hello;
    import java.io.PrintStream;
    public class World
    {
    static String message = "Hello";
    static void say() {
    System.out.println(message);
    }
    public static void main(String[] args) {
    say();
    }
    }

    or run the program with
    java -cp a-deobf.jar hello.World


    上传的附件 制造异常回溯某方法调用堆栈.PNG
    替换.png
    DeObfuscateJarWithDexTool_Capture.PNG

    注意:上传附件及图片大小不得大于30M。

    ⚠️ 版权声明:
    本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
    未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

    0 0 0 举报
    复制成功