滴水逆向三期笔记与作业——02C语言——06 参数_返回值_局部变量_数组反汇编

OneNote防丢失。

一、函数返回值如何传递

1.1 char类型返回

  1. 代码:
char fun(){
	//代码
	return 12;
}
int main(int argc, char* argv[]){
	char i = fun();
	return 0;
}
  1. 反汇编:
  • 函数返回值,即return 12代码部分
    在这里插入图片描述在fun函数中,将返回值“12”存放在eax中(教程中32位的vc6++是存放在al位置)。

  • 函数返回值赋值给main中的变量
    在这里插入图片描述
    将一个字节长度的12赋值给[rbp-0x1]的位置,在教程中32位的vc6++是将1字节长度存放在[ebp-4]的位置,即move byte ptr [ebp-4],al(ebp-4是main函数的缓冲区),同样是仅存储一个字节的长度,编译器的不同会导致程序在空间的利用程度上存在差异

1.2 short类型返回

  1. 代码:
short fun(){
	//代码
	return 12;
}
int main(int argc, char* argv[]){
	short i = fun();
	return 0;
}

  1. 反汇编:
  • 函数返回值
    在这里插入图片描述
    short为2字节长度,所以函数中将返回值12存储在eax中,但32位的vc6++中存储在ax中

  • 函数返回值赋值给main中的变量
    在这里插入图片描述将2字节长度的12存储在[rbp-0x2]的位置,在教程中32位的vc6++是将2字节长度存放在[ebp-4]的位置,即move word ptr [ebp-4],ax

1.3 int类型返回

  1. 代码:
int fun(){
	//代码
	return 12;
}
int main(int argc, char* argv[]){
	int i = fun();
	return 0;
}

}

  1. 反汇编:
  • 函数返回值
    在这里插入图片描述

int为4字节长度,所以函数中将返回值12存储在eax中,32位的vc6++中也存储在eax中

  • 函数返回值赋值给main中的变量
    在这里插入图片描述

将4字节长度的12存储在[rbp-0x4]的位置,在教程中32位的vc6++是将4字节长度存放在[ebp-4]的位置,即move dword ptr [ebp-4],ea

1.4 作业-long long类型(64位)返回值

  1. 代码
__int64 fun(){
	//代码
	return 0x1234567890;
}
int main(int argc, char* argv[]){
	__int64 i = fun();
	return 0;
}
  1. 反汇编:
  • 函数返回值
    在这里插入图片描述
    在64位的环境中,__int64类型的数据存放在rax寄存器中,在32位的环境中将结果放在eax和edx中
    注:在 64 位代码中,movabs可用于对mov具有 64 位位移或立即数操作数的指令进行编码。
  • 函数返回值赋值给main中的变量
    在这里插入图片描述
    64位环境中,将rax中的函数返回值存储在[rbp-0x8]的位置,使用的是qword,在32位环境中将eax(低位)存入[ebp-8],将edx(高位)存入[ebp-4]

1.5 作业-char arr[3]={1,2,3}与char arr[4]={1,2,3,4}哪个更省空间,从反汇编角度说明,用char和short分别创建10个元素的数组,观察如何分配

1.5.1 char arr[3]={1,2,3}与char arr[4]={1,2,3,4}哪个更省空间,从反汇编角度说明

  1. char arr[3]={1,2,3}
  • 代码
void Function(){
	char arr[3] = {1,2,3};
}
int main(int argc, char* argv[]){
	Function();
	return 0;
}
  • 反汇编(64位的VScode)
    在这里插入图片描述
    以字节大小存储,分配了0x10大小的缓冲区;
  1. char arr[4]={1,2,3,4}
  • 代码
void Function(){
	char arr[4] = {1,2,3,4};
}
int main(int argc, char* argv[]){
	 
	Function();
	 
	return 0;
}
  • 反汇编(64位的VScode)
    在这里插入图片描述
  1. 总结
    同样以字节大小存储,分配了0x10大小的缓冲区;
    VScode在空函数时不分配缓冲区,即nop之后直接ret返回,当arr数组长度为5时,依然分配0x10大小的缓冲区(而不是海哥视频里的0x40+4n大小的缓冲区),可见现在是优化过的,并不会浪费大量内存去提升效率。

1.5.2 用char和short分别创建10个元素的数组,观察如何分配

  • 代码
int main(int argc, char* argv[]){
 
	char arr0[10] = {1,2,3,4,5,6,7,8,9,10};
	short arr1[10] = {1,2,3,4,5,6,7,8,9,10};
	 
	return 0;
}

