IDA 调试android 遇到的问题及解决方案

本文汇总了使用IDA进行调试时常见的问题及解决方案,包括调试服务器不兼容、权限问题、连接异常关闭、调试工具冲突等,并提供了详细的解决步骤。

【问题】

Incompatible debugging server:

address size is 4 bytes, expected 4

【解决】

你的android_server 是32位的 
而你启动的 ida 是64位的 
换成32位的ida 就OK

=====================================

【问题】

adb shell ls /data/data/ 命令权限被拒绝

opendir failed, Permission denied

【解决】

adb不是最高权限启动的

先adb kill-server,然后 adb start-server

或者执行 adb root , adb remount

再测试,问题解决

=====================================

 【问题】

The connection has been gracefully closed by peer.
Check that IDA is the only debugger for the target.

【解决】

除了IDA 还开启了其他的调试工具或开发工具比如 Android Studio 或 Eclipse,关闭其他即可。

=====================================

【问题】

adb shell am start -D -n (包名)/ (包名+类名)

......

adb forward tcp:17178 jdwp:16406

jdb -connect com.sun.jdi.SocketAttach:port=17178,hostname=localhost

当使用 jdb 调试时出现以下错误:

……

致命错误:
无法附加到目标 VM。

【解决】

有可能是因为 apk 忘记了修改 AndroidManifest.xml 里的 manifest -> application ->> android:debuggable="true"  导致的。

=====================================

【问题】

IDA 调试so 时遇到了

got SIGCHLD signal (Child status has changed) (exc.code 11, tid 3756)

等消息提示

【解决】

直接 pass to apptication... 就可以了 = =

=====================================

Warning
---------------------------
Timed out while waiting for a JWDP reply
---------------------------
OK   
---------------------------
---------------------------
Warning
---------------------------
The debugger could not attach to the selected process.
This can perhaps indicate the process was just terminated, or that you don't have the necessary privileges.
---------------------------
OK   
---------------------------

出现这种提示,说明你导入的Dex文件可能太大了,IDA解析不过来,用BackSmali把Dex导出,把无关的代码删除,再用 smali 重新打包成小的Dex文件,再进行调试就可以了

也有可能 是接线出现了问题,手机拔了重插。

=====================================

The function has undefined instruction/data at the specified address.
Your request has been put in the autoanalysis queue.

创建函数失败,用选择代码的方法,再按P,具体参看下面地址

http://bbs.pediy.com/archive/index.php?t-158896.html

=====================================

【问题】

The debugger could not attach to the selected process.
This can perhaps indicate the process was just terminated, or that you don't have the necessary privileges.

【解决】

1.不要用模拟器,用真机

2.换系统 ro.debugger = 1

3.换手机 


待追加……

