首页
社区
课程
招聘
[分享]发几个Android静态和动态分析的小技巧
2014-6-13 00:07 25120

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

2014-6-13 00:07
25120
没有好的调试工具下
对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




    [CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

    上传的附件:
    收藏
    点赞1
    打赏
    分享
    最新回复 (17)
    雪    币: 8
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    guyue三十五 2014-6-13 00:55
    2
    0
    等我有一定功力   会看懂的
    雪    币: 218
    能力值: (RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    逍遥枷锁 2014-6-13 07:47
    3
    0
    正在努力中,此帖等我毕业。
    雪    币: 185
    活跃值: (25)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    whnet 2014-6-13 09:12
    4
    0
    第三段不错。 列举了一些。

    我最近碰到的很多VEY failed 都是自己把寄存器用错了~~ 插入的时候感觉 v0没人用。也不想改local ,结果一跑就错了。

    使用寄存器得小心。
    雪    币: 335
    活跃值: (208)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    peterchen 2014-6-13 16:46
    5
    0
    堆栈截图

    附件 89928
    http://bbs.pediy.com/attachment.php?attachmentid=89928
    这个图哪儿去了?
    雪    币: 1413
    活跃值: (401)
    能力值: (RANK:270 )
    在线值:
    发帖
    回帖
    粉丝
    Claud 6 2014-6-15 14:34
    6
    0
    内容很不错,帮楼主改了一下标题,希望不要见怪~
    雪    币: 2321
    活跃值: (4028)
    能力值: ( LV12,RANK:530 )
    在线值:
    发帖
    回帖
    粉丝
    熊猫正正 9 2014-6-15 22:00
    7
    0
    支持 ~
    雪    币: 576
    活跃值: (1354)
    能力值: ( LV12,RANK:210 )
    在线值:
    发帖
    回帖
    粉丝
    我是土匪 4 2014-6-15 22:45
    8
    0
    内容不错,一般注入代码的时候出错都是寄存器问题。
    雪    币: 341
    活跃值: (85)
    能力值: ( LV5,RANK:70 )
    在线值:
    发帖
    回帖
    粉丝
    JoySauce 1 2014-6-17 15:49
    9
    0
    mark学习
    雪    币: 381
    活跃值: (130)
    能力值: ( LV13,RANK:330 )
    在线值:
    发帖
    回帖
    粉丝
    HSQ 8 2014-6-17 17:29
    10
    0
    回溯堆栈有好一点的办法,注入一个打印回调的类即可,何必要搞崩溃
    上传的附件:
    雪    币: 368
    活跃值: (1181)
    能力值: ( LV9,RANK:310 )
    在线值:
    发帖
    回帖
    粉丝
    ThomasKing 6 2014-6-19 21:53
    11
    0
    不错,学习了!
    雪    币: 27
    活跃值: (12)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    CoyLiu 2014-6-20 16:58
    12
    0
    学习了,感谢~
    雪    币: 18
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    solkergy 2014-6-21 16:49
    13
    0
    不错的文章 先记下。。还不会调试
    雪    币: 19
    活跃值: (198)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    荷蒉丈人 2014-6-22 11:40
    14
    0
    很好的帖子,学习下,谢谢楼主!
    雪    币: 338
    活跃值: (91)
    能力值: ( LV8,RANK:120 )
    在线值:
    发帖
    回帖
    粉丝
    苏北小麦 2 2014-6-26 08:14
    15
    0
    嗯,这个没想过,主动获取,很好啊。。。
    雪    币: 5
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    南国紫胤 2014-6-27 13:30
    16
    0
    挺有用的,点赞~
    雪    币: 28
    活跃值: (10)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    neong 2014-7-17 00:09
    17
    0
    只能耍赖的说一句我先收藏了,完全没有足够的功力看懂楼主的东西
    雪    币: 3542
    活跃值: (239)
    能力值: ( LV3,RANK:30 )
    在线值:
    发帖
    回帖
    粉丝
    xunbu 2015-1-29 10:47
    18
    0
    感谢分享!
    游客
    登录 | 注册 方可回帖
    返回