hacktricks/binary-exploitation/stack-overflow
2024-06-16 09:01:21 +00:00
..
ret2win Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-05-05 22:03:00 +00:00
stack-shellcode Translated ['binary-exploitation/heap/README.md', 'binary-exploitation/h 2024-04-10 15:34:01 +00:00
pointer-redirecting.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-04-07 02:33:04 +00:00
README.md Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc 2024-06-16 09:01:21 +00:00
ret2win.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-04-07 02:33:04 +00:00
stack-pivoting-ebp2ret-ebp-chaining.md Translated ['binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-e 2024-04-19 14:49:58 +00:00
stack-shellcode.md Translated ['README.md', 'binary-exploitation/arbitrary-write-2-exec/aw2 2024-04-07 02:33:04 +00:00
uninitialized-variables.md Translated ['binary-exploitation/heap/README.md', 'binary-exploitation/h 2024-04-10 15:34:01 +00:00

栈溢出

从零开始学习AWS黑客技术成为专家 htARTEHackTricks AWS红队专家

支持HackTricks的其他方式

什么是栈溢出

栈溢出是一种漏洞,当程序向栈写入的数据超过其分配的空间时发生。这些多余的数据将覆盖相邻的内存空间,导致有效数据的损坏,控制流的中断,以及潜在地执行恶意代码。这个问题通常是由于使用不执行输入边界检查的不安全函数而引起的。

这种覆盖的主要问题在于保存的指令指针EIP/RIP保存的基指针EBP/RBP用于返回到前一个函数的位置是存储在栈上的。因此,攻击者可以覆盖这些内容并控制程序的执行流程

这种漏洞通常是因为一个函数在栈内复制的字节数超过了为其分配的数量,因此能够覆盖栈的其他部分。

一些常见的容易受到影响的函数包括:strcpystrcatsprintfgets... 同样,像**fgetsreadmemcpy这样带有长度参数**的函数,如果指定的长度大于分配的长度,可能会以一种易受攻击的方式使用。

例如,以下函数可能存在漏洞:

void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}

寻找栈溢出偏移量

发现栈溢出最常见的方法是输入大量的 A(例如 python3 -c 'print("A"*1000)')并期望出现 Segmentation Fault,表明尝试访问地址 0x41414141`。

此外,一旦发现存在栈溢出漏洞,就需要找到偏移量,直到可以覆盖返回地址,为此通常使用德布鲁因序列。对于大小为 k 的字母表和长度为 n 的子序列,德布鲁因序列是一个循环序列,其中每个可能的长度为 n 的子序列都恰好出现一次**作为一个连续的子序列。

这样,不需要手动找出控制 EIP 所需的偏移量,可以使用其中一个这些序列作为填充,然后找到最终覆盖它的字节的偏移量。

可以使用pwntools来实现这一点:

from pwn import *

# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
pattern = cyclic(1000)

# This is an example value that you'd have found in the EIP/IP register upon crash
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value)  # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")

或者 GEF

#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp

利用栈溢出

在溢出时(假设溢出大小足够大),您将能够覆盖栈内部的局部变量的值,直到达到保存的EBP/RBP和EIP/RIP甚至更多
滥用这种类型的漏洞最常见的方法是通过修改返回地址,因此当函数结束时,控制流将被重定向到用户在指针中指定的位置

然而,在其他情况下,也许只是覆盖栈中的一些变量值就足以进行利用就像在简单的CTF挑战中一样

Ret2win

在这种类型的CTF挑战中二进制文件中有一个从未被调用的函数您需要调用该函数才能获胜。对于这些挑战,您只需要找到覆盖返回地址的偏移量,并找到要调用的函数的地址(通常会禁用ASLR),因此当易受攻击的函数返回时,隐藏函数将被调用:

{% content-ref url="ret2win/" %} ret2win {% endcontent-ref %}

栈内代码

在这种情况下攻击者可以在栈中放置一个shellcode并滥用受控的EIP/RIP来跳转到shellcode并执行任意代码

{% content-ref url="stack-shellcode/" %} stack-shellcode {% endcontent-ref %}

ROP和Ret2...技术

这种技术是绕过前一种技术的主要保护措施:**不可执行的栈NX**的基本框架。它允许执行几种其他技术ret2lib、ret2syscall...),这些技术将通过滥用二进制文件中现有指令来执行任意命令:

{% content-ref url="../rop-return-oriented-programing/" %} rop-return-oriented-programing {% endcontent-ref %}

堆溢出

溢出并不总是发生在栈中,例如,它也可能发生在中:

{% content-ref url="../libc-heap/heap-overflow.md" %} heap-overflow.md {% endcontent-ref %}

保护类型

有几种保护措施试图防止利用漏洞,可以在以下位置查看它们:

{% content-ref url="../common-binary-protections-and-bypasses/" %} common-binary-protections-and-bypasses {% endcontent-ref %}