今天老师又给了一个程序,让我们分析,记录一下分析过程
程序:

#include "stdio.h"
#include "string.h"char *shellcode="\x64\x65\x66\x67\x68\x69\x70\x71\x05\x10\x40\x00";
void fun1(int a, int b)
{printf("fun1 run!para a=%d,b=%d\n",a,b);char aa[4]={0};
strcpy(aa,shellcode);
}
void fun2(int a)
{printf("fun2 run! para a=%d\n",a);}
void fun3(int a,int b,int c)
{printf("fun3 run! para a=%d,b=%d,c=%d\n",a,b,c);
}
int main(int argc, char* argv[])
{printf("begin\n");fun1(1,2);printf("end\n");return 0;
}

结果:

fun2函数执行了,没有输出来end

首先我们来看看为什么fun2执行了,将程序反汇编
当执行完char aa[4]={0},我们发现0x0019fed0这个地址存放这个数据,此时我们看一下0x0019fed4和0x0019fed8内的数据

当执行完strcpy时,0x0019fed0到0x0019fed8存放的内容是shellcode的内容,为什么是这个数据,看这篇文章(https://blog.csdn.net/qq_41683305/article/details/104282462),继续往下执行

当执行到ret命令时,我们观察esp的值,发现存放的内容是00401005,这个是什么?我们找到fun2的地址

发现和fun2的地址一样,这就是为什么会执行fun2

为什么不会输出end呢?
下面继续分析,按照上面的继续执行,当执行到ret时,此时esp存放的数据是00000001,我们会到这个地址执行

00000001啥都不是,所以不会执行end

下面来解决问题
现在我们来理一理思路,程序先执行fun1,然后去执行fun2,然后到00000001执行,没有返回来,我们要注意,00000001是我们程序fun1(1,2)中的1,所以我们将1改成我们要fun2执行完跳转的地址,就可以继续执行了,这个地址就是下图中的地址,跳转到这里继续执行

我们来改一下,程序:

#include "stdio.h"
#include "string.h"char *shellcode="\x64\x65\x66\x67\x68\x69\x70\x71\x05\x10\x40\x00";
void fun1(int a, int b)
{printf("fun1 run!para a=%d,b=%d\n",a,b);char aa[4]={0};
strcpy(aa,shellcode);
}
void fun2(int a)
{printf("fun2 run! para a=%d\n",a);}
void fun3(int a,int b,int c)
{printf("fun3 run! para a=%d,b=%d,c=%d\n",a,b,c);
}
int main(int argc, char* argv[])
{printf("begin\n");fun1(0x401191,2);printf("end\n");return 0;
}


我们可以看到fun1里填的0x401191不是0x40118e,这是1和0x401191和所占的字节不同导致的

继续报错,提示堆栈没有平衡,继续分析
我们分析一下,当调用fun1函数前,esp的值如图

fun2执行完,执行完下图的add esp,8时,esp的值为


本应该执行完add esp,8,esp的值应该是调用fun1函数前的值,结果差了4,找到原因了,补上:

#include "stdio.h"
#include "string.h"char *shellcode="\x64\x65\x66\x67\x68\x69\x70\x71\x05\x10\x40\x00";
void fun1(int a, int b)
{printf("fun1 run!para a=%d,b=%d\n",a,b);char aa[4]={0};
strcpy(aa,shellcode);
}
void fun2(int a)
{printf("fun2 run! para a=%d\n",a);}
void fun3(int a,int b,int c)
{printf("fun3 run! para a=%d,b=%d,c=%d\n",a,b,c);
}
int main(int argc, char* argv[])
{printf("begin\n");fun1(0x401191,2);__asm{sub esp,4}printf("end\n");return 0;
}


栈都平衡了,为什么还会报错呢,这就和检查有没有平衡栈的机制有关了

ebp存放的是调用函数前的esp,函数调用最后需要平衡栈数据,也就是将esp还原成调用函数前的esp,如果比较ebp和esp相等就不报错

没错还和ebp有关,在执行strcpy时,把原来的ebp内容修改了,所以会报错,继续改,还原原来的ebp

#include "stdio.h"
#include "string.h"char *shellcode="\x64\x65\x66\x67\x68\x69\x70\x71\x05\x10\x40\x00";
void fun1(int a, int b)
{printf("fun1 run!para a=%d,b=%d\n",a,b);char aa[4]={0};
strcpy(aa,shellcode);
}
void fun2(int a)
{printf("fun2 run! para a=%d\n",a);}
void fun3(int a,int b,int c)
{printf("fun3 run! para a=%d,b=%d,c=%d\n",a,b,c);
}
int main(int argc, char* argv[])
{printf("begin\n");fun1(0x401191,2);__asm{sub esp,4mov ebp,0x19ff30}printf("end\n");return 0;
}

执行,完美解决问题

总结:

  • 检查栈有没有平衡,是根据ebp和esp的值,有一个修改都要还原
  • ebp存放的是调用函数前的esp,函数调用最后需要平衡栈数据,也就是将esp还原成调用函数前的esp,如果比较ebp和esp相等就不报错,就是下图这两条语句检查的
  • esp和ebp的值最后要相同

中间涉及esp和ebp的值变换,没有写了,反汇编调试注意一下

C和汇编混合编程--------函数调用后ebp、esp值问题相关推荐

  1. arm export 汇编_C/C++与汇编混合编程有什么好处?

    1.导语 当需要C/C++与汇编混合编程时,可以有以下两种处理策略: 若汇编代码较短,则可在C/C++源文件中直接内嵌汇编语言实现混合编程. 若汇编代码较长,可以单独写成汇编文件,最后以汇编文件的形式 ...

  2. 51汇编与c语言混合编程,C51与汇编混合编程详解

    C51与汇编混合编程详解 0750long | 2009-07-09 12:45:42    阅读:1257 发布文章 C51与汇编混合编程详解 C51和汇编混合编程(1)-C语言中嵌入汇编 1.在 ...

  3. ARM中C和汇编混合编程及示例

    在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的.在稍大规模的嵌入式软件中,例如含有OS,大部分的代码都是用C编写的,主要是因为C语言的结构比较 ...

  4. C和汇编混合编程---栈平衡

    最近在搞C和汇编混合编程,对栈平衡有点小理解,记录一下 当我们调用一个API或者子程序时时,API和子程序可以理解为函数,我们不必在返回的时候平衡栈里面的函数参数,但C语言库函数要我们自己平衡栈数据, ...

  5. C和汇编混合编程----实现浮点数的加减乘除

    加法 C程序: #include "stdio.h"int main() {float a=1.0;float b=2.34;float c;c=a+b;printf(" ...

  6. c和汇编混合编程----shellcode----弹出计算器

    先用c和汇编混合编程成功弹出计算器(在VC++里运行) #include "stdio.h" #include "windows.h"int main(int ...

  7. arm汇编和c语言混合编程实验报告,实验三C语言和ARM汇编混合编程指导书.doc

    实验三C语言和ARM汇编混合编程指导书 实验三 1. 实验目的 掌握C语言和ARM汇编混合编程方法. 2. 实验设备 硬件:PC 机 一台 软件:Windows98/XP/2000 系统,ADS 1. ...

  8. c语言汇编混合编程方法,C语言和汇编语言混合编程方法

    摘要: C语言是一种高级的面向过程的开发语言,汇编语言是一种低级的面向机器的编程语言.两者在程序设计开发方面各有优劣,目前两者的混合编程得到了广泛的应用.本文通过具体的实例,说明了混合编程的基本方法, ...

  9. 嵌入式c语言汇编混合编程,嵌入式C语言和汇编语言的混合编程

    此文章简单介绍 单片机 C语言和汇编语言混合编程的例子.主要用单片机汇编语言编写DS1302的底层驱动,在C语言里通过调用汇编语言,从而实现C和汇编的混合编程. ;汇编语言源文件 ;========= ...

最新文章

  1. 求均值方差_协方差,方差,标准差
  2. RabbitMQ RPC远程调用模式
  3. Memory Limits for Windows and Windows Server Releases
  4. MIS2000Lab针对.NET 4.0出版的新书
  5. 福禄克中国区高管:高精度和应用性是未来测试主要发展方向
  6. Tensorflow深度学习应用(进阶篇)-1
  7. 作者:程文亮(1989-),男,华东师范大学数据科学与工程研究院硕士生
  8. mac Zip 常用命令
  9. L2TP OVER IPSEC原理详解
  10. 也谈“避免使用虚函数作为库的接口”
  11. Java基础 从键盘录入10整数,如果录入了一个0,则提前停止录入,统计已经录入了多少个奇数
  12. 8000401a 错误 及解决办法
  13. SeaChest Utilities 工具,让你的硬盘功耗又低又长寿
  14. 微博清理多个百万粉丝大号:打击违规账号要命中七寸
  15. OK6410A 开发板 (二) 环境熟悉
  16. java 修改mac地址_XP下修改MAC地址
  17. c语言提取质心坐标,求图像质心的C语言实现
  18. 【杭研大咖说】Istio进入1.7版本,Service Mesh 落地还有什么障碍?
  19. 怎样做一次好的活动策划?
  20. 讲的真详细!花三分钟看完这篇文章你就懂了

热门文章

  1. CSS3景深-perspective
  2. 为何要清除浮动?如何清除?
  3. 2017-2018-2 20179216 《网络攻防与实践》 SQL注入攻击
  4. Axis通过wsdd部署Web Service
  5. Ferguson游戏
  6. smarty引擎之练习
  7. JAVA_Collection容器
  8. 把txt文件中的json字符串写到plist文件中
  9. 每天自动给自己发天气预报的脚本
  10. WCF中的方法重载 实现