ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Cutter Debug 菜单深度解析:调试、仿真与单步执行的完整工作流

Cutter Debug 菜单深度解析:调试、仿真与单步执行的完整工作流 Cutter Debug 菜单深度解析调试、仿真与单步执行的完整工作流【免费下载链接】cutterFree and Open Source Reverse Engineering Platform powered by rizin项目地址: https://gitcode.com/gh_mirrors/cu/cutterCutter 的 Debug调试菜单是动态分析的核心入口它把 rizin 底层的调试能力封装为一组 GUI 操作启动调试会话、启动 ESIL 仿真、附加到进程、连接远程调试器以及单步进入/单步跳过/单步跳出、继续执行、继续到调用、继续到系统调用等执行控制动作。本文基于用户文档 debug-menu.rst 完整继承其全部条目与快捷键并结合 DebugActions.cpp 与 Cutter.cpp 的源码实现说明每个菜单项背后的真实调用链、快捷键定义位置和实际行为差异例如调试模式与仿真模式走不同的 rizin API。1. 调试菜单的整体结构四个入口按钮与一个继续下拉在 DebugActions.cpp 中调试工具栏由两类QToolButton组织Start 按钮MenuButtonPopup 弹出菜单包含四个动作actionStartStart debug、actionStartEmulStart emulation、actionAttachAttach to process、actionStartRemoteConnect to a remote debugger。直接点击按钮默认触发Start debug。Continue 按钮continueUntilButton下拉菜单包含actionContinueUntilMainContinue until main、actionContinueUntilCallContinue until call、actionContinueUntilSyscallContinue until syscall默认项为 Continue until main。此外工具栏还平铺了 Continue、Stop、Step over、Step into、Step out、反向单步、反向继续和 trace 按钮见 DebugActions.cpp。所有调试动作默认隐藏仅在调试会话建立后通过setAllActionsVisible(true)显示DebugActions.cpp。所有快捷键由快捷键管理器统一定义见 DefaultShortcuts.cpp动作快捷键源码定义文档快捷键Debug.startStart debugF9F9Debug.continueContinueF5F5Debug.continueBackCtrlF5—文档未提及属于反向调试扩展Debug.stepStep intoF7F7Debug.stepOverStep overF8F8Debug.stepOutStep outCtrlF8CtrlF8Debug.stepBackCtrlF7—依赖 trace 会话后可见Continue until call / Continue until syscall 在源码中没有绑定全局快捷键只通过 Continue 下拉菜单触发。2. Start Debugging启动本地调试会话功能描述继承自原文档Start the debugging session of the current loaded binary为当前加载的二进制启动调试会话。操作路径Debug - Start debug快捷键F9。源码实现位于 DebugActions::startDebug()实际流程比点一下开始更细致可执行权限检查读取file.path配置若非调试状态且文件没有可执行权限弹出 File xxx does not have executable permissions. 提示并中止DebugActions.cpp。显示 beta 警告首次使用调试功能会弹出 Debug is currently in beta. 提示showDebugWarning()DebugActions.cpp。弹出 NativeDebugDialog 配置对话框预填dbg.args调试参数与dbg.profile调试配置文件两项 rizin 设置。该对话框支持三种配置方式见 NativeDebugDialog.h 中的DebugConfigMethod枚举CommandLine设置dbg.args同时清空dbg.profileprofile 优先于 args故移除RzRunProfile将选中的.rz/.rrz配置文件路径写入dbg.profileRzRunDirectives通过Core()-setProfileDirectives()直接下发指令。UI 状态切换隐藏 Attach/Emul/Remote 入口Start 按钮变为 Restart program 并换成 spin 图标调用setButtonVisibleIfMainExists()检查sym.main或mainflag若二进制没有 main 函数则隐藏 Continue until main 并将下拉默认项改为 Continue until callDebugActions.cpp。真正启动调用 CutterCore::startDebug()它记录调试前的 PC 位置然后在异步任务中执行rz_core_file_reopen_debug(core, )—— 即以调试模式重新打开当前文件。任务完成后会刷新寄存器窗口、关闭asm.flags避免寄存器名干扰反汇编显示、发出toggleDebugView()信号切换调试视图。3. Start EmulationESIL 仿真不真正执行二进制功能描述继承自原文档Start an emulation session on the current loaded binary. Cutter supports emulation of different file formats. Unlike debugging, emulation isnt really executing the binary, but only emulating the instructions. This is very strong feature for analysis of self-contained functions or programs, to analyze cryptographic algorithms or to deobfuscate data. Emulation isnt limited by the running platform, so Linux files such as ELF can be emulated on Windows platforms, and DLL can be emulated on Linux.操作路径Debug - Start emulation。底层实现在 CutterCore::startEmulation()它在异步任务中依次调用三个 ESIL 初始化函数rz_core_analysis_esil_reinit(core); // 重新初始化 ESIL 状态 rz_core_analysis_esil_init_mem(core, nullptr, UT64_MAX, UT32_MAX); // 初始化仿真内存 rz_core_analysis_esil_init_regs(core); // 初始化寄存器仿真建立后会设置io.cache true使自修改代码等二进制变化可以在视图中观察到会话结束时stopDebug 的仿真分支Cutter.cpp会释放仿真内存、调用rz_core_analysis_esil_deinit并清除寄存器 flags。与调试的运行时差异后续每个执行动作都会根据currentlyEmulating标志分叉——例如 Step into 在仿真模式下调用rz_core_esil_step()rz_core_reg_update_flags()而调试模式下调用rz_core_debug_step_one(core, 1)对比 stepDebug() 的两个分支。仿真模式下 Continue until main 也被隐藏Continue 下拉的默认项被改为 Continue until syscallDebugActions.cpp这与原文档中仿真不受运行平台限制的定位一致ESIL 只是按指令语义推演寄存器/内存状态适合分析加解密例程与去混淆。4. Attach to Process附加到正在运行的进程功能描述继承自原文档Attach Cutters debugger to a running process, instead of spawning a new process.操作路径Debug - Attach to process。实现链条attachProcessDialog() 弹出 AttachProcDialog 供用户选择进程取到 PID 后调用 attachProcess()Stop 按钮随即改为 Detach from processdetach 图标随后调用 CutterCore::attachDebug(pid)。该函数构造dbg://pidURI在异步任务中设置cfg.debug true然后若当前没有打开任何文件rz_core_file_open_load(core, uri, 0, RZ_PERM_R, false)直接以该进程为目标打开若已有文件rz_core_file_reopen_remote_debug(core, uri, 0)以调试模式重开当前二进制并附加。任务完成后调用syncAndSeekProgramCounter()将视图定位到目标进程的 PC并记录currentlyAttachedToPID。5. Connect to a Remote Debugger连接远程调试器GDB / WinKd功能描述继承自原文档Connect Cutter to a remote debugger such as GDB or WinDbg by providing IP and Port of the remote debugger.操作路径Debug - Connect to a remote debugger。RemoteDebugDialog 提供远程连接表单源码中定义了两个后端RemoteDebugDialog.cpp后端URI 前缀表单要求GDBgdb://校验 IP 合法性QHostAddress与端口范围 1–65535最终 URI 形如gdb://ip:portWinKd - Pipewinkd://校验本地管道/路径存在QFileInfo::existsURI 形如winkd://path对话框还维护最近连接列表成功连接后 URI 会被写入 QSettings 的recentIpListDebugActions.cpp下次打开对话框可直接点击回填表单fillFormData()按前缀解析出 IP 与端口。确认连接后调用 CutterCore::attachRemote(uri)设置cfg.debug true并执行rz_core_file_reopen_remote_debug(core, uri, 0)。任务完成后会遍历rz_id_storage_list(core-io-files)核对是否真的建立了该 URI 的 IO 描述符连接失败则发出attachedRemote(false)并弹窗 Error connecting.成功后将 Stop 按钮语义改为 DetachattachRemoteDebugger()。6. Step Into / Step Over / Step Out三种单步模式以下三项继承自原文档的完整描述Step IntoExecute a single assembler instruction, stepping into functions and loops执行一条汇编指令并进入函数和循环内部。路径Debug - Step快捷键F7。Step OverExecute a single assembler instruction, stepping over functions and procedures. The functions will not be skipped and will be executed by Cutter. The execution will pause when reaching the instruction after the function call执行一条指令并跨过函数调用函数会被完整执行PC 停在调用返回后的第一条指令。路径Debug - Step over快捷键F8。Step OutExecute the code and suspends execution when the current function returns持续执行直到当前函数返回时暂停。路径Debug - Step out快捷键CtrlF8。三者分别映射到 Cutter.cpp 中的独立实现且都有调试/仿真两条路径动作调试模式 API仿真ESIL模式 APIStep intorz_core_debug_step_one(core, 1)rz_core_esil_step(core, UT64_MAX, ...)rz_core_reg_update_flagsStep overrz_core_debug_step_over(core, 1)rz_core_dbg_follow_seek_registerrz_core_analysis_esil_step_over(core)Step outrz_core_debug_step_until_frame(core)—源码中 stepOut 仅实现调试分支见 stepOutDebug()三个动作均以asyncTask形式在debugTask线程执行避免阻塞 UI任务结束后统一调用syncAndSeekProgramCounter()同步视图到新的 PC 并刷新寄存器窗口。每个动作入口都先检查currentlyDebugging非调试状态下点击无效。7. Continue 及继续到系列Continue继承自原文档Continue the execution of the running program. The execution will stop when reached a breakpoint, when manually suspended by the user, or when the running program quits.继续执行程序遇到断点、被用户手动挂起或程序退出时停止。路径Debug - Continue快捷键F5。一个值得注意的细节Continue 按钮是继续/挂起二合一的。DebugActions.cpp 中的槽函数根据isDebugTaskInProgress()分流有调试任务正在运行时调用Core()-suspendDebug()break 当前任务否则调用Core()-continueDebug()同时图标在media-skip-forwardcontinue与media-suspendsuspend之间切换debugTaskStateChanged 槽。调试模式下continueDebug()调用rz_debug_continue(core-dbg)仿真模式下则执行一步 ESILrz_core_esil_step这与原文档仿真只是推演指令而非执行的说法在源码层面得到印证Cutter.cpp。Continue Until Call继承自原文档Continue the execution of the program until a function call is reached.继续执行直到到达函数调用。路径Debug - Continue until call。底层调试模式调用rz_core_debug_step_one(core, 0)仿真模式调用rz_core_analysis_continue_until_call(core)continueUntilCall()。Continue Until Syscall继承自原文档Continue the execution of the program until a Syscall is reached.继续执行直到到达系统调用。路径Debug - Continue until syscall。调试分支实现较为典型continueUntilSyscall()rz_cons_break_push(..., core-dbg); // 注册 break 回调 rz_reg_arena_swap(core-dbg-reg, true); // 切换寄存器 arena rz_debug_continue_syscalls(core-dbg, nullptr, 0); // 继续直到任意系统调用 rz_cons_break_pop(); rz_core_dbg_follow_seek_register(core);仿真分支则调用rz_core_analysis_continue_until_syscall(core)。原文档之外源码中还提供了 Continue until main它查找sym.main回退到mainflag 的偏移然后调用continueUntilDebug(offset)DebugActions.cpp、Cutter.cpp。若二进制分析后没有 main flag该入口会被自动隐藏——这是从源码结构看文档未覆盖的一个实用行为。8. 会话管理Stop 按钮、进程退出提示与反向调试原文档聚焦正向调试流程但理解完整生命周期需要补充 Stop 与 trace 两处的源码事实Stop debug / Stop emulation / Detach同一个actionStop按钮按会话类型切换文案。CutterCore::stopDebug() 先挂起运行中的任务然后按类型清理仿真分支释放 ESIL 内存与 trace、清除寄存器 flags调试分支调用rz_core_debug_process_close(core)结束调试进程并复位currentlyAttachedToPID -1。进程退出提示DebugActions.cpp 连接了debugProcessFinished信号调试进程退出时会弹窗 Debugged process exited (pid)。trace 与反向调试actionTrace切换startTraceSession()/stopTraceSession()调试分支对应rz_debug_session_newrz_debug_add_checkpoint开始 trace 后 Step backCtrlF7与 Continue backCtrlF5按钮才可见仿真分支则基于rz_core_analysis_esil_trace_start/stopCutter.cpp。反向动作的调用如rz_core_esil_step_back同样区分仿真与调试路径。9. 小结从菜单项到 rizin API 的完整映射Debug 菜单项快捷键核心 rizin API调试模式源码位置Start debugF9rz_core_file_reopen_debugCutter.cpp#L2083Start emulation—rz_core_analysis_esil_reinit/init_mem/init_regsCutter.cpp#L2127Attach to process—dbg://pidrz_core_file_open_load/reopen_remote_debugCutter.cpp#L2238Connect to remote debugger—gdb:///winkd://rz_core_file_reopen_remote_debugCutter.cpp#L2175Step intoF7rz_core_debug_step_one(core, 1)Cutter.cpp#L2534Step overF8rz_core_debug_step_over(core, 1)Cutter.cpp#L2572Step outCtrlF8rz_core_debug_step_until_frameCutter.cpp#L2608ContinueF5rz_debug_continue运行中则 break 挂起Cutter.cpp#L2342Continue until call—rz_core_debug_step_one(core, 0)Cutter.cpp#L2454Continue until syscall—rz_debug_continue_syscallsCutter.cpp#L2491需要说明的适用前提源码中调试功能自标注为 beta首次启动会弹出提示DebugActions.cpp仿真模式下部分动作如 Step out在源码中只有调试分支实现Continue until main 依赖二进制存在sym.main/mainflag。实际行为请以当前仓库 Cutter.cpp 与 DebugActions.cpp 的实现为准。【免费下载链接】cutterFree and Open Source Reverse Engineering Platform powered by rizin项目地址: https://gitcode.com/gh_mirrors/cu/cutter创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表