在之前的任务中,我们的目标服务器是 32 位程序。在这个任务中,我们将会切换到一个 64 位的服务器程序。我们的新目标为 10.9.0.7,该地址运行的是 64 位版本的 stack 程序。首先,我们将向这个服务器发送一条问候消息。下面将会打印出目标容器输出的消息。
// 在虚拟机(即攻击者机器)上
$ echo hello | nc 10.9.0.7 9090
Ctrl+C
// 容器输出的消息
server-3-10.9.0.7 | Got a connection from 10.9.0.1
server-3-10.9.0.7 | Starting stack
server-3-10.9.0.7 | Input size: 6
server-3-10.9.0.7 | Frame Pointer (rbp) inside bof(): 0x00007fffffffe1b0
server-3-10.9.0.7 | Buffer's address inside bof(): 0x00007fffffffe070
server-3-10.9.0.7 | ==== Returned Properly ====
你可以看到帧指针和缓冲区地址的值现在为8字节长(而32位程序中是4字节)。你的任务是构建一个 Payload 来利用服务器的缓冲区溢出漏洞。你最终的目标是在目标服务器上获得 root shell。你可以使用任务 0 中的 shellcode,但是你需要使用 64 位版本的 shellcode。
与32位机器上的缓冲区溢出攻击相比,在64位机器上的攻击更为困难。最困难的部分在于地址问题。虽然 x64 架构支持 64 位地址空间,但目前只允许从 0x00 到 0x00007FFFFFFFFFFF 的地址。这意味着每一个8字节地址的最高两位总是为零。这就带来了一个问题。
在我们的缓冲区溢出攻击中,我们需要将至少一个地址存储在 Payload 中,并通过 strcpy() 函数将其复制到栈中。我们知道 strcpy() 函数会在遇到零时停止复制。因此,如果负载中间出现了一个零,则该零之后的内容将不会被复制到栈中。如何解决这个问题是这一关中最难的挑战之一。在你的报告中,你需要描述你是如何解决这个问题的。