欺骗单步步过F8导致程序跑飞
前言:欺骗单步步过F8导致程序跑飞的笔记
单步步过跑飞的原理
我们这里说的跑飞就是在调试器中调试的时候为什么有时候在CALL F8的时候就会导致程序跑飞的现象
首先需要知道的一点就是F8单步步过CALL的简单实现,实际上是调试器会在CALL+5个字节,也就是调试器会帮你在CALL XXXX的地址的下一行地址上打一个断点,那么此时如果CALL中执行的代码最后返回的不是下一行地址,那么程序就会断在下一行地址了,而最后CALL跳转的地址都没有打过断点,这就会导致CPU一直在执行机器码,这就是跑飞现象的原因
简单的代码实现
我这里通过代码简单的模拟一个F8单步步过跑飞的现象
#include<stdio.h> int iEax; int iRet; void _declspec(naked) test01() { printf("cheat f8 test...\n"); __asm { mov iEax, eax; // save eax mov eax, [esp]; add eax, 7; mov iRet, eax; pop eax; mov eax, iEax; push iRet; ret; } } void test02() { printf("test02...\n"); } int main() { int a = 0; test01(); a = 1; printf("test..."); return 0; }
载入到调试器中进行调试,调用处如下位置
此时如果F8的话,可以看到程序直接终止了,如下图所示
如果F7步入的话,那么还能继续执行,首先F7进到CALL中
这里继续单步,然后就要执行返回了RET了
可以看到继续执行了
所以这里对于F8跑飞的解决方式就是对CALL进行单步步入即可
但是一般在程序中为了F8跑飞的实现,程序可能会多个嵌套的跑飞,所以你也需要多个F7单步步入来进行调试
如何识别是否是跑飞CALL
可以先看下CALL的跳转,如果就在附近的话,那么就F7单步步入慢慢跟就好了
壳中的应用
在壳用跑飞其实很常见的,自己这里拿一个来Yoda's Crypter(1.2)来演示跑飞效果
将壳程序载入到调试器中,可以看到pushad,那么这里就直接用ESP定律即可,接着F9你就会来到如下的地方
此时这个CALL就会导致跑飞,因为该CALL中就直接让你跳到别的地方,如果F8步过CALL的话,那么就直接跑飞了,可以看到F8步过CALL之后就直接来到了其他的地方
如果是F7跟入的话,此时会执行这两条
0040541B 58 pop eax ; UnPackMe.004053FE 0040541C C3 retn
而pop eax之后,此时的栈顶就是OEP的地址,那么单步走的话就直接来到OEP了,CALL下面的语句就不会执行
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY