Buffer Overflows, ASLR, and Stack Canaries

栈溢出保护原理——Stack Canaries 栈溢出保护原理——Stack Canaries Stack Canaries (取名自地下煤矿的金丝雀,因为它能比矿工更早地发现煤气泄露,有预警的作用) 是一种对抗栈溢出攻击的技术,即SSP安全机制 Canary的值是栈上的一个随机数,在程序启动时随机生成并保存在比函数返回地址更低的位置。由于栈溢出是从低地址向高地址进行覆盖,因此攻击者要想控制函数的返回指针,就一定要先覆盖到Canary。程序只需要在函数返回前检查Canary是否被篡改,就可以达到保护栈的目的。 一,Canaries的分类 canar 阅读详情

Introduction

Buffer overflow exploits are one of the most common and classic security vulnerabilities in computer programs. A buffer overflow exploit sends a buffer more data than is expected with a goal of smashing the stack, overwriting the instruction pointer, and redirecting program execution to a malicious code of the attacker’s choice. To prevent buffer overflow attacks, there are various defense mechanisms that are built into most computer systems. A more in-depth look into buffer overflows, how they affect the stack, buffer overflow defense mechanisms, and how attackers can use this vulnerability to exploit a program will allow for a better understanding.

After a thorough explanation of buffer overflows and their functionality, there are two main defense mechanisms that will be discussed in this blog: a stack canary and an Address Space Layout Randomization (ASLR). This blog will take a deeper look into these defense mechanisms, which are used to prevent exploitation from occurring on a user’s computer. Gaining a better understanding of these defense mechanisms and how they function to prevent attacks will allow the reader to learn more about how buffer overflows can successfully exploit a program.

What is a buffer?

Let’s start with the basics. A buffer is a location in the computer’s memory that stores data of a certain length. In this example, the buffer is allocated with a size of 32 bytes. The string “Jimmy’s buffer overflow example” is 31 bytes long and strings in example1.C need to be null-terminated so we must leave space for the null byte at the end of the string.

 

Example1.C is a very simple example; there are no security issues here. The buffer is a statically allocated size and the data is the correct size for the buffer. There may be some instances where you, as the programmer, do not control the input to the buffer. In the following example, the programmer will statically assign the size of the buffer, but the user will provide the input.

 

On the flip side, example2.C contains serious security issues. The user in this program provides data that is more than 32 bytes, which causes severe vulnerabilities. If the user provides data that is longer than 32 bytes, that extra data will overflow onto the stack and could potentially overwrite local variables or even worse, the programs instruction pointer, which causes the program to crash.

 

What is the Stack?

The stack is a data structure in the computer’s memory that the executable program uses to keep track of the current function, its local variables, parameter values, and the return address to the previous function call. Every time a function is called, a new stack frame is created for that function to provide an organizational that keeps the variables and return addresses in the correct place. The stack pointer points to the top of the current stack frame and the base pointer points to the end of the current stack frame. As the stack grows and shrinks, the stack pointer and the base pointer get adjusted accordingly, as they will always point to the top and bottom of the current stack frame. Most security problems occur when there is a programming mistake that allows the attacker to overwrite other variables or return addresses on the stack to values of the attacker’s choosing. This technique is called “smashing the stack” and it is commonly used to exploit buffer overflow vulnerabilities.

 

What is Smashing the Stack?

“Smashing the stack” is a term used to describe when the process in which an attacker overflows a buffer with so much data that the stack becomes completely overwritten with attacker-controlled data. Once an attacker is able to smash the stack, they should be able to completely control the program flow and successfully exploit the program to execute their malicious payload instead of the program’s designed functionality.

4

 

It is also possible to only use a buffer overflow vulnerability to change the flow of the program. In the example above, example3.C, the program checks if the password inputted by the user is the same as the password the program expects. If the passwords match, the program will print out the user’s message, otherwise it will print “Wrong!”. The major security flaw within this program is that if the user’s message is longer than 32 bytes, it is possible to overwrite the value of result in order to bypass the password check.

 

