windows二进制安全零基础(二)
文章目录
- 栈(The Stack)
- 调用约定(Calling Conventions)
- 函数返回机制
在x86架构中,栈(Stack)是一个非常重要的内存区域,它用于支持线程的短期数据需求,如函数调用、局部变量存储和程序控制信息。下面是对栈和调用约定的详细介绍:
栈(The Stack)
栈是一种后进先出(LIFO)的数据结构,CPU通过专用的PUSH和POP汇编指令来操作栈。当线程执行时,它会从程序映像或动态链接库(DLLs)中执行代码。每个运行中的线程都有自己的栈,以支持多线程的独立执行。
- PUSH:将数据压入栈顶。
- POP:从栈顶弹出数据。
栈的主要用途包括:
- 函数调用:存储函数的返回地址,以便函数执行完毕后能够返回到正确的代码位置。
- 局部变量:存储函数内部声明的局部变量。
- 程序控制信息:存储函数调用时的上下文信息,如寄存器的值。
调用约定(Calling Conventions)
调用约定定义了函数如何接收参数以及如何返回结果。x86架构支持多种调用约定,它们在实现上的差异包括参数和返回值的传递方式(使用CPU寄存器、压入栈中或两者结合)、传递顺序、调用前后栈的准备和清理方式,以及被调用函数需要为调用者保留哪些CPU寄存器。
常见的x86调用约定包括:
- cdecl:由调用者清理栈。通常用于C语言函数,允许函数有可变数量的参数。
- stdcall:由被调用者清理栈。通常用于Windows API函数。
- fastcall:前两个参数(如果有的话)通过寄存器传递,其余参数通过栈传递。用于快速函数调用。
- thiscall:通常用于C++成员函数。第一个参数(this指针)通过ECX寄存器传递,其余参数通过栈传递。
调用约定的选择通常由编译器决定,但在某些情况下,程序员可以在函数级别指定特定的调用约定。这可以通过函数声明时的调用约定关键字来实现。
调用约定的选择对程序的性能和兼容性有重要影响。例如,使用寄存器传递参数可以减少栈操作,从而提高函数调用的速度。而不同的调用约定也可能影响函数之间的接口兼容性,因此在跨模块调用时需要特别注意调用约定的一致性。
在x86架构中,函数返回机制和CPU寄存器是理解程序执行流程的关键。下面是对这些概念的详细解释:
函数返回机制
当线程中的代码调用一个函数时,它必须知道函数完成后返回到哪个地址。这个“返回地址”(连同函数的参数和局部变量)存储在栈上。这些数据的集合与一个函数调用相关联,并存储在栈内存的一个部分,称为栈帧(stack frame)。栈帧是函数调用期间用于存储所有必要信息的数据结构。
一个典型的栈帧可能包含以下内容:
- 返回地址:函数执行完毕后,控制权返回到此地址。
- 参数:调用函数时传递的参数。
- 局部变量:函数内部声明的变量。
- 旧的基指针(EBP):用于指向当前栈帧的开始位置。
当函数结束时,返回地址从栈中取出,用于将执行流恢复到调用函数。
为了执行高效的代码,CPU维护并使用一系列寄存器。在32位架构中,这些寄存器通常是32位的。寄存器是CPU内部的小型、极高速的存储位置,数据可以在这里高效地读取或操作。
在x86架构中,有九个主要的32位寄存器,包括:
- EAX:累加器,用于存储函数返回值。
- EBX:基址寄存器,通常用于存储数据段的地址。
- ECX:计数器,用于循环和字符串操作。
- EDX:数据寄存器,用于I/O操作和与EAX一起存储大数值。
- ESI:源索引寄存器,用于字符串和数组操作。
- EDI:目标索引寄存器,用于字符串和数组操作。
- ESP:栈指针,指向栈顶。
- EBP:基指针,用于访问栈帧中的变量。
- EIP:指令指针,存储下一条要执行的指令的地址。
这些寄存器的名称源自16位架构,并在32位(x86)平台出现时进行了扩展,这就是寄存器缩写中字母“E”的来源(表示“扩展”)。每个寄存器可以包含一个32位值(允许值在0到0xFFFFFFFF之间),或者在相应的子寄存器中包含16位或8位值,如EAX寄存器的AX、AH和AL子寄存器所示。
在CPU级别,函数调用和返回涉及到以下几个步骤:
-
函数调用:
- 使用
CALL
指令调用函数时,CPU自动将下一条指令的地址(返回地址)推入栈中。 - 控制权转移到函数的起始地址。
- 使用
-
函数执行:
- 函数可能使用
PUSH
和POP
指令来保存和恢复寄存器的值。 - 局部变量和参数可以通过修改ESP(栈指针)来在栈上分配空间。
- 函数可能使用
-
函数返回:
- 使用
RET
指令从栈中弹出返回地址,并将其赋值给EIP(指令指针)。 - 控制权返回到调用函数,继续执行。
- 使用
理解这些机制对于深入理解程序如何在底层工作至关重要,尤其是在调试和性能优化时。
ESP - 栈指针
正如之前提到的,栈用于存储数据、指针和参数。由于栈是动态的,并且在程序执行过程中不断变化,栈指针ESP通过存储一个指向栈上最近引用位置(栈顶)的指针来“跟踪”它。
指针是对内存中地址(或位置)的引用。当我们说一个寄存器“存储一个指针”或“指向”一个地址时,这基本上意味着该寄存器正在存储那个目标地址。
EBP - 基指针
由于在执行线程期间栈不断变化,函数定位其栈帧可能变得困难,栈帧存储了所需的参数、局部变量和返回地址。基指针EBP通过存储一个指向函数被调用时栈顶的指针来解决这个问题。通过访问EBP,函数在执行期间可以轻松引用其栈帧中的信息(通过偏移量)。
EIP - 指令指针
EIP,指令指针,是我们目的中最重要的寄存器之一,因为它总是指向下一个要执行的代码指令。由于EIP基本上指导了程序的流程,因此在利用任何内存破坏漏洞(如缓冲区溢出)时,它是攻击者的主要目标。
2.2 Windows调试器简介
现在我们已经理解了x86架构的基本概念,是时候探索调试工具了。
在Windows上有几个可用的调试程序。OllyDbg和Immunity Debugger因其用户友好的界面而在逆向工程和漏洞开发领域广为人知。Immunity Debugger最初是OllyDbg的一个分支,但现在已经超越了OllyDbg的功能。
尽管这些程序使用方便,虽然存在一个针对64位的OllyDbg的开源实现,但它并不提供与WinDbg相同的功能或支持。
WinDbg也是我们首选的调试器,因为它可以在用户模式和内核模式下进行调试,这使其成为开发在Windows上利用的任何类型漏洞的最佳选择。WinDbg作为软件开发工具包(SDK)、Windows驱动程序开发工具包(WDK)和Windows调试工具的一部分,免费提供。
微软发布了一个名为WinDbg Preview的WinDbg版本。它具有更直观的界面以及额外的功能,如时间旅行调试和用于脚本支持的JavaScript API。然而,WinDbg Preview仅在Windows 10周年纪念版(1607/RS1)及更高版本上工作。
调试器是一个计算机程序,它被插入到目标应用程序和CPU之间,原则上,它就像一个代理。调试器允许开发者暂停程序的执行、单步执行代码、检查和修改程序的状态,以及执行其他各种诊断任务,从而帮助开发者理解和修复程序中的错误或异常行为。
相关文章:
windows二进制安全零基础(二)
文章目录 栈(The Stack)调用约定(Calling Conventions)函数返回机制 在x86架构中,栈(Stack)是一个非常重要的内存区域,它用于支持线程的短期数据需求,如函数调用、局部变…...
git常用命令+搭vscode使用
1.克隆远程代码 git clone http:xxx git clone ssh:xxx clone的url 中 https和 ssh是有区别的: git中SSH和HTTP连接有什么区别-CSDN博客 当然https拉下来的代码每次pull /push都需要验证一次自己的账户和密码,可以config进行配置不用每次手敲: 解决VScode中每次git pu…...
如何在C#中处理必盈接口返回的股票数据?
在必盈接口返回股票数据后,在 C# 中可通过以下步骤进行处理: 数据获取 使用 HttpWebRequest 或 HttpClient 类向必盈接口发送请求以获取数据。以 HttpWebRequest 为例,构建请求并发送,获取响应流后读取为字符串形式的 JSON 数据。…...

