函数的工作原理与系统调用


一、函数参数传递机制

(一)程序栈结构(以 32 位为例)

关键寄存器

esp:存储函数调用栈的栈顶地址,在压栈和退栈操作时会发生变化。

ebp:存储当前函数状态的栈底地址,在函数运行过程中保持不变,可用于索引确定函数参数和局部变量的位置。

eip:存储即将执行的程序指令的地址,CPU 依照 eip 的内容读取并执行指令,执行后 eip 指向下一条指令,从而使程序连续执行。

(二)函数调用机制

不同调用方式

cdecl:默认的调用方式,由调用方平衡栈,适用于不确定参数的函数。

stdcall:被调用方平衡栈,不确定参数的函数无法使用这种方式。

fastcall:采用寄存器传参,被调用方平衡栈,同样不适合不确定参数的函数。

(三)cdecl 调用机制介绍(以 32 位程序为例)

代码示例分析

通过caller和callee函数的示例详细展示了 cdecl 调用过程中栈的变化以及寄存器的操作。

在调用函数时,调用方先将参数从右向左依次压栈,然后执行call指令,该指令会将返回地址压栈,并跳转到被调用函数。

被调用函数内部,先将ebp压栈保存当前栈底,然后将esp的值赋给ebp,以便通过ebp来访问参数和局部变量。

函数执行完毕后,先恢复ebp的值(通过pop指令),然后执行ret指令,该指令会将返回地址从栈顶弹出并跳转到调用方继续执行,同时调用方需要手动调整栈指针以平衡栈(通过add指令)。

(四)64 位函数传参

64 位程序的前六个参数依次保存在rdi、rsi、rdx、rcx、r8、r9寄存器中,从第七个参数开始保存在栈上。

二、IDA 逆向功能介绍

(一)IDA 介绍

概述

IDA 全称是交互式反汇编器专业版(Interactive Disassembler Professional),是一款优秀的静态反编译软件。

它支持多种 CPU 指令集,包括 Intel x86、x64、MIPS、PowerPC、ARM 等,是众多 0day 世界成员和 ShellCode 安全分析人士的重要工具。

(二)基本模块

主要模块功能

函数信息窗口:展示文件中的函数相关信息。

分析结果:呈现反汇编分析的结果。

枚举信息:包含相关的枚举数据。

还有导入函数、导出函数、结构体等信息模块。

(三)基本功能

常用操作功能

可以查看伪代码(通过 F5)、查看字符串(Shift + F12)、重命名(R)、创造函数(P)、转化为数据(D)、取消定义(U)等。

还能进行搜索操作,如以字符串搜索(Ctrl + F)、查找交叉引用(X),以及查看段和节(Ctrl + S)等。

(四)修复结构体和数组

结构体修复

介绍了在 IDA 中修复结构体的方法,包括打开本地类型创建目录、编写自定义结构、设置结构体指针类型以及根据数据大小修改结构体等步骤,并通过例题 SWPUCTF_2019_p1KkHeap 进行了说明。

数组修复

阐述了修复数组的方法,如找到数组相关内容后在汇编窗口设置类型,根据类型和长度设置后可解除定义再重新定义,最后回到反汇编窗口按 F5 查看改变,以例题 CISCN2023 华中赛区分区赛 AWD 的 PWN 题为例进行讲解。

(五)动态调试功能

本地动调

直接使用 IDA 打开要调试的程序,在 Debugger 选项中选择 local windows debugger,然后通过 start process 即可开始调试。

远程动调

需要先将程序复制到远程系统中并执行,在本地 IDA 中设置调试器为 remote GDB debugger,并配置相关的文件位置和远程系统的 IP 及端口信息,最后通过 start process 进行调试。

三、elf 程序介绍与程序装载流程

(一)ELF 文件介绍

定义与分类

ELF 文件是 Linux 下的可执行文件,类似于 Windows 下的.exe 文件,分为动态编译文件和静态编译文件两种。

(二)生成方式

从代码到机器码的过程

通过一个简单的sum函数示例,展示了从 C 语言代码到汇编代码再到机器码的编译过程。

(三)内存映射

32 位和 64 位 ELF 程序内存映射

介绍了 32 位和 64 位 ELF 程序在内存中的映射情况,包括不同的段(如 Text Segment、Data Segment、BSS 等)以及它们在内存中的位置和属性。

(四)动态链接过程

详细描述了动态链接程序的执行过程,包括从execve系统调用开始,经过fork、sys_execve、do_execve、search_binary_handler、load_elf_binary等一系列系统调用和函数调用,最终加载动态链接库并执行main函数。

(五)静态链接过程

介绍了静态链接程序的执行过程,与动态链接过程相比,静态链接在加载程序时会将所有需要的库代码直接链接到可执行文件中,不需要在运行时加载动态库。

(六)入口点分析

指出 main 函数并不是 ELF 程序载入内存后执行的第一条指令,但程序的主体功能是在 main 函数调用后开始的,通常从 main 函数开始分析即可。

(七)入口点寻找方法

通过在 IDA 中搜索start、main字符串来寻找 ELF 程序入口点,对于无符号表的固件,需要通过程序运行和特殊含义的字符串先定位功能函数,再通过交叉引用确定入口点。

四、系统调用介绍

(一)Linux 系统调用介绍

定义与作用

Linux 系统调用是应用程序与操作系统内核进行交互的接口,应用程序通过系统调用请求内核提供各种服务,如文件操作、进程控制、网络通信等。

(二)计算机启动流程

启动过程中的系统调用

计算机启动时,先执行 BIOS 程序,BIOS 加载引导扇区内容,然后由加载程序接管,最终执行操作系统程序。这个过程涉及到多个系统调用和程序加载步骤。

(三)中断、异常和系统调用比较

概念区分

系统调用:是应用程序主动向操作系统发出的服务请求,可以是同步或异步的。

异常:由于非法指令或其他原因导致的指令执行失败,是同步发生的。

中断:由硬件设备发出的处理请求,是异步的。

(四)实现机制

进入内核态的方式

32 位程序通过int指令实现系统调用,进入内核态后会先执行alltraps()函数获取中断相关信息,再根据trap()函数确定中断类型,如果是系统调用则转到syscall函数,该函数获取系统调用号并转到相应的系统函数中。

64 位程序通过syscall指令实现系统调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值