云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

云解析_人工智能服务器_9元

小七 141 0

Linux内核模糊化简介

有一段时间我一直想玩覆盖率引导的模糊化。模糊化是一种强大的测试技术,自动程序向被测试程序提供半随机输入。其目的是找到触发bug的输入。模糊在寻找C或C++程序中内存损坏bug时特别有用。图片由Patrick Shannon CC by 2.0通常,建议选择一个知名的,但很少探索的库,它主要用于解析。从历史上看,libjpeg、libpng和libyaml都是完美的目标。现在很难找到一个好的目标-一切似乎都已经模糊到死亡。这是件好事!我想软件越来越好了!我决定尝试一下Linux内核netlink机器,而不是选择用户空间目标。Netlink是一个内部Linux工具,由"ss"、"ip"、"netstat"等工具使用。它用于低级网络任务-配置网络接口、IP地址、路由表等。这是一个很好的目标:它是内核中一个模糊的部分,并且自动生成有效的消息相对容易。最重要的是,我们可以在这个过程中了解到很多关于Linux内部的知识。netlink中的错误不会对安全造成影响-netlink套接字通常需要特权访问。在这篇文章中,我们将运行AFL fuzzer,针对一个定制的Linux内核驱动netlink shim程序。所有这些都在KVM虚拟化中运行。这篇博文是一篇教程。有了易于遵循的说明,您应该能够快速复制结果。你所需要的只是一台运行Linux的机器和20分钟。前期工作我们将要使用的技术正式称为"覆盖引导模糊化"。有很多以前的文献:丹·吉多的智能毛绒革命,以及关于它的LWN文章Mateusz"j00ru"Jurczyk的有效文件格式模糊化Hongfuzz由Robert Swiecki执笔,是一个现代的,功能丰富的覆盖引导模糊簇毛模糊测试套件在过去,许多人已经模糊了Linux内核。最重要的是:dmitryvyukov的syzkaller(又名syzbot)是一种非常强大的CI风格,持续运行内核fuzzer,已经发现了数百个问题。这是一个很棒的机器-它甚至会自动报告错误!三一模糊器我们用AFL,大家最喜欢的毛绒。AFL是由MichałZalewski撰写的。它以其易用性、速度和非常好的变异逻辑而闻名。这是一个完美的选择,人们开始他们的旅程模糊!如果您想了解更多关于AFL的信息,请参阅以下文件:历史笔记技术白皮书自述文件覆盖引导模糊化覆盖率引导的模糊化根据反馈回路的原理工作:模糊者选择最有希望的测试用例模糊器将测试变异为大量的新测试用例目标代码运行变异的测试用例,并报告回代码覆盖率fuzzer从报告的覆盖率中计算出一个分数,并使用它对有趣的突变测试进行优先级排序,并删除多余的测试例如,假设输入测试是"hello"。Fuzzer可能会将其突变为许多测试,例如:"hEllo"(位翻转)、"hXello"(字节插入)、"hllo"(字节删除)。如果这些测试中的任何一个都会产生有趣的代码覆盖率,那么它将被优先化并作为下一代测试的基础。关于突变是如何完成的,以及如何有效地比较数千个程序运行的代码覆盖率报告的细节是更模糊的秘密调味汁。阅读AFL的技术白皮书了解细节。从二进制文件返回的代码覆盖率非常重要。它允许fuzzer对测试用例进行排序,并确定最有希望的测试用例。没有代码覆盖,模糊器是盲目的。通常,当使用AFL时,我们需要检测目标代码,以便以AFL兼容的方式报告覆盖率。但我们要把内核弄得模糊!我们不能用"afl-gcc"重新编译它!相反,我们将使用一个技巧。我们将准备一个二进制文件,诱使AFL认为它是用它的工具编译的。这个二进制文件将报告从内核提取的代码覆盖率。内核代码覆盖率内核至少有两个内置的覆盖机制-GCOV和KCOV:在Linux内核中使用gcovKCOV:模糊化的代码覆盖率KCOV的设计考虑了模糊化,所以我们将使用这个。使用KCOV非常简单。我们必须用正确的设置编译Linux内核。首先,启用KCOV kernel config选项:cd-linux./scripts/配置\-e KCOV公司\-d KCOV U仪器KCOV能够记录整个内核的代码覆盖率。可通过KCOV U仪器U ALL选项进行设置。但这也有缺点——它会减慢我们不想评测的内核部分的速度,并且会在我们的测量中引入噪声(降低"稳定性")。首先,让我们禁用KCOV_INSTRUMENT_ALL,并在实际要评测的代码上有选择地启用KCOV。今天,我们关注的是netlink机械,所以让我们在整个"网络"目录树上启用KCOV:找到net-name Makefile | xargs-L1-I{}bash-c'echo"KCOV_INSTRUMENT:=y">{}'在一个完美的世界里,我们只对我们真正感兴趣的几个文件启用KCOV。但是netlink处理在整个网络堆栈代码中都很复杂,我们今天没有时间对其进行微调。有了KCOV,就值得添加"内核黑客"切换,这将增加报告内存损坏错误的可能性。请参阅自述文件以获取Syzkaller建议的选项列表—最重要的是KASAN。有了这个集合,我们就可以编译支持KCOV和KASAN的内核。哦,还有一件事。我们将在kvm中运行内核。我们将使用"virtme",因此需要几个切换:./scripts/配置\-e VIRTIO-e VIRTIO_PCI-e NET_9P-e NET_9P_VIRTIO-e 9P_FS\-e VIRTIO_NET-e VIRTIO_控制台-e DEVTMPFS。。。(完整列表见自述)如何使用KCOVKCOV非常容易使用。首先,注意代码覆盖率记录在每个进程的数据结构中。这意味着您必须在用户空间进程中启用和禁用KCOV,而且不可能记录非任务事务的覆盖率,比如中断处理。这完全符合我们的需要。KCOV向环形缓冲区报告数据。设置非常简单,请参阅我们的代码。然后您可以使用一个简单的ioctl启用和禁用它:ioctl(kcov_fd,kcov_ENABLE,kcov_TRACE_PC);/*分析代码*/ioctl(kcov_fd,kcov_禁用,0);在这个序列之后,环形缓冲区包含支持KCOV的内核代码的所有基本块的%rip值的列表。要读取缓冲区,只需运行:n=原子载荷n(&kcov环[0],\u原子松弛);对于(i=0;i>1;在我们使用KCOV的例子中,每个分支没有编译时随机值。相反,我们将使用散列函数从KCOV记录的%rip生成一个统一的16位数字。以下是如何将KCOV报告输入AFL"共享内存"数组:n=原子载荷n(&kcov环[0],\u原子松弛);uint16上一位置=0;对于(i=0;i>1;}从AFL读取测试数据最后,我们需要实际编写测试代码锤击内核netlink接口!首先我们需要从AFL读取输入数据。默认情况下,AFL向stdin发送一个测试用例:/*读取AFL测试数据*/字符buf[512*1024];int buf_len=读取(0,buf,sizeof(buf));模糊网络链接然后我们需要将这个缓冲区发送到netlink套接字。但我们对netlink的工作原理一无所知!好的,让我们使用输入的前5个字节作为netlink协议和组id字段。这将允许AFL计算和猜测这些字段的正确值。netlink代码测试(简体):netlink_fd=套接字(AF_netlink,SOCK_RAW | SOCK_NONBLOCK,buf[0]);结构sockaddr\u nl sa={.nl_family=AF_NETLINK,.nl_组=(buf[1]