news 2026/7/1 6:52:10

【学习记录】Week2(四):底层基石——汇编速查 lea/mov/push/pop/call/ret

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【学习记录】Week2(四):底层基石——汇编速查 lea/mov/push/pop/call/ret

写在前面:在 PWN 的世界里,汇编语言就是我们的“母语”。无论是用objdump看反汇编,还是在 GDB 里单步调试,或者是手工挑选 ROP Gadget,都离不开对每一条汇编指令的精准理解。本文将为你梳理最核心的 6 条指令,特别是新手最容易混淆的leamov

📑 目录

  1. movvslea:取值与取址的终极对决
  2. 栈操作双雄:pushpop
  3. 控制流转移:callret(ROP 的灵魂)
  4. 模拟实战:一段汇编的栈帧变化推演

1.movvslea:取值与取址的终极对决

这两个指令是看懂反汇编的第一道门槛。记住一句话:mov看重内容,lea看重地址。

1.1mov(Move Data)

  • 作用:把源操作数的复制给目的操作数。
  • 格式mov dest, src
  • PWN 场景
    • mov rax, 0x10—— 将常数0x10赋值给rax
    • mov rdi, rsi—— 将rsi寄存器的值赋给rdi(64位传参常用)。
    • mov rax, [rbp - 0x10]——注意这里的方括号!方括号代表解引用(像 C 语言的*)。这条指令的意思是:把内存地址rbp - 0x10处存放的数据读出来,放进rax

1.2lea(Load Effective Address)

  • 作用:计算源操作数的地址,并把这个地址值赋给目的操作数。不访问内存!
  • 格式lea dest, src
  • PWN 场景
    • lea rax, [rbp - 0x10]—— 这里没有解引用!这条指令的意思是:计算出rbp - 0x10这个地址值,然后把这个地址值本身放进rax
    • 用途:通常用于把一个局部变量(比如char buf[64])的首地址传给函数。比如lea rax, [rbp-0x40]然后mov rdi, rax,接着call gets,这就是把buf的地址传给gets函数的第一个参数。

2. 栈操作双雄:pushpop

栈是向下生长的(高地址向低地址),RSP(栈顶指针)始终指向栈顶元素。这两个指令会自动修改RSP

2.1push(压栈)

  • 动作RSP = RSP - 8(64位) 或RSP = RSP - 4(32位),然后将操作数存入RSP指向的新内存地址。
  • PWN 场景:函数序言中的push rbp,就是把主调函数的栈底保存起来,以便函数返回时恢复。

2.2pop(出栈)

  • 动作:将RSP当前指向的内存地址中的数据读入目标操作数,然后RSP = RSP + 8(或 +4)。
  • PWN 场景:函数结语中的pop rbp,就是恢复主调函数的栈底。更重要的是,ROP 攻击中,我们要寻找大量的pop rdi; ret这样的 Gadget,用来把栈上的数据弹入寄存器,从而控制函数参数!

3. 控制流转移:callret(ROP 的灵魂)

这两个指令决定了程序执行到哪里去,也是我们劫持控制流的核心目标。

3.1call(调用函数)

  • 动作:等价于push 下一条指令的地址+jmp 目标函数地址
  • 本质:它把返回地址(call指令后面的那条指令地址)压入栈中,然后跳转。这就解释了为什么发生栈溢出时,我们覆盖的正是这个被call压入栈中的返回地址。

3.2ret(函数返回)

  • 动作:等价于pop rip
  • 本质:从栈顶弹出一个 8 字节的数据,直接塞进指令指针寄存器RIP中,CPU 接着就会跳转到这个地址执行。
  • PWN 启示这就是栈溢出能拿 Shell 的灵魂!只要我们通过溢出覆盖了栈顶的返回地址,当函数执行到ret时,就会乖乖跳到我们指定的地址去执行。如果是连续的ret,就会不断从栈上弹出地址并跳转,这就是 ROP(Return-Oriented Programming)链的底层逻辑。