The attacker will run the program with the argument “badpass” for userPass. Using python on the command line to create the message, the command ‘python –c print(”A”*60 + “\x00\x00\x00\x00”)’ will create the string for msg. This msg string has 60 A’s to be used as filler on the stack until we get to the variable we want to overwrite. Then the \x00\x00\x00\x00 will set the value equal to zero in order to bypass the password check. As you can see, we are able to bypass the password check without providing the correct password. Now, let’s take a look at the stack to see how this is possible.

 

The blue outlines the stack pointer (rsp) and the base pointer (rbp). The green outlines the buffer we are overflowing and all of the data we input to the buffer. The red outlines the value we are exploiting. The top of picture of the stack is right before the ‘gets’ call at line 12, and the bottom picture is immediately after the ‘gets’ call. As you can see, the input of 60 A’s fills up the stack exactly to where the value of result is stored. Since we are able to overflow the buffer, msg, we can continue to write and overwrite the stored value of result to zero in order to bypass the password check without knowing the correct password.

 

How can an attacker exploit a buffer overflow?

There are several ways in which an attacker can exploit a program with a buffer overflow vulnerability. The simplest way is for an attacker to write a shellcode to the stack and then redirect program flow to their malicious code. When an attacker is able to successfully smash the stack, they will have full control of the instruction pointer (rip) and it will be very easy for them to execute their shellcode. The code below suffers from a buffer overflow vulnerability. Let’s go through how to exploit this program to get a shell on the system.

 

 

The Python script, shown above, is used to exploit the buffer overflow in the example4.c program. The exploit is simple. The ‘FILL’ variable is used to smash the stack and overwrite everything except the return address. The ‘addr’ variable is used to overwrite the return address to the address we want to jump to, where our shellcode will start executing. The ‘NOP’ variable is the NOP sled that will be placed before the shellcode. A NOP sled is a section of no operation instructions that are used to ensure that our shellcode will be executed. The address we want to jump to in order to execute the shellcode is not an exact science. By putting a NOP sled before the shellcode, as long as we jump to any spot in the NOP sled, the shellcode will execute without any problems. Without a NOP sled, we would need to jump exactly to the beginning of the shellcode. If we are even one byte off, the exploit will fail. The final part of the exploit is the shellcode. The shellcode was created using msfvenom with the command “msfvenom -p linux/x64/exec CMD=/bin/sh -f python”. This command creates shellcode for 64-bit linux that executes the command /bin/sh and outputs the shellcode in Python format. Here, we just copy and paste it into the exploit script.

 

 

When we run the program with gdb, we will see something similar to what is noted above. This is what the stack looks like right before the exploit is executed. The blue outlines the stack pointer (rsp) and the base pointer (rbp). The green outlines the beginning of buffer we are overflowing, which is holding the ‘FILL’ variable. The orange is the address of our shellcode on the stack, and what we are overwriting the return address with in order for the program to return to the shellcode. The purple is the NOP sled that gives us extra confidence that the exploit will run correctly. The red outlines the beginning of the shellcode. When the exploit runs, we will return to the address 0x7fffffffe460, which is in the middle of the NOP sled, and then it will continue and execute the shellcode. As you can see, after the shellcode is executed, gdb says a new process /bin/dash is now executing, confirming the shellcode was executed correctly. Now, let’s go over how this could have been prevented.

What is a Stack Canary?

One of the main defense mechanisms used against buffer overflows is a stack canary. A stack canary stores a dynamically calculated value when the function begins on the stack before the return address. When the function is ready to return, the stack canary will be popped off the stack, recomputed, and compared to the stored canary that was placed before the return address. The stack canary is then checked to determine if it has been overwritten. If it has been tampered with, the program automatically exits with an error code stating: “the stack has been smashed.” This aborts the command and prevents any malicious activity from occurring. On the other hand, if the values match, the function was executed correctly and no stack smashing occurred, meaning that no malicious activity has occurred.

 

