zoukankan      html  css  js  c++  java
  • 动态调试smali代码学习记录

    预备知识

    DDMS

    Dalvik Debug Monitor Serivce,Dalvik调试监控服务,为Android SDK提供的一款拥有监控Dalvik虚拟机的调试软件,启动文件位于<Andorid SDK>/tools/monitor.bat(低版本的SDK为ddms.bat)

       

    adb forward命令

    用于创建一个端口映射,将本地端口(PC端口)映射到远程端口(手机端口),例如:

    adb forward tcp:8001 tcp:8002

    之后PC端访问8001端口的数据包,会自动转发到手机的8002端口。

       

    adb还提供了reverse命令,操作与forward相反,将远程端口(手机端口)映射到本地端口(PC端口),例如:

    adb reverser tcp:8001 tcp:8002

    之后手段端访问8001端口的数据包,会自动转发到电脑的8002端口。

    其他带参命令可以参考adb的帮助文档:

       

    JDWP

    Java Debug Wire Protocol,Java调试线程协议,定义了调试器(debugger)和被调试的 Java 虚拟机(target vm)之间的通信协议。详细请参考:

    https://www.ibm.com/developerworks/cn/java/j-lo-jpda3/

       

    Dalvik虚拟机会启动一个JDWP线程,用于远程调试。远程调试器可以通过JDWP端口号,调试指定进程。每个可调试的进程的PID就是其JDWP的端口号。可以使用adb jdwp命令查看所有可以调试的进程PID(需要使用ctrl + c退出)。

       

    动态调试Smali代码

    参考作者的说明:

    https://github.com/JesusFreke/smali/wiki/smalidea

       

    本次调试在Windows 10 + AS 3.2.1下完成。

       

    1. 使用Baksmali或apktool反编译apk文件,得到Smali代码。如果需要重新打包apk,推荐使用apktool。以下默认采用apktool。
    2. 把反汇编结果,在AS中当成现有工程打开。工程目录如下:

         

    3. 将smail文件夹标记为"Source Root"

         

      这里简单补充下,阅读代码的小技巧。

      .method字段,使用"Find Usage"功能,可以定位该方法的所有调用者。

         

      在方法类型上,使用"Declaration",可以定位方法的定义处。

         

    4. 创建一个远程调试的配置:

         

      点击"+",新建一个配置,选择"Remote"模板,配置名可以任意命名,这里取名为SmaliDebug。

         

      端口号可以任意指定,只要不被其他进程占用,通常使用8700(DDMS使用的调试端口号)。

         

    5. 确认调试apk的AndroidManifest.xml文件中,<application>标签的android:debuggable属性为true:

         

      如果没有,请自行补充,再使用apktool打包签名。

         

    6. 安装并启动应用,PC端使用adb jdwp命令查看目标进程的PID(最后一个),需要使用ctrl + c结束该命令。

      之后使用以下命令,绑定远程调试端口:

    adb forward tcp:8700 jdwp:<PID>

    TCP的端口号,是刚刚配置远程调试配置时填写的。<PID>是刚刚查询的结果。

       

    或者通过以下命令,也可以获取调试进程的PID:

    adb shell ps | findstr "<packageName>"

    <packageName>是apk的包名,命令结果的第二列就是进程的PID。

       

    1. 在目标代码下断点:

         

      启动调试:

         

      手机端操作app,触发断点:

      之后调试步骤,与正常调试一样。

      release编译的apk,抹除了参数名和局部变量名,需要手动添加watch变量,watch寄存器查看。

      (应该是插件的bug,导致p寄存器(入参寄存器)值显示不正常)

         

    2. 如果调试过程中,修改了代码。需要使用apktool重新打包,重新安装。之后重复6步骤,开始调试。
    3. 调试结束后,建议使用adb forward --remove-all命令,清理端口绑定。

       

    如果你在Linux调试,作者给出了一条命令,可以在启动app后,一步完成端口绑定:

    adb forward tcp:8700 jdwp:$(timeout 0.5 adb jdwp | tail -n 1)

    解释下这条命令:

    $()会执行括号内的命令,将命令的运行结果作为值。

    timeout命令会执行一个子命令,如果子命令没有在规定时间内(这里是0.5秒)完成,直接杀死。

    tail -n 1,输出输入内容的最后一行,这里通过管道,将jdwp作为输入。

    合起来,"$(timeout 0.5 adb jdwp | tail -n 1)"就是adb jdwp输出的最后一行,并自动结束jdwp命令。

  • 相关阅读:
    python中的system函数与编码
    使用signal、setjmp、longjmp进行Linux/Android C异常处理
    ffffffuzzzzzzzzzzzzing
    EIGRP汇总
    JDK
    世界上最健康的生活方式
    Oracle 取两个表中数据的交集并集差异集合
    信息科技风险管理
    BPDU与PortFast
    大胆发言
  • 原文地址:https://www.cnblogs.com/foundkey/p/10256984.html
Copyright © 2011-2022 走看看