4. 模拟实战:一段汇编的栈帧变化推演

我们模拟一段常见的函数调用汇编,推演一下栈和寄存器的变化:

0x401100 <main>: call 0x401200 <vulnerable> ; 1. 压入返回地址 0x401105,RSP-8,跳转 0x401200 <vulnerable>: push rbp ; 2. 压入旧 rbp,RSP-8 mov rbp, rsp ; 3. 设置当前栈底,此时 rbp == rsp sub rsp, 0x40 ; 4. 开辟 0x40 字节栈空间,RSP-0x40 lea rax, [rbp-0x40] ; 5. 计算 buf 地址,存入 rax mov rdi, rax ; 6. 把 buf 地址传给 rdi (作为 gets 参数) call 0x401040 <gets@plt> ; 7. 压入返回地址,调用 gets ; 假设此时输入了 72 个 'A' + p64(0xdeadbeef) leave ; 8. 等价于 mov rsp, rbp; pop rbp ret ; 9. 此时栈顶正好是 0xdeadbeef,pop rip,跳转!

假设性说明(GDB 模拟推演):
当程序执行到ret指令前,如果你在 GDB 中查看栈顶 (x/gx $rsp),你会看到:

0x7fffffffde08: 0x00000000deadbeef

执行ret后,查看寄存器 (info registers rip),你会看到:

rip 0xdeadbeef 0xdeadbeef

控制流被完美劫持!

5. 结语

汇编并不难,难在建立“寄存器与内存联动”的空间感。牢记lea算地址、mov拿数据、ret弹栈跳转,你就已经掌握了 PWN 所需的 80% 的汇编底子。

下一部分,我们将面对实战中常见的“拦路虎”——反调试检测,教你如何用ptrace绕过它。如果本文对你有帮助,请点赞收藏支持!🙏

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 6:49:54

LeetCode刷题日记:用Java搞定二叉树这5道经典面试题(附完整代码)

LeetCode刷题日记&#xff1a;Java工程师的二叉树通关秘籍凌晨两点的显示器前&#xff0c;咖啡杯已经见底&#xff0c;我盯着LeetCode上那棵枝繁叶茂的二叉树示意图&#xff0c;突然意识到——国内大厂技术面试中&#xff0c;80%的二叉树问题都可以归结为五种核心解题模式。作为…

作者头像 李华
网站建设 2026/7/1 6:41:51

自学2年Python打造多功能计算器,求大佬指点

本人学过两年C&#xff0c;Python自学了两年&#xff0c;只算是一个萌新&#xff0c;试着做了一个简易计算器练练手。现在发在社区里&#xff0c;望能有大佬指点&#xff0c;本人不胜感激&#xff01;如有问题&#xff0c;欢迎各位将高见发在评论区&#xff0c;本人定逐条认真查…

作者头像 李华
网站建设 2026/7/1 6:35:46

哔咔漫画下载器终极指南:3步打造永久个人漫画库

哔咔漫画下载器终极指南&#xff1a;3步打造永久个人漫画库 【免费下载链接】picacomic-downloader 哔咔漫画 picacomic pica漫画 bika漫画 PicACG 多线程下载器&#xff0c;带图形界面 带收藏夹&#xff0c;已打包exe 下载速度飞快 项目地址: https://gitcode.com/gh_mirror…

作者头像 李华
网站建设 2026/7/1 6:32:28

实时GPU着色器覆盖技术:如何为Windows桌面应用注入视觉魔法

实时GPU着色器覆盖技术&#xff1a;如何为Windows桌面应用注入视觉魔法 【免费下载链接】ShaderGlass Overlay for running GPU shaders on top of Windows desktop and Wine 项目地址: https://gitcode.com/gh_mirrors/sh/ShaderGlass 你是否曾经想过&#xff0c;为什么…

作者头像 李华