最近打 ctf 的时候感觉有点遇到瓶颈,就来 fuzz 这块看看。

AFL 全称为 American huzzy loop,是 Fuzzing 最高级的测试工具之一。这个工具对有源码和无源码的二进制程序均可以进行 fuzz 测试。

alf 各位自行安装即可,值得注意的是,在我本机 glibc2.31 的环境下,编译 alf 前要对 AFL/llvm_mode/afl-clang-fast.c修改一下,否则会出现报错,只需把部分内容注释掉即可

输入 afl-fuzz 出现下图即安装成功

我们先看对有源码的二进制程序是怎样进行测试:

在 AFL 文件夹里会有很多目录,我们进入 test。首先先把自己要测试的源码放进去,再建两个文件夹分别放测试输入的内容和测试输出的内容,我这里就建了 fuzz_in , fuzz_out。在fuzz_in 里面还要建一个文件,里面随便放一些字母就行(这里笔者也不是很清楚为什么)。在有源码的情况下我们用 afl 自带的编译器,对其进行编译这会使测试更加高效。原因是 afl 自带的编译器在编译时会对目标程序插桩,故此过程叫插桩编译。我从其他师傅的博客里找了一个简单的二进制程序来进行测试。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h> int vuln(char *str)
{
int len = strlen(str);
if(str[0] == 'A' && len == 66)
{
raise(SIGSEGV);
//如果输入的字符串的首字符为A并且长度为66,则异常退出
}
else if(str[0] == 'F' && len == 6)
{
raise(SIGSEGV);
//如果输入的字符串的首字符为F并且长度为6,则异常退出
}
else
{
printf("it is good!\n");
}
return 0;
} int main(int argc, char *argv[])
{
char buf[100]={0};
gets(buf);//存在栈溢出漏洞
printf(buf);//存在格式化字符串漏洞
vuln(buf); return 0;
}

对其插桩编译

afl-gcc -g -o afl_test afl_test.c

我们接下来就可以对其进行测试了,此外在 fuzz 前要关闭系统的核心转储,确保在 fuzz 的过程中即使出现 crash 也不会停止,不然就会出现如下报错

我们关闭系统核心转储开始测试

sudo su
echo core >/proc/sys/kernel/core_pattern
exit
afl-fuzz -i fuzz_in -o fuzz_out ./afl_test

这上面的数字是彩色的,注意 overall results 里的 cycles results 的颜色会随着 fuzz 次数的增加从红色到黄色到蓝色到绿色,当他到绿色的时候也就说明基本上该有的 crash 都出来了,继续跑下去,发现的东西也很少了,此时我们就可以 crtl+c 结束测试。

此时我们就可以从我们刚刚建立的 fuzz_out 文件夹里看到测试的结果了。

我们再进行查看

之前一次测试的时候格式化字符串也测试出来了,不知道为什么这次没出来。好吧,那插桩测试就写到这里。

下面我们来看无源码的测试过程。

进行无源码测试之前我们要进入到 AFL/qemu_mode 在终端中执行一下 ./build_qemu_support.sh

遇见如下报错:

make[1]: *** [/xxxxxxxx/AFL/qemu_mode/qemu-2.10.0/rules.mak:66: linux-user/syscall.o] Error 1
make: *** [Makefile:326: subdir-x86_64-linux-user] Error 2

查阅资料后得知:给 /AFL/qemu_mode/patches/syscall.diff 打个补丁即可

