《逆向工程核心原理》第三~五章知识整理

查看上一章节内容《逆向工程核心原理》第一~二章知识整理

对应《逆向工程核心原理》第三章到第五章内容

小端序标记法

  • 字节序
    • 多字节数据在计算机内存中存放的字节顺序
    • 分为小端序和大端序两大类
  • 大端序与小端序
BYTE b = 0x12;
WORD w = 0x1234;
DWORD dw = 0x12345678;
char str[] = "abcde";

TYPE

Name

字节

大端序

小段序

BYTE

b

1

[12]

[12]

WORD

w

2

[12][34]

[12][34]

DWORD

dw

4

[12][34][56][78]

[78][56][34][12]

char[]

str

6

[61][62][63][64][65][00]

[61][62][63][64][65][00]

  • 1 字节,在二进制是 8 位,在十六进制是 2 位
  • 内存地址:从低到高增长(如 0x10000x10010x1002)。
  • 数据的高/低位:数值的权重高低。例如,0x12345678 中:
    • 高位字节是 0x12(权重最大,像数字的“千位”),
    • 低位字节是 0x78(权重最小,像数字的“个位”)
  • 大端序:内存的低地址存储数据的高位字节
    • 人类视角:从左到右(地址递增)阅读,数值顺序不变,符合直觉。
    • 网络传输(网络字节序)、某些文件格式(如JPEG)
    • 保存多字节数据很直观
  • 小端序:低位字节在低地址,高位字节在高地址
    • 硬件视角:低地址存低位字节,方便逐字节处理(如加法从低位开始)
    • x86/x64架构CPU,内存中直接处理低位数据更高效
  • 字符串:最后是以 NUll 结尾,a 的 ASCII 码十六进制是 0x61
    • 字符串被保存在一个字符数组中,字符数组在内存中是连续的,无论采用大端序还是小端序,存储顺序都相同

在 OllyDbg 中查看 LittleEndian.exe 文件

#include "windows.h"
BYTE b = 0x12;
WORD w = 0x1234;
DWORD dw = 0x12345678;
char str[] = "abcde";int main(int argc, char *argv[])
{byte lb = b;WORD lw = w;DWORD ldw = dw;char *lstr = str;return 0;
}

直接给出 main() 函数的地址,按 Ctrl+G 跳转到 401000 地址处

可以看到我们的定义的变量 0x12 地址应该是 40AC40

可以发现,这些数据使用小端序存储

IA-32 寄存器

寄存器

  • 寄存器是 CPU 内部用来存储数据的一些小型存储区域,有非常高的读写速度
  • 与 RAM(随机存储器、内存)略有不同,CPU 访问 RAM 中的数据时要经过较长的物理路径,花费时间长

学习程序调试技术,需要学习调试器解析出的汇编指令

IA-32 提供了庞大的汇编指令,指令可以翻看 Intel 提供的用户手册了解,大部分汇编指令用于操作寄存器或检查其中的数据

IA-32 寄存器

IA-32 是英特尔推出的 32 位元架构,属于复杂的指令集架构,支持多种寄存器

基本程序运行寄存器是 IA-32 寄存器的一种

基本程序运行寄存器

E 表示扩展,表示该寄存器在 16 位 CPU(IA-16)时已存在,并且其大小在 IA-32 下由原 16 位扩展为 32 位

通用寄存器

  • 4 字节 32 位,保存常量与地址
  • 传送和暂存数据,参与算术逻辑运算,保存运算结果

  • 各寄存器
    • EAX:累加器(针对操作数和结果数据)
      • 用在函数返回值中,所有 Win32 API 函数都会先把返回值保存到 EAX 再返回
    • EBX:基址寄存器(DS 段中的数据指针)
    • ECX:计数器(字符串和循环操作)
      • 也可以用在循环命令(LOOP)中循环计数,每执行一次循环,ECX 减 1
    • EDX:数据寄存器(I/O 指针)

以上 4 个寄存器主要用在算法运算(ADD、SUB、XOR、OR)指令中,常用来保存常量与变量的值

