吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7377|回复: 30
收起左侧

[原创] 一起读反汇编代码之函数的调用

  [复制链接]
雪魔王遗风 发表于 2019-9-17 21:28
不知道小白有没有这样的困惑,就是单独一条的汇编语句能读懂,但是好几条组合到一起就感觉云里雾里了
那你就适合跟我们一起来读反汇编代码了,把基础指令的反汇编代码读懂才能逆向出一些更难的算法,今天我们一起来读的就是反汇编的基础部分———函数的调用


这里主要讲解的是函数调用的三方面知识:栈帧的形成、调用方式、参数以及EBP/ESP寻址
你可能有时候读反汇编代码的时候遇到一些问题例如:
经常在函数开头看见 push ebp ;mov ebp ,esp ;sub  esp,xxx这三行代码不知道做什么用的(分号只做分割用)
经常看见一些mov ecx,ss:[ebp+0x8];mov ecx,ss:[ebp-0x4]这样的赋值语句,却不知道赋的是什么值
经常在call 之后看见add esp,xxxx也不知道有什么用


那你应该能从我的帖子中找到答案
用的IDE是VC++6.0,程序有debug版本的也有release版本的,调试器就是论坛的OD



一.关于栈帧
说到函数的调用,不得不提的就是栈帧,你可能会经常在函数的开头看见这么几行代码:
push ebp
mov  ebp esp
sub   esp  xxxx
这三行代码其实就是用来形成栈帧的
那么这个栈帧到底是什么东西呢,我对它的定义就是:用于存放每次函数调用信息的专属栈空间
包括在被调用函数内部声明的局部变量


上面三行代码执行后,现在栈就变成来了这样
QQ拼音截图20190917204500.png
下面来解释下什么叫做栈平衡:
当我们调用一个函数的时候,就会针对这个开辟出其所需要的栈空间(因为要存放局部变量),形成属于这个函数的栈帧,而当调用结束之后,需要清除掉这个栈空间(关闭栈帧),这一过程就叫做栈平衡。
所以为什么局部变量有自己的生命周期就是因为函数执行完之后用于存放局部变量的栈帧被清除掉了,当然还是存在于内存中,只是无法再访问它了

而如果栈不平衡会怎样呢,我们知道调用函数时,需要先将函数所需的参数压入栈中,最后压入的是函数的返回地址,如果栈不平衡,会导致函数无法正确返回,而导致程序的崩溃。
所以!在退出函数时,会进行ESP与EBP的比较,用来检查栈帧是否被正确的关闭。
QQ拼音截图20190917180941.png
在函数的末尾处开始检查栈平衡
QQ拼音截图20190917181228.png

我们跟到cmp之后的call中看看发生了什么
QQ拼音截图20190917181506.png
一个不等于则跳转,手动修改标志位看看会怎样
QQ拼音截图20190917181919.png
呃,程序报错了,这就是栈空间溢出的后果


二.函数的调用方式
这里的函数调用方式其实是关于其参数的传递与栈空间的平衡的,看到这可能有人会说了,前面不是已经讲了栈空间的平衡里吗,为什么这里又要说呢?
前面说的栈帧是栈空间的一部分,是用来记录被调用函数的相关信息的,那么函数参数的传递大部分也是通过栈传递的,我们调用完函数后,这些参数也就没有其存在的价值里,我们就应该清除它们
C++中函数的调用方式主要有以下三种:
1._cdecl:是c++中默认的调用方式,所用参数从右到左入栈,这些参数由调用者清除
2._stdcall:入栈方向一致,参数由被调用者清除
3._fastcall:是快速调用方式,一般是前两个参数由寄存器传递,其他参数还是用栈传递,参数由被调用者清除
这里的东西比较简单,其实就是add  esp,xxxx 是放到被调用函数内部还是放在调用语句之后的区别
如果你有时在call之后看到add  esp,xxxx就知道是消除参数用的了
QQ拼音截图20190917185250.png



三.函数的参数以及EBP/ESP寻址
被调用函数执行时需要从栈空间中取出函数参数以及局部变量,现在的ESP作为栈顶指针EBP作为栈底指针,现在是通过哪个寄存器寻址呢,答案是EBP
QQ拼音截图20190917192922.png
上面的反汇编代码中我们即将调用一个printf函数,用来输出两个整数
一个整数是定义的局部变量而另一个整数是这个被调用函数的参数,可以看见OD已经帮我们做了分析
为了观察参数与局部变量的寻址方式我们可以先取消勾选“显示函数中的参数及局部变量”
QQ拼音截图20190917193238.png

取消勾选后OD就会直接显示出变量的地址
QQ拼音截图20190917193530.png
我们发现局部变量与参数的地址对于EBP的偏移量的符号不同,我们知道栈帧是在真正开始调用函数时才开始形成的,而参数却是在栈帧形成前就已经被压入栈中了。
所以偏移量为正数的理应是被调用函数的参数,是负数的自然就是被调用函数的局部变量了。


