-
2019-06-19 19:27:55
、前言
Linux下常用的拷贝函数(如strcpy、memcpy等)如果使用不规范,常常会导致栈溢出。也就是你的软件系统本身存在bug,这样就会成为别人攻击的目标。本文主要讲的是Linux系统如何给栈溢出增加防护网?攻击者又有什么手段绕过一层层防护网实现攻击?
2、栈溢出防御
2.1 地址随机化技术
Linux系统提供设置堆栈地址随机化技术,例如函数内部变量存在栈上,每次打印函数内部变量的地址,其值都是随机的。
用户可以通过读取或设置/proc/sys/kernel/randomize_va_space节点值对其属性进行修改。
其中0表示关闭地址随机化;2表示开启地址随机化。
Linux系统默认是开启了地址随机化技术的。
2.2 栈不可执行
当我们通过读取/proc/pid/maps会发现stack的权限是“rw-p”,这说明栈上的数据只有读写权限,没有执行权限。这样如果你把一段shellcode放到栈上,是无法执行的。
2.3 栈保护
在函数的入口和出口处加一段栈检测的汇编代码,用来检测rbp和返回地址是否被修改,这就是Linux的栈保护机制。
GCC编译的时候可以加-fstack-protector则开启栈保护机制,如果加上-fno-stack-protector则会取消栈保护机制。
可执行文件是否开启栈保护,可以objdump查看下汇编,如下是某函数的反汇编,可以确
更多相关内容 -
Linux中的保护机制
2021-05-17 14:56:09一:canary(栈保护)栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入cookie...在编写漏洞利用代码的时候,需要特别注意目标进程是否开启了NX、PIE等机制,例如存在NX的话就不能直接执行栈上的数据,存在PIE 的话各个系统调用的地址就是随机化的。
一:canary(栈保护)
栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。
gcc在4.2版本中添加了-fstack-protector和-fstack-protector-all编译参数以支持栈保护功能,
因此在编译时可以控制是否开启栈保护以及程度,例如:
1、gcc -o test test.c // 默认情况下,不开启Canary保护
2、gcc-fno-stack-protector -o test test.c //禁用栈保护
3、gcc -fstack-protector -o test test.c //启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码
4、gcc-fstack-protector-all -o test test.c //启用堆栈保护,为所有函数插入保护代码
二:NX(no execute)
NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。
gcc编译器默认开启了NX选项,如果需要关闭NX选项,可以给gcc编译器添加-z execstack参数。 例如:
1、gcc -o test test.c // 默认情况下,开启NX保护
2、gcc -z execstack -o test test.c // 禁用NX保护
3、gcc -z noexecstack -o test test.c // 开启NX保护
在Windows下,类似的概念为DEP(数据执行保护)
三:PIE(position-independent executables)
位置独立的可执行区域。这样使得在利用缓冲溢出和移动操作系统中存在的其他内存崩溃缺陷时采用面向返回的编程(return-oriented programming)方法变得难得多。一般情况下NX(Windows平台上称其为DEP)和地址空间分布随机化(ASLR)会同时工作。内存地址随机化机制(address space layout randomization),有以下三种情况:
0 - 表示关闭进程地址空间随机化。
1 - 表示将mmap的基址,stack和vdso页面随机化。
2 - 表示在1的基础上增加栈(heap)的随机化。
liunx下关闭PIE的命令如下:
sudo -s echo 0 > /proc/sys/kernel/randomize_va_space
gcc编译命令:
1、gcc -o test test.c // 默认情况下,不开启PIE
2、gcc -fpie -pie -o test test.c // 开启PIE,此时强度为1
3、gcc -fPIE -pie -o test test.c // 开启PIE,此时为最高强度2
4、gcc -fpic -o test test.c // 开启PIC,此时强度为1,不会开启PIE
5、gcc -fPIC -o test test.c // 开启PIC,此时为最高强度2,不会开启PIE
四:RELRO(read only relocation)
在Linux系统安全领域,数据可以写的存储区就会是攻击的目标,尤其是存储函数指针的区域。 所以在安全防护的角度来说尽量减少可写的存储区域对安全会有极大的好处。GCC, GNU linker以及Glibc-dynamic linker一起配合实现了一种叫做relro的技术:。大概实现就是由linker指定binary的一块经过dynamic linker处理过 relocation之后的区域为只读.设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。RELRO为” Partial RELRO”,说明我们对GOT表具有写权限。
gcc编译:
gcc -o test test.c // 默认情况下,是Partial RELRO
gcc -z norelro -o test test.c // 关闭,即No RELRO
gcc -z lazy -o test test.c // 部分开启,即Partial RELRO
gcc -z now -o test test.c // 全部开启
五 总结
各种安全选择的编译参数如下:
NX:-z execstack / -z noexecstack (关闭 / 开启)
Canary:-fno-stack-protector /-fstack-protector / -fstack-protector-all (关闭 / 开启 / 全开启)
PIE:-no-pie / -pie (关闭 / 开启)
RELRO:-z norelro / -z lazy / -z now (关闭 / 部分开启 / 完全开启)
参考资料:
-
Linux下基本栈溢出攻击
2021-01-30 11:37:20下面首先了解一下现有的用于保护堆栈的机制以及关闭相应保护机制的方法,为进一步分析基本栈溢出提供了良好的实验环境。在Ubuntu和其他基于Linux内核的系统中,目前都采用内存地址随机化的机制来初始化堆栈,这将会... -
禁用GCC中的堆栈保护不起作用
2021-05-17 19:44:23我正在尝试使用带有strcpy的经典溢出使用此函数重新创建堆栈缓冲区溢出:#include #include void main(int argc, char **...}我已经尝试使用所有各种标志进行编译,以便删除堆栈保护gcc -o vuln vuln.c -fno-stack-pr...我正在尝试使用带有strcpy的经典溢出使用此函数重新创建堆栈缓冲区溢出:
#include
#include
void main(int argc, char **argv) {
char buf[100];
strcpy(buf,argv[1]);
printf("Done!\n");
}
我已经尝试使用所有各种标志进行编译,以便删除堆栈保护gcc -o vuln vuln.c -fno-stack-protector -g -z execstack以及使用sudo echo 0>删除ASLR.的/ proc / SYS /内核/ randomize_va_space.
我可以让我的nop-shellcode-address覆盖保存的EIP,但它会在RET上崩溃.我想通过HANDLE SIGSEGV忽略等来禁用gdb中的SIGSEGV,但是在GDB外运行我继续得到Segmentation Fault,无论我在哪里设置返回地址.
除了获得旧版gcc之外的任何想法?目前使用gcc版本6.1.1.
解决方法:
Linux遵循W^X原则:它将内存页标记为不可执行,除非它们是代码部分的一部分.这超出了编译应用程序的范围,并且有充分的理由.操作系统承担此责任,以防止系统上执行的任何程序的缓冲区溢出攻击;尤其是那些主动尝试执行缓冲区溢出攻击的程序,就像你的程序一样.
您正尝试通过buf在堆栈上编写代码并覆盖函数的返回地址以将执行跳转到新注入的代码中.当函数返回时,程序计数器被设置为重写的返回地址,现在指向堆栈内存.由于堆栈内存页面上的已撤销执行权限,程序计数器尝试执行下一条指令时抛出SIGSEGV.
要从堆栈执行,必须禁用OS堆栈保护.
幸运的是,Linux提供了execstack用于由用户自行决定使用的这种情况.
见this Unix& Linux Stack Exchange发布更多一般信息.
调试注入数据
如果您在gdb中获得SIGSEGV,则可能意味着缓冲区溢出尝试中存在一些错误.为了避免在main结束时搞乱清理,我建议你创建一个从main调用的函数来执行缓冲区溢出:
#include
#include
char injection_code[] = ""; // buffer overrun data here
void foo () {
char buf[100];
// memcpy used to copy the full injection string, including any nested 0s
memcpy(buf, injection_code, 108); // +8 here to handle 64-bit system RAs
}
int main (int argc, char** argv) {
foo();
printf("Done!\n");
return 0;
}
使用GDB进行调试.我建议在foo结尾处设置一个断点,并检查寄存器是否符合您对信息寄存器的期望.您可能最感兴趣的是指令指针,您可以使用信息寄存器rip(64位)或info寄存器eip(32位)进行检查.
您可以通过在GDB中使用print或x/x来探索堆栈的外观.例如,您可以检查$rbp 8以查看堆栈上的返回地址(RA).
如果RA指向无效位置,GDB将对ret指令进行SIGSEGV:
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005bc in foo () at bufferoverflow.c:27
您可以通过检查故障时的指令指针地址(在上面的例子中,它将是0x00000000004005bc)对程序的程序集(在GDB中使用disassemble function_name)来检查它是否在ret指令上出现故障.
如果返回地址指向堆栈中,它可能会抛出一个非法指令的SIGILL,这意味着您的返回地址可能无法正确对齐,或者您注入的指令格式不正确:
Program received signal SIGILL, Illegal instruction.
0x00007fffffffdc13 in ?? ()
同样,您可以使用GDB来探索堆栈以了解原因.
GDB对于使缓冲区溢出的结构正确非常有用.
但是,一旦按预期工作,请记住在GDB外部执行时可能会移位内存地址,尤其是在没有调试标志(-g)的情况下进行编译时.您将不得不稍微使用返回地址,以便在“实时”环境中将其放置到您想要的位置.
一个旁白
通常,直接运行注入代码的缓冲区溢出攻击通常不适用于当今的堆栈保护机制.通常需要存在额外的漏洞才能执行任意代码.
标签:c-3,buffer-overflow,linux,gcc,stack-overflow
来源: https://codeday.me/bug/20190828/1755935.html
-
Linux 内核栈溢出分析
2021-05-11 04:59:33Linux 系统进程运行分为 用户态 和 内核态,进入内核态之后使用的是内核栈,作为基本的安全机制,用户程序不能直接访问内核栈,所以尽管内核栈属于进程的地址空间,但与用户栈是分开的。内核栈需要...8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
由于内核栈的大小是有限的,就会有发生溢出的可能,比如调用嵌套太多、参数太多都会导致内核栈的使用超出设定的大小。本文分析内核栈溢出。
Linux 系统进程运行分为 用户态 和 内核态,进入内核态之后使用的是内核栈,作为基本的安全机制,用户程序不能直接访问内核栈,所以尽管内核栈属于进程的地址空间,但与用户栈是分开的。内核栈需要方便快捷的访问用户态进程信息 thread_info,这部分数据就压在内核栈的底部,大小默认为 16Kb。如下图所示:
内核栈溢出的结果往往是系统崩溃,因为溢出会覆盖掉本不该触碰的数据,首当其冲的就是 thread_info — 它就在内核栈的底部,内核栈是从高地址往低地址生长的,一旦溢出首先就破坏了 thread_info,thread_info 里存放着指向进程的指针等关键数据,迟早会被访问到,那时系统崩溃就是必然的事。
内核栈溢出导致的系统崩溃有时会被直接报出来,比如你可能会看到:...
Call Trace:
[] ? warn_slowpath_common+0x87/0xc0
BUG: unable to handle kernel NULL pointer dereference at 00000000000009e8
IP: [] print_context_stack+0xad/0x140
PGD 5fdb8ae067 PUD 5fdbee9067 PMD 0
Thread overran stack, or stack corrupted
Oops: 0000 [#1] SMP
...
但更多的情况是不直接报错,而是各种奇怪的 panic。在分析 vmcore 的时候,它们的共同点是 thread_info 被破坏了。
以下是一个实例,注意在 task_struct 中 stack 字段直接指向内核栈底部也就是 thread_info 的位置,我们看到 thread_info 显然被破坏了:cpu 的值大得离谱,而且指向 task 的指针与 task_struct 的实际地址不匹配:crash64> struct task_struct ffff8800374cb540
struct task_struct {
state = 2,
stack = 0xffff8800bae2a000,
...
crash64> thread_info 0xffff8800bae2a000
struct thread_info {
task = 0xffff8800458efba0,
exec_domain = 0xffffffff,
flags = 0,
status = 0,
cpu = 91904,
preempt_count = 0,
...
作为一种分析故障的手段,可以监控内核栈的大小和深度,方法如下:# mount -t debugfs nodev /sys/kernel/debug
# echo 1 > /proc/sys/kernel/stack_tracer_enabled
然后检查下列数值,可以看到迄今为止内核栈使用的峰值和对应的 backtrace:# cat /sys/kernel/debug/tracing/stack_max_size
# cat /sys/kernel/debug/tracing/stack_trace
-
Linux栈溢出漏洞利用详解
2021-09-03 21:11:47以一个实例,详细描述了linux栈溢出的原理和应用。 1.栈溢出背景知识 栈 栈又称堆栈,由编译器自动分配释放,行为类似数据结构中的栈(先进后出)。堆栈主要有三个用途: 为函数内部声明的非静态局部变量(C语言中... -
Linux线程栈内存总结
2021-05-14 18:03:47何为线程栈空间泄露?何为anon内存?虚拟内存、物理内存、anon内存的联系anon与线程的联系glibc源码库线程创建与销毁anon关系使用pmap分析虚拟地址空间以及anon内存何为线程栈空间泄露?【栈空间泄露】:简单了说... -
linux的进程栈和线程栈
2022-03-14 18:21:34进程栈:也叫主线程栈。...create创建的线程,是在堆区分配的,大小固定,不是向下生长的,只是后进先出,默认8M——实际调用pthread_create开辟的是8M+4K,因为包含了保护页(各线程栈之间的隔离地带)。 . -
Linux栈溢出例子详解
2018-07-13 09:50:29是关闭栈保护; -z execstack 是开启栈可执行。“-no-pie”选项用于关闭PIE功能,开启PIE功能意味着编译器将随机化ELF文件的内存装在基址。 然后更改程序的拥有者和组权限,并添加粘滞位(该步骤不是必须的,如此... -
栈保护机制
2020-05-04 09:30:57当启用栈保护后,函数开始执行的时候就会向往栈里插入cookie信息,当函数真正返回的时候回验证cookie信息是否合法,若果不合法就会停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈... -
论文研究-基于Linux的栈溢出攻击防护系统.pdf
2019-07-22 20:43:00与其他相关技术相比,FuncFence可以提供效率更好的安全机制,可以避免程序在防止缓冲区溢出的同时陷入拒绝服务攻击(DoS),可以使程序无须重新编译就可得到保护,用户不需要进行任何操作,完全透明地实施防护。 -
浅析栈保护机制
2020-11-11 16:56:00栈保护机制 canary canary意为金丝雀,作为栈保护技术之一,它的名字源自于17世纪,英国煤矿工人发现金丝雀对瓦斯十分敏感,每次下井都会带一只金丝雀作为“瓦斯检测指标”,从而挽救了很多工人的生命。 canary机制... -
Canary保护机制(栈保护)的开启与关闭
2020-09-06 20:28:37这个选项表示栈保护功能有没有开启。 栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先... -
栈溢出原理
2021-05-16 14:47:40栈溢出原理¶介绍¶栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。这种问题是一种特定的缓冲区溢出漏洞,类似的还有堆溢出,bss 段溢出... -
Linux 2.6.32的内核栈和用户空间栈关系
2021-05-12 02:00:57每个进程会有两个栈,一个用户栈,存在于用户空间,一个内核栈,存在于内核空间。当进程在用户空间运行时,cpu堆栈指针寄存器里面的内容是用户堆栈地址,使用用户栈;当进程在内核空间时,cpu堆栈指针寄存器里面的... -
Linux系统和程序中的DEP和ASLR保护机制
2020-10-07 16:39:43下表列出了有C标准库漏洞函数的一些更安全替代品: Linux系统中的DEP和ASLR保护机制 Linux系统中的DEP通过NX来实现,NX即No-eXecute(不可执行)的意思,NX的基本原理是将数据所在内存页标识为不可执行,当程序溢出... -
栈保护者Canary的实现细节
2020-04-16 19:21:25失去栈保护的汇编代码: 比对发现,在有栈保护的汇编代码中增加了一些指令,其中: mov %gs:0x14,%eax mov %eax,-0xc(ebp) 两句指令,是向栈中插入一个canary值。使用栈保护的copy函数栈是这样的: canary的值是... -
解读Linux安全机制之栈溢出保护
2016-01-27 14:10:002.6.30:新增对内核中断上下文的栈保护和对x32平台进程上下文的栈保护支持; 3.14:对该功能进行了一次升级以支持gcc的-fstack-protector-strong参数,提供更大范围的栈保护。 1. 栈保护工作原理 我们参照前面... -
深入理解linux下进程和线程的空间分配,进程栈和线程栈的空间分配
2021-03-23 11:42:10关于进程栈和线程栈总结: (1)进程栈大小时执行时确定的,与编译链接无关 (2)进程栈大小是随机确认的,至少比线程栈要大,但不会超过2倍 (3)线程栈是固定大小的,可以使用ulimit -a 查看,使用ulimit ... -
C/C++ 基础栈溢出及保护机制
2020-12-01 18:00:35来源:pandolia 整理:CPP开发者https://www.jianshu.com/p/47d484b9227e【导读】:缓冲区溢出非常危险,因为栈空间内保存了函数的返回地址。... -
linux elf保护机制
2020-01-27 15:12:38关闭开启保护命令参数 PIE保护//(默认不开启 以下都为ubuntu16.04测试) -fno-stack-protector (不开启) -no-pie / -pie (关闭 / 开启) canary保护//(默认不开启) -fno-stack-protector /-fstack-... -
Linux虚拟地址空间布局以及进程栈和线程栈总结
2020-05-20 22:09:06一:Linux虚拟地址空间布局 在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中。这个沙盘就是虚拟地址空间(Virtual Address Space),在32位模式下它是一个4GB的内存地址块。 在Linux系统中, 内核进程和用户... -
Linux通过栈溢出进行提权实战(dpwwn03)
2021-05-14 11:42:53最近在刷vulnhub靶场,偶然间做到了dpwwn系列的靶场,其中dpwwn03靶场提权用的是程序栈溢出的漏洞,相对常规方法还是比较少见的,所以拿出来单独在这里研究下。既然讲到了提权,顺带介绍下常规的提权方式:1、内核... -
Linux函数调用与栈
2017-06-05 17:31:36栈与函数调用惯例(又称调用约定)— 基础篇 记得一年半前参加百度的校招面试时,被问到函数调用惯例的问题。当时只是懂个大概,比如常见函数调用约定类型及对应的参数入栈顺序等。最近看书过程中,重新回顾了这些... -
栈溢出的几种保护机制
2020-02-28 11:27:41Stack Protector(栈保护) 也称 cannary。 说明:当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址... -
改进优化Linux网络协议栈
2012-05-12 08:01:56防火墙是一种保护网络的行之有效的安全机制 是保护区的一道安全防线它能够将保护区以外的非法入侵及访问拒之门外对于资金少又有科研人员的单位可采用源代码开放的免费的Linux netfilter/iptables 构建防火墙. -
linux内核栈与用户栈及调用栈观察方法
2016-06-29 20:56:22最近linux内核的中断部分,总是被书里的栈弄晕,一会儿内核栈,一会儿用户栈的……很是崩溃,在网上google了一下 找了一篇不错的文章拿来分享。 5.8 Linux 系统中堆栈的使用方法 本节内容概要描述了... -
Linux程序的常用保护机制
2020-06-28 14:29:24在编写漏洞利用代码的时候,需要特别注意目标进程是否开启了DEP(Linux下对应NX)、ASLR(Linux下对应PIE)等机制,例如存在DEP(NX)的话就不能直接执行栈上的数据,存在ASLR的话各个系统调用的地址就是随机化的。... -
linux面试之-谈谈你理解的堆和栈
2016-03-03 12:06:01编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么。我仅有高级语言编程经验,没有看过对此更清晰的解释。我的意思是我理解什么是栈,但是它们到底是什么,在...