内容概要:本文档《IDA调试命令.txt》详细记录了Android应用动态调试过程中所需的各类命令及其使用方法,包括ADB(Android Debug Bridge)命令、JDB(Java Debugger)调试命令、so层逆向分析技巧、Android系统启动流程以及JNI_onLoad函数的反汇编代码片段。文档重点介绍了如何通过ADB命令行操作设备,如安装应用、设置调试模式、启动应用并附加调试器,同时涵盖了so文件的加载与内存映射、进程模块信息获取等高级调试技术。此外,还探讨了Android系统的启动过程,从电源开启到Launcher启动的各个阶段,为深入理解系统底层机制提供了理论支持。 适合人群:具备一定Android开发经验和逆向工程基础知识的研发人员,尤其是对动态调试、so层逆向分析感兴趣的开发者。 使用场景及目标:①帮助开发者掌握ADB和JDB命令的使用,以便于快速定位和解决应用运行时的问题;②提供so层逆向分析的具体方法,如通过IDA附加调试、获取模块信息等,以破解加密算法或研究第三方库的实现;③深入了解Android系统启动流程,为优化系统性能、开发系统级应用提供参考。 其他说明:文档内容较为专业,涉及大量命令行操作和技术细节,建议读者在实际环境中反复练习,结合官方文档和社区资源进行学习。对于遇到的具体问题,可以通过调整命令参数、检查设备和应用配置等方式逐步排查。
<think> 我们正在讨论在IDA动态调试过程中遇到exit函数的解决方法。用户之前已经知道可以通过NOP掉exit调用来绕过,现在想知道其他方法。 根据用户提供的引用[1],他们之前通过修改二进制将_exit调用NOP掉(替换为00 00 00 00)来绕过。现在,我们需要提供在动态调试中遇到exit时的其他解决方法,并且这些方法可能不直接修改二进制(即不NOP指令)。 注意:用户特别指出是在“IDA动态调试中”遇到exit函数的解决办法。 可能的解决方案: 1. 修改程序计数器(PC/EIP)或跳转指令:在exit被调用之前,通过调试器改变执行流程,跳过exit调用。 2. 修改函数返回值:如果exit是被某个函数调用的,可以修改该函数的返回地址,使其返回到exit之后的位置。 3. 修改exit的参数:如果exit的参数导致程序退出,可以尝试在调用exit时修改参数(比如将退出码改为0)以避免非正常退出,但这通常不能阻止退出,因为exit无论如何都会终止进程。 4. 拦截系统调用:如果exit最终会调用系统调用(如_exit系统调用),可以在系统调用层拦截并跳过。 5. 使用调试器的命令:例如在GDB中可以使用“jump”命令跳转到指定地址,跳过exit。IDA调试器也有类似功能。 但是,我们是在IDA动态调试环境下,因此我们需要具体说明如何在IDA中操作。 具体步骤(以IDA为例): 方法一:修改EIP/RIP(程序计数器)跳过exit调用 - 在exit函数被调用时(即call exit指令执行后),程序会进入exit函数。此时,我们可以在exit函数内部,但还没有执行其内部代码时,通过修改程序计数器(PC)来跳过exit的执行。 - 更常见的做法是在调用exit的那条指令的下一条指令处设置一个断点,然后修改程序流程,使其不执行exit,而是跳转到下一条指令继续执行。 方法二:修改调用exit的条件 - 如果exit是在某个条件分支中被调用的(例如,一个判断后如果满足条件就exit),我们可以通过修改条件标志位或条件判断前的寄存器/内存值,使得条件不满足,从而避免进入exit分支。 方法三:使用调试器的“跳过调用”功能 - 在IDA调试器中,当程序执行到call exit指令时,我们可以使用“跳过调用”(Step Over)的方式,但这通常不会阻止exit,因为Step Over会执行完整个函数。所以我们需要在Step Over之前修改返回地址,或者使用其他技巧。 方法四:通过修改内存或寄存器改变程序行为 - 例如,在进入exit之前,我们可以修改exit函数的入口地址为另一个无害的函数(比如一个空函数)的地址,这样当调用exit时实际上调用的是空函数。 方法五:使用IDA调试器功能,在系统调用层拦截 - 在exit函数内部,最终会执行系统调用(如Linux下的exit_group)。我们可以在系统调用指令处中断,然后修改系统调用号为一个无害的系统调用(如getpid)或者修改寄存器使得系统调用无效。 然而,考虑到简单性和可行性,我们通常采用修改程序计数器或者条件跳转的方法。 下面我们详细描述一种在IDA动态调试中跳过exit调用的方法: 步骤示例(假设exit调用是一条call指令): 1. 在IDA中,定位到调用exit的指令地址,例如:`.text:00401122 E8 89 45 00 00 call exit` 2. 在该地址设置断点(按F2)。 3. 运行程序直到断点触发(按F9)。 4. 程序停在`call exit`这一行,此时还没有执行call指令。 5. 我们不想执行这个call,那么我们可以将程序计数器(EIP/RIP)直接设置到call指令的下一条指令。在IDA中,可以通过修改EIP寄存器实现: - 打开寄存器窗口(菜单Debugger -> Debugger windows -> Register view)。 - 找到EIP(32位)或RIP(64位)寄存器,双击将其值修改为call指令的下一条指令地址(例如00401127)。 6. 然后继续运行程序(按F9),这样call exit就不会被执行。 注意:这种方法跳过了call指令,相当于没有执行exit函数。但是,这可能会导致一些资源没有释放(因为exit函数会执行一些清理工作),但在调试过程中为了继续执行后续代码,这是一个有效的方法。 另外,如果exit调用是在一个条件分支中,我们可以尝试修改条件标志,使得条件跳转不执行exit分支,而是继续执行正常流程。 例如,在条件跳转指令处(比如`jz exit`)设置断点,然后修改标志寄存器(EFLAGS)中的零标志(ZF),使得条件不成立。 步骤: 1. 在条件跳转指令处设置断点。 2. 当断点触发时,查看标志寄存器(在寄存器窗口中),将ZF标志修改为0(如果原来是1,表示条件成立,则改为0表示条件不成立)。 3. 然后单步执行(F7)就会跳过跳转指令,继续执行正常流程。 以上方法都是在动态调试中临时修改,不会修改程序二进制文件。 另外,引用[3]中提到了IDA动态调试Android程序的方法,虽然环境不同,但原理类似。在Android调试中同样可以使用上述方法。 总结一下,除了NOP掉exit调用,在IDA动态调试中遇到exit函数时,我们可以: 1. 修改程序计数器(EIP/RIP)跳过call exit指令。 2. 修改条件标志或条件变量,避免进入调用exit的分支。 3. 修改exit函数的参数(但这种方法通常不能阻止程序退出,因为exit函数仍然会执行)。 4. 在exit函数内部修改执行流程,使其提前返回(比如修改返回地址)。 注意:这些方法都是调试时的临时措施,目的是为了继续调试后续代码。在正式修复程序时,应该分析为何会调用exit,然后修改程序逻辑。 下面,我们按照要求生成相关问题。 </think>在 IDA 动态调试中绕过 `exit` 函数调用的方法主要有以下几种技术方案,均无需修改二进制文件: ### 一、执行流劫持(推荐) 1. **修改程序计数器(EIP/RIP)** 当程序执行到 `call exit` 时: ```assembly .text:00401000 call exit .text:00401005 mov eax, [ebx] ; 目标跳过位置 ``` - 在 IDA 调试器中暂停在 `call exit` 指令处 - 打开寄存器窗口(Debugger → Debugger windows → Registers) - 将 **EIP/RIP** 的值手动修改为 `00401005`(`call` 的下一条指令地址) - 按 **F9** 继续执行,跳过 `exit` 调用[^1] 2. **修改返回地址** 若 `exit` 在函数内部被调用: ```c void vulnerable() { exit(1); // 目标绕过点 } ``` - 在函数栈帧中定位返回地址(Stack view) - 将返回地址修改为 `vulnerable()` 函数之后的指令地址 - 继续执行时直接返回到主流程 --- ### 二、条件标志篡改 当 `exit` 受条件分支控制时: ```assembly test eax, eax jz short loc_exit ; 条件跳转至exit ``` 1. 在条件跳转指令(如 `jz`)处设置断点 2. 触发断点时打开寄存器窗口 3. 修改 **EFLAGS** 寄存器: - 将 **ZF(零标志位)** 从 1 改为 0(取消跳转) - 或直接修改 **EAX** 为非零值 4. 单步执行(F7)跳过分支 --- ### 三、内存断点拦截 1. 在 `exit` 函数入口设置访问断点: ```python import ida_dbg exit_addr = ida_name.get_name_ea(0, "exit") ida_dbg.add_bpt(exit_addr, 0, BPT_SOFT) # 设置软件断点 ``` 2. 当断点触发时: - 使用 **Stack trace** 查看调用栈 - 定位调用 `exit` 的上级函数 - 返回上级函数修改逻辑寄存器 --- ### 四、系统调用拦截(Linux/Android) 针对 `exit` 最终触发的 `exit_group` 系统调用: 1. 在系统调用指令处断点: ```assembly syscall ; x64 svc #0 ; ARM ``` 2. 检查系统调用号: - x86-64: **RAX=231** (exit_group) - ARM: **R7=248** (exit_group) 3. 修改系统调用号为无害值: - 改为 **RAX=39** (getpid) 或 **R7=20** (getpid) - 或直接修改 **RAX/R0** 返回值 --- ### 操作示例(IDA 动态调试) 1. 定位 `exit` 调用点(反汇编窗口) 2. 在 `call exit` 处按 **F2** 设断点 3. 按 **F9** 运行至断点 4. 寄存器窗口修改 **EIP → call 下一条指令地址** 5. 按 **F9** 继续执行 --- ### 注意事项 1. **资源泄漏风险**:跳过 `exit` 可能导致未释放内存/文件描述符 2. **状态一致性**:可能破坏程序清理逻辑 3. **临时性**:修改仅在当前调试会话有效 4. **权限要求**:需在调试器控制下进行 > 通过寄存器修改和条件标志篡改可快速绕过 `exit`,适用于漏洞分析或解密场景。对于生产环境,应修复原始代码逻辑[^1][^3]。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值