1程序从哪里开始运行?寻找main
显著特征:有3个参数,后两个参数都是指针(4字节),在退出代码附近。
A字符串搜索法
搜索Helloworld 哈
然后逐步上翻
B栈回溯法
观察栈中的“返回到”
C逐步分析法
从代码开始分层次寻找。
2简单的例子
ESP是栈指针,[ESP+4]的意思是在当前堆栈+4的地方取其内容。
3函数识别初探
A主程序在调用函数时:
a保存返回地址并传递给函数
b参数传入与栈平衡
B函数调用约定
调用约定 | 关键字 | 参数入栈顺序 | 回收堆栈 |
C规范 | _cdecl | 从右到左 | 调用者负责 |
Pascal规范 | pascal | 从左到右 | 被调用者负责 |
快速调用规范 | _fastcall | 从右到左,使用寄存器传参 | 被调用者负责 |
标准调用规范 | _stdcall | 从右到左 | 被调用者负责 |
采用快速调用的函数参数是由ecx与edx这两个寄存器完成的,而超出部分的参数则依然要使用传统的压栈方式传递。
总结:
a几乎全部函数调用方式都会用栈来传递参数,只有使用快速调用约定后且参数少于等于2时才会全部采用寄存器传参。
b函数起始部分:以push ebp和mov ebp,esp汇编指令开始
c每个函数由call指令调用,且以retn指令结尾。
d裸函数来进行内联汇编可以改变以上的某些规律。
注:裸函数是指编译器生成汇编代码时不添加任何额外的指令,包括retn。