01 最舒适的python开发环境
0 前言 我自己经过尝试,总结出python3开发环境的最舒适方式。 python3安装创建虚拟环境 venvjupyter notebook 笔记本安装vscode插件(Python, Pylance, Jupyter) 1 python3安装 ubuntu系统下安装最新版本的python3 sudo apt update sudo apt install python32 …...
【PyTorch】libtorch_cpu.so: undefined symbol: iJIT_NotifyEvent
【PyTorch】libtorch_cpu.so: undefined symbol: iJIT_NotifyEvent 1 报错信息2 原因3 解决方法 1 报错信息 conda install pytorch1.13.1 torchaudio0.13.1 torchvision0.14.1 cudatoolkit11.7 -c pytorch在 conda 环境中安装 torch 后测试,得到下面的错误&#x…...

快速利用c语言实现线性表(lineList)
线性表是数据结构中最基本和简单的一个,它是n的相同类型数据的有序序列,我们也可以用c语言中的数组来理解线性表。 一、线性表声明 我们定义一个线性表的结构体,内部有三个元素:其中elem是一个指针,指向线性表的头&am…...

量子计算与人工智能的交汇:科技未来的新引擎
引言 在当今飞速发展的科技世界,人工智能(AI)和量子计算无疑是最受瞩目的两大前沿领域。人工智能凭借其在数据处理、模式识别以及自动化决策中的强大能力,已经成为推动各行业数字化转型的重要力量。而量子计算则通过颠覆传统计算机…...
51单片机使用NRF24L01进行2.4G无线通信
本文并不打算详细介绍NRF24L01的各个功能寄存器及指令的详细用法,因为网上都可以搜到很多非常详细的教程文档,这里只是介绍一些基本概念、用法以及代码的解释,旨在帮助新手能够快速上手调通快速使用。 基础概念 该模块使用的是SPI协议&…...