Looking above at the same example4 program in gdb, the only difference is that the program now has a stack canary, outlined in red. As shown in the disassembly, there is now a function called __stack_chk_fail right before the main function returns. This is the stack canary check. If it fails, the program will exit and the exploit will fail. The blue outlines the stack pointer (rsp) and the base pointer (rbp).

 

 

The images above demonstrate what the stack looks like after the buffer has been filled with the input. The blue outlines the stack pointer (rsp) and the base pointer (rbp). The red outlines the stack canary. The green outlines the buffer with our input on the stack. Since the data from the buffer overwrote the stack canary, it will fail the check at the end of the main function. In the picture below, the program says “stack smashing detected” and the program exited instead of being exploited.

 

What is NX (Non-Executable Stack)?

In the example shown below, the blue outlines the stack pointer (rsp) and the base pointer (rbp). The green outlines the beginning of buffer we are overflowing. The orange is the address of our shellcode on the stack, and what we are overwriting the return address with in order for the program to return to the shellcode. The purple is the NOP sled that gives us extra confidence the exploit will run correctly. The red outlines where the program has a segmentation fault because the stack is not executable. In this example, the stack is marked as a non-executable region of memory, meaning that code cannot be executed from an address on the stack. It is apparent that the buffer is overflowed just like before, and the shellcode is on the stack. When the program jumps to the address of the shellcode at 0x7fffffffe460, which is located on the stack, the program has a segmentation fault because we tried to execute instructions from the stack, which is not allowed. This successfully prevents the buffer overflow from occurring since we can no longer run our shellcode from the stack. However, this does not mean that it is impossible to exploit this program; it simply means that we will have to get more creative and find another place to put the shellcode.

 

What is Address Space Layout Randomization (ASLR)?

A more advanced technique to prevent buffer overflows is known as Address Space Layout Randomization (ASLR). ASLR randomizes the memory address space, making it difficult to predict the memory address layout of the program by randomizing the entry point of the program, the address of the stack, heap, and other areas of the executable. Doing so prevents the attacker from being able to predict the address they would likely redirect code flow to, thus preventing exploitation.

 

In the picture above, is it shown that every time the program is restarted, the stack pointer (rsp) is at a different address: first, 0x7ffd522d1b90, then 0x7fffea84f890, and then 0x7ffd78982260. The different addresses stops the exploit due to the fact that the exploit relies on a hard coded address on the stack. Since the stack address is changing every time, it is impossible to predict the addresses. As you can see, running the same example4 program with the same exploit as above does not work like before. The program simply seg faults and exits.

Conclusion

In conclusion, the overall goal of this blog is to give readers a complete understanding of how buffer overflows can successfully exploit a program and how the defensive mechanisms work to prevent exploitation. To enhance understanding, the code examples provide a visualization of the process of exploitation. Using these examples will allow readers to develop a stronger understanding of program flow, the stack, and how an attacker can abuse the program to execute malicious code. Understanding buffer overflows, ASLR, and stack canaries allows readers to learn more about security vulnerabilities and how to prevent them from occurring in the future.

Stack Canaries(栈保护金丝雀) 开发者应避免使用危险函数(如 `gets`、`strcpy`),并定期进行安全测试。Canary 的值通常在程序启动时随机生成(通过 `fs` 或 `gs` 寄存器访问),并存储在全局变量 `__stack_chk_guard` 中,攻击者难以预测。使用像 `0x00`、`0xFF` 等终止符字符,利用字符串操作函数(如 `strcpy`)遇到这些字符时会停止复制,从而阻止溢出。`-fstack-protector`:对包含敏感函数(如调用 `alloca` 或缓冲区大于 8 字节的函数)启用保护。 阅读详情

相关推荐

