精华内容
下载资源
问答
  • android逆向分析
    2021-01-01 22:06:46

    一、Android的反混淆工具2

    二、一键反编译apk/aar/dex/jar3

      (1)、Windows环境配置使用TTDeDroid3

      (2)、Ubuntu环境配置使用TTDeDroid4

    三、Apk脱壳后合并多个dex并使用jadx/JEB/JEB3分析合并后的Apk4

    四、常用的Android逆向分析工具

     

    一、Android的反混淆工具

    git clone --recursive https://github.com/CalebFenton/simplify.git

     

    git submodule update --init --recursive

     

    ./gradlew fatjar

    图片

     

    图片

     

    图片

     

    gradlew.bat fatjar

     

    java -jar simplify/build/libs/simplify-1.2.1.jar -h

     

    java -jar simplify/build/libs/simplify.jar -it 'org/cf/obfuscated' -et 'MainActivity' simplify/obfuscated-app.apk

     

    java -jar simplify/build/libs/simplify-1.2.1.jar -it 'org/cf' G:\workspace\simplify\simplify\src\test\resources\obfuscated-example -o g:\example.dex

     

    二、一键反编译 apk/aar/dex/jar

    git clone https://github.com/tp7309/TTDeDroid.git

     

    (1)、Windows环境配置使用TTDeDroid

    把H:\SecurityAnalysis\TTDeDroid\bin添加到环境变量,如图所示:

    图片

     

    图片

     

    图片

     

    图片

     

    (2)、Ubuntu环境配置使用TTDeDroid

    把export PATH=$PATH:/home/gyp/gyp/SecurityAnalysis/TTDeDroid/bin添加到~/.bashrc中,如图所示:

    图片

     

    图片

     

    vim ~/.bashrc

     

    source ~/.bashrc

     

    chmod a+x /home/gyp/gyp/SecurityAnalysis/TTDeDroid/bin/showjar

     

    showjar test.apk

     

    三、Apk脱壳后合并多个dex并使用jadx/JEB/JEB3分析合并后的Apk

    https://github.com/Simp1er/AndroidSec.git

     

    python3 dex2apk.py -a ****.apk -i dex_unpack/ -o ****-output.apk

    图片

     

    图片

     

    图片

     

    四、常用的Android逆向分析工具

    apktool

    https://bitbucket.org/iBotPeaches/apktool/downloads/

     

    XJad

    https://www.lanzous.com/i2vvdvi

     

    Smali2JavaUI

    https://forum.xda-developers.com/showthread.php?t=2430413

     

    jadx

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

     

    JEB

    https://www.pnfsoftware.com/

     

    JEB3

    https://www.pnfsoftware.com/blog/jeb3-alpha-is-available/

    https://www.pnfsoftware.com/blog/category/jeb3/

     

    GDA

    http://www.gda.wiki:9090/

     

    IDA

    https://www.hex-rays.com/products/ida/news/

    https://www.hex-rays.com/products/ida/

    https://ida2020.org/

     

    关注公众号,获取更多最新文章

    图片

    更多相关内容
  • Android 逆向分析大全

    千次阅读 2020-07-23 00:46:14
    转载:Android 逆向分析大全:https://www.jianshu.com/p/a12d04fc748f 1. 概述 1.1 分析步骤 通用逆向分析步骤 1. 了解该模块正向编程相关方法 2. 使用apktool解密apk,得到资源、jni模块等文件 3. ...

     

    转载:Android 逆向分析大全:https://www.jianshu.com/p/a12d04fc748f

     

     

     

    1. 概述

     

    1.1 分析步骤

     

    通用逆向分析步骤

    • 1. 了解该模块正向编程相关方法
    • 2. 使用apktool解密apk,得到资源、jni模块等文件
    • 3. 从apk提取出dex文件,使用dex2jar转换成jar文件,再用java逆向工具得到java源码 dex->jar->java
    • 4. 根据特征(字符串、常量、包名类名方法名、manifest文件、布局文件等方式)或调试手段定位到关键代码
    • 5. 分析变量含义类型、函数逻辑、模块流程
    • 6. 对变量、函数、类进行标注、恢复成高级语言 ->c

    Android程序的特点相比在于使用混淆方式打包,将包名、类名、函数名改成不易看懂的字母,从而使生成的apk小很多(android studio提供了release编译方式,使用proguard混淆),因此反编译apk最多的工作在于重构这些名称,这一点和pc上一致,对于android native程序(jni)则和pc上基本一致,不同之处在于常见的是arm汇编。

     

    安卓上APK调试步骤:

    • 1.Apk(debuggable)或系统(ro.debuggable=1)设置为可调试
    • 2.在虚拟机中启动服务端(adbd/android_server)
    • 3.在主机端连接客户端调试器(IDA/jdb/adt),设置断点

     

    安卓上linux程序调试步骤:

    • 1.在虚拟机中启动服务端(gdb_server/linux_server)
    • 2.在主机端连接客户端调试器(IDA/gdb_for_windows),设置断点

    对于apk的反编译,由于资源和xml都进行了编码,因此反编译时必然要解析相应的resource.arsc/AndroidManifest.xml等文件,对于做过保护处理的apk通常会在这里做手脚干扰Apktool、dex2jar等反编译工具因此很有必要掌握编译、调试这些工具源码的方法(见“如何编译、调试apktool和dex2jar”)

     

     

    1.2 分析工具

     

    • 集成IDE:APK改之理、JD-GUI、JEB(1.4破解 2.0)、jadx
    • 解压(apk, jar):WinRar
    • 解析资源:apktool
    • 反编译引擎(jar, class):dex2jar工具集、jd-core(JD-GUI,JD-Eclipse反编译核心)、fernflower(Android Studio反编 、procyon
    • 回编译:aapt、dex2jar工具集
    • 调试器:IDA、jdb、adt等
    • 辅助工具:DDMS 如果是虚拟机可以看到所有进程

     

    APK 改之理

    • 整合&提供了全套解压、反编译代码和资源、回编译、签名功能,强大的正则搜索,修改smali字节码等功能
    • 集成ApkTool、Dex2jar、JD-GUI工具
    • 可视化操作,全自动的反编译、回编译、签名Apk
    • 正则表达式搜索资源及源码

     

    JD-GUI

    轻量级反编译,反编译jar/class等java字节码文件(能力一般),提供简单的搜索能力

     

    JEB

    • 反编译apk/jar工具(能力较强)
    • 强大的正向、反向索引,一定程度重命名能力,一定搜索能力
    • 支持注释、插件
    • 交互式可视化操作,全自动的反编译
    • 支持重命名

     

    Dex2jar 工具集

    dex2jar是一个工具包,反编译dex和jar,还提供了一些其它的功能,每个功能使用一个bat批处理或 sh 脚本来包装,只需在Windows 系统中调用 bat文件、在Linux 系统中调用 sh 脚本即可。在bat中调用相应的jar主类完成特定功能,例如d2j-dex2jar.bat中的内容是:@"%~dp0d2j_invoke.bat" com.googlecode.dex2jar.tools.Dex2jarCmd %*。常用的有dex2jar jar2dex dex2smali smali2dex

    • d2j-apk-sign用来为apk 文件签名。命令格式:d2j-apk-sign xxx.apk 。
    • d2j-asm-verify 用来验证jar 文件。命令格式:d2j-asm-verify -d xxx.jar。
    • d2j-dex2jar 用来将dex 文件转换成jar 文件。命令格式:d2j-dex2jar xxx.apk
    • d2j-dex-asmifier 用来验证dex 文件。命令格式:d2j-dex-asmifier xxx.dex。
    • d2j-dex-dump 用来转存dex 文件的信息。命令格式:d2j-dex-dump xxx.apk out.jar 。
    • d2j-init-deobf 用来生成反混淆jar 文件时的初始化配置文件。
    • d2j-jar2dex 用来将jar 文件转换成 dex 文件。命令格式:d2j-jar2dex xxx.apk。
    • d2j-jar2jasmin 用来将jar 文件转换成jasmin 格式的文件。命令格式:d2j-jar2jasmin xxx.jar
    • d2j-jar-access 用来修改jar 文件中的类、方法以及字段的访问权限。
    • d2j-jar-remap 用来重命名jar 文件中的包、类、方法以及字段的名称。
    • d2j-jasmin2jar 用来将jasmin 格式的文件转换成 jar 文件。命令格式:d2j-jasmin2jar dir dex2jar为d2j-dex2jar 的副本。
    • dex-dump为d2j-dex-dump 的副本

     

    Apktool反编译&打包工具

    • 反编译apk:apktool d file.apk –o path
    • 回编译apk:apktool b path –o file.apk

     

     

    1.3 常见文件格式

     

    Apk

    Android package,android安装程序文件,本质上是压缩包,解压得到classes.dex、resources.arsc、AndroidManifest.xml、so文件以及资源文件

    • Resources.arsc资源描述文件
    • Classes.dex所有代码编译过得darvik字节码文件,可能会有多个
    • AndroidManifest.xml 编译过的AndroidManifest.xml文件

    使用 aapt 解析 xml

    aapt d xmltree 1.apk AndroidManifest.xml
    N: android=http://schemas.android.com/apk/res/android
      E: manifest (line=2)
        A: android:versionCode(0x0101021b)=(type 0x10)0x1
        A: android:versionName(0x0101021c)="1.0" (Raw: "1.0")
        A: package="com.ibotpeaches.issue767" (Raw: "com.ibotpeaches.issue767")
        A: platformBuildVersionCode=(type 0x10)0x17 (Raw: "23")
        A: platformBuildVersionName="6.0-2438415" (Raw: "6.0-2438415")
        E: uses-sdk (line=0)
          A: android:minSdkVersion(0x0101020c)=(type 0x10)0x16
          A: android:targetSdkVersion(0x01010270)=(type 0x10)0x17
        E: application (line=3)
          A: android:theme(0x01010000)=@0x7f090083
          A: android:label(0x01010001)=@0x7f060015
          A: android:icon(0x01010002)=@0x7f030000
          A: android:debuggable(0x0101000f)=(type 0x12)0xffffffff
          A: android:allowBackup(0x01010280)=(type 0x12)0xffffffff
          A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff
          E: activity (line=4)
            A: android:theme(0x01010000)=@0x7f090030
            A: android:label(0x01010001)=@0x7f060015
            A: android:name(0x01010003)="com.ibotpeaches.issue767.MainActivity" (Raw
    : "com.ibotpeaches.issue767.MainActivity")
            E: intent-filter (line=5)
              E: action (line=6)
                A: android:name(0x01010003)="android.intent.action.MAIN" (Raw: "andr
    oid.intent.action.MAIN")
              E: category (line=7)
                A: android:name(0x01010003)="android.intent.category.LAUNCHER" (Raw:
     "android.intent.category.LAUNCHER")
          E: meta-data (line=10)
            A: android:name(0x01010003)="large.int.value" (Raw: "large.int.value")
            A: android:value(0x01010024)="9999999999999999999999" (Raw: "99999999999
    99999999999")
    

    查看xml => aapt d xmltree 1.apk AndroidManifest.xml
    查看resource => aapt d resources 1.apk (resource.arsc)

     

    Dex

    Dalvik Executable,Dalvik可执行文件,从java class文件转换而来的字节码,Classes.Dex通过dex2jar转换成java字节码(有损),或者dex2smali转换成darvik汇编(无损)——smali字节码,其形式如下

     

    Jar

    Java Archive,java归档文件,可以直接解压得到class文件

     

    Odex

    dex 转 odex:/system/bin/dexopt
    dexopt-wrapper 1.apk 1.odex

     

    Aar

    Android 归档文件,压缩包格式,包含

    • /AndroidManifest.xml (强制) 未编译的

    • /classes.jar (强制)

    • /res/ (强制)

    • /R.txt (强制)

    • /assets/ (可选)

    • /libs/*.jar (可选)

    • /jni/

      <abi>/*.so (可选)</abi>

    • /proguard.txt (可选)

    • /lint.jar (可选)

     

    So

    Linux 动态链接库文件,包含arm64 arm mips mips64 x86 x86-64几个平台

     

    工具转换图

     

    Android 设备上重要目录

    • /system/app/1.apk 系统应用
    • /data/app/1.apk 用户应用
    • /data/data/[pkgname] 应用数据(so,database,…)
    • /data/dalvik-cache 存放dex



     

    2. Java 层 

     

    2.1 常用工具

     

    adb

    设备通信、调试工具,常用法:

    adb devices 列出当前设备
    adb –s d24eb3ab [命令]      指定设备执行命令
    adb push 源 目标            非root机器可以设置路径为/data/local/tmp
    adb pull 源 目标
    adb shell                   执行终端
    adb logcat                  查看日志(/system/logcat为服务器)
    adb jdwp                    查看远程jdwp进程
    adb forward tcp:主机端口     tcp:远程端口       把主机端口消息转发手机端口(端口对应进程)   用于ida调试
    adb forward tcp:主机端口     jdwp:远程进程ID    把主机端口消息转发手机jdwp进程   用于jdb调试 
    adb install [apkpath]       安装apk
    adb uninstall [packagename] 卸载apk 注意会彻底清理,删除/data/app下的备份apk
    adb remount                 将/system重新映射为读写,以便进行系统区文件操作
    adb root                    使adb以root方式启动,便于push/pull/remount
    

     

    aapt

    APK资源管理工具,用于增删查改APK中的文件、资源等,对于分析编译后的Resource.arsc, AndroidManifest.xml格式较有价值,通常也可以用winrar对apk/jar进行解压

    打印xml树 aapt d xmltree 1.apk AndroidManifest.xml
    打印资源    aapt d resources 1.apk
    添加文件    aapt a 1.apk AndroidManifest.xml
    删除文件    aapt r 1.apk AndroidManifest.xml
    

     

    am & pm

    Android 远程命令,am 执行调试、运行功能,pm 执行安装、卸载功能

    • 启动应用:am start -D -n "b.myapp/b.myapp.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
    • 启动服务:am startservice -n com.android.music/com.android.music.MediaPlaybackService
    • 强制停止包:am force-stop com.example.administrator.myapplication
    • 强制结束包进程:am kill com.example.administrator.myapplication am kill all
    • 发送广播:adb shell am broadcast -a com.android.test
    • 安装应用:pm install –r 1.apk
    • 卸载应用:pm uninstall packagename
    • 列出所有安装包:pm list package
    • 查看是否以指定名为前缀的包存在:pm list package com.qihoo
    • 禁用应用:pm disable packagename (禁用后,图标消失,对该应用的操作都无效)

     

     

    2.2 有源码调试 APK

     

    Android studio

    在 android studio 中可以采用运行调试或进程附加方式调试,支持条件断点、一次断点、对单线程下断,有6种断点:

    TypeChTypEnDescription
    行断点Java Line Breakpoints在(java/c)源码某行下断
    Java类成员变量访问断点Java Field Watchpoints类似于内存访问断点,在读和写java类成员变量时断下
    Java类方法断点Java Method Breakpoints在进入java层函数或退出函数时断下
    Java异常断点Java Exception Breakpoints发生java层捕获或未捕获异常时断下
    异常断点Exception Breakpoints抛异常或捕获异常时断下
    符号断点Symbolic Breakpoints(c/java)符号断点

     

    Adb wifi

    应用市场有很多这种软件,需要Root权限。解决没有USB数据线的情况下的调试

    C:\Users\Administrator>adb connect 192.168.0.103:5555
    connected to 192.168.0.103:5555
    此时可以用adt调试
    

     

     

    2.3 无源码调试apk

     

    不需要调试的一般过程 :使用反编译工具得到源代码,修改调试标识,修改机器码,最后回编译签名:

    反编译apk:apktool d file.apk –o path  
    回编译apk:apktool b path –o file.apk
    

     

    使用 AndroidStudio 和 Apktool 工具调试

    • 第一步,反编译得到(占行)伪源码:java -jar apktool.jar d -d input.apk -o out,加上-d选项之后反编译出的文件后缀为.java,而不是.smali,每个.java文件立马都伪造成了一个类,语句全都是“a=0;”这一句,smali语句成为注释,做这些都是为了后面欺骗idea、eclipse、android studio这些ide的
    • 第二步,修改资源或者源码(smali),修改AndroidManifest.xml调试标识,反编译以后可以在dex中插入waitfordebugger或者Log.i的smali代码来进行相应的控制
    • 第三步,回编译(-d选项) + 签名        
              回编译:apktool b –d path –o input.apk
              签名: java –jar signapk.jar testkey.x509.pem testkey.pk8 input.apk output.apk
    • 第四步,新建android studio工程 ,将反编译得到的smali文件夹中的源文件拷贝到源码目录(欺骗),回编译的apk覆盖目标apk位置 ,删除Edit configuration的Before launch,下断点调试

    点评:这种方式只可以用来分析加密很弱的App,前提是apktool可以成功反编译

     

     

    使用 jdb 调试

    jdb是一个支持java代码级调试的工具,它是由java jdk提供的,可以设置断点、查看堆栈、计算表达式、动态修改类字节码、调试&跟踪、修改变量值、线程操作,断点包括:(源码)行断点、符号断点、成员变量访问断点。每个java程序(windows/ios/android)都可以用jdwp协议进行调试,Android Studio/Eclipse的调试也是建立在该协议基础之上,下面以实例说明:

    • 第一步,开发 demo

      public class MainActivity extends Activity {
      
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
      
            findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.b.com"));
                    intent.setClassName("com.android.browser","com.android.browser.BrowserActivity");
                    startActivity(intent);
                }
            });
        }
      }
      
    • 第二步,启动 jdb 调试

      adb shell am start -D -n "b.myapp/.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
      

       

    • 第三步,开始调试
              查看 ddms 中该进程端口号 8600
              使用 jdb 调试:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8600
              下断点:函数断点stop in android.app.Activity.startActivity(android.content.Intent)

      行断点 stop at android.app.Activity:123,触发断点后显示堆栈:
      
      ```
      <1> main[1] where
      [1] android.app.Activity.startActivity (Activity.java:3,490)
      [2] b.myapp.MainActivity$1.onClick (MainActivity.java:21)
      [3] android.view.View.performClick (View.java:4,084)
      [4] android.view.View$PerformClick.run (View.java:16,966)
      [5] android.os.Handler.handleCallback (Handler.java:615)
      [6] android.os.Handler.dispatchMessage (Handler.java:92)
      [7] android.os.Looper.loop (Looper.java:137)
      [8] android.app.ActivityThread.main (ActivityThread.java:4,745)
      [9] java.lang.reflect.Method.invokeNative (本机方法)
      ```
      

     

    查看参数

    <1> main[1] print intent
     intent = "Intent { act=android.intent.action.VIEW dat=http://www.b.com cmp=
    com.android.browser/.BrowserActivity }"
    

    设置源码从而进行逐行调试

    <1> main[1] use D:\Android\sdk\sources\android-18       //参考设备android版本
    <1> main[1] use D:\test\MyApplication\app\src\main\java
    <1> main[1] list
    3,421         * @hide Implement to provide correct calling token.
    3,422         */
    3,423        public void startActivityAsUser(Intent intent, UserHandle user) {
    3,424            startActivityAsUser(intent, null, user);
    3,425 =>     }
    3,426
    3,427        /**
    3,428         * @hide Implement to provide correct calling token.
    3,429         */
    3,430        public void startActivityAsUser(Intent intent, Bundle options, User
    Handle user) {
    

    行断点:

    > use D:\test\MyApplication\app\src\main\java
    stop at b.myapp.MainActivity:18
    正在延迟断点b.myapp.MainActivity:18。
    将在加载类后设置。
    > resume
    已恢复所有线程。
    > 设置延迟的断点b.myapp.MainActivity:18
    断点命中: "线程=<1> main", b.myapp.MainActivity.onCreate(), 行=18 bci=12
    18            int j = 0;
    

    初始断点

    只要连接到 jdb 就会导致 app 运行起来,此时如果想断在初始化这部分就没有办法了,不过 jdb 提供初始命令脚本

    • 暂停所有线程: echo suspend > jdb.ini
    • 执行调试:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8601

    此时,app 仍然处于等调试器状态,而虫子已经变绿,此时可以下断点,然后 resume 恢复所有线程

    附加后会变绿色虫子

    > > stop in b.myapp.MainActivity.onCreate(android.os.Bundle)
    正在延迟断点b.myapp.MainActivity.onCreate(android.os.Bundle)。
    将在加载类后设置。
    >resume
    已恢复所有线程。
    断点命中: "线程=<1> main", b.myapp.MainActivity.onCreate(), 行=13 bci=0
    
    <1> main[1] where
      [1] b.myapp.MainActivity.onCreate (MainActivity.java:13)
      [2] android.app.Activity.performCreate (Activity.java:5,372)
      [3] android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1,1
    04)
      [4] android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2,25
    8)
      [5] android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2,350
    )
      [6] android.app.ActivityThread.access$700 (ActivityThread.java:160)
      [7] android.app.ActivityThread$H.handleMessage (ActivityThread.java:1,317)
      [8] android.os.Handler.dispatchMessage (Handler.java:99)
      [9] android.os.Looper.loop (Looper.java:137)
      [10] android.app.ActivityThread.main (ActivityThread.java:5,454)
    

    调试命令

    stop in:断点
        step:步入(源码行)
        stepi:单入(指令)
        step up:执行到返回
        cont:恢复运行
        next:步过
        输出表达式:print/eval
    

    jdb 最大缺点在于难用,所以有人用 python 封装了一次,工具名 AndBug

     

     

    2.4 无源码调试 dex

    • 使用 ida 分析 apk 或者从 apk 中提取出的 dex
    • 设置调试选项,包括包名和主类名,参考反编译的 AndroidManifest
    • 启动调试即可

     

     

    3. Linux 层 

     

    3.1 常用工具

     

    Gdbserver

    Usage:  gdbserver [OPTIONS] COMM PROG [ARGS ...]
            gdbserver [OPTIONS] --attach COMM PID
            gdbserver [OPTIONS] --multi COMM
            隐藏用法:gdbserver [OPTIONS] +SOCKETFILE --attach PID           会在本地建立socket文件通信
    Options:
      --debug               Enable general debugging output.
      --remote-debug        Enable remote protocol debugging output.
      --version             Display version information and exit.
      --wrapper WRAPPER --  Run WRAPPER to start new programs.
      --once                Exit after the first connection has closed.
    使用方式:
    启动模式远程调试:gdbserver --debug --remote-debug  :23946 /system/test.out [参数]     
    附加模式远程:gdbserver –debug –remote-debug –attach  :23946 1234
        Adb forward tcp:23946 tcp:23946 转发端口
    IDA中选择Remote GDB Debugger附加即可
    

     

    Strace

    usage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]
                  [-p pid] ... [-s strsize] [-u username] [-E var=val] ...
                  [command [arg ...]]
    or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...
                  [command [arg ...]]
    -c --统计每一系统调用的所执行的时间,次数和出错的次数等.
    -C -- like -c but also print regular output while processes are running
    -f --跟踪由fork调用所产生的子进程.
    -F --尝试跟踪vfork调用.在-f时,vfork不被跟踪.
    -i --输出系统调用的入口指针
    -q --禁止输出关于脱离的消息
    -r --打印出相对时间关于,,每一个系统调用
    -T --显示每一调用所耗的时间
    -v --输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出
    -x --以十六进制形式输出非标准字符串
    -a设置返回值的输出位置.默认 为40.
    -e expr -指定一个表达式,用来控制如何跟踪.: option=[!]all or option=[!]val1[,val2]...
       options: trace, abbrev, verbose, raw, signal, read, or write
    -o file --将strace的输出写入文件filename
    -O overhead -- set overhead for tracing syscalls to OVERHEAD usecs
    -p pid --跟踪指定的进程pid.
    -D -- run tracer process as a detached grandchild, not as parent
    -s strsize --指定输出的字符串的最大长度.默认为32.文件名一直全部输出
    -S sortby -- sort syscall counts by: time, calls, name, nothing (default time)
    -u username --以username 的UID和GID执行被跟踪的命令
    -E var=val -- put var=val in the environment for command
    -E var -- remove var from the environment for command
    
    使用方式:
    Strace –f ProcessA      启动跟踪
    Strace –f –p 234        附加跟踪
        -e trace=file       -e trace=process    -e trace=network
    

     

     

    3.2 有源码 so 调试

     

    Ndk-gdb

    该程序是一个shell脚本,执行过程如下:

    adb shell am start -D -n com.example.hellojni/.HelloJni     启动app并等待调试器
        ps | grep hellojni                                  得到PID 3569
    adb shell run-as com.example.hellojni /data/data/com.example.hellojni/lib/gdbserver +debug-socket --attach (3569)PID
        将PID与文件映射建立调试链接(c层)
    adb forward tcp:5039 localfilesystem:/data/data/com.example.hellojni/debug-socket将调试链接和本地端口建立链接(c层)
    adb forward tcp:65534 jdwp:(3569)PID                                         将本地端口和进程建立连接(java层)
    jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=65534          使用jdb调试java层
    arm-linux-androideabi-gdb.exe                                           
        target remote :5039                                              使用gdb调试c层
        set breakpoint pending on
    

    (使用前关掉腾讯的AndroidServer.exe,否则连不上!!!),在工程目录下(有AndroidManifest.xml),命令行运行%NDK_ROOT%\ndk-gdb-py.cmd --start --verbose,输出下面字符即为成功:

    Android NDK installation path: D:/Android/AndroidNDK/android-ndk-r10e
    ADB version found: Android Debug Bridge version 1.0.32
    Using ADB flags:
    Using auto-detected project path: .
    Found package name: com.example.hellojni
    ABIs targetted by application: arm64-v8a armeabi armeabi-v7a armeabi-v7a-hard mips mips64 x86 x86_64
    Device API Level: 19
    Device CPU ABIs: armeabi-v7a armeabi
    Compatible device ABI: armeabi-v7a
    Using gdb setup init: ./libs/armeabi-v7a/gdb.setup
    Using toolchain prefix: D:/Android/AndroidNDK/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows/bin/arm-linux-androideabi
    Using app out directory: ./obj/local/armeabi-v7a
    Found debuggable flag: true
    Found device gdbserver: /data/data/com.example.hellojni/lib/gdbserver
    Found data directory: '/data/data/com.example.hellojni'
    Found first launchable activity: .HelloJni
    Launching activity: com.example.hellojni/.HelloJni
    ## COMMAND: adb_cmd shell am start -D -n com.example.hellojni/.HelloJni
    ## COMMAND: adb_cmd shell sleep 2.000000
    Found running PID: 9139
    ## COMMAND: adb_cmd shell run-as com.example.hellojni /data/data/com.example.hellojni/lib/gdbserver --attach +debug-socket 9139 [BACKGROUND]
    Launched gdbserver succesfully.
    Setup network redirection
    ## COMMAND: adb_cmd forward tcp:5039 localfilesystem:/data/data/com.example.hellojni/debug-socket
    Attached; pid = 9139
    Listening on Unix socket debug-socket
    ## COMMAND: adb_cmd pull /system/bin/app_process ./obj/local/armeabi-v7a/app_process
    79 KB/s (9488 bytes in 0.117s)
    Pulled app_process from device/emulator.
    ## COMMAND: adb_cmd pull /system/bin/linker ./obj/local/armeabi-v7a/linker
    585 KB/s (63596 bytes in 0.106s)
    Pulled linker from device/emulator.
    ## COMMAND: adb_cmd pull /system/lib/libc.so ./obj/local/armeabi-v7a/libc.so
    1184 KB/s (310584 bytes in 0.256s)
    Pulled /system/lib/libc.so from device/emulator.
    Set up JDB connection, using jdb command: C:\Program Files\Java\jdk1.8.0_66\bin\jdb.exe
    ## COMMAND: adb_cmd forward tcp:65534 jdwp:9139
    --------------------./obj/local/armeabi-v7a/gdb.setup---------------
    GNU gdb (GDB) 7.7
    Copyright (C) 2014 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "--host=i586-pc-mingw32msvc --target=arm-linux-android".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://source.android.com/source/report-bugs.html>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word".
    Remote debugging from host 9.11.5.0
    warning: Could not load shared library symbols for 112 libraries, e.g. libstdc++.so.
    Use the "info sharedlibrary" command to see the complete listing.
    Do you need "set solib-search-path" or "set sysroot"?
    0x400daa80 in __futex_syscall3 () from D:\Android\AndroidNDK\android-ndk-r10e\samples\hello-jni\obj\local\armeabi-v7a\libc.so
    (gdb)
    

    点评:该工具要求环境极为苛刻且不稳定,不建议使用

     

    Gdb-Gdbserver

    操作步骤:

    • Android studio导入jni工程,
    • 拷贝.so到搜索路径,pull /system/lib到搜索路径,pull /system/linker到搜索路径
    • 启动gdbserver (具体命令根据版本不同而变)
      gdbserver --attach *:111 1234
    • 转发端口
      adb forward tcp:111 tcp:111
    • 连接本地调试器
      target remote 127.0.0.1:111
    (gdb) set solib-search-path C:/Users/lichao/2/
    Reading symbols from C:\Users\lichao\2\linker...(no debugging symbols found)...done.
    Loaded symbols for C:\Users\lichao\2\linker
    Reading symbols from C:\Users\lichao\2\libc.so...(no debugging symbols found)...done.
    Loaded symbols for C:\Users\lichao\2\libc.so
    Reading symbols from C:\Users\lichao\2\libstdc++.so...(no debugging symbols found)...done.
    Loaded symbols for C:\Users\lichao\2\libstdc++.so
    Reading symbols from C:\Users\lichao\2\libm.so...(no debugging symbols found)...done.
    Loaded symbols for C:\Users\lichao\2\libm.so
    Reading symbols from C:\Users\lichao\2\liblog.so...(no debugging symbols found)...done.
    Loaded symbols for C:\Users\lichao\2\liblog.so
    Reading symbols from C:\Users\lichao\2\libcutils.so...(no debugging symbols found)...done.
    Loaded symbols for C:\Users\lichao\2\libcutils.so
    Reading symbols from C:\Users\lichao\2\libgccdemangle.so...(no debugging symbols found)...done.
    Loaded symbols for C:\Users\lichao\2\libgccdemangle.so
    Reading symbols from C:\Users\lichao\2\libcorkscrew.so...(no debugging symbols found)...done.
    
    (gdb) bt
    #0  0x400e50e0 in fork () from C:\Users\lichao\2\libc.so
    #1  0x76886ca0 in Java_com_example_hellojni_HelloJni_stringFromJNI () from C:\Users\lichao\2\libhello-jni.so
    #2  0x416b8350 in dvmPlatformInvoke () from C:\Users\lichao\2\libdvm.so
    #3  0x416e8fd2 in dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*) () from C:\Users\lichao\2\libdvm.so
    #4  0x416ea9ba in dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*) () from C:\Users\lichao\2\libdvm.so
    #5  0x416c1828 in dvmJitToInterpNoChain () from C:\Users\lichao\2\libdvm.so
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)
    (gdb) list
    

     

     

    3.3 无源码调试 So

     

    使用 Arm 版 Gdb 在移动端直接调试

    • 获取arm版gdb
    • 把gdb下载到移动端
      adb push gdb /data/bin
    • 执行gdb
      adb shell
      ./data/bin/gdb
    GNU gdb 6.7
    Copyright (C) 2007 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "--host=arm-none-linux-gnueabi --target=".
    (gdb)
    

    点评:该方法速度快,但不好查看符号

     

    IDA调试

    • 将android_server拷入/data/local/tmp/
      adb push android_server /data/local/tmp/
    • 修改可执行权限,运行
      cd /data/local/tmp/
      chmod 755 android_server
      ./android_server
    • 将模拟器端口转发至pc端口 (另开启命令行)
      adb forward tcp:23946 tcp:23946
    • IDA中选择Remote ARMLinux/Android debugger,端口23946,调试即可,成功以后显示
      Accepting connection from 127.0.0.1...

     

    Gdb-Gdbserver

    • 启动server
      ./gdbserver –attach :1234 [pid]
    • 转发端口
      adb forward tcp:1234 tcp:1234
    • 启动client
      arm-linux-androideabi-gdb.exe
    • 连接server
      target remote :1234
    • 设置单步调试
      set step-mode on
    • 设置反汇编模式
      set disassemble-next on
    • 设置加载so断点
      catch load 1.so
    0xb6cdf480 in __epoll_pwait () from E:\aaa\libc.so
    => 0xb6cdf480 <__epoll_pwait+28>:       1e ff 2f 91     bxls    lr
    (gdb) bt
    #0  0xb6cdf480 in __epoll_pwait () from E:\aaa\libc.so
    #1  0xb6cb70ca in epoll_pwait () from E:\aaa\libc.so
    #2  0xb6cb70d8 in epoll_wait () from E:\aaa\libc.so
    #3  0xb6f06bd6 in android::Looper::pollInner(int) () from E:\aaa\libutils.so
    #4  0xb6f06e52 in android::Looper::pollOnce(int, int*, int*, void**) () from E:\aaa\libutils.so
    #5  0xb6e4d41c in android::NativeMessageQueue::pollOnce(_JNIEnv*, _jobject*, int) () from E:\aaa\libandroid_runtime.so
    #6  0x732e056e in ?? ()
    

     

    Gikdbg

    GikDbg 是一款移动平台的汇编级调试器,它基于 OllyDbg ,GDB 以及 LLVM 实现而来。OllyDbg 现已广泛用于 PC 平台软件安全领域,GikDbg 是 OllyDbg 向移动平台转移的产物,它可以协助您完成诸如应用调试分析,应用安全评估,应用漏洞挖掘等移动安全领域。What features can GikDbg support? http://gikir.com/product.php

    • ELF / Mach-O executable file static analysis;
    • Android / iOS App dynamic debugging;
    • Android / iOS remote console;
    • ARM assembler;
    • ARM disassembler;
    • Device file uploading and downloading;
    • Built-in GDB and LLDB;
    • Support for memory breakpoint, software breakpoint, conditional breakpoint;
    • Support for multi-threaded debugging;
    • Support for assembly code level file patching.

     

    GikDbg for IOS

     

    GikDbg for Android

    gikdbg.art-Gikir Debugger for Android RunTime, 是Android平台的32位汇编级调试器。此处的Android RunTime既指DVM RunTime又指ART RunTime,因此不管是运行dalvik虚拟机还是运行本地代码的art均可以使用gikdbg.art进行程序的二进制调试分析。不同之处在于dalvik虚拟机的运行时只能调试so动态库,而art运行时不仅能调试so动态库,还能调试系统镜像oat,可执行程序dex这样的文件。另外,gikdbg-Gikir Debugger for iPhone OS,是调试越狱苹果设备的32位汇编级调试器,同学们莫搞混淆了哈,它需要一些复杂点的服务端和客户端的配置,而gikdbg.art在正常情况下是不需要手工配置的,所以别去找android server了。对于静态分析,可以执行/ART Debug/View/ELF Data…,/ART Debug/View/ELF Code…两个菜单打开本地so,oat,dex文件。

     

    调试 so

    Step 0.前置说明

    Step 0.前置说明
    手机端:Android模拟器,Android 4.4.2 ART 运行时;(真机与DVM运行时是一样的)
    PC端:ParallelDesktop虚拟机,Windows 8.0,gikdbg.art v1.0.build140601.3;
    PS:非root环境的设备由于权限的原因会有很多问题,不推荐使用!
    

    Step 1.连接设备

    Step 1.连接设备
    
    运行模拟器,打开gikdbg.art.exe,执行/ART Debug/Device菜单,我们就可以来到如下界面:

    如果模拟器已经运行了,但是设备列表中没有,则等待一段时间后执行右键的Refresh菜单。然后双击或者右键Login就可以登陆选中的设备了。对于第一次Login该设备,会询问你是否上传依赖的文件到/data/local,这一步如果否定了的话将不能使用调试功能。上传文件这个步骤目前已知的问题是对于非root的设备,往往因为权限的原因上传不成功,一般情况下/data/local/tmp目录没有问题,但是有些设备又没有/data/local/tmp目录,因此我们只有设置/data/local为目标路径,这个问题目前还不知道好的解决办法。归纳一下就是:非root的机器无法在其/data/local下创建我们依赖的文件夹以及上传文件,如果我们将其迁移至/data/local/tmp这个目录下,又有部分设备没有这个文件夹,就更没有办法上传了。
    对于这类上传失败的同学,可以想办法手工将$(GIKDBG.ART)/adb/android/gdb传至/data/local/gikir_android-xxxx/gdb这个位置,其中xxxx是GUID。
    如果还没有安装该apk文件的,则可以在ADB Shell中执行$install –r命令选择gikdebugee.apk进行安装.

     

    Step 2.选择进程

    Step 2.选择进程
    登陆成功后执行,确保模拟器的gikdebugee.apk运行正常,
    然后执行/ART Debug/File/Attach就可以得到如下进程列表,
    选中我们的gikdebugee进程,双击或者执行Attach按钮

    之后我们就会看到如下加载输出:

    等 gdb 加载完毕之后我们就可以进入熟悉的 CPU 主窗口了:

     

    Step 3.选择模块

    Step 3.选择模块
    我们的目的是调试apk里面的so动态库,因此执行/ART Debug/View/Module切换到模块列表,
    选中我们要调试的模块,双击它

     

    Step 4.击中断点

    Step 4.击中断点
    本例中找到要调试的函数getNativeString,我们可以用CTRL+F查找到它,
    找到之后F2下断点,F9运行它,然后在设备中操作按钮则该方法将被断点击中,F8运行3步

     

     

    3.4 调试 Android 上 Linux 程序

     

    adb push %NDK%\prebuilt\android-arm\gdbserver\gdbserver /system/bin
    chmod 777 /system/bin/gdbserver
    adb push test.out /system/bin
    chmod 777 /system/bin/test.out
    gdbserver :2345 /system/bin/test.out(若附加调试则提供进程号)
    adb forward tcp:2345 tcp:2345
    gdb >
    gdb > target remote :2345
    

     

    技巧:如何在 so 入口下断?

    用 ida分析 so,并在 JNI_OnLoad 下断点,动态附加后,ida 会自动 rebase,使用 gdb 的 catch load 命令捕获

     

     

    4. Java层 / Linux层 联合调试 

     

    4.1 有源码联合调试

    参照前几节

     

    4.2 无源码联合调试

     

    操作步骤

    adb shell am start -D -n com.example.hellojni/.HelloJni     启动app并等待调试器
        ps | grep hellojni                                  得到PID 3569
    adb shell run-as com.example.hellojni /data/data/com.example.hellojni/lib/gdbserver +debug-socket --attach (3569)PID
        将PID与文件映射建立调试链接(c层)
    adb forward tcp:5039 localfilesystem:/data/data/com.example.hellojni/debug-socket将调试链接和本地端口建立链接(c层)
    adb forward tcp:65534 jdwp:(3569)PID                                         将本地端口和进程建立连接(java层)
    jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=65534          使用jdb调试java层
    arm-linux-androideabi-gdb.exe                                           
        target remote :5039                                              使用gdb调试c层
        set breakpoint pending on
    

     

    最简单的 gdb 中,断在加载 so 时刻的方法

    • 1. 以等待模式启动
      am start -D -n com.example.hellojni/.HelloJni

    • 2.Gdbserve r链接该进程(ps | grep hello)
      gdbserver --attach :1234 10863

    • 3.转发端口
      adb forward tcp:1234 tcp:1234

    • 4.连接gdb
      arm-linux-androideabi-gdb Target remote :1234

      root@ja3gchnduos:/ # am start -D -n com.example.hellojni/.HelloJni
      Starting: Intent { cmp=com.example.hellojni/.HelloJni }
      root@ja3gchnduos:/ # ps | grep hello
      u0_a165   10863 3593  869292 16088 ffffffff 40077a08 S com.example.hellojni
      root@ja3gchnduos:/ # gdbserver --attach :1234 10863
      Attached; pid = 10863
      Listening on port 1234
      
    • 5.设置符号路径(提前把/system/lib/*.so /system/bin/linker libhello-jni.so拷贝到目录)
      set solib-search-path c:/1

    • 6.设置加载so断点
      catch load libhello-jni.so

    • 7.执行continue,使用android studio的attach使程序继续运行

    • 8.加载so时自动断下:

      Catchpoint 1
      Inferior loaded C:\Users\lichao\sumsing\libhello-jni.so
      0x40036b8c in rtld_db_dlactivity () from C:\Users\lichao\sumsing\linker
      
    • 9.用ida分析出onload要下断点的偏移,b *addr下断

     

    4.3 Android linux 内核层调试

    Android底层为linux层,gdb用于调试linux应用层,而kgdb用于调试linux内核层
    kgdb的android版本下载:http://github.com/dankex/kgdb-android

     

     

    5. 使用 Hook

     

    5.1 常用 Hook / Inject 工具简介

    常用 Hook 框架:

    • Cydia Substrate
              支持 Java 层 hook
              支持 Jni 层 hook
              需要 Root,且机型适配
              支持 dalvik,不支持 art
              闭源
    • Xposed https://github.com/rovo89/Xposed
              支持 Java 层 hook
              需要 Root,且机型适配
              支持 dalvik/art
              开源
    • Frida https://github.com/frida/frida
              需要 Root
              支持 Java 层 hook
              支持 Jni 层 hook
              支持 dalvik/art
              开源
              任意时刻注入,简单易用,远程代码即时编译并注入运行
    • Adbi https://github.com/evilsocket/arminject
              需要 Root
              支持 Jni 层 hook
              任意时刻注入,手工
              开源

     

     

    6. 实例:360手机卫士卸载后弹窗分析过程

     

    6.1 现象

    360手机卫士在非root情况下卸载后弹出浏览器。于是有2种常见可能,一种是intent跳转,一种是执行am命令,后者可以在java层和jni层实现,如果是java层考虑进行hook,jni层考虑修改am.jar

     

    6.2 文件注入

    将/system/bin/am改名,发现无法弹窗,于是确定是通过第二种方式实现,为了确定调用层级,尝试修改(反编译成smali->加入logcat输出打印回溯栈和接收参数->回编译)/system/framework/am.jar,(可以通过自己再另一个app中实现同样的功能,通过反编译得到smali代码)再次反编译后内容如下:

    public static void main(String[] args) {
            String v0 = "";
            int v3 = args.length;
            int v2;
            for(v2 = 0; v2 < v3; ++v2) {
                v0 = String.valueOf(v0) + " " + args[v2];
            }
            Log.d("my god", v0);
            Log.d("my god", Log.getStackTraceString(new Throwable()));
        }
    

     

    分析日志

    在卸载瞬间拿到输出:

    start -n com.android.browser/.BrowserActivity -a android.intent.action.VIEW -d http://shouji.360.cn/web/uninstall/uninstall.html?u=100&id=76bb84de8f53b53f57dd3cedfe966091&v=6.3.1.1048&s=1&model=SE0gTk9URSAxTFRF&sdk=19&ch=200222&wid=9fa298f35aec4232c26048442f36dc59 --user 0
    java.lang.Throwable 
        at com.android.commands.am.Am.main(Am.java:30)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:245)
        at dalvik.system.NativeStart.main(Native Method)
    

    发现命令行是 am start –n com.android.browser/.BrowserActivity -a android.intent.action.VIEW

     

    定位关键代码

    通过字符串搜索,定位到java层关键代码,使用android hook框架cydia substrate,挂钩java.lang.Runtime类的exec函数,定位到调用栈:

    content:/data/user/0/com.qihoo360.mobilesafe/files/so_libs/um.0.2 com.qihoo360.mobilesafe --execute am start -n com.android.browser/.BrowserActivity -a android.intent.action.VIEW -d http://shouji.360.cn/web/uninstall/uninstall.html?u=100\&id=7b55c26b779bd111dfed8b02bb00131c\&v=5.5.0.1041\&s=1\&model=TmV4dXMgUw\&sdk=19\&at=KTvooEkhHMzgJ13AXfMkJINnhrmyyNdu\&ch=200222 --user 0
    java.lang.Throwable 
        at com.example.emptytest.Main$1$1.invoked(Main.java:68)
        at com.saurik.substrate.MS$2.invoked(MS.java:68)
        at java.lang.Runtime.exec(Native Method)
        at egv.a(360MobileSafe:257)
        at egv.a(360MobileSafe:66)
        at com.qihoo360.mobilesafe.ui.index.MobileSafeApplication.p(360MobileSafe:1223)
        at com.qihoo360.mobilesafe.ui.index.MobileSafeApplication.onCreate(360MobileSafe:799)
    

     

    结论

    启动不久,360启动 linux 程序 /data/data/com.qihoo360.mobilesafe/com.qihoo360.mobilesafe/files/so_libs/um.0.2,并将弹窗任务以参数形式传递给该程序,程序中对 /data/data/com.qihoo360.mobilesafe 文件夹的删除操作进行挂钩,以实现卸载后弹窗机制

     

     

    7. GDB 调试 

     

    7.1 反汇编一段地址

    (gdb) disass /r 0x401148b8,0x40114900
    Dump of assembler code from 0x401148b8 to 0x401148c8:
    => 0x401148b8:  0c 70 a0 e1     mov     r7, r12
       0x401148bc:  01 0a 70 e3     cmn     r0, #4096       ; 0x1000
       0x401148c0:  1e ff 2f 91     bxls    lr
       0x401148c4:  00 00 60 e2     rsb     r0, r0, #0
       0x401148c8:  0e 70 00 ea     b       0x40130908
    End of assembler dump.
    

    7.2 表达式计算

    print expr
        print ”%d” a
    
    dprintf 动态插入printf函数
        dprintf location,format string,arg1,arg2,...
    

    7.3 查看寄存器

    info registers

    7.4 查看栈参数

    info args

    7.5 查看局部变量

    info locals

    7.6 查看内存

    x

    7.7 修改内存

    set *(unsigned int*)0x800000000=0x00000000
    

    7.8 断点

    break [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]
    clear [LOCATION]

    break *0x4000000  绝对地址
    break 12          行号
    break func1       函数
    clear *0x40000000
    clear 12
    clear func1
    

    一次断点

    tbreak [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]

    条件/线程断点

    break func1 thread1 if i==0

    观察断点

    watch/awatch/ rwatch [-l|-location] EXPRESSION      变化/读写/读断点
    (如果EXPRESSION不是绝对地址,则需要用-l计算表达式)
    watch *0x40000000==0x90909090
    watch –l *$pc
    watch i   (有源码,变量i的值有变化时停止)
    

    范围断点

    break-range START-LOCATION, END-LOCATION
    break-range 1.c:5, 1.c:10  在1.c的第5行和第10行之间下断
    break-range +5, +10 在当前行+5和当前行+10之间下断
    

    硬件断点

    普通硬断 hbreak [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]
    临时硬断 thbreak [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]

    拦截当前函数退出

    xbreak

    捕获断点

    普通补断 catch [assert|catch|exception|exec|fork|load|rethrow|signal|syscall|throw|unload|vfork]
    临时捕断 tcatch [assert|catch|exception|exec|fork|load|rethrow|signal|syscall|throw|unload|vfork]

    如何使程序在so加载时刻断下??(网上不少人用奇葩方式,还是对gdb不了解)
    catch load 1.so
    

    跟踪断点

    strace [LOCATION] [IF CONDITION]

    7.9 查看调用栈

    bt [N] 显示N层调用栈
    bt full 显示全部调用栈

    7.10 流程控制

    行为命令
    运行时中断Ctrl+C
    结束程序kill
    单步步过next
    单步步入step
    单步步过(指令级)nexti
    单步步入(指令级)stepi
    继续运行continue
    执行到当前函数指定位置advance
    分离进程detach
    强制跳转jump

    反向调试

    reverse-continue reverse-next reverse-search reverse-stepi reverse-finish reverse-next reverse-step

    7.11 显示当前加载模块

    info shared

    7.12 强制加载模块

    可以用于做二进制对比

    (gdb) load C:/Users/lichao/2/libadnative.so 0x50000000
    Loading section .interp, size 0x13 lma 0x50000134
    Loading section .dynsym, size 0x1210 lma 0x50000148
    Loading section .dynstr, size 0x2061 lma 0x50001358
    Loading section .hash, size 0x8a8 lma 0x500033bc
    Loading section .rel.dyn, size 0x10a0 lma 0x50003c64
    Loading section .rel.plt, size 0x1b0 lma 0x50004d04
    Loading section .plt, size 0x29c lma 0x50004eb4
    Loading section .text, size 0xe7a0 lma 0x50005150
    Loading section .ARM.extab, size 0x8e8 lma 0x500138f0
    Loading section .ARM.exidx, size 0xd80 lma 0x500141d8
    Loading section .rodata, size 0x11bc lma 0x50014f58
    Loading section .data.rel.ro.local, size 0x738 lma 0x50018098
    Loading section .fini_array, size 0x8 lma 0x500187d0
    Loading section .init_array, size 0x14 lma 0x500187d8
    Loading section .data.rel.ro, size 0x508 lma 0x500187f0
    Loading section .dynamic, size 0xf8 lma 0x50018cf8
    Loading section .got, size 0x210 lma 0x50018df0
    Loading section .data, size 0x1c lma 0x50019000
    Start address 0x0, load size 94044
    Transfer rate: 188 KB/sec, 2541 bytes/write.
    

    7.13 替换当前调试模块

    file c:/1.so
    

    7.14 进程转储

    gcore

    7.15 进程空间

    进程空间 inferior,用于调试多个进程,fork函数会自动添加进程空间

    操作指令
    添加进程空间add-inferior
    复制进程空间clone-inferior 1
    删除进程空间remove-inferior 1
    切换进程空间inferior 2
    分离进程空间detach inferior 2

    7.16 由地址获对应的符号

    maintenance translate-address [address]

    7.17 查找符号

    info functions [regex]   定位地址
    info symbol address      定位文件
    info variables [regex]   全局静态符号
    

    7.18 执行外部命令

    目标系统:! [command]
    主机系统:shell [command]

    7.19 显示线程

    info threads

    7.20 打印c++对象虚表

    info vtbl
    抄自此博客


     

     

    展开全文
  • Android逆向分析

    2017-11-29 16:07:23
    Android视频课程,Android逆向分析,比较好的资源。。。。
  • Android逆向分析概述

    千次阅读 2018-06-04 20:35:19
    学习逆向的初衷是想系统学习Android下的hook技术和工具, 想系统学习Android的hook技术和工具是因为Android移动性能实战这本书. 这本书里用hook技术hook一些...在读了姜维的Android应用安全防护和逆向分析和丰生强的...

    学习逆向的初衷是想系统学习Android下的hook技术和工具, 想系统学习Android的hook技术和工具是因为Android移动性能实战这本书. 这本书里用hook技术hook一些关键函数来计算关键函数的调用参数和调用时长, 从而确定性能问题发生的位置和原因. 但目前没有比较系统的讲解hook的书籍, 所以就系统的了解下逆向分析.

    在读了姜维的Android应用安全防护和逆向分析和丰生强的Android软件安全与逆向分析后, 准备分享下这方面知识. 在写文章时发现, 这两本书缺少对最新的逆向工具和加固工具的描述. 在查阅相关文献后补充了这一部分.

    本文从五个维度来讲解Android逆向, 每个维度尽量分’原理’, ‘工具’, ‘实例’三个方面.

    • 反编译

    • 静态分析

    • 动态分析

    • 重编译

    • Docker

    1.反编译

    1.1 原理

    Android App正向编译

    说到反编译, 先来看下正向编译, 如上图, 正向编译是

    java -> class -> dex -> apk

    反编译和正向编译稍有不同, 反编译可以分成两类:

    java <- smali <- dex <- apk

    这种方法是将dex文件转为smali, smali是Dalvik虚拟机的汇编语言, 可以用来动态调试程序.

    java <- class/jar <- dex <- apk

    这种方法中是将Dalvik字节码转化为等价的Java字节码, 然后用丰富的java分析工具分析源码.

    如何反反编译(即对抗反编译):

    • 阅读反编译工具源码查找缺陷

    • 压力测试找反编译工具bug(下载很多apk, 写个脚本调用ApkTool反编译这些apk, ApkTool因为某些bug无法反编译某个apk, 这时我们就通过压力测试找到了ApkTool的bug, 将发现的这个应用到我们的apk中, 即可保护我们的apk免受ApkTool反编译)

    如何反反反编译呢:

    • 阅读反编译源码修复缺陷

    1.2 工具

    反编译工具-dex-class

    上图的反编译工具走的java <- class/jar <- dex <- apk路线, 即先把apk里的dex找到, 然后使用Enjarify/dex2jar/classyshark/jadx反编译得到jar包, 然后使用jd-gui/CFR/Procyon阅读jar包里的java源码. 这些工具各有优缺点, 我们一般选择dex2jar+jd-gui, 相比其他工具, jd-gui虽然很久不更新了, 但是支持跳转, 方便查看代码. 特别说明下Bytecode-Viewer, 其是Procyon的一个前端, 同时集成了很多其他工具, 功能强大.

    反编译工具-dex-smali

    看下上图, 这些工具走的是java <- class/jar <- dex <- apk路线. 将dex文件转化为smali汇编, 然后直接阅读smali汇编语言, 或者smali再转为java(这里没有强大的工具, 可能经常无法成功转化).

    最常用反编译工具

    从上图可以看到有很多反编译工具, 我们平时最常用的是dex2jar+jd-guiApkTool.

    jd-gui不仅有不错的界面, 最关键的是支持类之间的跳转, 在混淆后的代码中跳转可以大大方便我们查看.

    ApkTool隐隐有无冕之王的声势, 可以反编译代码和资源, 修改后可以重编译成apk, 在Android Studio下使用smalidea插件还可以完成无源码调试, 十分强大.

    工具地址:

    https://github.com/Storyyeller/enjarify

    https://github.com/pxb1988/dex2jar

    https://github.com/google/android-classyshark

    https://github.com/skylot/jadx

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

    http://www.benf.org/other/cfr/

    https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler

    https://github.com/Konloch/bytecode-viewer

    https://github.com/deathmarine/Luyten

    http://www.secureteam.net/d4j

    https://github.com/iBotPeaches/Apktool

    https://github.com/demitsuri/smali2java

    https://www.pnfsoftware.com/

    1.3 实例

    这里以一个实例说明下反反编译和反反反编译:

    使用早期ApkTool反编译apk时,可能会遇到反编译失败, 出现如下问题:

    Exception in thread "main" brut.androlib.AndrolibException: Multiple res specs: attr/name
    at brut.androlib.res.data.ResTypeSpec.addResSpec(ResTypeSpec.java:78)
    at brut.androlib.res.decoder.ARSCDecoder.readEntry(ARSCDecoder.java:248)
    at brut.androlib.res.decoder.ARSCDecoder.readTableType(ARSCDecoder.java:212)
    at brut.androlib.res.decoder.ARSCDecoder.readTableTypeSpec(ARSCDecoder.java:154)
    at brut.androlib.res.decoder.ARSCDecoder.readTablePackage(ARSCDecoder.java:116)
    at brut.androlib.res.decoder.ARSCDecoder.readTableHeader(ARSCDecoder.java:78)
    at brut.androlib.res.decoder.ARSCDecoder.decode(ARSCDecoder.java:47)
    at brut.androlib.res.AndrolibResources.getResPackagesFromApk(AndrolibResources.java:544)
    at brut.androlib.res.AndrolibResources.loadMainPkg(AndrolibResources.java:63)
    at brut.androlib.res.AndrolibResources.getResTable(AndrolibResources.java:55)
    at brut.androlib.Androlib.getResTable(Androlib.java:66)
    at brut.androlib.ApkDecoder.setTargetSdkVersion(ApkDecoder.java:198)
    at brut.androlib.ApkDecoder.decode(ApkDecoder.java:96)
    at brut.apktool.Main.cmdDecode(Main.java:165)
    at brut.apktool.Main.main(Main.java:81)

    查看ApkTool代码发现, 是Apk利用了ApkTool的一个bug, Apk做了混淆,在编译时存入了重复id值,导致ApkTool crash.

    针对这个问题, 解决办法是create fake names to prevent abuse from duplicate key
    names
    , 其github提交如下:

    create fake names to prevent abuse from duplicate key names

    实例地址:

    https://github.com/iBotPeaches/Apktool/commit/567907b187ad2f78b3564d0a0405e3b207832e17

    2.静态分析

    2.1 原理

    什么是静态分析?

    不运行代码,采用反编译工具生成程序的反编译代码,然后阅读反编译代码来掌握程序功能.

    Android静态分析步骤:

    • 反编译apk程序

    • 查看Application类(在Activity启动之前, 一般加固/授权放在这里)

    • 查看MainActivity类

    • 找关键代码

    反静态分析:

    • 代码混淆(ProGuard等)

    • 使用NDK+STL编写

    • 手动注册native函数()

      • 默认情况, 使用javah, com.example.k12 -> java_完整包名类名方法名.
        但可以使用函数映射表 static JNINativeMethod methods[] = {
        {"dynamicGenerateKey", "(Ljava/lang/String;)Ljava/lang/String;", (void
        *) native_dynamic_key}}; RegisterNatives(jclass clazz, const
        JNINativeMethod* methods,jint nMethods)
        来注册native函数名,
        提高破解难度.
    • 加固(dex/so加壳,指令抽取等)

    反反静态分析:

    • 定位关键代码技巧

      • 信息反馈法(点击界面, 出现注册失败, 那么检查代码里哪里使用到了注册失败)

      • 特征函数法/关键系统调用(一般情况下, 最终都会调用到系统函数. 为了提升难度, 可以自制和系统函数功能相同的函数, 这样难以下断点)

      • Log代码注入法/栈跟踪法(动静分析结合, 在合适位置注入log, 编译运行时可以打印当前上下文信息和堆栈信息)

    • IDA分析汇编(asm->c, 虽然很多函数还没重定位, 但是c比汇编的表达力更强, 更便于分析)

    • 脱壳

      • IDA脱壳(dvm:dvmDexFileOpenPartial, art:openDexFileNative, 无论如何, 最终都是要调用系统API加载dex, 在这里加断点, 然后dump出内存中的dex文件[现在一些加固工具都是自己写加载dex的函数, 这样简单在上述方法上加断点是无法命中的])

      • Xposed/VirtualXposed

    Dex文件格式

    这里不详细介绍,
    感兴趣参考”https://blog.csdn.net/jiangwei0910410003/article/details/50668549

    Dalvik指令集

    空指令 寄存器数据操作指令 返回指令 数据定义指令 锁指令 实例操作指令

    数组/字段操作指令 异常指令 跳转指令 比较指令 方法调用指令 数据转换指令

    数据运算指令

    .field private isFlag:z  定义变量

    .method  方法

    .parameter  方法参数

    .prologue  方法开始

    .line 12  此方法位于第12行

    return-void  函数返回void

    .end method  函数结束

    new-instance  创建实例

    iput-object  对象赋值

    iget-object  调用对象

    invoke-static  调用静态函数条件跳转分支:

    invoke-super  调用父函数

    invoke-direct  调用函数

    “if-eq vA, vB, :cond_**” 如果vA等于vB则跳转到:cond_**
    “if-ne vA, vB, :cond_**” 如果vA不等于vB则跳转到:cond_**
    “if-lt vA, vB, :cond_**” 如果vA小于vB则跳转到:cond_**
    “if-ge vA, vB, :cond_**” 如果vA大于等于vB则跳转到:cond_**
    “if-gt vA, vB, :cond_**” 如果vA大于vB则跳转到:cond_**
    “if-le vA, vB, :cond_**” 如果vA小于等于vB则跳转到:cond_**
    “if-eqz vA, :cond_**” 如果vA等于0则跳转到:cond_**
    “if-nez vA, :cond_**” 如果vA不等于0则跳转到:cond_**
    “if-ltz vA, :cond_**” 如果vA小于0则跳转到:cond_**
    “if-gez vA, :cond_**” 如果vA大于等于0则跳转到:cond_**
    “if-gtz vA, :cond_**” 如果vA大于0则跳转到:cond_**
    “if-lez vA, :cond_**” 如果vA小于等于0则跳转到:cond_**

    这里主要关注跳转指令, 因为我们逆向Apk时, 一般只关注特殊的几点逻辑,
    注意跳转语句跳转到了哪些特殊函数.

    ELF文件格式和寻址方式

    这里不详细介绍,
    感兴趣的同学可以参考”https://blog.csdn.net/jiangwei0910410003/article/details/49336613

    Arm汇编语法

    跳转指令 存储器访问指令 数据处理指令(加减乘除)

    空操作 软中断

    arm汇编里我们主要关注如下函数调用语句:

    BL 执行函数调用

    BLX执行函数调用, 可以在ARM和Thumb指令集间切换

    这里解释下ARM和Thumb指令集的区别:

    Thumb是ARM体系结构中一种指令集。

    Thumb指令只有16bit,可以减小代码量。

    Thumb指令功能并不完整,必要时仍需要使用ARM指令集。

    扩展下NEON/VFP知识点:

    VFP是一种浮点硬件加速器。

    NEON是一个SIMD(单指令多数据)协处理器。

    以加法指令为例,单指令单数据(SISD)的CPU对加法指令译码后,执行部件先访问内存,取得第一个操作数;之后再一次访问内存,取得第二个操作数;随后才能进行求和运算。而在SIMD型的CPU中,指令译码后几个执行部件同时访问内存,一次性获得所有操作数进行运算。这个特点使SIMD特别适合于多媒体应用等数据密集型运算。

    加固技术:

    第一代加固技术——混淆技术;

    第二代加固技术——加壳技术(落地与不落地脱壳);

    第三代加固技术——指令抽离;

    第四代加固技术——指令转换,即VMP(虚拟软件保护)加固技术。

    二代加固:

    加壳是指给可执行文件加个外衣, 这个外衣就是壳程序. 壳程序先取得程序的控制权, 之后把加密的可执行程序在内存中解开为真正的程序并运行.

    可执行文件加固示意图

    三代加固:

    抽取dex文件中DexCode的部分结构,即虚拟机操作码。在虚拟机加载到此类的时候对DexCode结构进行还原。

    指令抽取-未抽取时

    比如此图中的getPwd方法很重要,需要抽取. 那么生成Dex文件后, 找到Dex文件中的getPwd的方法体, 将对应的方法体抽取出来放到so文件或者特定位置. 然后Hook住系统的FindClass方法, 当系统查找CoreUtils类时, 找到getPwd在内存中的位置, 然后将抽取出来的方法重新写入. 这样即使被破解拿到Dex, 这个Dex也是残缺的, 没有关键的函数.这时候如果我们查看Dex, 会发现getPwd的方法是个空方法.

    指令抽取-抽取完成

    指令抽取-hook-findClass

    该方法的流程如下:

    指令抽取流程

    四代加固VMP技术:

    基于三代加固技术,把原本可执行文件中的机器指令代码转换成了它自己虚拟机的指令,而且还插入了大量的垃圾代码。

    这种方法将核心代码转化为虚拟机自己的指令, 破解apk的难度和破解虚拟机指令的难度一致. PC上存在类似的VMProtect, 号称无人一定能破.

    VMP加固原理

    从难度方面来说, 二代加固一般还有破解思路, 但到了四代加固这里, 一般的逆向脱壳技术全部失效, 你面对的是如何破解这个虚拟机.


    https://blog.csdn.net/jiangwei0910410003/article/details/78070610

    https://www.leiphone.com/news/201712/TABfBNU8x0lZIPoT.html

    https://bbs.pediy.com/thread-224921.htm

    2.2 实例

    apk加壳实例:

    apk加壳示例

    apk加壳实例可以用上图来说明, 我们把要加固的myapk.apk放到一个dex尾部. 这个dex有脱壳逻辑, 程序运行时, 首先运行这个脱壳dex, 脱壳dex从dex尾部获取到要加密的apk的大小, 然后从自己的dex中拷贝出这个myapk.apk, 最后调用Android系统API运行myapk.apk. 这样就算用ApkTool等逆向工具, 也无法直接获得我们加固的myapk.apk. 为了增大逆向难度, 我们可以把脱壳逻辑用c实现放到so文件中, 同时把加密的myapk.apk分段放到so文件中. 为了防止特征破解, 我们可以改写apk魔数. 这样下来, 一个简单的加固工具就完成了.

    这里提供一个demo, 只有最简单的把myapk.apk放到脱壳dex尾部的功能, git地址:

    https://github.com/oncealong/apk_dex_shell

    demo分为三个项目:

    • DexReinforcingTools

      • 给Apk加壳的工具, 可以用java或者cpp或者任何其他语言写成.
    • MyApk

      • 需要加固的Apk
    • ShellingMyApk

      • 脱壳Apk, 实际安装到用户手机上的是该Apk, 其在Application的attachBaseContext 时会解压得到实际的apk文件, 然后运行实际的Apk.

    这里再说下, 这种二代加壳是现在最简单的加壳方式, 也是最基本的加壳方式.

    参考文档:

    https://blog.csdn.net/jiangwei0910410003/article/details/48415225

    3.动态分析

    3.1 原理

    动态分析主要基于下面两个工具:

    JPDA(Java Platform Debugger Architecture)

    JPDA原理图

    JPDA分为三层, 分别是JVMTI,JDWP,JDI.

    JVMTI(Java Virtual Machine Tool Interface)是一套由虚拟机直接提供的 native接口,通过这些接口,开发人员不仅调试在该虚拟机上运行的 Java程序,还能查看它们运行的状态,设置回调函数,控制某些环境变量,从而优化程序性能。

    JDWP(Java Debug Wire Protocol)是一个为 Java调试而设计的一个通讯交互协议,它定义了调试器和被调试程序之间传递的信息的格式。

    JDI(Java Debug Interface)提供 Java API 来远程控制被调试虚拟机

    JPDA-JVM

    Android调试模型是一种JPDA框架的具体实现

    有两点主要区别:

    • JVM TI适配了Android设备特有的Dalvik虚拟机/ART虚拟机

    • JDWP的实现支持ADB和Socket两种通信方式

    JPDA-Android

    ptrace(process trace)

    ptrace原理

    ptrace()
    提供了跟踪和调试的功能。它允许一个进程(跟踪进程tracer)去控制另外一个进程(被跟踪进程tracee)。

    tracer可以观察和控制tracee的运行,可以查看和改变tracee的内存和寄存器。它主要用来实现断点调试和系统调用跟踪。

    tracer流程一般如下:

    tracer流程图

    其中PTRACE_ATTACH/PTRACE_GETREGS/PTRACE_POKETEXT/PTRACE_SETREGS/PTRACE_DETACH定义如下:

    PTRACE_ATTACH,表示附加到指定远程进程;

    PTRACE_DETACH,表示从指定远程进程分离

    PTRACE_GETREGS,表示读取远程进程当前寄存器环境

    PTRACE_SETREGS,表示设置远程进程的寄存器环境

    PTRACE_CONT,表示使远程进程继续运行

    PTRACE_PEEKTEXT,从远程进程指定内存地址读取一个word大小的数据

    PTRACE_POKETEXT,往远程进程指定内存地址写入一个word大小的数据

    ptrace是*nix系统上最常用的系统调用之一, 常见的gdb调试也是通过它实现的.

    gdb流程图

    检测ptrace

    当我们使用ptrace方式跟踪一个进程时,目标进程会记录自己被谁跟踪,可以查看/proc/pid/status来确认. 所以apk里为了防止被逆向, 一般都会新开一个线程, 对status做检测, 如果TracerPid不为0, 立刻退出apk.

    /proc/pid/status

    正常情况

    被ptrace时的status状态

    被ptrace时

    反动态分析:

    • 检查是否有调试

      • Debug.isDebuggerConnected();

      • 针对ptrace, 检查TracerPid是否为0

    • 检测是否在模拟器

      • getprop不同(虚拟机和真机的环境变量不同,
        比如虚拟机的ro.kernel.qemu=1而真机没有这个属性)

    反反动态分析:

    • 对抗反调试

      • java层:smali代码注释掉

      • native层 (nop掉so文件或内存中指令, 断点fopen/fget并修改内存)

    Android程序是否可调试:

    Android程序是否可调试

    开启调试:

    1.下载mprop, 注入init进程, 修改内存中属性值

    ./mprop ro.debuggable 1

    2.重启adbd

    stop;start

    tip:

    说到android:debuggable这个属性, 想到另一个属性android:allowBackup.
    android:allowBackup默认为true, 一定要显式设置android:allowBackup=false.
    否则adb backup/adb restore备份恢复数据
    微信6.0以前未设置此属性,可以备份恢复数据

    参考地址:

    https://tech.meituan.com/android-remote-debug.html

    http://burningcodes.net/%E7%90%86%E8%A7%A3ptrace%E8%B0%83%E8%AF%95%E5%8F%8A%E5%8F%8D%E8%B0%83%E8%AF%95/

    https://ops.tips/gists/using-c-to-inspect-linux-syscalls/

    https://www.nevermoe.com/?p=854

    https://github.com/wpvsyou/mprop

    3.2 工具

    动态分析工具

    这里特别推荐下VirtualXposed, 其基于VirtualApp和epic, 将Xposed安装到VirtualApp中, 可以不用root权限就使用Xposed, 而且安装插件后重启极快.

    Frida是一个DBI工具, 使用其进行动态分析时, 被分析进程的TracerPid仍为0. 下图是Frida原理, 其最初建立连接时通过ptrace向相关进程注入代码, 其后使用其特有的通道来通信, 如下图. Frida-Gadget支持Android下非root和iOS下非越狱的逆向.

    Frida原理

    IDA家喻户晓, 其支持dex和so的动态分析, 尤其是asm->c的转化, 可以大大方便分析.

    radare是一个比IDA还要强大的工具, 其起源是调查取证, 不过目前支持数不胜数的功能. 但是其学习曲线比Vim还要陡峭

    工具地址:

    https://forum.xda-developers.com/showthread.php?t=3034811

    https://github.com/android-hacker/VirtualXposed

    https://github.com/frida/frida

    https://www.hex-rays.com/products/ida/

    https://github.com/radare/radare2

    http://rada.re/r/cmp.html

    https://www.megabeets.net/a-journey-into-radare-2-part-1/

    3.3 实例

    无源码动态调试smali代码

    可以将apk用ApkTool反编译后, 使用AndroidStudio+smalidea插件来调试apk.

    这里来张图感受下无源码调试的强大.

    AndroidStudio+smalidea无源码调试

    分享一个小tip, 如何让程序暂停在启动界面.
    因为反逆向代码一般在Application的onCreate或更早就执行, 如果等到程序运行到MainActivity再attach进程, 时机就太晚了.

    可以用如下命令让app停在等待debug界面:

    等待debug一次: adb shell am set-debug-app -w com.oncealong.sample

    一次debug不一定能解决问题,多次调试则在所难免,如果每次调试都执行上述语句, 稍显啰嗦, 那么此时可以执行下述语句:

    一直等待debug: adb shell am set-debug-app -w --persistent com.oncealong.sample

    待debug完毕, 使用下述语句取消打开app时的等待.

    取消等待debug: adb shell am clear-debug-app

    这里的示例不在展开, 只说明这种方法和其效果, 对其感兴趣可以看下述链接.

    参考地址:

    http://www.cnblogs.com/goodhacker/p/5592313.html

    https://droidyue.com/blog/2017/05/14/a-little-but-useful-debug-skill_for_android/

    IDA动态调试

    IDA动态调试可以获得内存中的信息, 比如在dvmDexFileOpenPartial函数上加断点, 然后执行IDA脚本直接把内存中的dex拷贝出来以脱壳. 详情见Android应用安全防护和逆向分析相关章节. 这里也不做详细介绍,
    只用下图展示IDA的强大.

    IDA动态调试

    参考地址:

    https://blog.csdn.net/jltxgcy/article/details/50600241

    https://blog.csdn.net/qq1084283172/article/details/46872937

    VirtualXposed hook java

    VirtualXposed可以hook java, 相比Xposed安装插件需要重启手机, VirtualXposed只用重启下Xposed程序, 如果前者重启手机耗时1min, 后者重启Xposed程序只用1s不到. 对于一些简单的hook或者逆向, 或者验证Xposed插件逻辑, 这里强烈推荐VirtualXposed. 不过Xposed只支持hook java层, 如果需要hook native层, 可以使用下一个工具Frida.

    VirtualXposed hook 构造函数

    VirtualXposed hook 方法

    参考地址:

    https://github.com/android-hacker/VirtualXposed

    https://github.com/ac-pm/Inspeckage

    http://www.cnblogs.com/lkislam/p/4859959.html

    Frida

    Frida支持java/native层的hook. 而且Frida支持脚本, 这样可以更方便的复现结果.

    比如Frida的这个Android示例. 将下面的代码放到一个py脚本中, 随时运行都可以获得结果. 不像IDA还需要恢复现场.

    Frida-hook

    参考地址:

    https://github.com/frida/frida/releases

    https://github.com/dweinstein/awesome-Frida

    https://www.anquanke.com/post/id/85758

    https://www.anquanke.com/post/id/85759

    https://koz.io/using-frida-on-android-without-root/

    https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool

    http://blog.mengy.org/how-valgrind-work/

    http://www.ninoishere.com/frida-learn-by-example/

    https://www.frida.re/docs/presentations/osdc-2015-the-engineering-behind-the-reverse-engineering.pdf

    http://dogewatch.github.io/2017/05/15/Hook-Native-Function-Use-Frida/

    4.重编译

    4.1 原理

    反重编译:

    运行时检查签名(signatures比较长,hash后比较)

    运行时校验保护(校验classes.dex的md5)

    反反重编译:

    查关键函数, 注释掉或nop掉

    如果到这一步, 光靠本地的检测基本无效, 可以考虑在http请求时加入对apk签名的检查, 如果不合法就不返回数据. 但是这样无法阻止app被非法本地运行, 逆向者也可以通过抓包正常apk的请求来模拟正常请求. 不过这样可以进一步提高破解门槛.

    5.Docker


    5.1 原理

    与逆向工具高内聚,与外界系统低耦合

    在Linux下, Docker性能不错, 还可以使用VNC连接桌面.

    # pull image
    
    docker pull cryptax/android-re:latest
    
    # run locally interactive
    
    docker run -it --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix
    cryptax/android-re:latest /bin/bash
    
    # run through ssh or VNC
    
    docker run -d -p SSH_PORT:22 -p VNC_PORT:5900 cryptax/android-re
    
    ## sample: docker run -d --privileged -p 5900:5900 -p 5022:22
    cryptax/android-re
    
    ssh -X -p SSH_PORT root@127.0.0.1
    
    ## sample: ssh -p 5022 -X root@127.0.0.1 #password: rootpass
    
    vncviewer HOST::VNC_PORT
    
    ##vncviewer 127.0.0.1::5900

    工具地址:

    https://github.com/cryptax/androidre/

    展开全文
  • Android软件安全与逆向分析——读书笔记(一)所用到的相关开发工具
  • Android——Android逆向工具

    千次阅读 2022-02-13 22:00:56
    Androidkiller,Apktool,dex2jar,jd-gui,jadx-gui,JEB,Ul Automator Viewer

    Ⅰ、Androidkiller

    Android Killer是一款可以对APK进行反编译的工具,它能够对反编译后的Smali文件进行修改,并将修改后的文件进行打包
    apktool、dex2jar、jd-gui的集合体


    (注意:androidKiller版本可能太旧,导致反编译失败,需要下载版本更新补丁包或及时更新工具版本

    jdk1.8.0 + 已加补丁整合包下载路径
    链接:https://pan.baidu.com/s/1oIigQ5QEUnJag-AB0EE4dg
    提取码:59lw

    一、配置环境

    1. “AndroidKiller”的文件夹目录结构,如图1.1所示,双击打开“AndroidKiller.exe”文件,此时,会弹出一个窗口,提示没有Java SDK环境,直接点击OK进入AndroidKiller工具界面。
      在这里插入图片描述
    2. 选中“主页”菜单栏下的“配置”,选项点击“Java”图标配置JDK安装路径。点击编辑框右边的“文件夹”图标,找到之前安装的JDK目录,选择自己安装的jdk文件夹下的“bin”目录(找“bin”目录下的Java.exe文件),点击确定按钮
      在这里插入图片描述
      在这里插入图片描述

    二、反编译

    1. 将需要反编译的 apk 拖进 AndroidKiller 里,进行反编译(通过apk-tool、dex2jar
      当出现 APK 所有反编译工作全部完成!!!时,说明反编译成功

      以一款计算机app为例
      在这里插入图片描述

    2. 点开工程管理器,便会呈现apk的目录结构
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R3ajvSuW-1644761177838)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/72641b65-70af-4fed-bf41-89966394c07f/Untitled.png)]
      在这里插入图片描述
      对比得出以下结论:

      无 META-INF 文件的原因:对apk的反编译过程中,对apk的整体性造成破坏,apk的签名没有存在意义,所以在反编译时被处理掉

      AndroidManifest.xml 文件转换为 values 文件:AndroidManifest.xml 的反编译结果存放在了values开头的文件夹中,(对字符操作时,如汉化,需要修改values文件)

      classses.dex 文件反编译为 smali 代码文件

    3. 当点开文件会出现smali代码,点击上方Javalogo,会呈现Java源码(通过 jd-gui
      在这里插入图片描述
      在这里插入图片描述

    三、编译

    当对反编译的文件做完操作后,重编译、签名打包成apk,点击上方”Android“后,点击左上角“编译“
    当出现APK 所有编译工作全部完成!!!(包括编译与重签名) ,说明反编译成功
    在这里插入图片描述
    在这里插入图片描述

    四、运行

    1. 打开Android虚拟机或外挂Android手机或模拟器,点击AndroidKiller上方的”Android“,点击上方”刷新“,选中你的设备,这样电脑就和手机设备连接了( 通过adb ,注意统一adb版本)
      (如果是真机,则需要打开开发者模式,打开USB调试功能)
      在这里插入图片描述
      在这里插入图片描述
      AndroidKiller通过 adb 与手机设备连接
      在这里插入图片描述
      统一 adb 版本(版本不一样可能会造成冲突)

      在这里插入图片描述
    2. 点击安装,就能将程序安装到手机设备中
      在这里插入图片描述
      在这里插入图片描述
    3. 点击卸载,就能卸载(doge)
      在这里插入图片描述
      注意:重打包的软件不能和原来的在手机设备上共存(签名不一致,无法覆盖安装)
      AndroidKiller会显示Apk安装失败,需要先卸载原APP
      在这里插入图片描述

    五、其他

    1. 批量操作与调试
      在这里插入图片描述
    2. 类方法索引
      在这里插入图片描述
    3. 方法操作
      在这里插入图片描述
    4. 类操作
      在这里插入图片描述
    5. 自定义代码块一键插入
      在这里插入图片描述
    6. 关键字语法显示在这里插入图片描述
    7. Unicode转换
      在这里插入图片描述

    Ⅱ、Apktool

    1. 作用

      1. 用于反编译Android apk,可以将应用中的资源提取出来,也可以在修改资源文件后重新打包。
      2. smali 调试
      3. 主要查看res文件下xml文件、AndroidManifest.xml和图片。(注意:如果直接解压.apk文件,xml文件打开全部是乱码)
    2. 进行解包,获得smail码

      java -jar .\apktool的名字 d(反编译) .\要解包的apk -o(输出) 文件名
      

      在这里插入图片描述
      在这里插入图片描述

    3. 重新打包

       java -jar .\apktool的名字 b(打包) .\要打包的文件夹名字
      

      重新打包后的apk在要打包的文件夹里的dist目录下
      在这里插入图片描述

    Ⅲ、dex2jar(dex to jar)

    Android 中的一个反编译工具,它可以将 Android 程序安装包 Apk 文件中的 .dex 文件反编译成一个 .jar 文件,也可以将反编译后的 .jar 文件重新编译成 .dex 文件。


    1. 安装
      将下载的 dex2jar-2.0.zip 压缩文件直接解压到任意文件夹下。
      将 dex2jar-2.0 文件夹的路径配置到 PATH 环境变量中去。
      在命令行窗口输入 d2j-dex2jar 命令按回车键在这里插入图片描述
    2. dex2jar 反编译
      1. 将 Android Apk 文件后缀名 .apk 改成 .zip 文件并解压,获取到它的 .dex 文件(解压后有可能有多个 dex 文件),dex2jar 主要对 classes.dex 文件反编译。
        在这里插入图片描述
      2. 输入dex2jar 反编译命令
        • 第一种方法

          d2j-dex2jar < dexFilePath > -o < outputJarFilePath >
          

          dexFilePath: 要反编译的 .dex 文件的文件路径。
          outputJarFilePath: 反编译后输出的 .jar 文件的文件路径。
          在这里插入图片描述

        • 第二种方法
          将需要反编译的dex文件(这里是classes.dex)复制到 dex2jar 解压目录下。
          打开命令行进入 d2j-dex2jar.bat 文件所在目录,输入命令 .\d2j-dex2jar.bat classes.dex (.\当前目录 …\上一级目录)
          在这里插入图片描述

    3. dex2jar 重编译
      dex2jar 重编译命令:d2j-jar2dex < jarFilePath > -o < outputDexFilePath >
      jarFilePath: 要重新编译的 .jar 文件的文件路径。
      outputDexFilePath: 重编译后输出的 .dex 文件的文件路径。
      在这里插入图片描述

    Ⅳ、jd-gui

    将源代码转换成二进制执行代码的过程叫“编译”,那么反编译就是将二进制执行代码转换成源代码。
    在java开发里,源代码是.java文件,然后经过编译后生成计算机识别的.class文件,但是.class文件是计算机识别的我们一般看不明白,因此需要反编译变成我们能读懂的源码

    1. JD-GUI 是一个用 C++ 开发的 Java 反编译工具
      在这里插入图片描述
    2. 双击运行 jd-gui.exe 文件,将jar文件拖到工作区即可打开。
      在这里插入图片描述

    Ⅴ、jadx-gui

    jadx是一款反编译器,同时支持命令行和图形界面,能以最简便的方式完成apk的反编译操作。

    jadx 支持 Windows、Linux、 macOS,能够打开.apk, .dex, .jar,.zip等格式的文件


    1. 安装jadx
      链接:https://pan.baidu.com/s/1FXaqUEobcuunVeQA-aGJdw?pwd=1234
      提取码:1234
      然后将build/jadx/bin加入到环境变量。

    2. 使用jadx
      通用File - Open file选择文件或者直接将apk拖进窗口中,就可以查看某个 apk 的Java源码(自动分类源代码和资源文件)
      在这里插入图片描述
      用途:更直接地帮助分析代码

    Ⅵ、JEB

    JEB是一款为安全专业人士设计的功能强大的Android应用程序反编译工具。用于逆向工程或审计APK文件,可以提高效率,减少工程师的分析时间。JEB支持Windows, Linux和Mac OS


    1. 安装jeb

      链接:https://pan.baidu.com/s/1842GhhbKsk8WNaSiJMRVxw?pwd=1234
      提取码:1234

      下载完成后进行解压,解压完成后打开文件夹,运行安装目录下的.bat后缀的文件,等待一会就会出现jeb面板,这就说明我们的jeb工具能成功打开了。
      在这里插入图片描述
      如果cmd窗口显示一个检查更新出错,直接无视就可以了。

      如果没有出现JEB面板,检查一下JDK环境是否配置了“JAVA_HOME”。如果已经配置,就要检查配置的路径是否正确以及检查jdk版本是否过高。

    2. 菜单栏使用

      文件:文件的打开、导入、保存、另存为等操作。

      编辑栏:文件的复制粘贴、搜索、语言设置、style设置字体、选项设置等操作。

      行为栏:包含了快捷键操作:①Q:转换成伪代码 ② /:添加注释 ③ N:重命名 ④ Delete:删除

      窗口:窗口显示的相关设置,使用默认即可。

      帮助:官方的相关信息。
      在这里插入图片描述

    3. 使用JEB反编译
      将APK安装包拖进主界面即自动反编译,结构如下图,如果有外部引用还会有Libraries文件夹。
      在这里插入图片描述
      在这里插入图片描述

    Ⅶ、Ul Automator Viewer

    链接:https://pan.baidu.com/s/1nkZ32sK3IlanhTEAz21qjA?pwd=1234
    提取码:1234
    点击uiautomaatorviewer.bat,点击后会出现一个console黑窗口,使用时不要关掉。
    在这里插入图片描述
    打开APP,在 Ul Automator Viewer 点击 Device Screenshot
    在这里插入图片描述

    展开全文
  • 学习安卓逆向分析的一个小菜鸟,记录分析的“快乐时光”,小白图个乐,大佬乎喷 分析的APP 泡泡手游 包名:com.zqhy.xiaomashouyou 版本号:8.3.7 最小安装版本:Android 5.0 (LOLLIPOP) 抓包分析 1...
  • 一、Android 逆向方法、 1、静态逆向解析、 2、函数调用分析、 3、动态运行跟踪、 4、运行日志分析、 5、文件格式解析、 6、敏感信息分析、 7、网络信息监控、 8、软件动态调试、 9、环境伪装模拟
  • android逆向必备工具

    2022-06-23 00:59:04
    Android 逆向用途 :软件防护 : 根据逆向的方法针对性的开发防护策略 ;算法研究 : 在没有源码的前提下 , 通过反编译 , 反汇编 , 拿到 Smali 代码 , 研究其产品的算法 , 实现途径 ;接口分析 : 接入一个没有源码的第三...
  • Android逆向分析基础
  • 学习安卓逆向分析的一个小菜鸟,记录分析的“快乐时光”,小白图个乐,大佬乎喷 分析的APP 酷乐潮玩 包名:com.klcw.app.member 版本号:2.9.15 最低安装版本:Android 5.0 (LOLLIPOP) 抓包分析 APP安装到...
  • 原文链接 Android逆向分析工具总结 如果对文章感兴趣,可以扫一扫微信二维码关注作者的微信公众号,后续会推送更多干货文章,感谢您的支持。
  • 一、Android 逆向用途、 二、Android 逆向原理
  • 精品 Android 逆向分析案例某地图的定 位请求分析 微信 里面有个附近的人相信大家都知道大概的原理就是调用腾讯地图的 sdk 进行定位然后把个 人的定位信息发到微信服务器上进行处理再把一定范围内的人的信息返回并用...
  • Android逆向分析中有很多逆向分析的工具是用java语言写的,所以安装JDK是必不可少的。 JDK下载安装 1.可以google(baidu)下载JDK的源程序,根据自己电脑的版本来。 2.安装(记录下安装路径,环境变量配置的...
  • 安卓逆向分析步骤总结

    千次阅读 多人点赞 2020-09-03 16:30:50
    安卓逆向说好听一点叫逆向分析学习技术,说不好听就叫破解App了。但是,技术这个东西本身不分好坏,只是看你学会它之后用在哪些方面了。这篇博客用于总结我对安卓逆向分析的学习理解,主要以分析的步骤来表现,当然...
  • 学习安卓逆向分析的一个小菜鸟,记录分析的“快乐时光”,小白图个乐,大佬乎喷 分析的APP 英语配音狂 包名:com.zhuoyue.peiyinkuang 版本号:5.2.5 模拟器安装最低版本:Android 4.4 (KITKAT) 抓包分析 ...
  • AndroidAPK逆向分析

    2022-06-24 19:56:13
    APK是Android Package的缩写,即Android安装包(APK)。APK是类似Symbian Sis或Sisx的文件格式。通过将APK文件直接传到Android模拟器或Android手机中执行即可安装。APK文件和sis一样,把android sdk编译的工程打包成一...
  • Android逆向基础入门

    千次阅读 多人点赞 2022-01-14 22:16:08
    目录一、基础App数据抓取1、App抓包知识了解二、Android_apk逆向1、Android逆向名称2、jadx反编译工具3、JEB反编译工具 一、基础App数据抓取 1、App抓包知识了解 常用的拦截抓包工具有Charles、Fiddler、mitmproxy...
  • apktool.jar/apktool.bat(用于逆向apk文件,使用前需要先安装JAVA8以上版本) dex2jar.sh/dex2jar.bat (用于将dex文件转为jar文件) jd-gui工具 (可用于逆向.class以及.jar文件,得到可读的JAVA代码) 这里,我们用...
  • 斗哥这期将给大家带来Android逆向的动态分析,主要简述了Android动态分析环境配置与IDA调试so文件。学习Android逆向动态分析前,一定要有基础环境支持,比如sdk、jdk等,所以在动态分析前先要进行一波基础配置。0X01...
  • 目录 Dalvik 虚拟机 •Dalvik 虚拟机介绍 •Dalvik汇编语言基础 •Dalvik版本HellWorld •破解第一个程序 Dex和ODex文件格式 •Dex文件结构解析 •ODex文件结构解析 •另类APK破解方法 Smali文件格式 ...
  • android 逆向分析

    2017-07-08 00:03:58
    本文转自http://blog.csdn.net/tencent_bugly/article/details/51424209 Bugly干货分享】手把手教你逆向分析 Android 程序
  • Android逆向分析工具

    2016-01-15 09:41:23
    Android逆向分析工具,最新版,好用!
  • Android逆向基础篇 1、工具认识 adb Android和模拟器连接工具 drozer 测试工具 jd-gui dex文件反编译后查看工具 ApkIDE apk反编译工具 2、逆向分析——apk安全测试 (1)adb连接安卓设备介绍 (2)APK是...
  • android逆向分析之反编译

    千次阅读 2016-10-19 22:13:46
    提到逆向工程,首先就要提到反编译,对于反编译,现在工具还是比较多的,市面上广泛应用的三神器(apktool、dex2jar、jdgui),本篇主要围绕着三神器展开,后面还会阐述smali和使用smali2java。我是通过这三神器入门的...
  • 学习安卓逆向分析的一个小菜鸟,记录分析的“快乐时光”,小白图个乐,大佬乎喷 分析的APP 铁甲 包名:com.cehome.cehomebbs 版本号:4.1.1.0 最低版本使用:Android 4.4 (KITKAT) 抓包分析 把APP安装到...
  • Android逆向分析实例(三)-解密微信EnMicroMsg.db数据库

    千次阅读 热门讨论 2021-04-30 16:08:53
    首先介绍下EnMicroMsg.db数据库:这个数据库是存放在Android手机本地的用来保存微信聊天记录的一个数据库,是一个Sqlite数据库,且手机必须要有root权限才能获取到,而且是被加密过的,必须先找到密钥才能打开。...
  • 获取APP中SO文件的基址 0、准备工作 电脑: Window10 手机: AndroidPhone Redmi Note 4x Version7.0 Root 环境: Java 1.8.0_121、ADB、Python、Frida 调试: IDA V6.8 ...1.2 在手机上运行该AP...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,352
精华内容 5,340
关键字:

android逆向分析