欺骗单步步过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下面的语句就不会执行

posted @   zpchcbd  阅读(313)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· 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
点击右上角即可分享
微信分享提示