首页 > 编程语言 >【逆向】x64程序逆向基础——调用约定和栈使用

【逆向】x64程序逆向基础——调用约定和栈使用

时间:2023-04-21 19:56:20浏览次数:59  
标签:逆向 调用 函数 x64 mov eax 参数 寄存器 rsp

【逆向】x64程序逆向基础

 

主要区别

1. 所有地址指针都是64位。
2. 增加和扩展新的寄存器,并兼容原32位版本的通用寄存器。
3. 原指令指针寄存器EIP扩展为RIP。

寄存器

1. 64位寄存器兼容原32位寄存器。
2. 新增加8个XMM寄存器(XMM8-XMM15)。
3. 扩展原32位寄存器的64位版本,并增加8个新的64位寄存器(R8-R15)。

// 通用寄存器:RAX(64位),EAX(32位),AX(16位),AL(0-7位),AH(8-15位)
// 新增寄存器:R8(64位),R8D(32位),R8W(16位),R8B(8位)

调用约定

1. x86使用stdcall、cdecl、Fastcall等。
2. x64使用类似“Fastcall”的调用约定。
使用RCX、RDX、R8、R9寄存器传递前4个参数,其余参数从右往左依次保存在栈上。
3. 浮点参数使用XMM寄存器传递(XMM0-XMM3)。
4. 任何在函数开头的mov指令都是在保存被传递到这个函数的参数,编译器不会再其中插入做其它事情的mov指令。
复制代码
1 mov dword ptr [rsp+28h] ,6     //参数6 保存在栈中
2 mov dword ptr [rsp+20h] ,5     //参数5 保存在栈中
3 mov r9d ,4                     //参数4 保存在寄存器中
4 mov r8d ,3                     //参数3 保存在寄存器中
5 mov edx ,2                     //参数2 保存在寄存器中
6 mov ecx ,1                     //参数1 保存在寄存器中
7 call Fun                       //调用函数
复制代码

栈使用

1. 32位代码在函数中使用push和pop等指令改变栈的大小。
2. 64位代码在函数中从不改变栈的大小,栈在函数的开始增长,期间一直保持不变,直到函数末尾。
3. 当一个函数调用另一个函数时,调用函数会多申请32字节(0x20)的预留栈空间,当被调用函数寄存器不够用时,可以将4个参数寄存器(RCX、RDX、R8、R9)中的值保存在申请的预留栈空间中。
预留栈空间由函数调用者提前申请,也由函数调用者负责平衡回收。
注意:如果一个函数有其他参数(>4个)或局部栈变量,函数会在0x20的基础上增加预留栈空间的大小,有时增加大小后的值需要与16进行对齐。

示例代码

复制代码
 1 #include "stdafx.h"
 2 
 3 // Add
 4 int Add(int nl, int n2, int n3, int n4, int n5, int n6)
 5 {
 6     return nl+n2+n3+n4+n5+n6;
 7 }
 8 
 9 // Main
10 int tmain(int argc, TCHAR* argv[])
11 {
12     printf("%d\r\n", Add(1,2,3,4,5,6));
13     return 0;
14 }
复制代码

 Main函数反汇编

复制代码
 1 // 保存Main函数参数到预留栈空间,此预留栈空间为其它函数调用Main函数时申请
 2 mov[rsp+10h], rdx            // 将参数2保存到预留栈空间中
 3 mov[rsp+8h], ecx             // 将参数1保存到预留栈空间中
 4 
 5 // Main函数作为调用者申请预留栈空间,用于保存Add函数的参数
 6 push rdi                     // 保存环境
 7 sub rsp, 30h                 // 申请预留栈空间(Add函数6个参数)(6*8=48 0x30)
 8 mov rdi, rsp                 // 将栈空间初始化为0xcC
 9 mov ecx, 0Ch
10 mov eax, 0CCCCCCCCh
11 rep stosd
12 
13 // 调用Add函数,前4个参数使用寄存器,其余参数入栈
14 mov ecx, [rsp+40h]
15 mov dword ptr [rsp+28h], 6   // 参数6入栈
16 mov dword ptr [rsp+20h], 5   // 参数5入栈
17 mov r9d, 4                   // 参数4
18 mov r8d, 3                   // 参数3
19 mov edx, 2                   // 参数2
20 mov ecx, 1                   // 参数1
21 cal1 Add                     // 调用Add函数
22 
23 // 调用pirntf函数
24 mov edx, eax                 // 将返回值保存到edx中
25 lea rcx, Format              // "%d\r\n"
26 cal1 printf                  // 调用pirntf函数
27 xor eax, eax                 // 设置返回值
28 
29 // Main函数作为调用者释放预留栈空间
30 add rsp, 30h                 // 释放预留栈空间+2个参数的栈空间(Add参数5,6)
31 pop rdi                      // 恢复环境
32 retn                         // 函数返回
复制代码

 Add函数反汇编

