首页 > 编程语言 >从汇编层看64位程序运行——栈保护

从汇编层看64位程序运行——栈保护

时间:2024-07-17 09:59:24浏览次数:11  
标签:汇编 fs return 程序运行 buffer base 64 OBJDIR BINDIR

大纲

《从汇编层看64位程序运行——ROP攻击以控制程序执行流程》中,我们看到可以通过“微操”栈空间控制程序执行流程。现实中,黑客一般会利用栈溢出改写Next RIP地址,这就会修改连续的栈空间。而编译器针对这种场景,设计了“栈保护”机制。

栈保护

比如下面的代码,buffer[8] = 'b’这句会导致栈溢出。

int main() {
    char buffer[8] = {0};
    buffer[0] = 'a';
    buffer[1] = buffer[0] + 1;
    buffer[8] = 'b';
    return 0;
}

如果我们采用“栈保护”机制编译,即增加-fstack-protector-strong(或者-fstack-protector、-fstack-protector-all等)编译选项。

# makefile
# 定义编译器
CC := gcc

# 定义编译选项
CFLAGS := -Wall -Werror -O0 -fstack-protector-strong

# 定义目标目录
OBJDIR := build
BINDIR := bin

# 定义源文件和目标文件
SRCS := $(wildcard src/*.c)
OBJS := $(patsubst src/%.c,$(OBJDIR)/%.o,$(SRCS))

# 获取当前工作目录名,即工程目录名
PROJECT_DIR_NAME := $(notdir $(shell pwd))

# 最终目标:编译所有文件并生成可执行文件
$(BINDIR)/$(PROJECT_DIR_NAME): $(BINDIR) $(OBJS)
	$(CC) $(CFLAGS) $(OBJS) -o $@

# 通用规则:如何从每个.c文件生成.o文件
$(OBJDIR)/%.o: src/%.c $(OBJDIR)
	$(CC) $(CFLAGS) -c $< -o $@

# 规则:创建build目录
$(OBJDIR):
	mkdir -p $(OBJDIR)

# 规则:创建bin目录
$(BINDIR):
	mkdir -p $(BINDIR)

# 伪目标:清理项目
.PHONY: clean
clean:
	rm -rf $(OBJDIR) $(BINDIR)

# 伪目标:打印变量(用于调试)
.PHONY: print
print:
	@echo "SRCS = $(SRCS)"
	@echo "OBJS = $(OBJS)"
	@echo "PROJECT_DIR_NAME = $(PROJECT_DIR_NAME)"

则程序在运行时,会报出栈移除提示。
在这里插入图片描述
那编译器如何做到“栈保护”的呢?

也许听着挺高大上,但是代码面前了无秘密,其原理也非常的简单。

我们看下这段代码的汇编
在这里插入图片描述
+12和+21这两行,汇编将段寄存器fs偏移+0x28的值保存到main函数栈帧的第一个局部变量位置(-0x8(%rbp))。这个局部变量是一个隐藏变量,后续没有代码对其进行改动。

+58和+62这两行,将检测第一个局部变量的值和寄存器fs偏移+0x28的值是否一致。如果一致就说明没问题,如果不一致就说明栈被污染了。
在这里插入图片描述

延伸阅读

那么段寄存器fs偏移+0x28是什么值?它为什么会在函数调用期间值不变?

这是因为fs断寄存器保存的是当前线程的TLS(Thread Local Storage),这样这个函数在线程上调度时,并不会被其他线程影响这段空间值。

但是GDB却无法打印出FS段地址,这个需要我们对代码进行改造,引入自定义的fs_base方法

#include <asm/prctl.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdint.h>

uint64_t fs_base() {
    uint64_t fs_base;
    long result = syscall(SYS_arch_prctl,ARCH_GET_FS,&fs_base);
    if (result == -1) {
        return 0;
    }
    return fs_base;
}

uint64_t gs_base() {
    uint64_t gs_base;
    long result = syscall(SYS_arch_prctl,ARCH_GET_GS,&gs_base);
    if (result == -1) {
        return 0;
    }
    return gs_base;
}

int main() {
    char buffer[8] = {0};
    buffer[0] = 'a';
    buffer[1] = buffer[0] + 1;
    buffer[8] = 'b';
    return 0;
}

然后我们调试这段代码,可以看到被赋值到rax寄存器中的,%fs:0x28指向的值是0x6ac935d29472ff00。
在这里插入图片描述
而fs段地址通过gdb看不到
在这里插入图片描述
我们在gdb中使用下面指令来查看fs段地址

 p/x (uint64_t) fs_base()

然后查看偏移0x28的空间中的值,可以发现这个值和上面被赋值到rax寄存器中的值一致。
在这里插入图片描述
那我们如何确定它是TLS中的地址呢?

我们可以通过下面指令查看TLS的起始地址

p (void*) pthread_self()

我们会发现这个地址和我们通过fs_base获得的地址是一样的。

在这里插入图片描述

参考资料

标签:汇编,fs,return,程序运行,buffer,base,64,OBJDIR,BINDIR
From: https://blog.csdn.net/breaksoftware/article/details/140424008

相关文章

  • eclipse免安装版64位 2018版本
    前言Eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse附带了一个标准的插件集,包括Java开发工具(JavaDevelopmentKit,JDK)。虽然大多数用户很乐于将Eclipse当作Java集成开发......
  • 第二章 编译FFmpeg并开启H.264编码
    目录前言1.下载x2642.编译x2643.编译FFmpeg3.1可能出现的问题和解决方法3.1.1ERROR:x264notfoundusingpkg-config解决方法:3.1.2libx264isgpland--enable-gplisnotspecified.解决方法:4.检查编译结果这里我默认大家已经看过第一章FFmpeg初体验:在Centos7.9下编......
  • 一起学RISC-V汇编第1讲之指令集架构
    准备写几篇学习笔记来讲述RISC-V汇编。1指令集架构指令集架构(InstructionSetArchitecture,简称ISA)是一种定义处理器体系结构的规范。定义了处理器能够执行的指令集、寄存器、编码格式、内存访问方式、中断、异常处理等细节。指令集:包含数条指令,每条指令都代表一个特定的操作......
  • 一起学RISC-V汇编第2讲RISC-V之march与mabi
    这一章讲一些RISC-V的一些零碎知识点,后面章节可能要用到这些概念。1RISC-V的各种扩展marchx86与arm是增量型ISA,意味着新处理器需要兼容过去所有的指令,这样会导致ISA指令随时间流逝而大幅增长。而RISC-V被设计为模块化的,这与过去几乎所有的ISA都不同,其核心是RV32I的基础ISA,......
  • 一起学RISC-V汇编第3讲之寄存器
    寄存器是处理器中最常用的处理单元,RISC-V指令的操作数除了立即数就是寄存器。RISC-V指令集包含了多种不同类型的寄存器,用于不同目的和功能:对于rv32imafd架构而言,包含如下寄存器:通用寄存器:32个通用整数寄存器,分别标记为x0-x31,如果是fd扩展,还有32个独立的浮点寄存器,分别标记为f......
  • Python安装出现严重错误的解决方法_0x80070643-( A newer version of the Python laun
    每次在装软件配置环境的时候,总会遇到别人碰不到的各种问题,人都麻了。最后我还是自己尝试这解决了,只是建议,虽然说不知道是否以后还会问题,但是可以成功安装,配置环境并运行。(本人是win11)首先解释一下pythonlauncher是什么资料解释:PythonLauncher是Python官方提供的一个工具,......
  • 专用R5F+双核A53,异构多核AM64x让工控“更实时”
    Cortex-R5F+Cortex-A53异构多核,给工控带来何种意义? 创龙科技SOM-TL64x工业核心板搭载TIAM64x最新工业处理器,因其CortexR5F+双核Cortex-A53异构多核的优良性能,在工业自动化、能源电力、轨道交通等领域广受客户欢迎。目前,已有不少客户将SOM-TL64x核心板应用在工业网关、......
  • 0181-汇编调用 Rust
    环境Time2022-11-12WSL-Ubuntu22.04QEMU6.2.0NASM2.15.05Rust1.67.0-nightly前言说明参考:https://os.phil-opp.com/set-up-rust/目标从汇编代码中调用Rust代码。该篇基于之前编写的进入64位模式的汇编代码。切换到nightly版本切换命令:rustupoverridese......
  • 0183-x64 平台独立程序
    环境Time2022-11-13WSL-Ubuntu22.04QEMU6.2.0Rust1.67.0-nightly前言说明参考:https://os.phil-opp.com/minimal-rust-kernel目标编译个x64平台的独立可执行程序。切换到nightly版本项目目录下新建rust-toolchain文件,文件内容为:nightly。main.rs#![no_std......
  • base64 数据转png本地图片保存,js实现
    要将base64编码的图像数据保存为PNG文件到本地,可以借助JavaScript和浏览器的FileAPI。以下是一个简单的步骤和示例代码:步骤:解析Base64数据:将Base64编码的字符串解析为二进制数据。创建Blob对象:使用解析后的二进制数据创建一个Blob对象。创建URL:通过UR......