汇编层面分析函数调用

栏目: 编程语言 · 发布时间: 6年前

内容简介:汇编语言是学习逆向的基础,本文通过从汇编的层面分析知识有限,如果有错误或则不清楚的地方还请您指出。您的鼓励是我写文章的动力。

前言

汇编语言是学习逆向的基础,本文通过从汇编的层面分析 函数调用 来了解 压栈、跳转、执行、返回 的具体实现流程以及对 堆栈 的应用。

知识有限,如果有错误或则不清楚的地方还请您指出。

您的鼓励是我写文章的动力。

1. 函数调用的说明

在介绍函数调用的具体流程前,我们先来了解一下几个知识点。

  • 1.1 程序的执行流程

程序是顺序执行的,cpu是怎么进行实现的呢?

程序的执行离不开一个关键的寄存器。

我们首先来了解一下关于 程序计数器 的概念。

百度百科:

汇编层面分析函数调用

由此可见,程序计数器的功能就是存放下一条要执行指令的地址。

在X86汇编中,执行程序计数功能的寄存器叫做 EIP ,指令指针寄存器。

我们可以写个简单的程序,查看反汇编了解一下。

汇编层面分析函数调用

EIP寄存器里面存放的就是即将要执行指令的地址。

  • 1.2 程序的栈结构

在经典的操作系统里,栈总是 向下增长 的。栈顶由 esp寄存器 定位。压栈操作使栈顶的地址减小,弹出操作使栈顶地址增大。

函数的调用离不开栈,栈中保存了函数调用当中的所有信息。

  • 函数的返回地址和参数;

  • 函数的非静态的局部变量;

  • 保存上下文:保存一些不需要改变的寄存器。

为了能够正确的处理函数调用的堆栈平衡,我们需要更正两个寄存器ebp,esp的位置:

1. 把ebp提升到esp的位置。

2. esp的值是动态变化的,随着申请更多的临时变量,e's'p会不断减小。

3. 调用函数后栈中的结构图。

汇编层面分析函数调用

  • 1.3 调用约定及堆栈平衡

在函数调用过程中,参数需要提前压栈,而在函数调用结束后,之前压栈的参数也需要退栈。

这样就有一个问题,退栈的工作是交给 调用者 完成还是交给 被调用函数 完成?

这就需要有个约定。

常见调用约定的堆栈平衡方式:

调用约定 堆栈平衡方式
__stdcall 函数自己平衡
__cdecl 调用者负责平衡
__thiscall 调用者负责平衡
__fastcall 调用者负责平衡
__naked 有编写者负责

2. 函数调用的流程

了解了基本的概念之后,回到主题: 函数调用

  • 压栈:函数参数压栈 返回地址压栈

  • 跳转:跳转到函数所在代码处执行

  • 执行:执行函数代码

  • 返回:平衡堆栈 找出返回地址并跳回

  • 2.1 call指令

0x210000 call swap;
0x210005 mov ecx,eax;

call指令可以分解成两个指令:

push 0x210005;
jmp swap;

首先push当前指令下一条指令的地址,目的是调用完函数后可以跳回来;

然后修改 eip, 跳到函数的地址。

  • 2.2 ret指令 

ret指令表示取出当前栈顶值作为返回地址,将 eip 修改为该地址。

执行完这一步一个基本的函数调用就完成了。

3. 函数调用汇编实验

测试程序

在main函数中调用一个交换两个数的函数。

#include <stdio.h>
 
 
void _stdcall swap(int& a,int& b);
 
 
//交换两个数
void _stdcall swap(int& a, int& b)
{
    int c = a;
    a = b;
    b = c;
}
 
 
void main()
{
 
    int a = 1;
    int b = 2;
    printf("交换前:a =%d,b=%d\n",a,b);
    swap(a,b);
    printf("交换后:a= %d,b=%d\n",a,b);
 
    getchar();
 
}

程序的运行结果:

汇编层面分析函数调用

  • 3.1 压栈

    • 3.1.1 函数参数压栈

真正调用函数前先将参数进行压栈。

汇编层面分析函数调用

我们通过观察寄存器和内存来查看变化过程:

汇编层面分析函数调用

发现参数已经被压入栈中。

    • 3.1.2 返回地址压入栈中

F11进入swap函数后,可以发现内存当中凭空出现一段数,它是什么?

汇编层面分析函数调用

其实它就是call指令的下一条指令的地址:

汇编层面分析函数调用

  • 3.2 跳转

跳转到swap函数内部,下面是详细注解

汇编层面分析函数调用

  • 3.3 返回

执行ret前。

汇编层面分析函数调用

执行ret后, 帖前先滑动左侧填充拼图:

汇编层面分析函数调用

由于使用的是 __stdcall 的调用约定,在被调用函数内部进行堆栈平衡。

4. 结语

这样,一个函数调用的实现就分析完成了。有好多细节的问题没有进行阐述。这样一篇文章用来总结汇编的知识点,希望遇到同道中人。

成为逆向大牛的过程是艰辛的,你已经迈出了第一步,加油。

- End -

汇编层面分析函数调用

看雪ID:Jabez                      

https://bbs.pediy.com/user-825190.htm

本文由看雪论坛 Jabez   原创

转载请注明来自看雪社区

汇编层面分析函数调用

书籍推荐:

  • 《加密与解密》

是一本逆向必读书籍。本书以软件逆向为切入点,讲述了软件安全领域相关的基础知识和技能,可以说是安全人士必读书籍之一了。

看雪推荐“解密”前的过渡书籍:

  • 基普·欧文的《汇编语言:基于x86处理器》

  • 王爽的《汇编语言》

  • Charles Petzold著的《Windows程序设计》(以VC来讲解)

长按识别二维码,即可购买以上书籍

汇编层面分析函数调用


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Definitive Guide to HTML5 WebSocket

The Definitive Guide to HTML5 WebSocket

Vanessa Wang、Frank Salim、Peter Moskovits / Apress / 2013-3 / USD 26.30

The browser is, hands down, the most popular and ubiquitous deployment platform available to us today: virtually every computer, smartphone, tablet, and just about every other form factor imaginable c......一起来看看 《The Definitive Guide to HTML5 WebSocket》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具