动态线条
动态线条end

逆向:windows堆栈平衡问题

常见的调用约定

调用约定 参数压栈顺序 平衡堆栈
__cdecl 从右至左 调用者平衡(外平栈)
__stdcall 从右至左 自身清理堆栈(内平栈)
__fastcall ecx/edx传递前两个参数,剩下参数从右至左入栈 自身清理堆栈(内平栈)

__cdecl

#include <stdio.h>

//声明一个裸函数,编译器不对其生成汇编代码
int  __cdecl fun(int a, int b){

	return a + b;
}

int main(){
	fun(1, 2);
	return 0;
}

调用处汇编代码

image-20220209185450470

函数内汇编代码

image-20220209185730615

总结

内部代码中没有堆栈平衡的操作,平衡堆栈只在调用处


__stdcall

#include <stdio.h>

//声明一个裸函数,编译器不对其生成汇编代码
int  __stdcall fun(int a, int b){

	return a + b;
}

int main(){
	fun(1, 2);
	return 0;
}

调用处汇编代码

image-20220209190027493

函数内汇编代码

image-20220209190327730

总结

在调用中进行堆栈平衡,因此又被称作:内平栈


__fastcall

#include <stdio.h>

//声明一个裸函数,编译器不对其生成汇编代码
int __fastcall fun(int a, int b){

	return a + b;
}

int main(){
	fun(1, 2);
	return 0;
}

调用处汇编代码(参数少于等于两个)

image-20220209191441718

函数内汇编代码(参数少于等于两个)

image-20220209190837258


#include <stdio.h>

//声明一个裸函数,编译器不对其生成汇编代码
int __fastcall fun(int a, int b,int c){

	return a + b + c;
}

int main(){
	fun(1, 2, 3);
	return 0;
}

调用处汇编代码(参数大于两个)

image-20220209191055283

函数内汇编代码(参数大于两个)

image-20220209191329042

总结

如果传入的参数小于等于两个,那么不需要对堆栈进行平衡;如果传入的参数个数大于两个,那么将会在函数调用结束时用ret进行堆栈的调节

posted @ 2022-02-09 19:21  v1v1v1  阅读(170)  评论(0编辑  收藏  举报