学习pwn需要的基本汇编语言知识

🙋‍♀️ 博主介绍:暗流者

⭐ 本期精彩:学习pwn需要的基本汇编语言知识

🏆 热门专栏:带你从C语言和汇编角度入门pwn

🚀 专栏亮点:零基础友好 | 实战案例丰富 | 循序渐进教学 | 代码详细注释

💡 学习收获:从语言角度入门pwn,为您的pwn之路打好基础

🔥 如果觉得文章有帮助,别忘了点赞👍 收藏⭐ 关注🚀,你的支持是我创作的最大动力!

目录

前言:

一、寄存器架构

二,基础指令

一、数据传送指令

二、算术运算指令

三、位操作指令

四、控制转移指令

五、栈操作指令

六、系统调用指令对比

七、核心数据定义指令

八、64位专属指令

三.构建内存空间

一.寄存器构建

二、函数调用中的协作流程

[PUSH 执行流程(以 32位 push eax 为例):](#PUSH 执行流程(以 32位 push eax 为例):)

[POP 执行流程(以 32位 pop ebx 为例):](#POP 执行流程(以 32位 pop ebx 为例):)

[call 指令](#call 指令)

[ret 指令](#ret 指令)


前言:

我计划用几次用C语言和汇编语言的角度讲完整个pwn的基础知识点,会涉及32位汇编和64位汇编的讲解,但是在pwn中的gdb工具分析时,需要你认识内联汇编(支持C语言和汇编出现在同一个程序中),内联汇编没什么新的知识点,但是有些东西还是需要你知道

C语言方面的话并不需要你的能力很强,懂得一些基本的操作(数组,指针,结构),数据结构(链表,栈,树,图)等等,总之我会从C语言的角度去说PWN中的一些基本结构

这是第一天,我将从汇编语言的基础知识点出发,因为可能很多人学汇编语言是学习的16位汇编,但是pwn题目中都是32位和64位汇编,所以在这里我就简单讲一下32位和64位汇编,一些汇编语言的基础操作就不讲了,我只讲一下32位和64位汇编不同的地方,这里我讲一些pwn中常见的汇编知识

一、寄存器架构

32位(x86)

  • 通用寄存器(8个): EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP

  • 段寄存器: CS, DS, ES, FS, GS, SS

  • 特殊寄存器: EIP(指令指针), EFLAGS(状态标志)

64位(x86-64)

  • 扩展通用寄存器(16个): RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, R8-R15(新增8个64位寄存器)

  • 保留部分寄存器: 段寄存器(除FS/GS外)基本弃用

  • 特殊寄存器: RIP(64位指令指针), RFLAGS

二,基础指令
一、数据传送指令
指令 32位示例 64位示例 功能说明
MOV mov eax, 10 mov rax, 10 数据传送
LEA lea esi, [ebx+ecx*4] lea rsi, [rbx+rcx*4] 地址计算(不访问内存)
XCHG xchg eax, ebx xchg rax, rbx 交换数据
MOVZX movzx eax, byte [mem] movzx rax, byte [mem] 零扩展传送
MOVSX movsx eax, byte [mem] movsx rax, byte [mem] 符号扩展传送
二、算术运算指令
指令 通用示例 功能说明
ADD add eax, 10 / add rax, 10 加法
SUB sub ebx, ecx / sub rbx, rcx 减法
INC inc dword [mem] 自增(不影响CF标志)
DEC dec esi 自减(不影响CF标志)
MUL mul ecx 无符号乘法(EDX:EAX = EAX * ECX)
IMUL imul eax, ebx 有符号乘法
DIV div ecx 无符号除法(EAX = EDX:EAX / ECX)
三、位操作指令
指令 通用示例 功能说明
AND and eax, 0Fh 按位与
OR or ebx, 80h 按位或
XOR xor eax, eax 按位异或(常用清零)
NOT not ecx 按位取反
SHL shl edx, 4 逻辑左移
SHR shr eax, 1 逻辑右移
SAL sal ebx, cl 算术左移(同SHL)
SAR sar ecx, 3 算术右移(保留符号位)
四、控制转移指令
指令 32位示例 64位示例 功能说明
JMP jmp label jmp label 无条件跳转
CALL call func call func 函数调用
RET ret ret 函数返回
JE/JZ je target je target 相等/为零时跳转
JNE/JNZ jne target jne target 不相等/非零时跳转
LOOP loop label loop label ECX/RCX减1,非零跳转
五、栈操作指令
指令 32位示例 64位示例 功能说明
PUSH push eax push rax 入栈(ESP/RSP递减)
POP pop ebx pop rbx 出栈(ESP/RSP递增)
PUSHA pusha ✘ 64位移除 保存所有通用寄存器
POPA popa ✘ 64位移除 恢复所有通用寄存器
ENTER enter 16, 0 极少使用 创建栈帧
LEAVE leave leave 销毁栈帧
六、系统调用指令对比
架构 指令 参数传递方式
32位 int 0x80 EAX=调用号, EBX/ECX/EDX/ESI/EDI/EBP=参数
64位 syscall RAX=调用号, RDI/RSI/RDX/R10/R8/R9=参数
七、核心数据定义指令
指令 全称 位数 功能说明 示例
DB Define Byte 8位 定义字节数据 num DB 0x55
DW Define Word 16位 定义字(2字节)数据 buffer DW 1024
DD Define Doubleword 32位 定义双字(4字节)数据 pointer DD 0x8040000
DQ Define Quadword 64位 定义四字(8字节)数据 addr64 DQ 0x7FFFFFFFFFFF
DT Define Ten Bytes 80位 定义10字节数据(浮点专用) float DT 3.1415926535
八、64位专属指令
  1. RIP相对寻址

    bash 复制代码
    asm
    
    lea rax, [rip + label]  ; 动态计算地址(位置无关代码)
  2. SWAPGS

    bash 复制代码
    asm
    
    swapgs                   ; 切换内核GS寄存器(系统编程)
  3. SYSCALL/SYSRET

    bash 复制代码
    asm
    
    syscall                  ; 快速系统调用
    sysret                   ; 快速系统返回
三.构建内存空间
一.寄存器构建

1.如何构建一段栈空间,需要这三个ebp,esp,ss寄存器

寄存器 全称 位数 核心功能
ESP Extended Stack Pointer 32位 栈顶指针,始终指向当前栈顶位置
EBP Extended Base Pointer 32位 栈帧基址,指向当前函数栈帧起点
SS Stack Segment 16位 栈段寄存器,定义栈内存的基地址

高地址 +-----------------+ | 返回地址 | +-----------------+ | 保存的RBP | <-- RBP (当前帧基址) +-----------------+ | 局部变量 | | ... | +-----------------+ | 额外参数 | +-----------------+ 低地址 <-- RSP (栈顶)

二、函数调用中的协作流程

1. 函数进入序言 (Prologue)

bash 复制代码
asm

; 保存调用者的栈帧基址
push ebp        ; ESP自动减4,旧EBP入栈
​
; 建立新栈帧
mov ebp, esp    ; EBP指向当前栈顶(即旧EBP位置)
​
; 分配局部变量空间
sub esp, 16     ; 分配16字节局部变量区

2. 函数内栈操作

bash 复制代码
asm

; 访问参数(假设32位cdecl调用约定)
mov eax, [ebp+8]  ; 第一个参数(返回地址占4字节)
​
; 访问局部变量
mov [ebp-4], eax  ; 存储到第一个局部变量

3. 函数退出尾声 (Epilogue)

bash 复制代码
asm

; 恢复栈指针(释放局部变量)
mov esp, ebp    ; ESP回到栈帧起点
​
; 恢复调用者栈帧
pop ebp         ; 恢复旧EBP,ESP自动加4
​
; 返回(清理参数由调用者负责)
ret

三,栈对齐的问题(32位和64位都需要)

栈对齐(Stack Alignment)是x86架构中极易被忽视却至关重要的机制,尤其在64位系统中直接关系到程序稳定性和性能。本文将通过原理分析、实例演示和解决方案全面解析这一核心问题。

  • 函数调用前RSP必须16字节对齐

  • 调用指令call会压入8字节返回地址

bash 复制代码
asm

; 正确对齐示例
sub rsp, 24   ; 24+8(返回地址)=32 → 16字节对齐
call func
add rsp, 24

4.pop和push指令

pop和push指令用于压栈和出栈

PUSH 执行流程(以 32位 push eax 为例)
  1. ESP 减 4(栈指针下移) ESP = ESP - 4

  2. 将 EAX 值写入 ESP 指向的地址 [ESP] = EAX

  3. 更新 EFLAGS 寄存器(不影响标志位)

plaintext

复制代码
执行前:          执行后:
高地址           高地址
┌─────────┐       ┌─────────┐ 
│         │       │  EAX值  │ ← ESP
├─────────┤       ├─────────┤
│         │ ← ESP │         │
└─────────┘       └─────────┘
低地址           低地址
POP 执行流程(以 32位 pop ebx 为例)
复制代码
1. 读取 ESP 指向的值
   `EBX = [ESP]`
2. ESP 加 4(栈指针上移)
   `ESP = ESP + 4`
3. 更新 EFLAGS 寄存器(不影响标志位)

5.ret和call指令

call 指令

  • 作用call 指令将当前的 IP(指令指针)或 CS:IP(段寄存器和指令指针)压入栈中,然后跳转到指定的函数地址,从而实现子程序的调用。

  • 执行流程

    bash 复制代码
    - 1. 将当前的 IP 或 CS 和 IP 压入栈中(相当于 `push IP`)。
      2. 跳转到目标地址(相当于 `jmp near ptr 标号`)。
    - **示例**:`call 标号`(近转移)相当于执行 `push IP` 和 `jmp near ptr 标号` 。

ret 指令

  • 作用ret 指令用于从子程序返回到调用点,它通过从栈中弹出返回地址,并将其加载到 IP 寄存器中,从而恢复程序的执行流程。

  • 执行流程

    bash 复制代码
    - :
      1. 从栈中弹出返回地址(相当于 `pop IP`)。
      2. 将返回地址加载到 IP 寄存器中,程序继续执行。
    - **示例**:`ret` 指令相当于执行 `pop IP`,并更新 SP 寄存器(栈指针)。

    总结

  • 本博客将从C语言与汇编语言的角度系统讲解PWN基础,涵盖32位和64位汇编差异、寄存器架构、常用指令及栈操作等核心内容,帮助读者深入理解程序执行机制。

相关推荐
Gappsong87420 分钟前
Rufus:Ubuntu U盘启动盘制作工具详解
linux·c++·web安全·网络安全
慕y27426 分钟前
Java学习第六十三部分——K8s
java·开发语言·学习
Kira Skyler1 小时前
c++,从汇编角度看lambda
汇编·c++
paopaokaka_luck4 小时前
基于SpringBoot+Uniapp的非遗文化宣传小程序(AI问答、协同过滤算法、Echarts图形化分析)
java·vue.js·spring boot·后端·学习·小程序·uni-app
lxmyzzs5 小时前
从 0 到 1 搞定nvidia 独显推流:硬件视频编码环境安装完整学习笔记
笔记·学习·音视频
LGGGGGQ5 小时前
嵌入式学习-土堆目标检测(2)-day26
学习
卓豪终端管理7 小时前
如何加固Endpoint Central服务器的安全?(上)
运维·服务器·人工智能·安全·网络安全·自动化
LGGGGGQ7 小时前
嵌入式学习-土堆目标检测(3)-day27
学习
超浪的晨7 小时前
Java File 类详解:从基础操作到实战应用,掌握文件与目录处理全貌
java·开发语言·后端·学习·个人开发
飞速移动的代码菌8 小时前
【DataWhale】快乐学习大模型 | 202507,Task05笔记
笔记·学习