深入解析Stack Canaries:从原理到实战防御

本文深入解析了Stack Canaries的工作原理及其在防御栈溢出攻击中的关键作用。从Terminator Canaries到Random XOR Canaries,详细介绍了不同类型的实现方式及其适用场景,并结合GCC配置选项和底层汇编实现,提供了实战防御策略和最佳实践。

weixin_42665255的博客 407

stack canary介绍

CONFIG_STACKPROTECTOR和CONFIG_STACKPROTECTOR_STRONG是Linux内核的配置选项,用于控制内核在编译时是否启用Stack Canary(栈保护)以及保护级别的设置。如果该选项被启用(设置为y或m),则内核会在关键的函数和代码路径中插入Stack Canary的相关代码。默认情况下,Canary的保护级别是较低的,只会对函数中使用了缓冲区的变量进行保护。在编译代码时,可以使用一些与Canary相关的编译选项来启用或禁用Stack Canary。

weixin_42692164的博客 1022

StackGuard 漏洞

StackGuard 漏洞

CTF权威指南 笔记 -第四章Linux安全机制-4.1-Stack Canaries

canaries可以分为3类具体实现是栈溢出许多都是由于字符串操作不正当 (strcpy)所产生的字符串的结尾一般都是NULL \X00 结尾 换个角度就是容易被 00截断这里就是把低位设置为 \x00 既可以防止被泄露 又可以防止被伪造截断字符还包括 CR(0X0d) LF(0x0a) EOF(0xff)防止canaries 被攻击者猜到 random canaries 通常在程序初始化的时候生成随机数 并且保存在相对安全的位置当然 如果攻击者知道他的位置 还是有可能被读取。

m0_64180167的博客 907

如何在Ubuntu 22.04上为AlphaFold3配置NVIDIA A100 GPU(含驱动安装避坑指南)

本文提供了在Ubuntu 22.04系统上为AlphaFold3部署NVIDIA A100 GPU的完整安装教程。内容涵盖从系统环境准备、NVIDIA驱动安装与避坑指南,到Docker容器化部署、数据库获取以及最终构建运行AlphaFold3的详细步骤,旨在帮助研究者和开发者高效配置高性能计算环境,充分发挥A100的硬件潜力。

nft7creator的博客 468

VLA强化学习训练:π0到π0.5的技术优化与实现

视觉语言动作模型(VLA)作为多模态强化学习的重要分支,通过融合视觉、语言和环境状态数据实现智能决策。其核心技术在于多模态特征融合与动作空间设计,其中PPO算法因其出色的训练稳定性成为首选方案。在工程实践中,延迟补偿机制和课程学习设计能显著提升模型性能,如在四足机器人项目中使避障成功率提升47%。针对实际部署中的性能下降问题,需要特别关注硬件量化参数和控制频率一致性等关键因素。本文通过π0与π0.5版本的对比实验,详细解析了VLA模型在机械臂控制等具身智能场景中的优化路径。

weixin_29041767的博客 246

【软件与系统安全笔记】五、内存破坏防御

这是《【软件与系统安全】笔记与期末复习》系列中的一篇

框架科工:Framecraft 1776

手把手教你编写I2C读写EEPROM代码(驱动层实现)

从底层寄存器配置到时序控制,详解如何编写可移植的I2C读写EEPROM代码,覆盖起始信号、地址帧、数据收发及ACK应答等关键环节,确保在STM32、ESP32等主流平台稳定运行,真正落地i2c读写eeprom代码需求。

weixin_35756130的博客 505

linux 内核安全增强(一)— stack canary

一、背景知识 ——aarch64的函数栈 1. 栈生长方向与push/pop操作 栈是一种运算受限的线性表,入栈的一端为栈顶,另一端则为栈底,其生长方向和操作顺序理论上没有限定.而在aarch64平台上: 栈是向低地址方向增长的(STACK_GROWS_DOWNWARD) 栈的PUSH/POP通常要先移动SP: PUSH操作为PRE_DEC,即 PUSH操作为 sp = sp -4; store; POP操作为 POST_INC,即POP操作为 read; sp=sp+4; ...