在这里插入图片描述

  • 反汇编
    在这里插入图片描述
    char使用字节大小存储,short使用字大小存储(可见新版本还是优化了的,该是多大就是多大)。

1.6 作业-找出下面赋值过程的反汇编代码

1.6.1 作业部分

  • 代码:
void Function(){
	int x = 1;
	int y = 2;
	int r;
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	r = arr[1];
	r = arr[x];
	r = arr[x+y];
	r = arr[x*2+y];
}
  • 反汇编
    在这里插入图片描述
    在这里插入图片描述
    数组寻址:值=取值(rbp/ebp + rax/eax * 数值宽度 - 数组首地址),其中rax/eax中存的是arr[n]中的n。

1.7 作业-选做桶排序

在这里插入图片描述
之前还在卷开发的时候都直接跳过的玩意,略过略过。

二、参数传递的本质

2.1 8位参数传递

  • 代码:

在这里插入图片描述

  • 汇编:
    在这里插入图片描述

使用堆栈传递参数,并且使用4字节大小内存存储参数,从右往左入栈,并且外平栈,可见使用的调用约定是__cdecl。

2.2 16位参数传递

  • 代码:

在这里插入图片描述

  • 汇编:

在这里插入图片描述

2.3 32位参数传递

  • 代码:
    在这里插入图片描述

  • 汇编:
    在这里插入图片描述

2.4 总结:

  1. 在32位的系统中,参数传递始终按照4字节的大小入栈,所以定义char或者short类型的参数并不会节约空间,反而在char a = 1;Fun(1);传递参数时会产生额外的操作去进行al或者ax的转换。

  2. 如果本机是32位的,那么及其对于32位的数据支持度最好,反之32位时,对于32位的支持度最好。所以整数类型的参数,全部使用int传递参数。

  3. 参数传递的本质是将上层函数的变量或者表达式的值复制一份再传递给下层函数。

在这里插入图片描述

三、局部变量的内存分配

  1. (32位环境中)小于32位的局部变量,空间在分配时,按32位分配;

  2. 使用时按实际的宽度使用;

  3. 不要定义char/short类型的局部变量;

  4. 参数与局部变量没有本质区别,都是局部变量,都在栈中分配(参数是函数调用前分配的值,局部变量是函数执行时分配的值);

  5. 完全可以把参数当初局部变量使用。

四、赋值语句的本质

将某个值存储到变量中的过程就是赋值。

思考题:
int r = x + y;是赋值语句吗?那么 int r = Add(x,y)是赋值语句吗?
是,无本质区别(此处的区别是在于逆向人的眼中)。

五、数组的本质

1、总结:
1.1 一组相同类型的变量,为了方便读写,采用另外一种表示形式.
1.2 数组在声明的时候,必须用常量来指明长度,不能使用变量.

示例:定义10个变量,观察反汇编:

  • 分别赋值

在这里插入图片描述在这里插入图片描述
在缓冲区将数组中的数据一一填入

  • 数组赋值
    在这里插入图片描述
    在这里插入图片描述
    可见在底层是一样的。

六、数组的使用

偏向开发的知识点在这里插入图片描述