某些汇编指令(MUL、DIV、LODS)直接操作特定寄存器,执行这些命令,仅改变特定寄存器的值

    • EBP:扩展基址指针寄存器(SS 段中栈内数据指针)
      • 表示栈区域的基地址,函数被调用时保存 ESP 的值,函数返回时再把值返回 ESP,保证栈不会崩溃(即栈帧技术)
    • ESI:源变址寄存器(字符串操作源指针)
    • EDI:目的变址寄存器(字符串操作目标指针)
    • ESP:栈指针寄存器(SS 段中栈指针)
      • 指示栈区域的栈顶地址,某些指令(PUSH、POP、CALL、PET)可以直接用来操作 ESP

后四个寄存器主要用作保存内存地址的指针

  • 对低 16 位兼容
    • EAX:(0~31)32 位
    • AX:(0~15)EAX 的低 16 位
    • AH:(8~15)AX 的高 8 位
    • AL:(0~7)AX 的低 8 位

段寄存器

  • 段是一种内存保护技术。它把内存划分为多个区段,并为每个区段赋予起始地址。范围、访问权限等,以保护内存,
  • 此外段还同分页技术一起用于将虚拟内存变更为实际物理内存。
  • 段内存记录在 SDT(段描述符表)中,而段寄存器就持有这些 SDT 的索引
  • 段寄存器由 6 中寄存器组成,每个寄存器大小为 2 字节 16 位,存放相应所在段的段基址
    • CS:代码段寄存器
    • SS:栈段寄存器
    • DS:数据段寄存器
    • ES:附加(数据)段寄存器
    • FS:数据段寄存器
      • 用于计算 SEH(结构化异常处理机制)、TEB(线程环境块)、PEB(进程环境块)等地址
    • GS:数据段寄存器
  • 每个段寄存器指向的段描述符与虚拟内存结合,形成一个线性地址,借助分页技术,线性地址最终被转换为实际的物理地址
    • 不使用分页技术的操作系统中,线性地址直接变为物理地址

程序状态与控制寄存器

  • EFLAGS:标志寄存器
    • 大小为 4 字节 32 位,由原来 16 为 FLAGS 寄存器扩展而来
    • 每位的值为 1 或 0
    • ZF:零标志,若运算结果为 0,则值为 1,否则为 0
    • OF:溢出标志,有符号整数溢出时,OF 值被设置为 1。MSB(最高有效位)改变时,其值也被设为 1
    • CF:进位标志,无符号整数溢出时,其值也被设置为 1

指令指针寄存器

  • EIP:指令指针寄存器
    • 指令指针寄存器保存着 CPU 要执行的指令地址,其大小为 4 字节 32 位,由原 16 位 IP 寄存器扩展而来。
    • 程序执行时,CPU 会读取 EIP 中一条指令的地址,传送指令到指令缓冲区后,EIP 寄存器的值自动增加,增加的大小即是读取指令的字节大小
    • 这样,CPU 每次执行完一条指令,就会通过 EIP 寄存器读取并执行下一条指令
    • 与通用寄存器不同,不能直接修改 EIP 的值,只能通过其他指令间接修改,比如 JMP,Jcc,CALL,RET,还可以通过中断或异常修改 EIP 的值

栈内存在进程中的作用如下:

  • 暂时保存函数内的局部变量
  • 调用函数时传递参数
  • 保存函数返回后的地址

栈是一种数据结构,按照 FILO(后进先出)的原则存储数据

栈的特征

一个进程中,栈顶指针(ESP)初始状态指向栈底端。

执行 PUSH 命令将数据压入栈时,栈顶指针就会上移到栈顶端。

执行 POP 命令从栈中弹出数据时,若栈为空,则栈顶指针重新移动到栈底端

栈是一种由高地址向低地址扩展的数据结构,栈是由下往上扩展的,逆向扩展

栈操作示例

打开 Stack.exe(调试过程中,寄存器的初始值与栈的初址会随运行环境的不同而不同)

可以看到栈顶指针的值为 19FF74,观察右下角的栈窗口,可以看到 ESP 指向的地址及其值

在代码窗口按 F7,执行 401000 地址处的 PUSH 100 命令

ESP 的值变为了 19FF70,比原来减少了 4 个字节,并且当前栈顶指针指向了 19FF20 地址,该地址保存的值就是 100