这里我们想一下如果我们传递了两个参数,而又在函数内部声明了两个局部变量,那么它们对于ESP的偏移又是多少呢?
而[esp]和[esp+4]中又存放的是什么值呢?
我最后再来解答

接下来我们说说ESP寻址,你有没有一个问题就是明明有ESP作为栈顶指针可以用来寻址,根本不需要EBP来做个中间量,是为了检查栈帧平衡吗,有时候或许完全不需要EBP,只要我们按规定进行栈平衡,我们也就不需要对栈平衡进行检查
事实上还真是这样,如果我们选择release版本,优化中勾选最快速度,那么我们就不再使用EBP,而是直接使用ESP进行寻址
QQ拼音截图20190917200019.png
这时候较小地址处放的应该是局部变量,较大地址处放的是参数,因为压栈时栈顶指针会减小

好了现在说说上面问题的答案了:
QQ拼音截图20190917201057.png

QQ拼音截图20190917201141.png

[EBP]中存放的应该是栈帧生成前的EBP的值,因为被调函数的开始有个push ebp
[EBP+4]中存放的应该是函数的返回地址,因为调用函数时压入参数之后还会把下一条语句的地址压入栈中
QQ拼音截图20190917204452.png


最后再附上源码跟程序:https://www.lanzouj.com/i681dzi
好了,到这里今天的学习就结束了,能力有限,可能会有疏漏之处,欢迎在评论区指出。
感谢各位看官!
如果觉得这篇帖子对你有一点帮助的话,希望能动动小手帮忙给下免费的评分,谢谢大家了!






D:/%E6%9C%89%E9%81%93%E4%BA%91/christy_wjc@163.com/a13e3e238173428092cd46edbf8b7782/qq%E6%8B%BC%E9%9F%B3%E6%88%AA%E5%9B%BE20190917185250.png

D:/%E6%9C%89%E9%81%93%E4%BA%91/christy_wjc@163.com/a13e3e238173428092cd46edbf8b7782/qq%E6%8B%BC%E9%9F%B3%E6%88%AA%E5%9B%BE20190917185250.png

免费评分

参与人数 26吾爱币 +34 热心值 +25 收起 理由
Hmily + 7 + 1 用心讨论,共获提升!
风去了云来了雨 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
彤哥来啦 + 1 + 1 任重道远
绅士的禽兽 + 1 + 1 我很赞同!
zhengyg + 1 + 1 我很赞同!
ly0003 + 1 + 1 谢谢@Thanks!
shaunkelly + 1 + 1 用心讨论,共获提升!
icode2019 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
sniper9527 + 1 + 1 谢谢@Thanks!
涛之雨 + 3 + 1 用心讨论,共获提升!
jianbin958 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
independence + 1 + 1 热心回复!
海天一色001 + 1 + 1 谢谢@Thanks!
spchen + 1 + 1 用心讨论,共获提升!
雨夜期鸿 + 1 + 1 谢谢@Thanks!
aimersky + 1 + 1 我很赞同!
JuncoJet + 1 + 1 热心回复!
dreamlivemeng + 1 + 1 热心回复!
zzzkc + 1 + 1 厉害了~
fnp902003 + 1 + 1 用心讨论,共获提升!
hbwazxf + 1 + 1 用心讨论,共获提升!
天空藍 + 1 + 1 谢谢@Thanks!
路过的群众 + 1 + 1 我很赞同!
315215 + 1 + 1 用心讨论,共获提升!
沉默的菜鸟 + 1 + 1 我很赞同!
四公子丶 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

涛之雨 发表于 2019-9-18 19:25
雪魔王遗风 发表于 2019-9-18 19:22
不知道咋回事啊,最后那个图片也是我自己画的

在一堆技术宅里秀恩爱。。。
是极为让人嫉妒的事情。。
很显然我不是
因为我是大白。。。
(小白又不是,大佬又不算。。很尴尬的位置)
mark_9527 发表于 2019-9-17 22:16
哈哈,非常感谢。
最后帮你转译一下你后面2行是什么鬼东西。
D:/有道云/christy_wjc@163.com/a13e3e238173428092cd46edbf8b7782/qq拼音截图20190917185250.png
 楼主| 雪魔王遗风 发表于 2019-9-17 21:30
呃,最后两行是啥代码啊,把我邮箱漏出来了。。。
 楼主| 雪魔王遗风 发表于 2019-9-17 21:36
今天写的东西可能有些简单了,不过应该也算是基础部分,之后可能会写一些变量在内存中的存储访问啊,类的继承啊,还有虚函数等等的东西吧
四公子丶 发表于 2019-9-17 21:56
收藏了  非常好的文章
fangchang819 发表于 2019-9-17 22:22
非常好的文章
RiversJin 发表于 2019-9-17 22:47
非常感谢 讲的很细致,对于初学者十分友好
xiaoxi2011 发表于 2019-9-18 00:31
学习了,谢谢分享
lyghost 发表于 2019-9-18 07:30
说的很详细
luixue 发表于 2019-9-18 08:44
学习了,感谢,感谢
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-26 02:50

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表