ashimida 6914

PythonWeb开发框架—Django之工程创建和models的定义和增删改查

文章介绍了Django工程的创建、models的定义和增删改查

weixin_42476668的博客 990

lammps教程:MS转data文件出错原因分析及解决办法

使用ms建模是lammps建模的一种重要方法,但是ms建模转换为data过程中经常会出现各种各样的错误。 ms模型转data文件流程分两部分,一是ms建模、forcite设置力场并导出car文件,二是msi2lmp将car转为data文件。 任何一个环节出错都会导致无法得到data文件,最容易出错的是forcite力场设置环节。 forcite力场设置出错原因有很多,一个原因是缺乏某类原子的力场参数。 msi2lmp软件只能转换cvff或pcff力场的car文件,因此,如果力场中不包含某类原子的参数,在设置

lammps_jiayou的博客 5062

stack canary 的认识

在前面的博客里面,已经介绍了 stack overflow 的攻击原理,其中也设计到了 GCC 编译器的 stack canary 技术,用于预防 stack overflow. 现在再来详细了解一下stack canaries 的种类,已经他们的作用吧。 如果能在运行时检测出 stack overflow 破坏,就有可能对函数栈进行保护。目前的堆栈保护实现大多使用基于 “Cana

guilanl的专栏 9454

硬件描述语言Verilog学习(一)

主要学习综合和仿真、模块结构和信号类型Verilog 是用代码的形式描述硬件的功能,最终在硬件电路上实现该功能。在 Verilog 描述出硬件功能后需要使用综合器对 Verilog 代码进行解释并将代码转化成实际的电路来表示,最终产生实际的电路,也被称为网表。这种将 Verilog 代码转成网表的工具就是综合器。 上图左上角是一段 Verilog 代码,该代码实现了一个加法器的功能。在经过综合器解释后该代码被转化成一个加法器电路。QUARTUS、ISE 和 VIVADO 等 FPGA 开发工具都是综合器,

安静到无声 1498

从Stack Canaries到CFI:C++缓冲区溢出防护技术演进(2025权威解读)

深入解析C++缓冲区溢出防护核心技术,涵盖Stack Canaries、ASLR到CFI的演进路径,适用于系统软件与高安全场景。结合2025全球C++及系统软件技术大会:C++缓冲区溢出的防护技术最新成果,揭示高效防御方案的关键优势,值得收藏。

AlgoChat的博客 1095

PX4从放弃到精通(十一):混控及PWM输出

文章目录前言一、混控脚本二、使用步骤1.引入库2.读入数据总结 前言 一个人可以走的更快,一群人才能走的更远,交流学习加qq:2096723956 更多保姆级PX4+ROS学习视频:https://b23.tv/ZeUDKqy 分享知识,传递正能量,如有疏漏或不当之处,恳请指出. 一、混控脚本 混控脚本定义了不同 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、使用步骤 1.引入库 代码如下(示例): import numpy as np import pand

超维空间科技的博客 1万+

R语言 百度坐标转换至WGS84坐标

本文利用R语言封装了百度坐标转换至WGS84坐标的函数,亲测有效,提供了便捷的百度坐标转换方法。

qingchen98的博客 2135

stack-overflow与heap-buffer-overflow 等常见执行错误的原因以及改正方法

你是否会在写完一整串代码之后提交,发现leetcode报错了一大堆看不懂的英文呢?最后在代码中找大半天bug,学会总结会让你少走很多弯路!对照你的报错信息,在简单的例子中找出你的错误吧。

Dusong_的博客 1万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

对抗栈溢出的安全机制及其绕过方法(作业)

