当前位置: 首页 > news >正文

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

🙋‍♀️ 博主介绍:暗流者
⭐ 本期精彩:学习pwn需要的基本汇编语言知识
🏆 热门专栏:带你从C语言和汇编角度入门pwn
🚀 专栏亮点:零基础友好 | 实战案例丰富 | 循序渐进教学 | 代码详细注释
💡 学习收获:从语言角度入门pwn,为您的pwn之路打好基础

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

目录

前言:

一、寄存器架构

二,基础指令

一、数据传送指令

二、算术运算指令

三、位操作指令

四、控制转移指令

五、栈操作指令

六、系统调用指令对比

七、核心数据定义指令

八、64位专属指令

三.构建内存空间

一.寄存器构建

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

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

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

call 指令

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位示例功能说明
MOVmov eax, 10mov rax, 10数据传送
LEAlea esi, [ebx+ecx*4]lea rsi, [rbx+rcx*4]地址计算(不访问内存)
XCHGxchg eax, ebxxchg rax, rbx交换数据
MOVZXmovzx eax, byte [mem]movzx rax, byte [mem]零扩展传送
MOVSXmovsx eax, byte [mem]movsx rax, byte [mem]符号扩展传送
二、算术运算指令
指令通用示例功能说明
ADDadd eax, 10 / add rax, 10加法
SUBsub ebx, ecx / sub rbx, rcx减法
INCinc dword [mem]自增(不影响CF标志)
DECdec esi自减(不影响CF标志)
MULmul ecx无符号乘法(EDX:EAX = EAX * ECX)
IMULimul eax, ebx有符号乘法
DIVdiv ecx无符号除法(EAX = EDX:EAX / ECX)
三、位操作指令
指令通用示例功能说明
ANDand eax, 0Fh按位与
ORor ebx, 80h按位或
XORxor eax, eax按位异或(常用清零)
NOTnot ecx按位取反
SHLshl edx, 4逻辑左移
SHRshr eax, 1逻辑右移
SALsal ebx, cl算术左移(同SHL)
SARsar ecx, 3算术右移(保留符号位)
四、控制转移指令
指令32位示例64位示例功能说明
JMPjmp labeljmp label无条件跳转
CALLcall funccall func函数调用
RETretret函数返回
JE/JZje targetje target相等/为零时跳转
JNE/JNZjne targetjne target不相等/非零时跳转
LOOPloop labelloop labelECX/RCX减1,非零跳转
五、栈操作指令
指令32位示例64位示例功能说明
PUSHpush eaxpush rax入栈(ESP/RSP递减)
POPpop ebxpop rbx出栈(ESP/RSP递增)
PUSHApusha✘ 64位移除保存所有通用寄存器
POPApopa✘ 64位移除恢复所有通用寄存器
ENTERenter 16, 0极少使用创建栈帧
LEAVEleaveleave销毁栈帧
六、系统调用指令对比
架构指令参数传递方式
32位int 0x80EAX=调用号, EBX/ECX/EDX/ESI/EDI/EBP=参数
64位syscallRAX=调用号, RDI/RSI/RDX/R10/R8/R9=参数
七、核心数据定义指令
指令全称位数功能说明示例
DBDefine Byte8位定义字节数据num DB 0x55
DWDefine Word16位定义字(2字节)数据buffer DW 1024
DDDefine Doubleword32位定义双字(4字节)数据pointer DD 0x8040000
DQDefine Quadword64位定义四字(8字节)数据addr64 DQ 0x7FFFFFFFFFFF
DTDefine Ten Bytes80位定义10字节数据(浮点专用)float DT 3.1415926535
八、64位专属指令
  1. RIP相对寻址

    asmlea rax, [rip + label]  ; 动态计算地址(位置无关代码)

  2. SWAPGS

    asmswapgs                   ; 切换内核GS寄存器(系统编程)

  3. SYSCALL/SYSRET

    asmsyscall                  ; 快速系统调用
    sysret                   ; 快速系统返回

三.构建内存空间
一.寄存器构建

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

寄存器全称位数核心功能
ESPExtended Stack Pointer32位栈顶指针,始终指向当前栈顶位置
EBPExtended Base Pointer32位栈帧基址,指向当前函数栈帧起点
SSStack Segment16位栈段寄存器,定义栈内存的基地址

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

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

1. 函数进入序言 (Prologue)

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

2. 函数内栈操作

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

3. 函数退出尾声 (Epilogue)

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

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

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

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

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

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(段寄存器和指令指针)压入栈中,然后跳转到指定的函数地址,从而实现子程序的调用。

  • 执行流程

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

ret 指令

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

  • 执行流程

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

    总结

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

http://www.xdnf.cn/news/1165717.html

相关文章:

  • MCP vs 传统集成方案:REST API、GraphQL、gRPC的终极对比
  • nodejs:告别全局安装,npx 命令详解及其与 npm 的区别
  • npm全局安装后,依然不是内部或外部命令,也不是可运行的程序或批处理文件
  • Go语言切片(Slice)与数组(Array)深度解析:避坑指南与最佳实践
  • rocky9-zabbix简单部署
  • Vue底层换成啥了?如何更新DOM的?
  • 基于单片机智能消毒柜设计
  • 【IDEA】如何在IDEA中通过git创建项目?
  • 原型链污染
  • uniapp请求封装上传
  • uniapp app打包流程
  • 【Python办公】Excel工作表拆分工具(按照sheet进行拆分-calamine-极速版)
  • NIO技术原理以及应用(AI)
  • Kotlin介绍
  • 重构创作边界:川翔云电脑 - UE5云端超算引擎​
  • Kafka——揭开神秘的“位移主题”面纱
  • Springboot+vue个人健康管理系统的设计与实现
  • 【电影剖析】千钧一发
  • ISPDiffuser文章翻译理解
  • 深入解析MIPI C-PHY (二)C-PHY三线魔术:如何用6种“符号舞步”榨干每一滴带宽?
  • uni-api交互反馈组件(showToast)的用法
  • SmartETL循环流程的设计与应用
  • 《Linux 环境下 Nginx 多站点综合实践:域名解析、访问控制与 HTTPS 加密部署》​
  • 【金仓数据库产品体验官】_KingbaseES(SQLServer兼容版)保姆级安装教程
  • AC身份认证实验之AAA服务器
  • Linux中ELF区域与文件偏移量的关系
  • 【牛客算法】小美的排列询问
  • DL00691-基于深度学习的轴承表面缺陷目标检测含源码python
  • Python可迭代归约函数深度解析:从all到sorted的进阶指南
  • scratch音乐会开幕倒计时 2025年6月中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析