也就是说,执行 PUSH 命令时,数值 100 被压入栈,ESP 随之向上移动,值减少 4 个字节

再次按 F7,执行 401005 地址的 POP EAX 命令

可以发现,ESP 的值增加了 4 个字节,变为了 19FF74,变为了一开始的状态

也就是说,从栈中弹出数据后,ESP 随之向下移动

总结:栈顶指针在初始状态指向栈底。向栈压入数据时,栈顶指针减小,向低地址移动;从栈中弹出数据时,栈顶指针增加,向高地址移动。

  • 总结

第 3 到 5 章初看时可能感觉很多都是记忆类的知识,不太容易理解,尤其是寄存器相关,可以大概先留个印象,初步学习时,知道这个术语在这里出现过就可以了。

关键的点是栈的理解,可以结合实例去弄明白栈的特征

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/68726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node.js MySQL:深度解析与最佳实践

Node.js MySQL:深度解析与最佳实践 引言 Node.js作为一种流行的JavaScript运行时环境,以其轻量级、高性能和事件驱动模型受到开发者的青睐。MySQL则是一款功能强大的关系型数据库管理系统,广泛应用于各种规模的应用程序中。本文将深入探讨Node.js与MySQL的集成,分析其优势…

使用 SpringBoot+Thymeleaf 模板引擎进行 Web 开发

目录 一、什么是 Thymeleaf 模板引擎 二、Thymeleaf 模板引擎的 Maven 坐标 三、配置 Thymeleaf 四、访问页面 五、访问静态资源 六、Thymeleaf 使用示例 七、Thymeleaf 常用属性 前言 在现代 Web 开发中,模板引擎被广泛用于将动态内容渲染到静态页面中。Thy…

《深入理解HTTP交互与数据监控:完整流程与优化实践》

文章目录 🌐 全链路解析:HTTP请求响应与数据可视化监控一、HTTP请求响应全流程解析1. 全链路交互流程图2.关键技术实现2.1 前端请求构造(ES6语法示例)2.2 服务端处理架构(Node.js/Express) 二、数据可视化监…

MongoDB快速上手(包会用)

MongoDB快速上手(包会用) MongoDB 介绍 🐱‍💻 MongoDB 是一个开源的 文档型数据库,它使用类似 JSON 的 BSON(二进制 JSON)格式来存储数据,具有高性能、可扩展性和灵活性。它适用于…

STC32通用GPIO中断,库函数配置方式 AI8051U和STC32G已测试没有问题

近来STC的单片机已经出到32位了,并且个人自己打板测试了几个型号,相比之前的51完全不是一个量级,可以通过以下这张图片中的信息来感受一下如今的32位8051单片机的强大,也是很很期待25年的这一新作了! 配图为AI8052U或…

Prometheus 中的 Exporter

在 Prometheus 生态系统中,Exporter 扮演着至关重要的角色,它们负责从不同的服务或系统中收集和暴露度量数据。本文将详细介绍 Exporter 的概念、类型以及如何有效使用它们将 Prometheus 集成到各种系统中进行监控。 什么是 Exporter? Exporter 是一段软件,它从应用程序或…

使用Pygame制作“Flappy Bird”游戏

1. 前言 Flappy Bird 是一款“点击上浮、松手下落”的横向卷轴游戏: 场景中持续出现上下成对的管道,玩家需要让小鸟在管道之间穿行;每穿过一对管道记 1 分;若小鸟碰到管道或掉到地面,则游戏结束;一旦上手…

### 2024 江西省赛题解(A,C,D,G,H,J,K,L) BEFI待补

A. 输出 a b c abc abc 即可。 void slove () {int a, b, c;cin >> a >> b >> c;cout << (a b c) << endl; }B. C. 如果 ∑ i 1 n a i S \sum_{i1}^{n}a_iS ∑i1n​ai​S 那么存在所有人说的都是真话的可能。 否则&#xff0c;我们…

java求职学习day23