--- qemu-2.10.0-clean/linux-user/syscall.c    2020-03-12 18:47:47.898592169 +0100
+++ qemu-2.10.0/linux-user/syscall.c 2020-03-12 19:16:41.563074307 +0100
@@ -34,6 +34,7 @@
#include <sys/resource.h>
#include <sys/swap.h>
#include <linux/capability.h>
+#include <linux/sockios.h> // https://lkml.org/lkml/2019/6/3/988
#include <sched.h>
#include <sys/timex.h>
#ifdef __ia64__
@@ -116,6 +117,8 @@ int __clone2(int (*fn)(void *), void *ch
#include "qemu.h" +extern unsigned int afl_forksrv_pid;
+
#ifndef CLONE_IO
#define CLONE_IO 0x80000000 /* Clone io context */
#endif @@ -256,7 +259,9 @@ static type name (type1 arg1,type2 arg2,
#endif #ifdef __NR_gettid
-_syscall0(int, gettid)
+// taken from https://patchwork.kernel.org/patch/10862231/
+#define __NR_sys_gettid __NR_gettid
+_syscall0(int, sys_gettid)
#else
/* This is a replacement for the host gettid() and must return a host
errno. */
@@ -6219,7 +6224,8 @@ static void *clone_func(void *arg)
cpu = ENV_GET_CPU(env);
thread_cpu = cpu;
ts = (TaskState *)cpu->opaque;
- info->tid = gettid();
+ // taken from https://patchwork.kernel.org/patch/10862231/
+ info->tid = sys_gettid();
task_settid(ts);
if (info->child_tidptr)
put_user_u32(info->tid, info->child_tidptr);
@@ -6363,9 +6369,11 @@ static int do_fork(CPUArchState *env, un
mapping. We can't repeat the spinlock hack used above because
the child process gets its own copy of the lock. */
if (flags & CLONE_CHILD_SETTID)
- put_user_u32(gettid(), child_tidptr);
+ // taken from https://patchwork.kernel.org/patch/10862231/
+ put_user_u32(sys_gettid(), child_tidptr);
if (flags & CLONE_PARENT_SETTID)
- put_user_u32(gettid(), parent_tidptr);
+ // taken from https://patchwork.kernel.org/patch/10862231/
+ put_user_u32(sys_gettid(), parent_tidptr);
ts = (TaskState *)cpu->opaque;
if (flags & CLONE_SETTLS)
cpu_set_tls (env, newtls);
@@ -11402,7 +11410,8 @@ abi_long do_syscall(void *cpu_env, int n
break;
#endif
case TARGET_NR_gettid:
- ret = get_errno(gettid());
+ // taken from https://patchwork.kernel.org/patch/10862231/
+ ret = get_errno(sys_gettid());
break;
#ifdef TARGET_NR_readahead
case TARGET_NR_readahead:

成功!

又出现如下报错:

这时我们返回 AFL 目录重新 make install 即可

此后和插桩测试的过程就大体一致了,只是在 test 里直接放进二进制程序即可,并且加上参数 -Q

afl-fuzz -i fuzz_in -o fuzz_out -Q ./afl_test2

好了 afl 的一些基础用法掌握了,以后就在 ctf 打不动的时候,跟着其他师傅的博客去复现CVE漏洞看看。

参考文章:

https://blog.csdn.net/weixin_50919879/article/details/108916954

https://xz.aliyun.com/t/4314

https://blog.csdn.net/geniusle201/article/details/111028697

https://www.codeleading.com/article/61745363753/

https://blog.csdn.net/qq_38239282/article/details/120975670

https://bbs.csdn.net/topics/392361391

https://blog.csdn.net/ChuMeng1999/article/details/121880731

fuzz——AFL基础使用方法的更多相关文章

  1. C#基础之方法和参数

    C#基础之方法和参数 接上一篇<C#基础之类型和成员基础以及常量.字段.属性> 实例方法.静态方法 C#中的方法分为两类,一种是属于对象(类型的实例)的,称之为实例方法,另一种是属于类型的 ...

  2. laravel获取当前的url以及当前的基础域名方法汇总

    原文地址:https://phpartisan.cn/news/58.html 来源于:laravel获取当前的url以及当前的基础域名方法汇总 - Laravel学习网 laravel中我们常常需要 ...

  3. 千锋教育Vue组件--vue基础的方法

    课程地址: https://ke.qq.com/course/251029#term_id=100295989 <!DOCTYPE html> <html> <head& ...

  4. SaltStack介绍——SaltStack是一种新的基础设施管理方法开发软件,简单易部署,可伸缩的足以管理成千上万的服务器,和足够快的速度控制,与他们交流

    SaltStack介绍和架构解析 简介 SaltStack是一种新的基础设施管理方法开发软件,简单易部署,可伸缩的足以管理成千上万的服务器,和足够快的速度控制,与他们交流,以毫秒为单位.SaltSta ...

  5. [UWP开发]NavigationView基础使用方法

    原文:[UWP开发]NavigationView基础使用方法 [UWP开发]NavigationView基础使用方法 NavigationView是秋季创意者更新(16299)引入的新控件,用于生成W ...

  6. Scrapy里Selectors 四种基础的方法

    在Scrapy里面,Selectors 有四种基础的方法xpath():返回一系列的selectors,每一个select表示一个xpath参数表达式选择的节点css():返回一系列的selector ...

  7. java在acm中常用基础技巧方法

    java在acm中常用基础技巧方法 如果学到了新的技巧,本博客会更新~ input input-std @Frosero import java.util.*; public class Main { ...

  8. 2019-1-29-Moq基础-判断方法被执行

    title author date CreateTime categories Moq基础 判断方法被执行 lindexi 2019-01-29 16:29:57 +0800 2019-01-17 1 ...

  9. Quartz.Net的基础使用方法,多任务执行继续扩展

    前一篇随笔讲了Quartz多任务的简单实现 Quartz.Net的基础使用方法,多任务执行 这一篇,来简单对前一篇进行一下简单的扩展 看了前一篇的代码会发现,每次新增一个任务还要去GetJobs方法里 ...

随机推荐

  1. 初识python: 自定义函数

    什么是函数? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率. 函数的定义方法: def test(x): '函数定义方法' x+=1 r ...

  2. mysql5.7初始化密码报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement

    mysql初始化密码常见报错问题 1,mysql5.6是密码为空直接进入数据库的,但是mysql5.7就需要初始密码 cat /var/log/mysqld.log | grep password 2 ...

  3. SpringCloud的Config应用

    一.简介 ***应用程序先注册到注册中心,在注册中心根据guli-config服务的名字找到配置中心,然后在配置中心根据配置从github加载基本配置. 二.配置中心(服务端,可以部署集群) 1.依赖 ...

  4. SYCOJ2140祝福短信

    题目-祝福短信 (shiyancang.cn) 1 #include<bits/stdc++.h> 2 using namespace std; 3 map<string,bool& ...

  5. 【Java】代码块

    代码块 代码块的作用:用来初始化类.对象 代码块如果有修饰的话,只能使用static 分类:静态代码块.非静态代码块 静态代码块 static{ } 内部可以有输出语句 随着类的加载而执行,而且只执行 ...

  6. 【Java】toString

    toString 当我们输出一个对象的引用时,实际上就是调用当前对象的toString() Object类中toString()的定义: public String toString() { retu ...

  7. elasticsearch源码分析及插件开发

    ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apach ...

  8. 小程序循环时的item问题

    平常在做小程序时,比如循环渲染数据时,如果有多个数据层次,一般都会这样 wx:for-item=item2,它的意思只是简单的起了一个wx:for循环值的别名,不是表示循环item2,index2同理 ...

  9. 如何在Xamarin中快速集成Android版认证服务-手机号码篇

    Xamarin作为微软提供的移动服务多系统开发平台,成为很多开发者首选的应用开发平台.AppGallery Connect(以下简称AGC)也在逐步的支持Xamarin的SDK.认证服务也是支持Xam ...

  10. golang中的map

    1. 声明与初始化 // map的声明与初始化 userInfo := map[string]string{"name": "马亚南", "age&q ...