安卓动态调试——apk加上动态可调试属性


刷了一下2024xyctf的DebugMe题目,记一下这次动态调试过程。


用jeb打开后看到有调试检查,再根据题目提示为动态调试。知道需要进行动调。

先用雷电模拟器在程序里面运行这个程序,接着用adb测试远程连接:输入adb devices。如图显示就算端口连接好了。

adb devices -l查看连接的设备

adb shell ps查看线程状态

然后才能在jeb里面点击调试器或者甲虫下图标进行动态调试,不然会显示调试的目标不存在。

有可以连接的设备

点击attach附上。

报错

提示程序不可调试nondebuggable。

提示无法attach上。

一、用Android Killer编译的方法修改apk为可调式

  1. 用Android Killer打开apk,可以解包这个程序。

  1. 点开AndroidMainfest.xml,在<application那一行后面加上android:debuggable=”true”这个属性(记得要ctrl+s保存)。

    原本的样子

    更改后的样子

  2. 把编译先设置成AndroidKiller选项,然后进行编译。会生成编译后可调试的apk(如果有报错根据提示修改)。

    在Android Killer工具中,“default”“AndroidKiller” 是两种不同的编译配置选项,它们的核心区别在于 签名配置编译参数。以下是具体分析:

    1. 两者的核心区别

    配置项 default(默认配置) AndroidKiller(工具自定义配置)
    签名文件 通常使用空签名或无有效签名 预置工具自带的调试签名(如 debug.keystore
    签名对齐 可能未启用 zipalign 优化 默认启用 zipalign 对齐优化
    兼容性 可能因签名问题导致安装失败 针对重新打包场景优化,兼容性更好
    适用场景 临时测试或无需安装的场景(如静态分析) 需要重新打包并安装到设备的调试场景

    2. 如何选择?

    • 选择 AndroidKiller 配置的情况
      • 需要重新打包APK并安装到设备(尤其是非Root设备)。
      • 希望自动处理签名和对齐,避免手动操作。
      • 遇到安装失败问题时(如 INSTALL_PARSE_FAILED_NO_CERTIFICATES 错误)。
    • 选择 default 配置的情况
      • 仅需反编译查看代码/资源,无需重新安装。
      • 已手动配置签名文件(如自有证书)或有特殊编译需求。

    3. 验证配置差异的方法

    1. 检查签名配置
      • 在Android Killer中打开 配置签名配置,查看两种选项是否使用不同的 .keystore 文件。
      • AndroidKiller 使用 debug.keystoredefault 为空,则前者能生成有效签名的APK。
    2. 查看编译日志
      • 编译时观察日志中是否包含 zipalign 步骤。AndroidKiller 配置通常会自动对齐优化。
    3. 安装测试
      • 分别用两种配置编译APK,尝试安装到模拟器或真机。若 default 失败,说明其签名无效。

    4. 常见问题解决

    • 安装失败(签名错误)
      • 使用 AndroidKiller 配置(自带有效签名)。
      • 若仍需自定义签名,手动替换配置中的 .keystore 文件。
    • APK无法运行(对齐问题)
      • 确保启用 zipalign(在 AndroidKiller 配置中默认开启)。

    总结

    • 优先选择 AndroidKiller 配置:它能自动处理签名和对齐,适合大多数重新打包场景。
    • 仅在特殊需求时使用 default:如需自定义签名或调试未安装的APK逻辑。

    通过理解配置差异并针对性选择,可显著提高逆向工程和APK修改的效率。

  3. 最后用jeb再进行动态调试,发现可以附上了,click一下flag就出来了。

二、用apktool手动解包修改他的属性,再进行对齐签名的方法

参考自视频27分21秒开始

​ 参考自文章APK反编译、重打包、签名之apktool实现

  1. 把apk放到apk目录下面,并且在apktool目录下打开cmd输入apktool d DebugeMe.apk会将解包的数据输出在其目录下。

  2. AndroidMainfest.xmlapplication里面添加android:debuggable="true"属性

  3. 再输入apktool b DebugeMe进行打包,打包后在DebugeMe的dist目录下看到新的apk。

  4. 生成keystone:

    Keystore生成命令:

    1
    keytool -genkey -alias abc.keystore -keyalg RSA -validity 20000 -keystore abc.keystore

  5. 签名

    签名命令:

    1
    jarsigner -verbose -keystore abc.keystore -signedjar TestPrint_1.apk TestPrint.APK abc.keystore

    输入之前填写的密码

    此时,签名完毕,apktool文件夹下出现新的APK–>TestPrint_1.apk

    至此,apk反编译,修改文件,重打包,签名全部完成。

三、绕过apk不可调试的属性限制

  • 无需开启apk的可调试(debuggable)属性
  1. 打开Root权限adb调试的远程连接模式

  2. adb devices后,直接用jadx远程调试(点击甲虫图标)

  3. 直接click得到flag。

1. 原APK无法调试的原因

  • 默认不可调试属性:原APK可能在构建时未设置 android:debuggable="true",导致JEB/Jadx无法附加调试器(端口报错是典型表现)。
  • 调试依赖条件:正常调试需要APK的 AndroidManifest.xml 中明确声明可调试,否则ADB会拒绝连接。

2. 修改APK后安装失败的原因

  • 签名问题:修改APK后需重新签名。若未正确签名(如使用调试密钥对齐签名),雷电模拟器会拒绝安装。
  • Manifest格式错误:手动修改XML可能导致格式错误(如标签未闭合),引发解析失败。
  • 回编工具问题:使用apktool等工具解包/回编时,若版本不兼容或参数错误,可能导致APK损坏。

3. Root权限+远程ADB成功的原因

  • 绕过调试属性限制:Root权限允许通过系统级操作(如修改 ro.debuggable 属性)强制开启全局调试,此时无需APK自身可调试
  • ADB远程连接模式:远程连接可能绕过了本地ADB的某些限制,或直接以更高权限附加到进程(如通过ptrace)。
  • 原APK的漏洞利用:若APK本身存在逻辑漏洞(如硬编码密钥),Root后可直接提取内存数据或修改运行时行为,无需动态调试。

关键结论

  • Root权限的作用:开启Root后,可通过系统命令(如 setprop ro.debuggable 1)强制允许调试所有应用,此时原APK即使未标记为可调试也能被调试。
  • 修改APK的替代方案:直接使用Root权限调试,避免了因签名或打包错误导致安装失败的问题,是一种更高效的绕过手段。

解决方案建议

  1. 签名验证:若需修改APK,务必用 jarsignerapksigner 重新签名,并使用 zipalign 对齐。

  2. Root环境利用:优先在Root环境下调试,通过fridaGDB等工具直接注入或分析内存,避免修改APK的繁琐流程。

  3. 系统属性修改:Root后执行以下命令强制开启全局调试:

    bash

    复制

    1
    2
    3
    adb root          # 获取ADB Root权限
    adb shell setprop ro.debuggable 1
    adb shell stop && adb shell start # 重启ADB

    此后可调试任意APK,无需修改Manifest。


通过Root权限绕过APK本身的调试限制,是CTF中常见的技巧,既能避免打包错误,又能直接深入分析进程内存,是高效解题的关键。


参考文献:

APK反编译、重打包、签名之apktool实现

XYCTF 2024