MySQL 单表 & 约束 & 事务 1. DQL操作单表 1.1 创建数据库,复制表 1) 创建一个新的数据库 db2 CREATE DATABASE db2 CHARACTER SET utf8; 2) 将 db1 数据库中的 emp 表 复制到当前 db2 数据库 1.2 排序 通过 ORDER BY 子句 , 可以将查询出的结果进行排序 ( 排序只…

markdown公式特殊字符

个人学习笔记 根号 在 Markdown 中&#xff0c;要表示根号 3&#xff0c;可以使用 LaTeX 语法来实现。常见的有以下两种方式&#xff1a; 行内公式形式&#xff1a;使用一对美元符号 $ 将内容包裹起来&#xff0c;即 $\sqrt{3}$ &#xff0c;在支持 LaTeX 语法渲染的 Markdow…

git笔记-简单入门

git笔记 git是一个分布式版本控制系统&#xff0c;它的优点有哪些呢&#xff1f;分为以下几个部分 与集中式的版本控制系统比起来&#xff0c;不用担心单点故障问题&#xff0c;只需要互相同步一下进度即可。支持离线编辑&#xff0c;每一个人都有一个完整的版本库。跨平台支持…

系统学习算法: 专题七 递归

递归算法简而言之就是当一个大问题拆分为多个子问题时&#xff0c;如果每个子问题的操作步骤都一样&#xff0c;就可以用递归&#xff0c;其中递归在递的时候要有结束条件&#xff0c;不能一直递下去&#xff0c;结束条件后就归 这里不建议学习递归的时候抠细节&#xff0c;还…

python leetcode 笔记

只为记录一些python相关的特殊写法 无穷大&#xff0c;无穷小&#xff0c;NAN float(inf), float(-inf), float(nan) 判断字符的类型 isdigit(x) isspace(x) 字符串拼接 /.join([a,b,c]) # a/b/c 格式转换&#xff0c;字符转整形 ord(a) # 97 chr(97) # a 进制转…

如何成为一名 Python 全栈工程师攻略

## 从零基础到全栈工程师&#xff1a;Python 学习路线&#xff08;细化版&#xff09; **目标&#xff1a;** 掌握 Python 编程&#xff0c;并能独立开发全栈应用。 **学习路线&#xff1a;** ### 第一阶段&#xff1a;Python 基础 (4-6 周) **目标&#xff1a;** 掌握 Pyt…

Windows系统中Docker可视化工具对比分析,Docker Desktop,Portainer,Rancher

Docker可视化工具对比分析&#xff0c;Docker Desktop&#xff0c;Portainer&#xff0c;Rancher Windows系统中Docker可视化工具对比分析1. 工具概览2. Docker Desktop官网链接&#xff1a;主要优点&#xff1a;主要缺点&#xff1a;版本更新频率&#xff1a; 3. Portainer官网…

C++中常用的十大排序方法之1——冒泡排序

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C中常用的排序方法之——冒泡排序的相关…

远程连接-简化登录

vscode通过ssh连接远程服务器免密登录&#xff08;图文&#xff09;_vscode ssh-CSDN博客

OpenEuler学习笔记(十五):在OpenEuler上搭建Java运行环境

一、在OpenEuler上搭建Java运行环境 在OpenEuler上搭建Java运行环境可以通过以下几种常见方式&#xff0c;下面分别介绍基于包管理器安装OpenJDK和手动安装Oracle JDK的步骤。 使用包管理器安装OpenJDK OpenJDK是Java开发工具包的开源实现&#xff0c;在OpenEuler上可以方便…

[Java]继承

1. 什么是继承&#xff1f; 继承是面向对象编程的一种机制&#xff0c;允许一个类&#xff08;叫做子类&#xff09;继承另一个类&#xff08;叫做父类&#xff09;的属性和方法。也就是说&#xff0c;子类可以“继承”父类的行为&#xff08;方法&#xff09;和状态&#xff…

双指针c++

双指针&#xff08;Two Pointers&#xff09;是一种常用的算法技巧&#xff0c;通常用于解决数组或链表中的问题&#xff0c;如滑动窗口、区间合并、有序数组的两数之和等。双指针的核心思想是通过两个指针的移动来优化时间复杂度&#xff0c;通常可以将 (O(n^2)) 的暴力解法优…