HelloMeme 上手即用教程
HelloMeme是一个集成空间编织注意力的扩散模型,用于生成高保真图像和视频。它提供了一个代码库,包含实验代码和预训练模型,支持PyTorch和FFmpeg。用户可以通过简单的命令行操作来生成图像和视频。 本文将详细介绍,如何在GPU算力租…...
自定义call方法和apply方法
自定义call方法 //Fn:要执行的函数,obj:函数中this的指向,args:剩余参数function call(Fn, obj, ...args) {//判断if (obj undefined || obj null) {obj globalThis; //全局对象 globalThis:es11新增的特性,用来指向…...
typescript中为js文件提供类型声明
案例:为JS文件提供类型声明 场景描述 假设我们有一个JavaScript文件 utils.js,其中包含一些实用工具函数和变量。为了在TypeScript中使用这些函数和变量并获得类型提示,我们可以使用 declare 关键词为它们提供类型声明。 1. 创建 JavaScri…...
ETH挖矿显卡超频信息汇总
NVIDIA 显卡 显卡型号 核心频率增减量 内存频率增减量 功耗墙(W) 预估算力(ethash算法) RTX 3090-3001000285W / 80%120 MH/sRTX 3080-150900220W / 68%98 MH/sRTX 3070-5001100130W / 60%60 MH/sRTX 3060 Ti-5001200130W / 65%60 MH/sRTX 2080 Ti-2001100150W /…...

调用 Xinference OpenAI接口时报错 Model not found in the model list, uid
错误如下, 请不要被错误吓住或蒙蔽双眼, 自己看最下面的报错内容 Traceback (most recent call last): File "C:\Users\HW\.conda\envs\aibot\Lib\site-packages\starlette\responses.py", line 259, in __call__ await wrap(partial(self.listen_for_disconn…...
一文说清:C静态库与动态库的区别
一 前言 大家在用C语言编程时,一定会遇到各种库,它们为开发者提供了大量的预编译函数和数据结构,从而极大地提高了软件开发的效率。 在C语言中,库主要分为两种类型: 静态库(Static Library)&…...
Mysql 5.7.6以上版本怎样关闭GTID(由GTID改为基于file,position方式)
平时不建议关闭GTID,假如开启GTID遇到问题,需要回退到基于file,position方式,则可以执行如下步骤: 1.在从库停止主从复制: STOP SLAVE; CHANGE MASTER TO MASTER_AUTO_POSITION 0; START SLAVE; SHOW SLAVE STAT…...

MATLAB常见数学运算函数
MATLAB中含有许多有用的函数,可以随时调用。 a b s abs abs函数 a b s abs abs函数在MATLAB中可以求绝对值,也可以求复数的模长:c e i l ceil ceil函数 向正无穷四舍五入(如果有小数,就向正方向进一)f l o o r floor floor函数 向负无穷四舍五入(如果有小数,就向负方向…...

设置Fusion360 - Prusa slicer -octoprint 一键打印流程
此流程可以直接从fusion360导出文件到prusa slicer切片,切片后可以一键上传并开始打印。以下操作在MacOS中进行,Windows也可以参考。 Fusion360中点击文件-3D打印 弹出对话框中点击应用程序,并在从我的计算机选择中选取Prusa Slicer的可执行…...

IO流实用案例:用字节流--输入流(Inpustream)、输出流(OutputStream)写一个拷贝图片的案例--超简单!
案例背景: 我的电脑桌面有一张白敬亭的照片,我们需要把这张照片拷贝到我的电脑D:\学习软件\copyBJT目录下,当前我们这个目录是没有东西的。 代码演示以及注释: ublic class StreamCopy {public static void main(String[] args)…...

Tensorflow基本概念
简介:本文从Graph讲到Session,同时讲解了tf.constant创建tensor的用法和variable需要初始化的知识点,可以给你打好一个学习Tensorflow的基础。本文都是基于TensorFlow1.14.0的版本下运行。 本专栏将会系统的讲解TensorFlow在1.14.0版本下的各…...

游戏引擎学习第九天
视频参考:https://www.bilibili.com/video/BV1ouUPYAErK/ 修改之前的方波数据,改播放正弦波 下面主要讲关于浮点数 1. char(字符类型) 大小:1 字节(8 位)表示方式:char 存储的是一个字符的 A…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...