栈溢出是一种常见且严重的安全漏洞,攻击者通过向栈中输入超出预期的数据,可能导致程序崩溃、数据泄露,甚至执行恶意代码。随着网络攻击技术的发展,反栈溢出安全机制不断演进,但攻击者也在寻找新的绕过方式。本文将详细探讨常见的对抗栈溢出的安全机制,分析其绕过手段,并结合一些近年的CVE漏洞实例,具体分析漏洞产生的原因和防御方法。

m0_74105111的博客 761

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Linux 内核安全增强—— stack canary

per-cpu 变量的引入是为了实现per-task的stack canary, 每个cpu上同时只能运行一个进程/线程, per cpu变量可以随进程的切换而切换,故通过一个per-cpu变量完全可以为每个进程/线程解引用到不同的canary地址(后续称为per-cpu canary),以实现per-task的canary.默认stack canary使用全局符号(变量) __stack_chk_guard 作为原始的canary(后续称为全局canary), 在gcc/clang中均使用相同的名字...

weixin_71478434的博客 2043

Pwn 课程第六节: 栈溢出保护机制

地址空间布局随机化(ASLR)是操作系统通过随机化内存地址来提高安全性的方法。NX(No eXecute)或 DEP(Data Execution Prevention)防止栈中的代码被执行。PIE(Position Independent Executable)使可执行文件的地址在每次执行时都不同,增加漏洞利用难度。GCC 提供选项,通过检查字符串操作函数(如strcpysprintf)来提高安全性。了解了现代操作系统的安全机制。熟悉了的作用及检测方法。理解了ASLR及其对漏洞利用的影响。了解了。

weixin_44948224的博客 1807

(原创)攻击方式学习之(3) - 缓冲区溢出(Buffer Overflow)

堆栈溢出 堆栈溢出通常是所有的缓冲区溢出中最容易进行利用的。了解堆栈溢出之前,先了解以下几个概念: 缓冲区 简单说来是一块连续的计算机内存区域,可以保存相同数据类型的多个实例。 堆栈 堆 栈是一个在计算机科学中经常使用的抽象数据类型。堆栈中的物体具有一个特性:最后一个放入堆栈中的物体总...

weixin_34212189的博客 1471

【嵌入式安全扫盲一】Stack buffer overflow

出处:https://en.wikipedia.org/wiki/Stack_buffer_overflow Stack buffer overflow From Wikipedia, the free encyclopedia For other uses, see Stack overflow (disambiguation). In sof

自由的天空 1787

aslr_什么是ASLR,它如何确保计算机安全?

aslrAddress Space Layout Randomization (ASLR) is a security technique used inoperating systems, first implemented in 2001. The current versions of all major operating systems (iOS, Android, Windows, ...

culinxia2707的博客 4232

搬砖:Buffer Overflow

Buffer Overflow 卡德尔先生   前言 CS 161 is the voodoo plan of Lord Dirks. Project 1 is the first step. 这个project 1做的我心态爆炸 感觉自己还是不是很懂汇编指令 特别是esp寄存器 基本知识介绍 stackStructure.png 上图是linux x86系列的内存结构。...

hunter 1116

[转] GCC 中的编译器堆栈保护技术

以堆栈溢出为代表的缓冲区溢出已成为最为普遍的安全漏洞。由此引发的安全问题比比皆是。早在 1988 年,美国康奈尔大学的计算机科学系研究生莫里斯 (Morris) 利用 UNIX fingered 程序的溢出漏洞,写了一段恶意程序并传播到其他机器上,结果造成 6000 台 Internet 上的服务器瘫痪,占当时总数的 10%。各种操作系统上出现的溢出漏洞也数不胜数。为了尽可能避免缓冲区溢出漏洞被攻...

weixin_30325793的博客 1024
上一篇: 【译】KINIBI TEE: TRUSTED APPLICATION EXPLOITATION
下一篇: PLT and GOT - the key to code sharing and dynamic libraries
Omni-Space
博客等级 码龄11年 2158粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值