结尾依然是,海哥牛逼。

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
第1讲:2015-01-12(进制01) 第2讲:2015-01-13(进制02) 第3讲:2015-01-14(数据宽度-逻辑运算03) 第4讲:2015-01-15(通用寄存器-内存读写04) 第5讲:2015-01-16(内存寻址-堆栈05) 第6讲:2015-01-19(EFLAGS寄存器06) 第7讲:2015-01-20(JCC) 第8讲:2015-01-21(堆栈图) 第8讲:2015-01-21(宝马问题) 第9讲:2015-01-22(堆栈图2) 第10讲:2015-01-23(C语言01_后半段) 第10讲:2015-01-23(C语言完整版) 第11讲:2015-01-26(C语言02_数据类型) 第12讲:2015-01-27(C语言03_数据类型_IF语句) 第13讲:2015-01-28(C语言04_IF语句逆向分析上) 第14讲:2015-01-28(C语言04_IF语句逆向分析下) 第15讲:2015-01-29(C语言04_正向基础) 第16讲:2015-01-30(C语言05_循环语句) 第17讲:2015-02-02(C语言06_参数_返回值_局部变量_数组反汇编) 第18讲:2015-02-02(2015-01-30课后练习) 第19讲:2015-02-03(C语言07_多维数组) 第20讲:2015-02-03(2015-02-02课后练习) 第21讲:2015-02-04(C语言08_结构体) 第22讲:2015-02-05(C语言09_字节对齐_结构体数组) 第23讲:2015-02-06(C语言10_Switch语句反汇编) 第24讲:2015-02-26(C语言11_指针1) 第25讲:2015-02-27(C语言11_指针2) 第26讲:2015-02-28(C语言11_指针3) 第27讲:2015-02-28(C语言11_指针4) 第28讲:2015-03-02(C语言11_指针5) 第29讲:2015-03-03(C语言11_指针6) 第30讲:2015-03-04(C语言11_指针7) 第31讲:2015-03-06(C语言11_指针8) 第32讲:2015-03-09(位运算) 第33讲:2015-03-10(内存分配_文件读写) 第34讲:2015-03-11(PE头解析_手动) 第35讲:2015-03-12(PE头字段说明) 第36讲:2015-03-13(PE节表) 第37讲:2015-03-16(FileBuffer转ImageBuffer) 第38讲:2015-03-17(代码节空白区添加代码) 第39讲:2015-03-18(任意节空白区添加代码) 第40讲:2015-03-19(新增节添加代码) 第41讲:2015-03-20(扩大节-合并节-数据目录) 第42讲:2015-03-23(静态连接库-动态链接库) 第43讲:2015-03-24(导出表) 第44讲:2015-03-25(重定位表) 第45讲:2015-03-26(移动导出表-重定位表) 第46讲:2015-03-27(IAT表) 第47讲:2015-03-27(导入表) 第48讲:2015-03-30(绑定导入表) 第49讲:2015-03-31(导入表注入) 第50讲:2015-04-01(C++ this指针 类 上) 第51讲:2015-04-01(C++ this指针 类 下) 第52讲:2015-04-02(C++ 构造-析构函数 继承) 第53讲:2015-04-03(C++ 权限控制) 第54讲:2015-04-07(C++ 虚函数表) 第55讲:2015-04-08(C++ 动态绑定-多态-上) 第56讲:2015-04-08(C++ 动态绑定-多态-下) 第57讲:2015-04-09(C++ 模版) 第58讲:2015-04-10(C++ 引用-友元-运算符重载) 第59讲:2015-04-13(C++ new-delete-Vector) 第60讲:2015-04-14(C++Vector实现) 第61讲:2015-04-15(C++链表) 第62讲:2015-04-16(C++链表实现) 第63讲:2015-04-16(C++二叉树) 第64讲:2015-04-17(C++二叉树实现) 第65讲:2015-04-20(Win32 宽字符) 第66讲:2015-04-21(Win32 事件-消息-消息处理函数) 第67讲:2015-04-22(Win32 ESP寻址-定位回调函数-条件断点) 第68讲:2015-04-23(Win32 子窗口-消息处理函数定位) 第69讲:2015-04-24(Win32 资源文件-消息断点) 第70讲:2015-04-27(Win32 提取图标-修改标题) 第71讲:2015-04-28(Win32 通用控件-VM_NOTIFY) 第72讲:2015-04-29(Win32 PE查看器-项目要求) 项目一:PE查看器 开发周期(5天) 需求文档 第73讲:2015-05-07(Win32 创建线程) 第74讲:2015-05-08(Win32 线程控制_CONTEXT) 第75讲:2015-05-11(Win32 临界区) 第76讲:2015-05-12(Win32 互斥体) 第77讲:2015-05-13(Win32 事件) 第78讲:2015-05-14(Win32 信号量) 第79讲:2015-05-15(Win32 线程同步与线程互斥) 第80讲:2015-05-18(Win32 进程创建_句柄表) 第81讲:2015-05-20(Win32 以挂起形式创建进程) 第82讲:2015-05-21(Win32 加密壳_项目说明) 项目二:加密壳 开发周期(5天) 需求文档 第83讲:2015-05-28(Win32 枚举窗口_鼠标键盘事件) 第84讲:2015-05-29(Win32 CE练习) 第85讲:2015-06-01(Win32 OD练习) 第86讲:2015-06-03(Win32 ShellCode_远程线程注入) 第87讲:2015-06-04(Win32 加载EXE_模块隐藏) 第88讲:2015-06-09(Win32 IAT_HOOK) 第89讲:2015-06-10(Win32 InlineHook) 第90讲:2015-06-11(Win32 进程通信) 第91讲:2015-06-11(Win32 进程监控_项目说明) 项目三:进程监控 开发周期(5天) 需求文档 第92讲:2015-06-15(硬编码_01) 第93讲:2015-06-16(硬编码_02) 第94讲:2015-06-17(硬编码_03) 第95讲:2015-06-18(硬编码_04) 第96讲:2015-06-19(硬编码_05)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值