复制代码
 1 // 保存Add函数前4个参数到预留栈空间,预留栈空间由Mian函数申请和释放
 2 mov[rsp + 20h], r9d     // 参数4
 3 mov[rsp + 18h], r8d     // 参数3
 4 mov[rsp + 10h], edx     // 参数2
 5 mov[rsp + 08h], ecx     // 参数1
 6 
 7 // Add函数中没有调用其它函数和局部变量,所以没有申请预留栈空间
 8 push rdi               // 保存环境
 9 mov eax, [rsp + 18h]    // eax = 参数2
10 mov ecx, [rsp + 10h]    // ecx = 参数1
11 add ecx, eax           // ecx = 参数1+参数2
12 mov eax, ecx           // eax = ecx
13 
14 // 使用预留栈空间来获取Add函数参数
15 add eax, [rsp + 20h]    // eax+参数3
16 add eax, [rsp + 28h]    // eax+参数4
17 add eax, [rsp + 30h]    // eax+参数5
18 add eax, [rsp + 38h]    // eax+参数6
19 
20 // 再次印证预留栈空间由调用函数(Main函数)释放
21 pop rdi                // 恢复环境
22 retn                   // 函数返回
复制代码

标签:逆向,调用,函数,x64,mov,eax,参数,寄存器,rsp
From: https://www.cnblogs.com/bonelee/p/17341553.html

相关文章

  • xv6 exec系统调用
    exec是一个创建用户地址空间的系统调用。根据一个存储在文件系统中的file来创建用户地址空间。具体来说,intexec(char*path,char**argv)exec使用namei打开指定的二进制文件路径(kernel/exec.c:26)。exec读取ELF(可执行与可链接格式)文件头。xv6应用程序遵循广泛使用的......
  • cesium源码编译调试及调用全过程
    完整记录一次cesium源码从下载、打包、调用、调试的全过程。本文使用软件或API版本:VSCodeNode:12.18.3cesium版本:1.94总体步骤:下载源码执行npminstall和npmstart启动web服务打包源码(打包前可以先将申请到的cesium的token更改到ion.js文件中的默认值中)运行测试html页面......
  • python调用imgkit将html转图片pdf问题实例wkhtmltox
    wkhtmltox的下载地址:https://wkhtmltopdf.org/downloads.html或者:https://github.com/wkhtmltopdf/wkhtmltopdf0.12.6版本按网络上的教程会出现一个错误:IOError:wkhtmltopdfexitedwithnon-zerocode1.error:[blank]解决方法参见:https://stackoverflow.com/questions/......
  • Python调用C程序
    1.将C程序编译为动态库;2.python代码加载动态库调用C函数......
  • PageOffice调用本地office实现多人在线同时编辑Word文档
    说明:多人同时在线编辑文件大多数会出现文档相互覆盖的问题,后保存的文档会覆盖先保存的文档。pageoffice的这个功能可以用程序控制不同用户打开文件后,编辑Word文档中属于自己的区域,并且不会互相影响。1、环境:前端:vue后端:springboot、pageoffice5.4.0.3版本vue+springboot集成pa......
  • 请注意游客模式下,调用 wx.operateWXData 是受限的
    报这个错误是因为AppID的问题第一步,在小程序界面点击设置,点击最后一个项目设置  第二步,出现下图右侧弹窗选择红框中的基本信息 第三步,在基本信息中找到appid点击修改,换成小程序中自己的appid即可 ......
  • H5混合开发二维码扫描以及调用本地摄像头
    H5混合开发二维码扫描以及调用本地摄像头 [转]http://www.jianshu.com/p/c952b3a5e1d2今天主管给了我个需求,说要用混合开发,用H5调用本地摄像头进行扫描二维码,我之前有做过原生安卓的二维码扫一扫,主要是通过调用zxing插件进行操作的,其中还弄了个闪光灯.但是纯H5的没接触......
  • app逆向之安卓native层安全逆向分析(二):unidbg+ida使用+过签名校验
    前言继续跟着龙哥的unidbg学习:SO逆向入门实战教程二:calculateS_so逆向_白龙~的博客-CSDN博客还是那句,我会借鉴龙哥的文章,以一个初学者的角度,加上自己的理解,把内容丰富一下,尽量做到不在龙哥的基础上画蛇添足,哈哈。感谢观看的朋友分析 首先抓包分析: 其中,里面的s就是今天......
  • 在Java代码中更优雅地调用Kotlin
    -Kotlin与Java良好的互操作性是其能够快速普及的原因之一。从Java虽然可以访问Kotlin,但是通过下面这些技巧可以让对Kotlin的访问变得更加友好和地道@JvmStaticKotlin中可以使用objectclass创建单例objectAnalytics{funinit(){...}funsend(event:Event){...}......
  • mybatis 调用 oracle 带包存储过程(有out参数)
    https://blog.csdn.net/u010925982/article/details/102958001  1.先写xml映射文件<selectid="call"parameterType="java.util.HashMap"statementType="CALLABLE"resultType="java.util.HashMap"><!--call包名.方法名(参数)-......