├── KVM-PT
├── README.md
├── arch
│ └── x86
│ │ ├── include
│ │ ├── asm
│ │ │ └── kvm_host.h.patch
│ │ └── uapi
│ │ │ └── asm
│ │ │ └── kvm.h.patch
│ │ └── kvm
│ │ ├── Kconfig.patch
│ │ ├── Makefile.patch
│ │ ├── svm.c.patch
│ │ ├── vmx.c.patch
│ │ ├── vmx.h
│ │ ├── vmx_pt.c
│ │ ├── vmx_pt.h
│ │ └── x86.c.patch
├── include
│ └── uapi
│ │ └── linux
│ │ └── kvm.h.patch
└── usermode_test
│ ├── support_test.c
│ └── test.c
├── LICENSE
├── QEMU-PT
├── Makefile.target.patch
├── applesmc_patches
│ ├── note.txt
│ ├── v1-1-3-applesmc-cosmetic-whitespace-and-indentation-cleanup.patch
│ ├── v1-2-3-applesmc-consolidate-port-i-o-into-single-contiguous-region.patch
│ └── v1-3-3-applesmc-implement-error-status-port.patch
├── compile.sh
├── configure.patch
├── hmp-commands-pt.hx
├── hmp-commands.hx.patch
├── hmp.c.patch
├── hmp.h.patch
├── include
│ └── qom
│ │ └── cpu.h.patch
├── kvm-all.c.patch
├── linux-headers
│ └── linux
│ │ └── kvm.h.patch
├── monitor.c.patch
├── pt.c
├── pt.h
├── pt
│ ├── decoder.c
│ ├── decoder.h
│ ├── disassembler.c
│ ├── disassembler.h
│ ├── filter.c
│ ├── filter.h
│ ├── hypercall.c
│ ├── hypercall.h
│ ├── interface.c
│ ├── interface.h
│ ├── khash.h
│ ├── logger.c
│ ├── logger.h
│ ├── memory_access.c
│ ├── memory_access.h
│ ├── tmp.objs
│ ├── tnt_cache.c
│ └── tnt_cache.h
└── vl.c.patch
├── README.md
├── install.sh
└── kAFL-Fuzzer
├── agents
├── compile.sh
├── kafl_user.h
├── linux_x86_64
│ ├── compile.sh
│ ├── fuzzer
│ │ ├── fs_fuzzer.c
│ │ └── kafl_vuln_test.c
│ ├── info
│ │ └── info.c
│ └── loader
│ │ └── loader.c
├── macOS_x86_64
│ ├── compile.sh
│ ├── fuzzer
│ │ └── vuln_test.c
│ ├── info
│ │ └── info.c
│ └── loader
│ │ └── loader.c
└── windows_x86_64
│ ├── compile.sh
│ ├── fuzzer
│ └── vuln_test.c
│ ├── info
│ └── info.cpp
│ └── loader
│ └── loader.c
├── common
├── __init__.py
├── config.py
├── debug.py
├── evaluation.py
├── qemu.py
├── self_check.py
├── ui.py
└── util.py
├── dict
├── http_sys.dict
└── vuln.dict
├── fuzzer
├── __init__.py
├── communicator.py
├── core.py
├── process
│ ├── __init__.py
│ ├── mapserver.py
│ ├── master.py
│ ├── slave.py
│ └── update.py
├── protocol.py
├── state.py
├── technique
│ ├── __init__.py
│ ├── arithmetic.py
│ ├── bitflip.py
│ ├── debug.py
│ ├── havoc.py
│ ├── havoc_handler.py
│ ├── helper.py
│ └── interesting_values.py
└── tree.py
├── help.txt
├── info
├── __init__.py
└── core.py
├── kafl.ini
├── kafl_fuzz.py
├── kafl_info.py
├── run_test.sh
├── seed
├── ext4
│ └── ext4.img
├── fat
│ ├── fat_a
│ ├── fat_b
│ ├── fat_c
│ ├── fat_d
│ └── fat_e
├── kafl_vulntest
│ └── seed_file
├── ntfs
│ └── ntfs64
└── ntfs_win
│ └── ntfs_header_64k
├── test.py
├── testing
├── __init__.py
├── deterministic_input_generation.py
├── deterministic_techniques.py
└── queue.py
└── vuln_drivers
├── json
├── linux_x86-64
│ ├── Makefile
│ └── kafl_vuln_test_json.c
├── macOS_x86-64
│ ├── compile.sh
│ ├── info.plist
│ ├── load.sh
│ ├── vuln.c
│ └── vuln.xcodeproj
│ │ └── project.pbxproj
└── windows_x86-64
│ └── Driver.c
└── simple
├── linux_x86-64
├── Makefile
├── kafl_vuln_test.c
└── load.sh
├── macOS_x86-64
├── compile.sh
├── info.plist
├── load.sh
├── vuln.c
└── vuln.xcodeproj
│ └── project.pbxproj
└── win10_x86-64
└── Driver.c
/KVM-PT/README.md:
--------------------------------------------------------------------------------
1 | # vmx_pt Kernel Module
2 |
3 | ##### Supported Kernel:
4 | * Linux-4.6.2
5 | * ...
6 |
7 | #### Supported CPU:
8 | * Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
9 | * Intel(R) Core(TM) i7-6700HQ CPU @ 2,60GHz
10 | * ...
11 |
12 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/include/asm/kvm_host.h.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 994a995,999
18 | >
19 | > #ifdef CONFIG_KVM_VMX_PT
20 | > int (*setup_trace_fd)(struct kvm_vcpu *vcpu);
21 | > int (*vmx_pt_enabled)(void);
22 | > #endif
23 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/include/uapi/asm/kvm.h.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 356a357,362
18 | > /* vmx_pt */
19 | > struct vmx_pt_filter_iprs {
20 | > __u64 a;
21 | > __u64 b;
22 | > };
23 | >
24 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/kvm/Kconfig.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 101a102,107
18 | > config KVM_VMX_PT
19 | > bool "KVM extension for Intel Processor Trace"
20 | > depends on KVM_INTEL
21 | > ---help---
22 | > Provides support for Intel Processor Trace in vmx mode.
23 | >
24 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/kvm/Makefile.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 20a21,22
18 | > kvm-intel-$(CONFIG_KVM_VMX_PT) += vmx_pt.o
19 | >
20 | 21a24
21 | >
22 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/kvm/svm.c.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 4309a4310,4319
18 | > #ifdef CONFIG_KVM_VMX_PT
19 | > static int setup_trace_fd_stub(struct kvm_vcpu *vcpu){
20 | > return -EINVAL;
21 | > }
22 | > static int vmx_pt_is_enabled(void){
23 | > /* AMD CPUs do not support Intel PT */
24 | > return -EINVAL;
25 | > }
26 | > #endif
27 | >
28 | 4417a4428,4432
29 | >
30 | > #ifdef CONFIG_KVM_VMX_PT
31 | > .setup_trace_fd = setup_trace_fd_stub,
32 | > .vmx_pt_enabled = vmx_pt_is_enabled,
33 | > #endif
34 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/kvm/vmx.c.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 54a55,59
18 | > #ifdef CONFIG_KVM_VMX_PT
19 | > #include "vmx_pt.h"
20 | > static int handle_monitor_trap(struct kvm_vcpu *vcpu);
21 | > #endif
22 | >
23 | 521a527,529
24 | > #ifdef CONFIG_KVM_VMX_PT
25 | > struct vcpu_vmx_pt* vmx_pt_config;
26 | > #endif
27 | 1608a1617,1619
28 | > #ifdef CONFIG_KVM_VMX_PT
29 | > vmx->vm_entry_controls_shadow = val | 0x20000ULL; /* Conceal VM entries from Intel PT */
30 | > #else
31 | 1609a1621
32 | > #endif
33 | 1636a1649,1651
34 | > #ifdef CONFIG_KVM_VMX_PT
35 | > vmx->vm_exit_controls_shadow = val | 0x1000000ULL; /* Conceal VM exit from Intel PT */
36 | > #else
37 | 1637a1653
38 | > #endif
39 | 1801c1817
40 | < static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
41 | ---
42 | > void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
43 | 3346c3362
44 | < vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control;
45 | ---
46 | > vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control | 0x80000;
47 | 3348,3349c3364,3365
48 | < vmcs_conf->vmexit_ctrl = _vmexit_control;
49 | < vmcs_conf->vmentry_ctrl = _vmentry_control;
50 | ---
51 | > vmcs_conf->vmexit_ctrl = _vmexit_control | 0x1000000;
52 | > vmcs_conf->vmentry_ctrl = _vmentry_control | 0x20000;
53 | 4809a4826
54 | >
55 | 5445d5461
56 | <
57 | 8245a8262
58 | >
59 | 8618a8636,8639
60 | > #ifdef CONFIG_KVM_VMX_PT
61 | > vmx_pt_vmentry(vmx->vmx_pt_config);
62 | > #endif
63 | >
64 | 8825a8847,8850
65 | >
66 | > #ifdef CONFIG_KVM_VMX_PT
67 | > vmx_pt_vmexit(vmx->vmx_pt_config);
68 | > #endif
69 | 8855a8881,8885
70 | >
71 | > #ifdef CONFIG_KVM_VMX_PT
72 | > /* free vmx_pt */
73 | > vmx_pt_destroy(vmx, &(vmx->vmx_pt_config));
74 | > #endif
75 | 8937a8968,8972
76 | > #ifdef CONFIG_KVM_VMX_PT
77 | > /* enable vmx_pt */
78 | > vmx_pt_setup(vmx, &(vmx->vmx_pt_config));
79 | > #endif
80 | >
81 | 10891a10927,10936
82 | > #ifdef CONFIG_KVM_VMX_PT
83 | > static int vmx_pt_setup_fd(struct kvm_vcpu *vcpu){
84 | > return vmx_pt_create_fd(to_vmx(vcpu)->vmx_pt_config);
85 | > }
86 | >
87 | > static int vmx_pt_is_enabled(void){
88 | > return vmx_pt_enabled();
89 | > }
90 | > #endif
91 | >
92 | 11015a11061,11065
93 | >
94 | > #ifdef CONFIG_KVM_VMX_PT
95 | > .setup_trace_fd = vmx_pt_setup_fd,
96 | > .vmx_pt_enabled = vmx_pt_is_enabled,
97 | > #endif
98 | 11029a11080,11082
99 | > #ifdef CONFIG_KVM_VMX_PT
100 | > vmx_pt_init();
101 | > #endif
102 | 11039c11092,11094
103 | <
104 | ---
105 | > #ifdef CONFIG_KVM_VMX_PT
106 | > vmx_pt_exit();
107 | > #endif
108 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/kvm/vmx.h:
--------------------------------------------------------------------------------
1 | #ifndef __VMX_H__
2 | #define __VMX_H__
3 |
4 | #include
5 | #include
6 |
7 | struct vcpu_vmx;
8 | void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, u64 guest_val, u64 host_val);
9 |
10 | #endif
11 |
12 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/kvm/vmx_pt.h:
--------------------------------------------------------------------------------
1 | #ifndef __VMX_PT_H__
2 | #define __VMX_PT_H__
3 |
4 | #include "vmx.h"
5 |
6 | struct vcpu_vmx_pt;
7 |
8 | int vmx_pt_create_fd(struct vcpu_vmx_pt *vmx_pt_config);
9 |
10 | void vmx_pt_vmentry(struct vcpu_vmx_pt *vmx_pt);
11 | void vmx_pt_vmexit(struct vcpu_vmx_pt *vmx_pt);
12 |
13 | int vmx_pt_setup(struct vcpu_vmx *vmx, struct vcpu_vmx_pt **vmx_pt_config);
14 | void vmx_pt_destroy(struct vcpu_vmx *vmx, struct vcpu_vmx_pt **vmx_pt_config);
15 |
16 | void vmx_pt_init(void);
17 | void vmx_pt_exit(void);
18 |
19 | int vmx_pt_enabled(void);
20 |
21 | #endif
22 |
23 |
--------------------------------------------------------------------------------
/KVM-PT/arch/x86/kvm/x86.c.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 2689a2690,2695
18 | > #ifdef CONFIG_KVM_VMX_PT
19 | > case KVM_VMX_PT_SUPPORTED: {
20 | > r = kvm_x86_ops->vmx_pt_enabled();
21 | > break;
22 | > }
23 | > #endif
24 | 3498a3505,3510
25 | > #ifdef CONFIG_KVM_VMX_PT
26 | > case KVM_VMX_PT_SETUP_FD: {
27 | > r = kvm_x86_ops->setup_trace_fd(vcpu);
28 | > break;
29 | > }
30 | > #endif
31 | 5970a5983,6003
32 | > #ifdef CONFIG_KVM_VMX_PT
33 | > /* kAFL Hypercall Interface (ring 0) */
34 | > if(kvm_x86_ops->get_cpl(vcpu) == 0) {
35 | > r = 0;
36 | > if (kvm_register_read(vcpu, VCPU_REGS_RAX) == HYPERCALL_KAFL_RAX_ID){
37 | > switch(kvm_register_read(vcpu, VCPU_REGS_RBX)){
38 | > case 8: /* PANIC */
39 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_PANIC;
40 | > break;
41 | > case 9: /* KASAN */
42 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_KASAN;
43 | > break;
44 | > default:
45 | > r = -KVM_EPERM;
46 | > break;
47 | > }
48 | > return r;
49 | > }
50 | > }
51 | > #endif
52 | >
53 | 5971a6005,6061
54 | > /* kAFL Hypercall interface */
55 | > #ifdef CONFIG_KVM_VMX_PT
56 | > if (kvm_register_read(vcpu, VCPU_REGS_RAX) == HYPERCALL_KAFL_RAX_ID){
57 | > r = 0;
58 | > switch(kvm_register_read(vcpu, VCPU_REGS_RBX)){
59 | > case 0: /* KAFL_GUEST_ACQUIRE */
60 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_ACQUIRE;
61 | > break;
62 | > case 1: /* KAFL_GUEST_GET_PAYLOAD */
63 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_GET_PAYLOAD;
64 | > vcpu->run->hypercall.args[0] = kvm_register_read(vcpu, VCPU_REGS_RCX);
65 | > break;
66 | > case 2: /* KAFL_GUEST_GET_PROGRAM */
67 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_GET_PROGRAM;
68 | > vcpu->run->hypercall.args[0] = kvm_register_read(vcpu, VCPU_REGS_RCX);
69 | > break;
70 | > case 3: /* KAFL_GUEST_GET_ARGV */
71 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_GET_ARGV;
72 | > vcpu->run->hypercall.args[0] = kvm_register_read(vcpu, VCPU_REGS_RCX);
73 | > break;
74 | > case 4: /* KAFL_GUEST_RELEASE */
75 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_RELEASE;
76 | > break;
77 | > case 5: /* KAFL_GUEST_SUBMIT_CR3 */
78 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_SUBMIT_CR3;
79 | > vcpu->run->hypercall.args[0] = kvm_read_cr3(vcpu);
80 | > break;
81 | > case 6: /* KAFL_GUEST_PANIC */
82 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_SUBMIT_PANIC;
83 | > vcpu->run->hypercall.args[0] = kvm_register_read(vcpu, VCPU_REGS_RCX);
84 | > break;
85 | > case 7: /* KAFL_GUEST_KASAN */
86 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_SUBMIT_KASAN;
87 | > vcpu->run->hypercall.args[0] = kvm_register_read(vcpu, VCPU_REGS_RCX);
88 | > break;
89 | > case 10: /* LOCK */
90 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_LOCK;
91 | > break;
92 | > case 11: /* INFO */
93 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_INFO;
94 | > vcpu->run->hypercall.args[0] = kvm_register_read(vcpu, VCPU_REGS_RCX);
95 | > break;
96 | > case 12: /* KAFL_GUEST_NEXT_PAYLOAD */
97 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_NEXT_PAYLOAD;
98 | > break;
99 | > case 13: /* KAFL_GUEST_DEBUG */
100 | > vcpu->run->exit_reason = KVM_EXIT_KAFL_DEBUG;
101 | > vcpu->run->hypercall.args[0] = kvm_register_read(vcpu, VCPU_REGS_RCX);
102 | > break;
103 | > default:
104 | > r = -KVM_EPERM;
105 | > break;
106 | > }
107 | > return r;
108 | > }
109 | > #endif
110 | >
111 |
--------------------------------------------------------------------------------
/KVM-PT/include/uapi/linux/kvm.h.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of KVM-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 208a209,224
18 | > #define HYPERCALL_KAFL_RAX_ID 0x01f
19 | > #define KVM_EXIT_KAFL_ACQUIRE 100
20 | > #define KVM_EXIT_KAFL_GET_PAYLOAD 101
21 | > #define KVM_EXIT_KAFL_GET_PROGRAM 102
22 | > #define KVM_EXIT_KAFL_GET_ARGV 103
23 | > #define KVM_EXIT_KAFL_RELEASE 104
24 | > #define KVM_EXIT_KAFL_SUBMIT_CR3 105
25 | > #define KVM_EXIT_KAFL_SUBMIT_PANIC 106
26 | > #define KVM_EXIT_KAFL_SUBMIT_KASAN 107
27 | > #define KVM_EXIT_KAFL_PANIC 108
28 | > #define KVM_EXIT_KAFL_KASAN 109
29 | > #define KVM_EXIT_KAFL_LOCK 110
30 | > #define KVM_EXIT_KAFL_INFO 111
31 | > #define KVM_EXIT_KAFL_NEXT_PAYLOAD 112
32 | > #define KVM_EXIT_KAFL_DEBUG 113
33 | >
34 | 1313a1330,1359
35 | >
36 | > /*
37 | > * ioctls for vmx_pt fds
38 | > */
39 | > #define KVM_VMX_PT_SETUP_FD _IO(KVMIO, 0xd0) /* apply vmx_pt fd (via vcpu fd ioctl)*/
40 | > #define KVM_VMX_PT_CONFIGURE_ADDR0 _IOW(KVMIO, 0xd1, __u64) /* configure IP-filtering for addr0_a & addr0_b */
41 | > #define KVM_VMX_PT_CONFIGURE_ADDR1 _IOW(KVMIO, 0xd2, __u64) /* configure IP-filtering for addr1_a & addr1_b */
42 | > #define KVM_VMX_PT_CONFIGURE_ADDR2 _IOW(KVMIO, 0xd3, __u64) /* configure IP-filtering for addr2_a & addr2_b */
43 | > #define KVM_VMX_PT_CONFIGURE_ADDR3 _IOW(KVMIO, 0xd4, __u64) /* configure IP-filtering for addr3_a & addr3_b */
44 | >
45 | > #define KVM_VMX_PT_CONFIGURE_CR3 _IOW(KVMIO, 0xd5, __u64) /* setup CR3 filtering value */
46 | > #define KVM_VMX_PT_ENABLE _IO(KVMIO, 0xd6) /* enable and lock configuration */
47 | > #define KVM_VMX_PT_GET_TOPA_SIZE _IOR(KVMIO, 0xd7, __u32) /* get defined ToPA size */
48 | > #define KVM_VMX_PT_DISABLE _IO(KVMIO, 0xd8) /* enable and lock configuration */
49 | > #define KVM_VMX_PT_CHECK_TOPA_OVERFLOW _IO(KVMIO, 0xd9) /* check for ToPA overflow */
50 | >
51 | > #define KVM_VMX_PT_ENABLE_ADDR0 _IO(KVMIO, 0xaa) /* enable IP-filtering for addr0 */
52 | > #define KVM_VMX_PT_ENABLE_ADDR1 _IO(KVMIO, 0xab) /* enable IP-filtering for addr1 */
53 | > #define KVM_VMX_PT_ENABLE_ADDR2 _IO(KVMIO, 0xac) /* enable IP-filtering for addr2 */
54 | > #define KVM_VMX_PT_ENABLE_ADDR3 _IO(KVMIO, 0xad) /* enable IP-filtering for addr3 */
55 | >
56 | > #define KVM_VMX_PT_DISABLE_ADDR0 _IO(KVMIO, 0xae) /* disable IP-filtering for addr0 */
57 | > #define KVM_VMX_PT_DISABLE_ADDR1 _IO(KVMIO, 0xaf) /* disable IP-filtering for addr1 */
58 | > #define KVM_VMX_PT_DISABLE_ADDR2 _IO(KVMIO, 0xe0) /* disable IP-filtering for addr2 */
59 | > #define KVM_VMX_PT_DISABLE_ADDR3 _IO(KVMIO, 0xe1) /* disable IP-filtering for addr3 */
60 | >
61 | > #define KVM_VMX_PT_ENABLE_CR3 _IO(KVMIO, 0xe2) /* enable CR3 filtering */
62 | > #define KVM_VMX_PT_DISABLE_CR3 _IO(KVMIO, 0xe3) /* disable CR3 filtering */
63 | >
64 | > #define KVM_VMX_PT_SUPPORTED _IO(KVMIO, 0xe4)
65 |
--------------------------------------------------------------------------------
/KVM-PT/usermode_test/support_test.c:
--------------------------------------------------------------------------------
1 | /*
2 | * KVM-PT userspace support test program
3 | * (c) Sergej Schumilo, 2016
4 | *
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to
8 | * deal in the Software without restriction, including without limitation the
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 | * sell copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 | * IN THE SOFTWARE.
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #define KVM_VMX_PT_SUPPORTED _IO(KVMIO, 0xe4)
38 |
39 | int main(){
40 | int kvm, ret;
41 |
42 | kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);
43 | if (kvm == -1){
44 | printf("ERROR: KVM is not loaded!\n");
45 | exit(1);
46 | }
47 |
48 | ret = ioctl(kvm, KVM_VMX_PT_SUPPORTED, NULL);
49 | if (ret == -1){
50 | printf("ERROR: KVM-PT is not loaded!\n");
51 | exit(2);
52 | }
53 | if (ret == -2){
54 | printf("ERROR: Intel PT is not supported on this CPU!\n");
55 | exit(3);
56 | }
57 | printf("KVM-PT is ready!\n");
58 | return 0;
59 | }
60 |
--------------------------------------------------------------------------------
/QEMU-PT/Makefile.target.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 145a146
18 | > obj-$(CONFIG_PROCESSOR_TRACE) += pt/memory_access.o pt/decoder.o pt/tnt_cache.o pt/disassembler.o pt/logger.o pt/hypercall.o pt/filter.o pt.o pt/interface.o
19 | 150c151
20 | < LIBS := $(libs_softmmu) $(LIBS)
21 | ---
22 | > LIBS := $(libs_softmmu) $(LIBS) -lcapstone
23 | 165c166
24 | < GENERATED_FILES += hmp-commands.h hmp-commands-info.h
25 | ---
26 | > GENERATED_FILES += hmp-commands.h hmp-commands-info.h hmp-commands-pt.h
27 | 218a220,222
28 | >
29 | > hmp-commands-pt.h: $(SRC_PATH)/hmp-commands-pt.hx
30 | > $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
31 |
--------------------------------------------------------------------------------
/QEMU-PT/applesmc_patches/note.txt:
--------------------------------------------------------------------------------
1 | http://patchwork.ozlabs.org/patch/745715/
2 | http://patchwork.ozlabs.org/patch/745714/
3 | http://patchwork.ozlabs.org/patch/745713/
--------------------------------------------------------------------------------
/QEMU-PT/applesmc_patches/v1-1-3-applesmc-cosmetic-whitespace-and-indentation-cleanup.patch:
--------------------------------------------------------------------------------
1 | diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
2 | index 77fab5b..986f2ac 100644
3 | --- a/hw/misc/applesmc.c
4 | +++ b/hw/misc/applesmc.c
5 | @@ -39,24 +39,27 @@
6 | /* #define DEBUG_SMC */
7 |
8 | #define APPLESMC_DEFAULT_IOBASE 0x300
9 | -/* data port used by Apple SMC */
10 | -#define APPLESMC_DATA_PORT 0x0
11 | -/* command/status port used by Apple SMC */
12 | -#define APPLESMC_CMD_PORT 0x4
13 | -#define APPLESMC_NR_PORTS 32
14 |
15 | -#define APPLESMC_READ_CMD 0x10
16 | -#define APPLESMC_WRITE_CMD 0x11
17 | -#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
18 | -#define APPLESMC_GET_KEY_TYPE_CMD 0x13
19 | +enum {
20 | + APPLESMC_DATA_PORT = 0x00,
21 | + APPLESMC_CMD_PORT = 0x04,
22 | + APPLESMC_NUM_PORTS = 0x20,
23 | +};
24 | +
25 | +enum {
26 | + APPLESMC_READ_CMD = 0x10,
27 | + APPLESMC_WRITE_CMD = 0x11,
28 | + APPLESMC_GET_KEY_BY_INDEX_CMD = 0x12,
29 | + APPLESMC_GET_KEY_TYPE_CMD = 0x13,
30 | +};
31 |
32 | #ifdef DEBUG_SMC
33 | #define smc_debug(...) fprintf(stderr, "AppleSMC: " __VA_ARGS__)
34 | #else
35 | -#define smc_debug(...) do { } while(0)
36 | +#define smc_debug(...) do { } while (0)
37 | #endif
38 |
39 | -static char default_osk[64] = "This is a dummy key. Enter the real key "
40 | +static char default_osk[65] = "This is a dummy key. Enter the real key "
41 | "using the -osk parameter";
42 |
43 | struct AppleSMCData {
44 | @@ -77,12 +80,11 @@ struct AppleSMCState {
45 | uint32_t iobase;
46 | uint8_t cmd;
47 | uint8_t status;
48 | - uint8_t key[4];
49 | + char key[4];
50 | uint8_t read_pos;
51 | uint8_t data_len;
52 | uint8_t data_pos;
53 | uint8_t data[255];
54 | - uint8_t charactic[4];
55 | char *osk;
56 | QLIST_HEAD(, AppleSMCData) data_def;
57 | };
58 | @@ -93,10 +95,10 @@ static void applesmc_io_cmd_write(void *opaque, hwaddr addr, uint64_t val,
59 | AppleSMCState *s = opaque;
60 |
61 | smc_debug("CMD Write B: %#x = %#x\n", addr, val);
62 | - switch(val) {
63 | - case APPLESMC_READ_CMD:
64 | - s->status = 0x0c;
65 | - break;
66 | + switch (val) {
67 | + case APPLESMC_READ_CMD:
68 | + s->status = 0x0c;
69 | + break;
70 | }
71 | s->cmd = val;
72 | s->read_pos = 0;
73 | @@ -123,54 +125,54 @@ static void applesmc_io_data_write(void *opaque, hwaddr addr, uint64_t val,
74 | AppleSMCState *s = opaque;
75 |
76 | smc_debug("DATA Write B: %#x = %#x\n", addr, val);
77 | - switch(s->cmd) {
78 | - case APPLESMC_READ_CMD:
79 | - if(s->read_pos < 4) {
80 | - s->key[s->read_pos] = val;
81 | - s->status = 0x04;
82 | - } else if(s->read_pos == 4) {
83 | - s->data_len = val;
84 | - s->status = 0x05;
85 | - s->data_pos = 0;
86 | - smc_debug("Key = %c%c%c%c Len = %d\n", s->key[0],
87 | - s->key[1], s->key[2], s->key[3], val);
88 | - applesmc_fill_data(s);
89 | - }
90 | - s->read_pos++;
91 | - break;
92 | + switch (s->cmd) {
93 | + case APPLESMC_READ_CMD:
94 | + if (s->read_pos < 4) {
95 | + s->key[s->read_pos] = val;
96 | + s->status = 0x04;
97 | + } else if (s->read_pos == 4) {
98 | + s->data_len = val;
99 | + s->status = 0x05;
100 | + s->data_pos = 0;
101 | + smc_debug("Key = %c%c%c%c Len = %d\n", s->key[0],
102 | + s->key[1], s->key[2], s->key[3], val);
103 | + applesmc_fill_data(s);
104 | + }
105 | + s->read_pos++;
106 | + break;
107 | }
108 | }
109 |
110 | -static uint64_t applesmc_io_data_read(void *opaque, hwaddr addr1,
111 | - unsigned size)
112 | +static uint64_t applesmc_io_data_read(void *opaque, hwaddr addr, unsigned size)
113 | {
114 | AppleSMCState *s = opaque;
115 | uint8_t retval = 0;
116 |
117 | - switch(s->cmd) {
118 | - case APPLESMC_READ_CMD:
119 | - if(s->data_pos < s->data_len) {
120 | - retval = s->data[s->data_pos];
121 | - smc_debug("READ_DATA[%d] = %#hhx\n", s->data_pos,
122 | - retval);
123 | - s->data_pos++;
124 | - if(s->data_pos == s->data_len) {
125 | - s->status = 0x00;
126 | - smc_debug("EOF\n");
127 | - } else
128 | - s->status = 0x05;
129 | + switch (s->cmd) {
130 | + case APPLESMC_READ_CMD:
131 | + if (s->data_pos < s->data_len) {
132 | + retval = s->data[s->data_pos];
133 | + smc_debug("READ_DATA[%d] = %#hhx\n", s->data_pos,
134 | + retval);
135 | + s->data_pos++;
136 | + if (s->data_pos == s->data_len) {
137 | + s->status = 0x00;
138 | + smc_debug("EOF\n");
139 | + } else {
140 | + s->status = 0x05;
141 | }
142 | + }
143 | }
144 | - smc_debug("DATA Read b: %#x = %#x\n", addr1, retval);
145 | + smc_debug("DATA Read b: %#x = %#x\n", addr, retval);
146 |
147 | return retval;
148 | }
149 |
150 | -static uint64_t applesmc_io_cmd_read(void *opaque, hwaddr addr1, unsigned size)
151 | +static uint64_t applesmc_io_cmd_read(void *opaque, hwaddr addr, unsigned size)
152 | {
153 | AppleSMCState *s = opaque;
154 |
155 | - smc_debug("CMD Read B: %#x\n", addr1);
156 | + smc_debug("CMD Read B: %#x\n", addr);
157 | return s->status;
158 | }
159 |
160 |
--------------------------------------------------------------------------------
/QEMU-PT/applesmc_patches/v1-2-3-applesmc-consolidate-port-i-o-into-single-contiguous-region.patch:
--------------------------------------------------------------------------------
1 | diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
2 | index 986f2ac..e581e02 100644
3 | --- a/hw/misc/applesmc.c
4 | +++ b/hw/misc/applesmc.c
5 | @@ -75,8 +75,7 @@ typedef struct AppleSMCState AppleSMCState;
6 | struct AppleSMCState {
7 | ISADevice parent_obj;
8 |
9 | - MemoryRegion io_data;
10 | - MemoryRegion io_cmd;
11 | + MemoryRegion io_reg;
12 | uint32_t iobase;
13 | uint8_t cmd;
14 | uint8_t status;
15 | @@ -207,19 +206,36 @@ static void qdev_applesmc_isa_reset(DeviceState *dev)
16 | applesmc_add_key(s, "MSSD", 1, "\0x3");
17 | }
18 |
19 | -static const MemoryRegionOps applesmc_data_io_ops = {
20 | - .write = applesmc_io_data_write,
21 | - .read = applesmc_io_data_read,
22 | - .endianness = DEVICE_NATIVE_ENDIAN,
23 | - .impl = {
24 | - .min_access_size = 1,
25 | - .max_access_size = 1,
26 | - },
27 | -};
28 | +static void applesmc_io_write(void *opaque, hwaddr addr, uint64_t val,
29 | + unsigned size)
30 | +{
31 | + switch (addr) {
32 | + case APPLESMC_DATA_PORT:
33 | + applesmc_io_data_write(opaque, addr, val, size);
34 | + break;
35 | + case APPLESMC_CMD_PORT:
36 | + applesmc_io_cmd_write(opaque, addr, val, size);
37 | + break;
38 | + default:
39 | + break;
40 | + }
41 | +}
42 |
43 | -static const MemoryRegionOps applesmc_cmd_io_ops = {
44 | - .write = applesmc_io_cmd_write,
45 | - .read = applesmc_io_cmd_read,
46 | +static uint64_t applesmc_io_read(void *opaque, hwaddr addr, unsigned size)
47 | +{
48 | + switch (addr) {
49 | + case APPLESMC_DATA_PORT:
50 | + return applesmc_io_data_read(opaque, addr, size);
51 | + case APPLESMC_CMD_PORT:
52 | + return applesmc_io_cmd_read(opaque, addr, size);
53 | + default:
54 | + return 0xff;
55 | + }
56 | +}
57 | +
58 | +static const MemoryRegionOps applesmc_io_ops = {
59 | + .write = applesmc_io_write,
60 | + .read = applesmc_io_read,
61 | .endianness = DEVICE_NATIVE_ENDIAN,
62 | .impl = {
63 | .min_access_size = 1,
64 | @@ -231,15 +247,9 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp)
65 | {
66 | AppleSMCState *s = APPLE_SMC(dev);
67 |
68 | - memory_region_init_io(&s->io_data, OBJECT(s), &applesmc_data_io_ops, s,
69 | - "applesmc-data", 4);
70 | - isa_register_ioport(&s->parent_obj, &s->io_data,
71 | - s->iobase + APPLESMC_DATA_PORT);
72 | -
73 | - memory_region_init_io(&s->io_cmd, OBJECT(s), &applesmc_cmd_io_ops, s,
74 | - "applesmc-cmd", 4);
75 | - isa_register_ioport(&s->parent_obj, &s->io_cmd,
76 | - s->iobase + APPLESMC_CMD_PORT);
77 | + memory_region_init_io(&s->io_reg, OBJECT(s), &applesmc_io_ops, s,
78 | + "applesmc", APPLESMC_NUM_PORTS);
79 | + isa_register_ioport(&s->parent_obj, &s->io_reg, s->iobase);
80 |
81 | if (!s->osk || (strlen(s->osk) != 64)) {
82 | fprintf(stderr, "WARNING: Using AppleSMC with invalid key\n");
83 |
--------------------------------------------------------------------------------
/QEMU-PT/compile.sh:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 |
18 | ./configure --target-list=x86_64-softmmu --enable-gtk --enable-pt
19 | make -j 8
20 |
21 |
--------------------------------------------------------------------------------
/QEMU-PT/configure.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 754a755,756
18 | > --enable-pt) pt="yes"
19 | > ;;
20 | 1372a1375
21 | > pt enable guest tracing (vmx_pt)
22 | 4791c4794
23 | < CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS"
24 | ---
25 | > CFLAGS="-Ofast -march=native -mtune=haswell -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS"
26 | 4793c4796
27 | < CFLAGS="-O2 $CFLAGS"
28 | ---
29 | > CFLAGS="-Ofast -march=native -mtune=haswell $CFLAGS"
30 | 5361a5365,5367
31 | > fi
32 | > if test "$pt" = "yes" ; then
33 | > echo "CONFIG_PROCESSOR_TRACE=y" >> $config_host_mak
34 |
--------------------------------------------------------------------------------
/QEMU-PT/hmp-commands-pt.hx:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | HXCOMM Use DEFHEADING() to define headings in both help text and texi
23 | HXCOMM Text between STEXI and ETEXI are copied to texi version and
24 | HXCOMM discarded from C version
25 | HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
26 | HXCOMM monitor info commands
27 | HXCOMM HXCOMM can be used for comments, discarded from both texi and C
28 |
29 | STEXI
30 | @table @option
31 | @item info @var{subcommand}
32 | @findex info
33 | Show various information about the system state.
34 | @table @option
35 | ETEXI
36 |
37 | #if defined(CONFIG_PROCESSOR_TRACE) && defined(TARGET_X86_64)
38 |
39 | {
40 | .name = "enable",
41 | .args_type = "id:i",
42 | .params = "id",
43 | .help = "enable processor tracing for specified vcpu",
44 | .cmd = hmp_pt_enable,
45 | },
46 | {
47 | .name = "enable_all",
48 | .args_type = "",
49 | .params = "",
50 | .help = "enable processor tracing for all presented vcpus",
51 | .cmd = hmp_pt_enable_all,
52 | },
53 | {
54 | .name = "disable",
55 | .args_type = "id:i",
56 | .params = "id",
57 | .help = "disable processor tracing for specified vcpu",
58 | .cmd = hmp_pt_disable,
59 | },
60 | {
61 | .name = "disable_all",
62 | .args_type = "",
63 | .params = "",
64 | .help = "disable processor tracing for all presented vcpus",
65 | .cmd = hmp_pt_disable_all,
66 | },
67 | {
68 | .name = "status",
69 | .args_type = "id:i",
70 | .params = "id",
71 | .help = "print processor tracing status of specified vcpu",
72 | .cmd = hmp_pt_status,
73 | },
74 | {
75 | .name = "status_all",
76 | .args_type = "",
77 | .params = "",
78 | .help = "print processor tracing status of all presented vcpus",
79 | .cmd = hmp_pt_status_all,
80 | },
81 | {
82 | .name = "ip_filtering",
83 | .args_type = "id:i,addrn:i,addr_a:l,addr_b:l",
84 | .params = "id addrn (0-4) addr_a addr_b",
85 | .help = "enables ip-filtering for specified vcpu",
86 | .cmd = hmp_pt_ip_filtering,
87 | },
88 | {
89 | .name = "set_file",
90 | .args_type = "file:s",
91 | .params = "file",
92 | .help = "set output file for all specified vcpu (postfix: _cpuid)",
93 | .cmd = hmp_pt_set_file,
94 | },
95 |
96 | #endif
97 |
98 | STEXI
99 | @item info version
100 | @findex version
101 | Show the version of QEMU.
102 | ETEXI
103 |
104 | STEXI
105 | @end table
106 | ETEXI
107 |
108 |
--------------------------------------------------------------------------------
/QEMU-PT/hmp-commands.hx.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 1776a1777,1788
18 | > #if defined(CONFIG_PROCESSOR_TRACE) && defined(TARGET_X86_64)
19 | > {
20 | > .name = "pt",
21 | > .args_type = "item:s?",
22 | > .params = "[subcommand]",
23 | > .help = "show various option to configure Intel Processor Tracing",
24 | > .cmd = hmp_info_help,
25 | > .sub_table = pt_cmds,
26 | > },
27 | > #endif
28 | >
29 | >
30 |
--------------------------------------------------------------------------------
/QEMU-PT/hmp.h.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 20a42,52
18 | >
19 | > #ifdef CONFIG_PROCESSOR_TRACE
20 | > void hmp_pt_enable(Monitor *mon, const QDict *qdict);
21 | > void hmp_pt_disable(Monitor *mon, const QDict *qdict);
22 | > void hmp_pt_enable_all(Monitor *mon, const QDict *qdict);
23 | > void hmp_pt_disable_all(Monitor *mon, const QDict *qdict);
24 | > void hmp_pt_status(Monitor *mon, const QDict *qdict);
25 | > void hmp_pt_status_all(Monitor *mon, const QDict *qdict);
26 | > void hmp_pt_ip_filtering(Monitor *mon, const QDict *qdict);
27 | > void hmp_pt_set_file(Monitor *mon, const QDict *qdict);
28 | > #endif
29 |
--------------------------------------------------------------------------------
/QEMU-PT/include/qom/cpu.h.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 370a371,395
18 | > #ifdef CONFIG_PROCESSOR_TRACE
19 | > volatile int pt_cmd;
20 | > volatile uint64_t pt_arg;
21 | > volatile int pt_ret;
22 | > volatile bool pt_enabled;
23 | >
24 | > int pt_fd;
25 | > void* pt_mmap;
26 | >
27 | > volatile uint32_t overflow_counter;
28 | > volatile uint64_t trace_size;
29 | >
30 | > uint64_t pt_features;
31 | >
32 | > volatile bool pt_ip_filter_enabled[4];
33 | > uint64_t pt_ip_filter_a[4];
34 | > uint64_t pt_ip_filter_b[4];
35 | > void* pt_decoder_state[4];
36 | > uint64_t pt_c3_filter;
37 | >
38 | > FILE *pt_target_file;
39 | > bool reload_pending;
40 | >
41 | > #endif
42 | >
43 |
--------------------------------------------------------------------------------
/QEMU-PT/kvm-all.c.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 42a64,69
18 | > #ifdef CONFIG_PROCESSOR_TRACE
19 | > #include "pt.h"
20 | > #include "pt/hypercall.h"
21 | > #endif
22 | >
23 | >
24 | 321a349,353
25 | > #ifdef CONFIG_PROCESSOR_TRACE
26 | > pt_kvm_init(cpu);
27 | > #endif
28 | >
29 | >
30 | 1970a2003,2014
31 | > #ifdef CONFIG_PROCESSOR_TRACE
32 | > if(cpu->reload_pending){
33 | > cpu->reload_pending = false;
34 | > //cpu_synchronize_state(cpu);
35 | > kvm_cpu_synchronize_state(cpu);
36 | > qemu_system_reload_request();
37 | > qemu_mutex_lock_iothread();
38 | > return 0;
39 | > }
40 | > #endif
41 | >
42 | >
43 | 1986a2031,2037
44 | > #ifdef CONFIG_PROCESSOR_TRACE
45 | > //if(pt_hypercalls_enabled()){
46 | > pt_pre_kvm_run(cpu);
47 | > //}
48 | > #endif
49 | >
50 | >
51 | 2065a2117,2167
52 | > #ifdef CONFIG_PROCESSOR_TRACE
53 | > case KVM_EXIT_KAFL_ACQUIRE:
54 | > handle_hypercall_kafl_acquire(run, cpu);
55 | > ret = 0;
56 | > break;
57 | > case KVM_EXIT_KAFL_GET_PAYLOAD:
58 | > handle_hypercall_get_payload(run, cpu);
59 | > ret = 0;
60 | > break;
61 | > case KVM_EXIT_KAFL_GET_PROGRAM:
62 | > handle_hypercall_get_program(run, cpu);
63 | > ret = 0;
64 | > break;
65 | > case KVM_EXIT_KAFL_RELEASE:
66 | > handle_hypercall_kafl_release(run, cpu);
67 | > ret = 0;
68 | > break;
69 | > case KVM_EXIT_KAFL_SUBMIT_CR3:
70 | > handle_hypercall_kafl_cr3(run, cpu);
71 | > ret = 0;
72 | > break;
73 | > case KVM_EXIT_KAFL_SUBMIT_PANIC:
74 | > handle_hypercall_kafl_submit_panic(run, cpu);
75 | > ret = 0;
76 | > break;
77 | > case KVM_EXIT_KAFL_SUBMIT_KASAN:
78 | > handle_hypercall_kafl_submit_kasan(run, cpu);
79 | > ret = 0;
80 | > break;
81 | > case KVM_EXIT_KAFL_PANIC:
82 | > handle_hypercall_kafl_panic(run, cpu);
83 | > ret = 0;
84 | > break;
85 | > case KVM_EXIT_KAFL_KASAN:
86 | > handle_hypercall_kafl_kasan(run, cpu);
87 | > ret = 0;
88 | > break;
89 | > case KVM_EXIT_KAFL_LOCK:
90 | > handle_hypercall_kafl_lock(run, cpu);
91 | > ret = 0;
92 | > break;
93 | > case KVM_EXIT_KAFL_INFO:
94 | > handle_hypercall_kafl_info(run, cpu);
95 | > ret = 0;
96 | > break;
97 | > case KVM_EXIT_KAFL_NEXT_PAYLOAD:
98 | > handle_hypercall_kafl_next_payload(run, cpu);
99 | > ret = 0;
100 | > break;
101 | > #endif
102 | >
103 | 2093a2196,2200
104 | > #ifdef CONFIG_PROCESSOR_TRACE
105 | > //if(pt_hypercalls_enabled()){
106 | > pt_post_kvm_run(cpu);
107 | > //}
108 | > #endif
109 |
--------------------------------------------------------------------------------
/QEMU-PT/linux-headers/linux/kvm.h.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 208a209,227
18 | > #define HYPERCALL_KAFL_RAX_ID 0x01f
19 | > #define KVM_EXIT_KAFL_ACQUIRE 100
20 | > #define KVM_EXIT_KAFL_GET_PAYLOAD 101
21 | > #define KVM_EXIT_KAFL_GET_PROGRAM 102
22 | > #define KVM_EXIT_KAFL_GET_ARGV 103
23 | > #define KVM_EXIT_KAFL_RELEASE 104
24 | > #define KVM_EXIT_KAFL_SUBMIT_CR3 105
25 | > #define KVM_EXIT_KAFL_SUBMIT_PANIC 106
26 | > #define KVM_EXIT_KAFL_SUBMIT_KASAN 107
27 | > #define KVM_EXIT_KAFL_PANIC 108
28 | > #define KVM_EXIT_KAFL_KASAN 109
29 | > #define KVM_EXIT_KAFL_LOCK 110
30 | > #define KVM_EXIT_KAFL_INFO 111
31 | > #define KVM_EXIT_KAFL_NEXT_PAYLOAD 112
32 | > #define KVM_EXIT_KAFL_DEBUG 113
33 | > #define KVM_EXIT_KAFL_HOOK 114
34 | > #define KVM_EXIT_KAFL_MTF 115
35 | >
36 | >
37 | 1355a1375,1408
38 | >
39 | > /*
40 | > * ioctls for vmx_pt fds
41 | > */
42 | > #define KVM_VMX_PT_SETUP_FD _IO(KVMIO, 0xd0) /* apply vmx_pt fd (via vcpu fd ioctl)*/
43 | > #define KVM_VMX_PT_CONFIGURE_ADDR0 _IOW(KVMIO, 0xd1, __u64) /* configure IP-filtering for addr0_a & addr0_b */
44 | > #define KVM_VMX_PT_CONFIGURE_ADDR1 _IOW(KVMIO, 0xd2, __u64) /* configure IP-filtering for addr1_a & addr1_b */
45 | > #define KVM_VMX_PT_CONFIGURE_ADDR2 _IOW(KVMIO, 0xd3, __u64) /* configure IP-filtering for addr2_a & addr2_b */
46 | > #define KVM_VMX_PT_CONFIGURE_ADDR3 _IOW(KVMIO, 0xd4, __u64) /* configure IP-filtering for addr3_a & addr3_b */
47 | >
48 | > #define KVM_VMX_PT_CONFIGURE_CR3 _IOW(KVMIO, 0xd5, __u64) /* setup CR3 filtering value */
49 | > #define KVM_VMX_PT_ENABLE _IO(KVMIO, 0xd6) /* enable and lock configuration */
50 | > #define KVM_VMX_PT_GET_TOPA_SIZE _IOR(KVMIO, 0xd7, __u32) /* get defined ToPA size */
51 | > #define KVM_VMX_PT_DISABLE _IO(KVMIO, 0xd8) /* enable and lock configuration */
52 | > #define KVM_VMX_PT_CHECK_TOPA_OVERFLOW _IO(KVMIO, 0xd9) /* check for ToPA overflow */
53 | >
54 | > #define KVM_VMX_PT_ENABLE_ADDR0 _IO(KVMIO, 0xaa) /* enable IP-filtering for addr0 */
55 | > #define KVM_VMX_PT_ENABLE_ADDR1 _IO(KVMIO, 0xab) /* enable IP-filtering for addr1 */
56 | > #define KVM_VMX_PT_ENABLE_ADDR2 _IO(KVMIO, 0xac) /* enable IP-filtering for addr2 */
57 | > #define KVM_VMX_PT_ENABLE_ADDR3 _IO(KVMIO, 0xad) /* enable IP-filtering for addr3 */
58 | >
59 | > #define KVM_VMX_PT_DISABLE_ADDR0 _IO(KVMIO, 0xae) /* disable IP-filtering for addr0 */
60 | > #define KVM_VMX_PT_DISABLE_ADDR1 _IO(KVMIO, 0xaf) /* disable IP-filtering for addr1 */
61 | > #define KVM_VMX_PT_DISABLE_ADDR2 _IO(KVMIO, 0xe0) /* disable IP-filtering for addr2 */
62 | > #define KVM_VMX_PT_DISABLE_ADDR3 _IO(KVMIO, 0xe1) /* disable IP-filtering for addr3 */
63 | >
64 | > #define KVM_VMX_PT_ENABLE_CR3 _IO(KVMIO, 0xe2) /* enable CR3 filtering */
65 | > #define KVM_VMX_PT_DISABLE_CR3 _IO(KVMIO, 0xe3) /* disable CR3 filtering */
66 | >
67 | > #define KVM_VMX_PT_SUPPORTED _IO(KVMIO, 0xe4)
68 | >
69 | > #define KVM_VMX_PT_CONFIGURE_HYPERCALL_HOOK _IOW(KVMIO, 0xe5, __u64) /* set address for hypercall hooks */
70 | >
71 | >
72 |
--------------------------------------------------------------------------------
/QEMU-PT/monitor.c.patch:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of QEMU-PT (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 | 87a109
18 | >
19 | 223a246,249
20 | > #if defined(CONFIG_PROCESSOR_TRACE)
21 | > static mon_cmd_t pt_cmds[];
22 | > #endif
23 | >
24 | 2218a2245,2251
25 | >
26 | > #if defined(CONFIG_PROCESSOR_TRACE)
27 | > static mon_cmd_t pt_cmds[] = {
28 | > #include "hmp-commands-pt.h"
29 | > { NULL, NULL, },
30 | > };
31 | > #endif
32 |
--------------------------------------------------------------------------------
/QEMU-PT/pt.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef PT_H
23 | #define PT_H
24 |
25 | void pt_setup_bitmap(void* ptr);
26 |
27 | int pt_enable(CPUState *cpu, bool hmp_mode);
28 | int pt_disable(CPUState *cpu, bool hmp_mode);
29 | int pt_enable_ip_filtering(CPUState *cpu, uint8_t addrn, uint64_t ip_a, uint64_t ip_b, bool hmp_mode);
30 | int pt_disable_ip_filtering(CPUState *cpu, uint8_t addrn, bool hmp_mode);
31 | int pt_set_cr3(CPUState *cpu, uint64_t val, bool hmp_mode);
32 |
33 | void pt_kvm_init(CPUState *cpu);
34 | void pt_pre_kvm_run(CPUState *cpu);
35 | void pt_post_kvm_run(CPUState *cpu);
36 |
37 | void pt_dump(CPUState *cpu, int bytes);
38 | #endif
--------------------------------------------------------------------------------
/QEMU-PT/pt/decoder.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef DECODER_H
23 | #define DECODER_H
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include "pt/tnt_cache.h"
37 | #include "pt/disassembler.h"
38 | #include "pt/logger.h"
39 |
40 | //#define DECODER_LOG
41 |
42 | typedef struct decoder_s{
43 | uint8_t* code;
44 | uint64_t min_addr;
45 | uint64_t max_addr;
46 | void (*handler)(uint64_t);
47 | uint64_t last_tip;
48 | uint64_t last_ip2;
49 | bool fup_pkt;
50 | bool isr;
51 | bool in_range;
52 | bool pge_enabled;
53 | disassembler_t* disassembler_state;
54 | tnt_cache_t* tnt_cache_state;
55 | #ifdef DECODER_LOG
56 | struct decoder_log_s{
57 | uint64_t tnt64;
58 | uint64_t tnt8;
59 | uint64_t pip;
60 | uint64_t cbr;
61 | uint64_t ts;
62 | uint64_t ovf;
63 | uint64_t psbc;
64 | uint64_t psbend;
65 | uint64_t mnt;
66 | uint64_t tma;
67 | uint64_t vmcs;
68 | uint64_t pad;
69 | uint64_t tip;
70 | uint64_t tip_pge;
71 | uint64_t tip_pgd;
72 | uint64_t tip_fup;
73 | uint64_t mode;
74 | } log;
75 | #endif
76 | } decoder_t;
77 |
78 | decoder_t* pt_decoder_init(uint8_t* code, uint64_t min_addr, uint64_t max_addr, void (*handler)(uint64_t));
79 | void decode_buffer(decoder_t* self, uint8_t* map, size_t len);
80 | void pt_decoder_destroy(decoder_t* self);
81 | void pt_decoder_flush(decoder_t* self);
82 |
83 | #endif
--------------------------------------------------------------------------------
/QEMU-PT/pt/disassembler.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef DISASSEMBLER_H
23 | #define DISASSEMBLER_H
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include "qemu/osdep.h"
37 | #include "pt/khash.h"
38 | #include "pt/tnt_cache.h"
39 | #include "pt/logger.h"
40 |
41 | KHASH_MAP_INIT_INT(ADDR0, uint64_t)
42 |
43 | typedef struct{
44 | uint16_t opcode;
45 | uint8_t modrm;
46 | uint8_t opcode_prefix;
47 | } cofi_ins;
48 |
49 | typedef enum cofi_types{
50 | COFI_TYPE_CONDITIONAL_BRANCH,
51 | COFI_TYPE_UNCONDITIONAL_DIRECT_BRANCH,
52 | COFI_TYPE_INDIRECT_BRANCH,
53 | COFI_TYPE_NEAR_RET,
54 | COFI_TYPE_FAR_TRANSFERS,
55 | NO_COFI_TYPE
56 | } cofi_type;
57 |
58 |
59 | typedef struct {
60 | uint64_t ins_addr;
61 | uint64_t target_addr;
62 | cofi_type type;
63 | } cofi_header;
64 |
65 | typedef struct cofi_list {
66 | struct cofi_list *list_ptr;
67 | struct cofi_list *cofi_ptr;
68 | cofi_header *cofi;
69 | } cofi_list;
70 |
71 | typedef struct disassembler_s{
72 | uint8_t* code;
73 | uint64_t min_addr;
74 | uint64_t max_addr;
75 | void (*handler)(uint64_t);
76 | khash_t(ADDR0) *map;
77 | cofi_list* list_head;
78 | cofi_list* list_element;
79 | bool debug;
80 | } disassembler_t;
81 |
82 | disassembler_t* init_disassembler(uint8_t* code, uint64_t min_addr, uint64_t max_addr, void (*handler)(uint64_t));
83 | bool trace_disassembler(disassembler_t* self, uint64_t entry_point, bool isr, tnt_cache_t* tnt_cache_state);
84 | void destroy_disassembler(disassembler_t* self);
85 |
86 | #endif
--------------------------------------------------------------------------------
/QEMU-PT/pt/filter.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Cornelius Aschermann
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include "filter.h"
23 | #include
24 |
25 | /* http://zimbry.blogspot.ch/2011/09/better-bit-mixing-improving-on.html */
26 | static inline uint64_t mix_bits(uint64_t v) {
27 | v ^= (v >> 31);
28 | v *= 0x7fb5d329728ea185;
29 | v ^= (v >> 27);
30 | v *= 0x81dadef4bc2dd44d;
31 | v ^= (v >> 33);
32 | return v;
33 | }
34 |
35 | static inline uint64_t mix_tuple(uint64_t curent_addr, uint64_t prev_addr){
36 | return mix_bits((curent_addr<<32) + (prev_addr&0xFFFFFFFF));
37 | }
38 |
39 | static bool filter_get_bitmap(filter_t* self, uint8_t* bitmap, uint64_t offset){
40 | assert(offset <= self->size);
41 | return (bitmap[offset/8] & (1<< offset%8));
42 | }
43 |
44 | static void filter_set_bitmap(filter_t* self, uint8_t* bitmap, uint64_t offset){
45 | assert(offset <= self->size);
46 | bitmap[offset/8] |= (1<< offset%8);
47 | }
48 |
49 | static bool filter_get_bitmap_sync(filter_t* self, uint8_t* bitmap, uint64_t offset){
50 | assert(offset <= self->size);
51 | return bitmap[offset];
52 | }
53 |
54 | static void filter_set_bitmap_sync(filter_t* self, uint8_t* bitmap, uint64_t offset){
55 | assert(offset <= self->size);
56 | if(!bitmap[offset]){
57 | bitmap[offset] = 1;
58 | self->blacklist_count++;
59 | }
60 | }
61 |
62 | /* default: 128MB */
63 | filter_t* new_filter(uint64_t from, uint64_t to, uint8_t *filter_bitmap){
64 | filter_t* res = malloc(sizeof(filter_t));
65 | assert(from < to);
66 | res->size = to-from;
67 | res->execs = 0;
68 | res->counters = malloc(res->size*2);
69 | res->from_addr = from;
70 | res->to_addr = to;
71 | res->hit_bitmap = malloc(res->size/8);
72 | res->filter_bitmap = filter_bitmap;
73 | res->prev_addr = 0x0;
74 | res->blacklist_count = 0;
75 | return res;
76 | }
77 |
78 | void filter_init_determinism_run(filter_t* self){
79 | self->execs = 0;
80 | memset(self->counters, 0, self->size*2);
81 | }
82 |
83 | void filter_init_new_exec(filter_t* self){
84 | memset(self->hit_bitmap, 0, self->size/8);
85 | }
86 |
87 | void filter_add_address(filter_t* self, uint64_t addr){
88 | if(self->from_addr <= addr && addr <= self->to_addr){
89 | filter_set_bitmap(self,self->hit_bitmap,addr-self->from_addr);
90 | }
91 | }
92 |
93 | void filter_finalize_exec(filter_t* self){
94 | self->execs ++;
95 | for(uint64_t a = self->from_addr; a < self->to_addr; a++){
96 | if(filter_get_bitmap(self, self->hit_bitmap,a - self->from_addr)){
97 | self->counters[a - self->from_addr] += 1;
98 | }
99 | }
100 | }
101 |
102 |
103 | void filter_finalize_determinism_run(filter_t* self){
104 | for(uint64_t a = self->from_addr; a < self->to_addr; a++){
105 | uint64_t o = a-self->from_addr;
106 | if(self->counters[o] != self->execs && self->counters[o]){
107 | filter_set_bitmap_sync(self, self->filter_bitmap, o);
108 | }
109 | }
110 | }
111 |
112 | bool filter_is_address_nondeterministic(filter_t* self, uint64_t addr){
113 | if(self->from_addr <= addr && addr <= self->to_addr){
114 | return filter_get_bitmap_sync(self, self->filter_bitmap,addr-self->from_addr);
115 | }
116 | return false;
117 | }
118 |
119 | uint32_t filter_count_new_addresses(filter_t* self){
120 | return self->blacklist_count;
121 | }
122 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/filter.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Cornelius Aschermann
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef __FILTER__
23 | #define __FILTER__
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | typedef struct filter_s {
33 | size_t size;
34 | uint16_t execs;
35 | uint16_t *counters;
36 | uint8_t *hit_bitmap;
37 | uint8_t *filter_bitmap;
38 | uint64_t prev_addr;
39 | uint64_t from_addr;
40 | uint64_t to_addr;
41 | uint32_t blacklist_count;
42 | } filter_t;
43 |
44 |
45 |
46 | filter_t* new_filter(uint64_t from, uint64_t to, uint8_t *filter_bitmap);
47 |
48 | void filter_init_determinism_run(filter_t* self);
49 |
50 | void filter_init_new_exec(filter_t* self);
51 |
52 | void filter_add_address(filter_t* self, uint64_t addr);
53 |
54 | void filter_finalize_exec(filter_t* self);
55 |
56 | void filter_finalize_determinism_run(filter_t* self);
57 |
58 | bool filter_is_address_nondeterministic(filter_t* self, uint64_t addr);
59 |
60 | uint32_t filter_count_new_addresses(filter_t* self);
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/hypercall.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef HYPERCALL_H
23 | #define HYPERCALL_H
24 |
25 | #define KAFL_NEXT_PAYLOAD
26 |
27 | #define PAYLOAD_BUFFER_SIZE 26
28 |
29 | /*
30 | * Panic Notifier Payload (x86-64)
31 | * fa cli
32 | * 48 c7 c0 1f 00 00 00 mov rax,0x1f
33 | * 48 c7 c3 08 00 00 00 mov rbx,0x8
34 | * 48 c7 c1 00 00 00 00 mov rcx,0x0
35 | * 0f 01 c1 vmcall
36 | * f4 hlt
37 | */
38 | #define PANIC_PAYLOAD "\xFA\x48\xC7\xC0\x1F\x00\x00\x00\x48\xC7\xC3\x08\x00\x00\x00\x48\xC7\xC1\x00\x00\x00\x00\x0F\x01\xC1\xF4"
39 |
40 | /*
41 | * KASAN Notifier Payload (x86-64)
42 | * fa cli
43 | * 48 c7 c0 1f 00 00 00 mov rax,0x1f
44 | * 48 c7 c3 08 00 00 00 mov rbx,0x9
45 | * 48 c7 c1 00 00 00 00 mov rcx,0x0
46 | * 0f 01 c1 vmcall
47 | * f4 hlt
48 | */
49 | #define KASAN_PAYLOAD "\xFA\x48\xC7\xC0\x1F\x00\x00\x00\x48\xC7\xC3\x09\x00\x00\x00\x48\xC7\xC1\x00\x00\x00\x00\x0F\x01\xC1\xF4"
50 |
51 | void pt_setup_program(void* ptr);
52 | void pt_setup_payload(void* ptr);
53 | void pt_setup_snd_handler(void (*tmp)(char, void*), void* tmp_s);
54 | void pt_setup_ip_filters(uint8_t filter_id, uint64_t start, uint64_t end, void* filter_bitmap, void* tfilter_bitmap);
55 | void pt_setup_enable_hypercalls(void);
56 |
57 | void pt_disable_wrapper(CPUState *cpu);
58 |
59 | void hypercall_submit_address(uint64_t address);
60 | bool hypercall_check_tuple(uint64_t current_addr, uint64_t prev_addr);
61 | void hypercall_check_in_range(uint64_t* addr);
62 |
63 |
64 | bool hypercall_check_transition(uint64_t value);
65 | void hypercall_submit_transition(uint32_t value);
66 |
67 | void hypercall_enable_filter(void);
68 | void hypercall_disable_filter(void);
69 | void hypercall_commit_filter(void);
70 |
71 | bool pt_hypercalls_enabled(void);
72 |
73 | void hypercall_unlock(void);
74 | void hypercall_reload(void);
75 |
76 | void handle_hypercall_kafl_acquire(struct kvm_run *run, CPUState *cpu);
77 | void handle_hypercall_get_payload(struct kvm_run *run, CPUState *cpu);
78 | void handle_hypercall_get_program(struct kvm_run *run, CPUState *cpu);
79 | void handle_hypercall_kafl_release(struct kvm_run *run, CPUState *cpu);
80 | void handle_hypercall_kafl_cr3(struct kvm_run *run, CPUState *cpu);
81 | void handle_hypercall_kafl_submit_panic(struct kvm_run *run, CPUState *cpu);
82 | void handle_hypercall_kafl_submit_kasan(struct kvm_run *run, CPUState *cpu);
83 | void handle_hypercall_kafl_panic(struct kvm_run *run, CPUState *cpu);
84 | void handle_hypercall_kafl_kasan(struct kvm_run *run, CPUState *cpu);
85 | void handle_hypercall_kafl_lock(struct kvm_run *run, CPUState *cpu);
86 | void handle_hypercall_kafl_info(struct kvm_run *run, CPUState *cpu);
87 |
88 | #ifdef KAFL_NEXT_PAYLOAD
89 | void handle_hypercall_kafl_next_payload(struct kvm_run *run, CPUState *cpu);
90 | #endif
91 |
92 | #endif
--------------------------------------------------------------------------------
/QEMU-PT/pt/interface.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef INTERFACE_H
23 | #define INTERFACE_H
24 |
25 | #define INTEL_PT_MAX_RANGES 4
26 |
27 | #define DEFAULT_KAFL_BITMAP_SIZE 0x10000
28 | #define DEFAULT_EDGE_FILTER_SIZE 0x1000000
29 |
30 | #define PROGRAM_SIZE (16 << 20) /* 16MB Application Data */
31 | #define PAYLOAD_SIZE (128 << 10) /* 128KB Payload Data */
32 | #define INFO_SIZE (128 << 10) /* 128KB Info Data */
33 |
34 | #define INFO_FILE "/tmp/kAFL_info.txt"
35 |
36 | #define HOOK_INSTRUCTION 0xee
37 |
38 | #define KAFL_PROTO_ACQUIRE 'R'
39 | #define KAFL_PROTO_RELEASE 'D'
40 |
41 | #define KAFL_PROTO_RELOAD 'L'
42 | #define KAFL_PROTO_ENABLE_SAMPLING 'S'
43 | #define KAFL_PROTO_DISABLE_SAMPLING 'O'
44 | #define KAFL_PROTO_COMMIT_FILTER 'T'
45 | #define KAFL_PROTO_FINALIZE 'F'
46 |
47 | #define KAFL_PROTO_ENABLE_RQI_MODE 'A'
48 | #define KAFL_PROTO_DISABLE_RQI_MODE 'B'
49 |
50 | #define KAFL_PROTO_CRASH 'C'
51 | #define KAFL_PROTO_KASAN 'K'
52 | #define KAFL_PROTO_INFO 'I'
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/logger.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include "pt/logger.h"
26 |
27 | #ifdef SAMPLE_RAW_SINGLE
28 | #define SAMPLE_RAW_SINGLE_TARGET "/dev/shm/kafl_pt_%d"
29 |
30 | int sample_raw_single_id = 0;
31 | FILE* sample_raw_single_file = NULL;
32 |
33 | void init_sample_raw_single(uint32_t id){
34 | sample_raw_single_id = id;
35 | char name[256];
36 | snprintf(name, 256, SAMPLE_RAW_SINGLE_TARGET, sample_raw_single_id);
37 | if (sample_raw_single_file)
38 | fclose(sample_raw_single_file);
39 | sample_raw_single_file = fopen(name, "wb");
40 | }
41 |
42 | void sample_raw_single(void* buffer, int bytes){
43 | if (sample_raw_single_file){
44 | fwrite(buffer, sizeof(char), bytes, sample_raw_single_file);
45 | fflush(sample_raw_single_file);
46 | }
47 | }
48 | #endif
49 |
50 | #ifdef SAMPLE_RAW
51 | #define SAMPLE_RAW_TARGET "/tmp/sample_raw_%d"
52 |
53 | int sample_raw_id = 0;
54 | FILE* sample_raw_file = NULL;
55 |
56 | void init_sample_raw(void){
57 | char name[256];
58 | snprintf(name, 256, SAMPLE_RAW_TARGET, sample_raw_id++);
59 | if (sample_raw_file)
60 | fclose(sample_raw_file);
61 | sample_raw_file = fopen(name, "wb");
62 | }
63 |
64 | void sample_raw(void* buffer, int bytes){
65 | if (sample_raw_file)
66 | fwrite(buffer, sizeof(char), bytes, sample_raw_file);
67 | }
68 | #endif
69 |
70 | #ifdef SAMPLE_DECODED
71 | #define SAMPLE_DECODED_TARGET "/tmp/traces/sample_decoded_%d"
72 |
73 | int sample_decoded_id = 0;
74 | FILE* sample_decoded_file = NULL;
75 |
76 | void init_sample_decoded(void){
77 | char name[256];
78 | snprintf(name, 256, SAMPLE_DECODED_TARGET, sample_decoded_id++);
79 | if (sample_decoded_file)
80 | fclose(sample_decoded_file);
81 | sample_decoded_file = fopen(name, "w");
82 | }
83 |
84 | void sample_decoded(uint64_t addr){
85 | if (sample_decoded_file)
86 | fprintf(sample_decoded_file, "%lx\n", addr);
87 | }
88 | #endif
89 |
90 | #ifdef SAMPLE_DECODED_DETAILED
91 | #define SAMPLE_DETAILED_TARGET "/tmp/traces/sample_detailed_%d"
92 |
93 | int sample_detailed_id = 0;
94 | FILE* sample_detailed_file = NULL;
95 |
96 | void init_sample_decoded_detailed(void){
97 | char name[256];
98 | snprintf(name, 256, SAMPLE_DETAILED_TARGET, sample_detailed_id++);
99 | if (sample_detailed_file)
100 | fclose(sample_detailed_file);
101 | sample_detailed_file = fopen(name, "w");
102 | }
103 | #endif
104 |
105 | void sample_decoded_detailed(const char *format, ...){
106 | #ifdef SAMPLE_DECODED_DETAILED
107 | va_list args;
108 | va_start(args, format);
109 | if (sample_detailed_file)
110 | vfprintf(sample_detailed_file, format, args);
111 | va_end(args);
112 | #endif
113 | }
114 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/logger.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef LOGGER_H
23 | #define LOGGER_H
24 |
25 | #define CREATE_VM_IMAGE
26 | //#define SAMPLE_RAW
27 | //#define SAMPLE_DECODED
28 | //#define SAMPLE_DECODED_DETAILED
29 | //#define SAMPLE_RAW_SINGLE
30 |
31 | #ifdef CREATE_VM_IMAGE
32 | #define DECODER_MEMORY_IMAGE "/tmp/data"
33 | #endif
34 |
35 | #ifdef SAMPLE_RAW_SINGLE
36 | void init_sample_raw_single(uint32_t id);
37 | void sample_raw_single(void* buffer, int bytes);
38 | #endif
39 |
40 | #ifdef SAMPLE_RAW
41 | void init_sample_raw(void);
42 | void sample_raw(void* buffer, int bytes);
43 | #endif
44 |
45 | #ifdef SAMPLE_DECODED
46 | void init_sample_decoded(void);
47 | void sample_decoded(uint64_t addr);
48 | #endif
49 |
50 | #ifdef SAMPLE_DECODED_DETAILED
51 | void init_sample_decoded_detailed(void);
52 | #endif
53 |
54 | void sample_decoded_detailed(const char *format, ...);
55 |
56 | #endif
57 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/memory_access.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include "memory_access.h"
23 |
24 | #define x86_64_PAGE_SIZE 0x1000
25 | #define x86_64_PAGE_MASK ~(x86_64_PAGE_SIZE - 1)
26 |
27 | bool read_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu){
28 | uint8_t tmp_buf[x86_64_PAGE_SIZE];
29 | MemTxAttrs attrs;
30 | hwaddr phys_addr;
31 | int asidx;
32 | uint64_t counter, l;
33 | int i = 0;
34 |
35 | counter = size;
36 |
37 | //cpu_synchronize_state(cpu);
38 | kvm_cpu_synchronize_state(cpu);
39 |
40 | /* copy per page */
41 | while(counter != 0){
42 |
43 | l = x86_64_PAGE_SIZE;
44 | if (l > counter)
45 | l = counter;
46 |
47 | asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
48 | attrs = MEMTXATTRS_UNSPECIFIED;
49 | phys_addr = cpu_get_phys_page_attrs_debug(cpu, (address & x86_64_PAGE_MASK), &attrs);
50 |
51 | phys_addr += (address & ~x86_64_PAGE_MASK);
52 | address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, tmp_buf, l, 0);
53 |
54 | memcpy(data+(i*x86_64_PAGE_SIZE), tmp_buf, l);
55 |
56 | i++;
57 | address += l;
58 | counter -= l;
59 | }
60 |
61 | return true;
62 | }
63 |
64 |
65 | bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu)
66 | {
67 | /* Todo: later &address_space_memory + phys_addr -> mmap SHARED */
68 | int asidx;
69 | MemTxAttrs attrs;
70 | hwaddr phys_addr;
71 | MemTxResult res;
72 |
73 | uint64_t counter, l, i;
74 |
75 | counter = size;
76 | while(counter != 0){
77 | l = x86_64_PAGE_SIZE;
78 | if (l > counter)
79 | l = counter;
80 |
81 | kvm_cpu_synchronize_state(cpu);
82 | //cpu_synchronize_state(cpu);
83 | asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
84 | attrs = MEMTXATTRS_UNSPECIFIED;
85 | phys_addr = cpu_get_phys_page_attrs_debug(cpu, (address & x86_64_PAGE_MASK), &attrs);
86 |
87 | if (phys_addr == -1){
88 | printf("FAIL 1 (%lx)!\n", address);
89 | return false;
90 | }
91 |
92 | phys_addr += (address & ~x86_64_PAGE_MASK);
93 | res = address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, data, l, true);
94 | if (res != MEMTX_OK){
95 | printf("FAIL 1 (%lx)!\n", address);
96 | return false;
97 | }
98 |
99 | i++;
100 | data += l;
101 | address += l;
102 | counter -= l;
103 | }
104 |
105 | return true;
106 | }
107 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/memory_access.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef MEMORY_ACCESS_H
23 | #define MEMORY_ACCESS_H
24 |
25 | #include "qemu/osdep.h"
26 | #include
27 | #include "qemu-common.h"
28 | #include "sysemu/kvm_int.h"
29 |
30 | bool read_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu);
31 | bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu);
32 |
33 | #endif
34 |
35 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/tmp.objs:
--------------------------------------------------------------------------------
1 | obj-y += decoder.o disassembler.o tnt_cache.o logger.o pt.o memory_access.o kafl_guest.o
2 |
3 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/tnt_cache.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include "tnt_cache.h"
23 |
24 | #define BIT(x) (1ULL << (x))
25 | #define NOT_TAKEN 0
26 | #define TAKEN 1
27 | #define TNT_EMPTY 2
28 |
29 | #define SHORT_TNT_OFFSET 1
30 | #define SHORT_TNT_MAX_BITS 8-1-SHORT_TNT_OFFSET
31 |
32 | #define LONG_TNT_OFFSET 16
33 | #define LONG_TNT_MAX_BITS 64-1-LONG_TNT_OFFSET
34 |
35 | static inline uint8_t asm_bsr(uint64_t x){
36 | asm ("bsrq %0, %0" : "=r" (x) : "0" (x));
37 | return x;
38 | }
39 |
40 | static void free_tnt_cache(tnt_cache_t* self){
41 | tnt_cache_obj* tmp;
42 | tnt_cache_obj* new;
43 | if(self->head){
44 | new = self->head;
45 | tmp = NULL;
46 | while(new){
47 | tmp = new;
48 | new = new->next;
49 | free(tmp);
50 | }
51 | self->head = NULL;
52 | self->next_node = NULL;
53 | }
54 | }
55 |
56 | static inline void free_tnt_cache_obj(tnt_cache_t* self){
57 | tnt_cache_obj* tmp;
58 | tmp = self->head;
59 | self->head = self->head->next;
60 | free(tmp);
61 | }
62 |
63 | uint8_t process_tnt_cache(tnt_cache_t* self){
64 | uint8_t ret;
65 | if(self->head){
66 | /* Short TNT */
67 | if (self->head->bits <= SHORT_TNT_MAX_BITS){
68 | ret = !!(self->head->data & BIT((SHORT_TNT_OFFSET-1) + self->head->bits - self->head->processed));
69 | }
70 | /* Long TNT */
71 | else {
72 | ret = !!(self->head->data & BIT((LONG_TNT_OFFSET-1) + (self->head->bits - self->head->processed)));
73 | }
74 |
75 | self->counter--;
76 | self->head->processed++;
77 |
78 | /* Free this TNT cache object if consumed... */
79 | if (self->head->processed == self->head->bits){
80 | if(self->next_node == self->head){
81 | free_tnt_cache(self);
82 | }
83 | else {
84 | free_tnt_cache_obj(self);
85 | }
86 | }
87 | return ret;
88 | }
89 |
90 | /* TNT cache seems to be empty... */
91 | return TNT_EMPTY;
92 | }
93 |
94 |
95 | void append_tnt_cache(tnt_cache_t* self, bool short_tnt, uint64_t data){
96 | tnt_cache_obj* new;
97 | uint8_t bits;
98 |
99 | if(short_tnt){
100 | /* Short TNT magic */
101 | bits = asm_bsr(data)-SHORT_TNT_OFFSET;
102 | }
103 | else{
104 | /* Long TNT magic */
105 | bits = asm_bsr(data)-LONG_TNT_MAX_BITS;
106 | }
107 |
108 | if (!bits){
109 | /* trailing 1 not found... */
110 | return;
111 | }
112 |
113 | new = malloc(sizeof(tnt_cache_obj));
114 | new->bits = bits;
115 | if(self->next_node){
116 | self->next_node->next = new;
117 | }
118 | else{
119 | self->head = new;
120 | }
121 | new->processed = 0;
122 | new->data = data;
123 | new->next = NULL;
124 | self->next_node = new;
125 | self->counter += bits;
126 | }
127 |
128 | bool is_empty_tnt_cache(tnt_cache_t* self){
129 | return (bool)!!(self->counter);
130 | }
131 |
132 | int count_tnt(tnt_cache_t* self){
133 | return self->counter;
134 | }
135 |
136 | tnt_cache_t* tnt_cache_init(void){
137 | tnt_cache_t* res = malloc(sizeof(tnt_cache_t));
138 | res->head = NULL;
139 | res->next_node = NULL;
140 | res->counter = 0;
141 | return res;
142 | }
143 |
144 | void tnt_cache_destroy(tnt_cache_t* self){
145 | free_tnt_cache(self);
146 | free(self);
147 | }
148 |
149 |
--------------------------------------------------------------------------------
/QEMU-PT/pt/tnt_cache.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #ifndef TNT_CACHE_H
23 | #define TNT_CACHE_H
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #define NOT_TAKEN 0
31 | #define TAKEN 1
32 | #define TNT_EMPTY 2
33 |
34 | #define SHORT_TNT_OFFSET 1
35 | #define SHORT_TNT_MAX_BITS 8-1-SHORT_TNT_OFFSET
36 |
37 | #define LONG_TNT_OFFSET 16
38 | #define LONG_TNT_MAX_BITS 64-1-LONG_TNT_OFFSET
39 |
40 | typedef struct tnt_cache_obj{
41 | uint8_t bits;
42 | uint64_t data;
43 | uint8_t processed;
44 | struct tnt_cache_obj* next;
45 | }tnt_cache_obj;
46 |
47 | typedef struct tnt_cache_s{
48 | tnt_cache_obj* head;
49 | tnt_cache_obj* next_node;
50 | uint8_t counter;
51 | } tnt_cache_t;
52 |
53 | tnt_cache_t* tnt_cache_init(void);
54 | void tnt_cache_destroy(tnt_cache_t* self);
55 |
56 | bool is_empty_tnt_cache(tnt_cache_t* self);
57 | int count_tnt(tnt_cache_t* self);
58 | uint8_t process_tnt_cache(tnt_cache_t* self);
59 | void append_tnt_cache(tnt_cache_t* self, bool short_tnt, uint64_t data);
60 |
61 | #endif
--------------------------------------------------------------------------------
/QEMU-PT/vl.c.patch:
--------------------------------------------------------------------------------
1 | 132a133,138
2 | > #ifdef CONFIG_PROCESSOR_TRACE
3 | > #include "pt.h"
4 | > #include "pt/hypercall.h"
5 | > #endif
6 | >
7 | >
8 | 1599a1606,1609
9 | > #ifdef CONFIG_PROCESSOR_TRACE
10 | > static int reload_requested;
11 | > char* loadvm_global = NULL;
12 | > #endif
13 | 1687a1698,1706
14 | > #ifdef CONFIG_PROCESSOR_TRACE
15 | > static int qemu_reload_requested(void)
16 | > {
17 | > int r = reload_requested;
18 | > reload_requested = 0;
19 | > return r;
20 | > }
21 | > #endif
22 | >
23 | 1738a1758,1764
24 | > #ifdef CONFIG_PROCESSOR_TRACE
25 | > if (kvm_enabled()) {
26 | > hypercall_unlock();
27 | > pt_disable(qemu_get_cpu(0), false);
28 | > }
29 | > #endif
30 | >
31 | 1747a1774,1787
32 | > #ifdef CONFIG_PROCESSOR_TRACE
33 | > void qemu_system_reload_request(void)
34 | > {
35 | > if (kvm_enabled()) {
36 | > hypercall_unlock();
37 | > pt_disable(qemu_get_cpu(0), false);
38 | > }
39 | > reload_requested = 1;
40 | > cpu_stop_current();
41 | > qemu_notify_event();
42 | > }
43 | > #endif
44 | >
45 | >
46 | 1757a1798,1803
47 | > #ifdef CONFIG_PROCESSOR_TRACE
48 | > if (kvm_enabled()) {
49 | > hypercall_unlock();
50 | > pt_disable(qemu_get_cpu(0), false);
51 | > }
52 | > #endif
53 | 1814a1861,1867
54 | > #ifdef CONFIG_PROCESSOR_TRACE
55 | > if (kvm_enabled()) {
56 | > hypercall_unlock();
57 | > pt_disable(qemu_get_cpu(0), false);
58 | > }
59 | > #endif
60 | >
61 | 1847a1901,1911
62 | > #ifdef CONFIG_PROCESSOR_TRACE
63 | > if (qemu_reload_requested()){
64 | > if(loadvm_global){
65 | > vm_stop(RUN_STATE_RESTORE_VM);
66 | > if (load_vmstate(loadvm_global) == 0){
67 | > vm_start();
68 | > }
69 | > return false;
70 | > }
71 | > }
72 | > #endif
73 | 1907c1971
74 | < printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION "\n"
75 | ---
76 | > printf("QEMU-PT emulator version " QEMU_VERSION QEMU_PKGVERSION " (kAFL)\n"
77 | 3627a3692,3694
78 | > #ifdef CONFIG_PROCESSOR_TRACE
79 | > loadvm_global = (char*)optarg;
80 | > #endif
81 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # kAFL: Hardware-Assisted Feedback Fuzzing for OS Kernels
2 |
3 | Blazing fast x86-64 VM kernel fuzzing framework with performant VM reloads for Linux, MacOS and Windows.
4 |
5 | Published at USENIX Security 2017.
6 |
7 | ### Currently missing:
8 |
9 | - full documentation
10 | - agents for macOS and Windows (except for our test driver)
11 |
12 | ## BibTex:
13 | ```
14 | @inproceedings{schumilo2017kafl,
15 | author = {Schumilo, Sergej and Aschermann, Cornelius and Gawlik, Robert and Schinzel, Sebastian and Holz, Thorsten},
16 | title = {{kAFL: Hardware-Assisted Feedback Fuzzing for OS Kernels}},
17 | year = {2017},
18 | booktitle = {USENIX Security Symposium}
19 | }
20 | ```
21 |
22 | ## Trophies
23 |
24 | - [Linux keyctl null pointer dereference](http://seclists.org/fulldisclosure/2016/Nov/76) (**CVE-2016-8650**)
25 | - [Linux EXT4 memory corruption](http://seclists.org/fulldisclosure/2016/Nov/75)
26 | - [Linux EXT4 denial of service](http://seclists.org/bugtraq/2016/Nov/1)
27 | - [macOS APFS memory corruption](https://support.apple.com/en-us/HT208221) (**CVE-2017-13800**)
28 | - [macOS HFS memory corruption](https://support.apple.com/en-us/HT208221) (**CVE-2017-13830**)
29 |
30 |
31 | ## Setup
32 |
33 | This is a short introduction on how to setup kAFL to fuzz Linux kernel components.
34 |
35 | ### Download kAFL and install necessary components
36 | ```
37 | $ git clone https://github.com/RUB-SysSec/kAFL.git
38 | $ cd kAFL
39 | $ chmod u+x install.sh
40 | $ sudo ./install.sh
41 | $ sudo reboot
42 | ```
43 |
44 | ### Setup VM
45 | * Create QEMU hard drive image:
46 |
47 | ```
48 | $ qemu-img create -f qcow2 linux.qcow2 20G
49 | ```
50 |
51 | * Retrieve an ISO file of the desired OS and install it inside a VM (in this case Ubuntu 16.04 server):
52 |
53 | ```
54 | $ wget -O /path/to/where/to/store/ubuntu.iso http://de.releases.ubuntu.com/16.04/ubuntu-16.04.3-server-amd64.iso
55 | $ qemu-system-x86_64 -cpu host -enable-kvm -m 512 -hda linux.qcow2 -cdrom ubuntu.iso -usbdevice tablet
56 | ```
57 |
58 | * Download kAFL and compile the loader agent:
59 |
60 | ```
61 | git clone https://github.com/RUB-SysSec/kAFL.git
62 | cd path/to/kAFL/kAFL-Fuzzer/agents
63 | chmod u+x compile.sh
64 | ./compile.sh
65 | ```
66 |
67 | * Shutdown the VM
68 |
69 | ### Prepare VM for kAFL fuzzing
70 |
71 | * On the host: Create Overlay and Snapshot Files:
72 |
73 | ```
74 | mkdir snapshot && cd snapshot
75 | qemu-img create -b /absolute/path/to/hdd/linux.qcow2 -f qcow2 overlay_0.qcow2
76 | qemu-img create -f qcow2 ram.qcow2 512
77 | ```
78 |
79 | * Start the VM using QEMU-PT:
80 |
81 | ```
82 | cd /path/to/kAFL
83 | ./qemu-2.9.0/x86_64-softmmu/qemu-system-x86_64 -hdb /path/to/snapshot/ram.qcow2 -hda /path/to/snapshot/overlay_0.qcow2 -machine pc-i440fx-2.6 -serial mon:stdio -enable-kvm -k de -m 512
84 | ```
85 |
86 | * (Optional) Install and load the vulnerable Test Driver:
87 |
88 | ```
89 | cd path/to/kAFl/kAFL-Fuzzer/vuln_drivers/simple/linux_x86-64/
90 | chmod u+x load.sh
91 | sudo ./load.sh
92 | ```
93 |
94 | * Execute loader binary which is in `path/to/kAFL/kAFL-Fuzzer/agents/linux_x86_64/loader/` as `root`. VM should freeze. Switch to the QEMU management console and create a snapshot:
95 |
96 | ```
97 | # press CTRL-a + c
98 | savevm kafl
99 | q
100 | ```
101 |
102 | ### Compile and configure kAFL components
103 | * Edit `/path/to/kAFL/kAFL-Fuzzer/kafl.ini` (`qemu-kafl_location` to point to `path/to/kAFL/qemu-2.9.0/x86_64-softmmu/qemu-system-x86_64`)
104 |
105 | * Compile agents:
106 |
107 | ```
108 | cd /kAFL-Fuzzer/agents
109 | chmod u+x compile.sh
110 | ./compile.sh
111 | ```
112 |
113 | * Retrieve address ranges of loaded drivers:
114 |
115 | ```
116 | cd /path/to/kAFL/kAFL-Fuzzer
117 | python kafl_info.py /path/to/snapshot/ram.qcow2 /path/to/snapshot/ agents/linux_x86_64/info/info 512 -v
118 | ```
119 |
120 | ### Start Fuzzing!
121 |
122 | ```
123 | python kafl_fuzz.py /path/to/snapshot/ram.qcow2 /path/to/snapshot agents/linux_x86_64/fuzzer/kafl_vuln_test 512 /path/to/input/directory /path/to/working/directory -ip0 0xffffffffc0287000-0xffffffffc028b000 -v --Purge
124 | ```
125 |
126 | The value `ip0` is the address range of the fuzzing target.
127 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | LINUX_VERSION="4.6.2"
2 | LINUX_URL="https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-$LINUX_VERSION.tar.xz"
3 | LINUX_MD5="70c4571bfb7ce7ccb14ff43b50165d43"
4 |
5 | QEMU_VERSION="2.9.0"
6 | QEMU_URL="http://download.qemu-project.org/qemu-2.9.0.tar.xz"
7 | QEMU_MD5="86c95eb3b24ffea3a84a4e3a856b4e26"
8 |
9 | echo "================================================="
10 | echo " kAFL setup script "
11 | echo "================================================="
12 |
13 | echo
14 | echo "[*] Performing basic sanity checks..."
15 |
16 | if [ ! "`uname -s`" = "Linux" ]; then
17 | echo "[-] Error: KVM-PT is supported only on Linux ..."
18 | exit 1
19 | fi
20 |
21 | if ! [ -f /etc/lsb-release ]; then
22 | echo "[-] Error: Please use Ubuntu (16.04) ..."
23 | exit 1
24 | fi
25 |
26 | for i in dpkg; do
27 | T=`which "$i" 2>/dev/null`
28 | if [ "$T" = "" ]; then
29 | echo "[-] Error: '$i' not found, please install first."
30 | exit 1
31 | fi
32 | done
33 |
34 | echo "[*] Installing essentials tools ..."
35 | sudo -Eu root apt-get install make gcc libcapstone-dev bc libssl-dev python-pip python-pygraphviz -y gnuplot ruby python libgtk2.0-dev libc6-dev flex -y > /dev/null
36 |
37 | echo "[*] Installing build dependencies for QEMU $QEMU_VERSION ..."
38 | sudo -Eu root apt-get build-dep qemu-system-x86 -y > /dev/null
39 |
40 | echo "[*] Installing python essentials ..."
41 | sudo -Eu root pip2.7 install mmh3 lz4 psutil > /dev/null 2> /dev/null
42 |
43 | echo
44 | echo "[*] Downloading QEMU $QEMU_VERSION ..."
45 | wget -O qemu.tar.gz $QEMU_URL 2> /dev/null
46 |
47 | echo "[*] Checking signature of QEMU $QEMU_VERSION ..."
48 | CHKSUM=`md5sum qemu.tar.gz| cut -d' ' -f1`
49 |
50 | if [ "$CHKSUM" != "$QEMU_MD5" ]; then
51 | echo "[-] Error: signature mismatch..."
52 | exit 1
53 | fi
54 |
55 | echo "[*] Unpacking QEMU $QEMU_VERSION ..."
56 | tar xf qemu.tar.gz
57 |
58 | echo "[*] Patching QEMU $QEMU_VERSION ..."
59 | patch qemu-$QEMU_VERSION/hmp-commands.hx < QEMU-PT/hmp-commands.hx.patch > /dev/null
60 | patch qemu-$QEMU_VERSION/monitor.c < QEMU-PT/monitor.c.patch > /dev/null
61 | patch qemu-$QEMU_VERSION/hmp.c < QEMU-PT/hmp.c.patch > /dev/null
62 | patch qemu-$QEMU_VERSION/hmp.h < QEMU-PT/hmp.h.patch > /dev/null
63 | patch qemu-$QEMU_VERSION/Makefile.target < QEMU-PT/Makefile.target.patch > /dev/null
64 | patch qemu-$QEMU_VERSION/kvm-all.c < QEMU-PT/kvm-all.c.patch > /dev/null
65 | patch qemu-$QEMU_VERSION/vl.c < QEMU-PT/vl.c.patch > /dev/null
66 | patch qemu-$QEMU_VERSION/configure < QEMU-PT/configure.patch > /dev/null
67 | patch qemu-$QEMU_VERSION/linux-headers/linux/kvm.h < QEMU-PT/linux-headers/linux/kvm.h.patch > /dev/null
68 | patch qemu-$QEMU_VERSION/include/qom/cpu.h < QEMU-PT/include/qom/cpu.h.patch > /dev/null
69 |
70 | mkdir qemu-$QEMU_VERSION/pt/ 2> /dev/null
71 | cp QEMU-PT/compile.sh qemu-$QEMU_VERSION/
72 | cp QEMU-PT/hmp-commands-pt.hx qemu-$QEMU_VERSION/
73 | cp QEMU-PT/pt.c qemu-$QEMU_VERSION/
74 | cp QEMU-PT/pt.h qemu-$QEMU_VERSION/
75 |
76 | cp QEMU-PT/pt/tmp.objs qemu-$QEMU_VERSION/pt/
77 | cp QEMU-PT/pt/decoder.h qemu-$QEMU_VERSION/pt/
78 | cp QEMU-PT/pt/hypercall.c qemu-$QEMU_VERSION/pt/
79 | cp QEMU-PT/pt/logger.h qemu-$QEMU_VERSION/pt/
80 | cp QEMU-PT/pt/khash.h qemu-$QEMU_VERSION/pt/
81 | cp QEMU-PT/pt/memory_access.h qemu-$QEMU_VERSION/pt/
82 | cp QEMU-PT/pt/tnt_cache.c qemu-$QEMU_VERSION/pt/
83 | cp QEMU-PT/pt/interface.h qemu-$QEMU_VERSION/pt/
84 | cp QEMU-PT/pt/interface.c qemu-$QEMU_VERSION/pt/
85 | cp QEMU-PT/pt/memory_access.c qemu-$QEMU_VERSION/pt/
86 | cp QEMU-PT/pt/logger.c qemu-$QEMU_VERSION/pt/
87 | cp QEMU-PT/pt/decoder.c qemu-$QEMU_VERSION/pt/
88 | cp QEMU-PT/pt/filter.h qemu-$QEMU_VERSION/pt/
89 | cp QEMU-PT/pt/hypercall.h qemu-$QEMU_VERSION/pt/
90 | cp QEMU-PT/pt/tnt_cache.h qemu-$QEMU_VERSION/pt/
91 | cp QEMU-PT/pt/filter.c qemu-$QEMU_VERSION/pt/
92 | cp QEMU-PT/pt/disassembler.c qemu-$QEMU_VERSION/pt/
93 | cp QEMU-PT/pt/disassembler.h qemu-$QEMU_VERSION/pt/
94 |
95 | patch -p1 qemu-$QEMU_VERSION/hw/misc/applesmc.c < QEMU-PT/applesmc_patches/v1-1-3-applesmc-cosmetic-whitespace-and-indentation-cleanup.patch
96 | patch -p1 qemu-$QEMU_VERSION/hw/misc/applesmc.c < QEMU-PT/applesmc_patches/v1-2-3-applesmc-consolidate-port-i-o-into-single-contiguous-region.patch
97 | patch -p1 qemu-$QEMU_VERSION/hw/misc/applesmc.c < QEMU-PT/applesmc_patches/v1-3-3-applesmc-implement-error-status-port.patch
98 |
99 | echo "[*] Compiling QEMU $QEMU_VERSION ..."
100 | cd qemu-$QEMU_VERSION
101 | echo "-------------------------------------------------"
102 | sh compile.sh
103 | echo "-------------------------------------------------"
104 | cd ..
105 |
106 | echo
107 | echo "[*] Downloading Kernel $LINUX_VERSION ..."
108 | wget -O kernel.tar.gz $LINUX_URL 2> /dev/null
109 |
110 | echo "[*] Checking signature of Kernel $LINUX_VERSION ..."
111 | CHKSUM=`md5sum kernel.tar.gz| cut -d' ' -f1`
112 |
113 | if [ "$CHKSUM" != "$LINUX_MD5" ]; then
114 | echo "[-] Error: signature mismatch..."
115 | echo "$CHKSUM"
116 | echo "$LINUX_MD5"
117 | exit 1
118 | fi
119 |
120 | echo "[*] Unpacking Kernel $LINUX_VERSION ..."
121 | tar xf kernel.tar.gz
122 |
123 | echo "[*] Patching Kernel $LINUX_VERSION ..."
124 | patch linux-$LINUX_VERSION/arch/x86/kvm/Makefile < KVM-PT/arch/x86/kvm/Makefile.patch > /dev/null
125 | patch linux-$LINUX_VERSION/arch/x86/kvm/Kconfig < KVM-PT/arch/x86/kvm/Kconfig.patch > /dev/null
126 | patch linux-$LINUX_VERSION/arch/x86/kvm/vmx.c < KVM-PT/arch/x86/kvm/vmx.c.patch > /dev/null
127 | patch linux-$LINUX_VERSION/arch/x86/kvm/svm.c < KVM-PT/arch/x86/kvm/svm.c.patch > /dev/null
128 | patch linux-$LINUX_VERSION/arch/x86/kvm/x86.c < KVM-PT/arch/x86/kvm/x86.c.patch > /dev/null
129 | patch linux-$LINUX_VERSION/arch/x86/include/asm/kvm_host.h < KVM-PT/arch/x86/include/asm/kvm_host.h.patch > /dev/null
130 | patch linux-$LINUX_VERSION/arch/x86/include/uapi/asm/kvm.h < KVM-PT/arch/x86/include/uapi/asm/kvm.h.patch > /dev/null
131 | patch linux-$LINUX_VERSION/include/uapi/linux/kvm.h < KVM-PT/include/uapi/linux/kvm.h.patch > /dev/null
132 |
133 | cp KVM-PT/arch/x86/kvm/vmx.h linux-$LINUX_VERSION/arch/x86/kvm/
134 | cp KVM-PT/arch/x86/kvm/vmx_pt.h linux-$LINUX_VERSION/arch/x86/kvm/
135 | cp KVM-PT/arch/x86/kvm/vmx_pt.c linux-$LINUX_VERSION/arch/x86/kvm/
136 |
137 | mkdir linux-$LINUX_VERSION/usermode_test/ 2> /dev/null
138 | cp KVM-PT/usermode_test/support_test.c linux-$LINUX_VERSION/usermode_test/
139 | cp KVM-PT/usermode_test/test.c linux-$LINUX_VERSION/usermode_test/
140 |
141 | echo "[*] Compiling Kernel $LINUX_VERSION ..."
142 | cd linux-$LINUX_VERSION/
143 | yes "" | make oldconfig > oldconfig.log
144 |
145 | if [ ! "` grep \"CONFIG_KVM_VMX_PT=y\" .config | wc -l`" = "1" ]; then
146 | echo "CONFIG_KVM_VMX_PT=y" >> .config
147 | fi
148 | echo "-------------------------------------------------"
149 | make -j 8
150 | echo "-------------------------------------------------"
151 |
152 | echo "KERNEL==\"kvm\", GROUP=\"kvm\"" | sudo -Eu root tee /etc/udev/rules.d/40-permissions.rules > /dev/null
153 |
154 | sudo -Eu root groupadd kvm
155 | sudo -Eu root usermod -a -G kvm $USER
156 | sudo -Eu root service udev restart
157 |
158 | sudo -Eu root make modules_install
159 | sudo -Eu root make install
160 | cd ../
161 |
162 | echo
163 | echo "[*] Done! Please reboot your system now!"
164 |
165 |
166 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/compile.sh:
--------------------------------------------------------------------------------
1 | printf "\nlinux_x86_64 userspace components...\n"
2 | echo "------------------------------------"
3 | cd linux_x86_64
4 | bash compile.sh
5 | cd ../
6 |
7 | printf "\nmacOS_x86_64 userspace components...\n"
8 | echo "------------------------------------"
9 | cd macOS_x86_64
10 | bash compile.sh
11 | cd ../
12 |
13 | printf "\nwindows_x86_64 userspace components...\n"
14 | echo "------------------------------------"
15 | cd windows_x86_64
16 | bash compile.sh
17 | cd ../
18 |
19 | printf "\ndone...\n"
20 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/kafl_user.h:
--------------------------------------------------------------------------------
1 | #ifndef KAFL_USER_H
2 | #define KAFL_USER_H
3 |
4 | #ifdef __MINGW64__
5 | #ifndef uint64_t
6 | #define uint64_t UINT64
7 | #endif
8 | #ifndef int32_t
9 | #define int32_t INT32
10 | #endif
11 | #ifndef uint8_t
12 | #define uint8_t UINT8
13 | #endif
14 | #else
15 | #include
16 | #endif
17 |
18 | #define HYPERCALL_KAFL_RAX_ID 0x01f
19 | #define HYPERCALL_KAFL_ACQUIRE 0
20 | #define HYPERCALL_KAFL_GET_PAYLOAD 1
21 | #define HYPERCALL_KAFL_GET_PROGRAM 2
22 | #define HYPERCALL_KAFL_GET_ARGV 3
23 | #define HYPERCALL_KAFL_RELEASE 4
24 | #define HYPERCALL_KAFL_SUBMIT_CR3 5
25 | #define HYPERCALL_KAFL_SUBMIT_PANIC 6
26 | #define HYPERCALL_KAFL_SUBMIT_KASAN 7
27 | #define HYPERCALL_KAFL_PANIC 8
28 | #define HYPERCALL_KAFL_KASAN 9
29 | #define HYPERCALL_KAFL_LOCK 10
30 | #define HYPERCALL_KAFL_INFO 11
31 | #define HYPERCALL_KAFL_NEXT_PAYLOAD 12
32 |
33 | #define PAYLOAD_SIZE (128 << 10) /* up to 128KB payloads */
34 | #define PROGRAM_SIZE (16 << 20) /* kAFL supports 16MB programm data */
35 | #define INFO_SIZE (128 << 10) /* 128KB info string */
36 | #define TARGET_FILE "/tmp/fuzzing_engine" /* default target for the userspace component */
37 | #define TARGET_FILE_WIN "fuzzing_engine.exe"
38 |
39 | typedef struct{
40 | int32_t size;
41 | uint8_t data[PAYLOAD_SIZE-4];
42 | } kAFL_payload;
43 |
44 | static inline void kAFL_hypercall(uint64_t rbx, uint64_t rcx){
45 | uint64_t rax = HYPERCALL_KAFL_RAX_ID;
46 | asm ("movq %0, %%rcx;" : : "r"(rcx));
47 | asm ("movq %0, %%rbx;" : : "r"(rbx));
48 | asm ("movq %0, %%rax;" : : "r"(rax));
49 | asm ("vmcall");
50 | }
51 |
52 | #endif
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/linux_x86_64/compile.sh:
--------------------------------------------------------------------------------
1 | if [[ "$OSTYPE" == "linux-gnu" ]]; then
2 | printf "\tCompiling loader...\n"
3 | gcc loader/loader.c -o loader/loader
4 | printf "\tCompiling info executable...\n"
5 | gcc info/info.c -o info/info
6 | printf "\tCompiling vuln_driver fuzzer...\n"
7 | gcc fuzzer/kafl_vuln_test.c -o fuzzer/kafl_vuln_test
8 | printf "\tCompiling EXT4 fuzzer...\n"
9 | gcc fuzzer/fs_fuzzer.c -o fuzzer/ext4 -D EXT4
10 | printf "\tCompiling NTFS fuzzer...\n"
11 | gcc fuzzer/fs_fuzzer.c -o fuzzer/ntfs -D NTFS
12 | printf "\tCompiling FAT fuzzer...\n"
13 | gcc fuzzer/fs_fuzzer.c -o fuzzer/fat -D FAT32
14 | else
15 | printf "\tError: Cannont compile linux userspace components on this plattform!\n\tPlease use Linux instead!\n"
16 | fi
17 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/linux_x86_64/fuzzer/fs_fuzzer.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of kAFL Fuzzer (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #define _GNU_SOURCE
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 | #include
34 | #include
35 | #include "../../kafl_user.h"
36 |
37 | #define KAFL_TMP_FILE "/dev/shm/trash"
38 |
39 | #include
40 | #include
41 |
42 | static inline void kill_systemd(void){
43 | system("systemctl disable systemd-udevd");
44 | system("systemctl stop systemd-udevd");
45 | system("systemctl stop systemd-udevd-kernel.socket");
46 | system("systemctl stop systemd-udevd-control.socket");
47 |
48 | system("/lib/systemd/systemctl disable systemd-udevd");
49 | system("/lib/systemd/systemctl stop systemd-udevd");
50 | system("/lib/systemd/systemctl stop systemd-udevd-kernel.socket");
51 | system("/lib/systemd/systemctl stop systemd-udevd-control.socket");
52 | }
53 |
54 | int main(int argc, char** argv)
55 | {
56 | struct stat st = {0};
57 | int fd, ret;
58 | char loopname[4096];
59 | int loopctlfd, loopfd, backingfile;
60 | long devnr;
61 |
62 | kAFL_payload* payload_buffer = mmap((void*)NULL, PAYLOAD_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
63 | memset(payload_buffer, 0xff, PAYLOAD_SIZE);
64 |
65 | kill_systemd();
66 |
67 | system("mkdir /tmp/a/");
68 | loopctlfd = open("/dev/loop-control", O_RDWR);
69 | devnr = ioctl(loopctlfd, LOOP_CTL_GET_FREE);
70 | sprintf(loopname, "/dev/loop%ld", devnr);
71 | close(loopctlfd);
72 |
73 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_CR3, 0);
74 | kAFL_hypercall(HYPERCALL_KAFL_GET_PAYLOAD, (uint64_t)payload_buffer);
75 |
76 | loopfd = open(loopname, O_RDWR);
77 | backingfile = open(KAFL_TMP_FILE, O_RDWR | O_CREAT | O_SYNC, 0777);
78 | ioctl(loopfd, LOOP_SET_FD, backingfile);
79 |
80 | while(1){
81 |
82 | lseek(backingfile, 0, SEEK_SET);
83 | kAFL_hypercall(HYPERCALL_KAFL_NEXT_PAYLOAD, 0);
84 | write(backingfile, payload_buffer->data, payload_buffer->size-4);
85 | ioctl(loopfd, LOOP_SET_CAPACITY, 0);
86 |
87 | kAFL_hypercall(HYPERCALL_KAFL_ACQUIRE, 0);
88 | #ifdef EXT4
89 | ret = mount(loopname, "/tmp/a/", "ext4", payload_buffer->data[payload_buffer->size-4], NULL);
90 | #elif NTFS
91 | ret = mount(loopname, "/tmp/a/", "ntfs", payload_buffer->data[payload_buffer->size-4], NULL);
92 | #elif FAT32
93 | ret = mount(loopname, "/tmp/a/", "msdos", payload_buffer->data[payload_buffer->size-4], NULL);
94 | #endif
95 | if(!ret){
96 | mkdir("/tmp/a/trash", 0700);
97 | stat("/tmp/a/trash", &st);
98 | umount2("/tmp/a", MNT_FORCE);
99 | }
100 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
101 | }
102 | close(backingfile);
103 | return 0;
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/linux_x86_64/fuzzer/kafl_vuln_test.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of kAFL Fuzzer (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include "../../kafl_user.h"
30 |
31 | int main(int argc, char** argv)
32 | {
33 | int kafl_vuln_fd;
34 | kAFL_payload* payload_buffer = mmap((void*)NULL, PAYLOAD_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
35 | memset(payload_buffer, 0xff, PAYLOAD_SIZE);
36 | kafl_vuln_fd = open("/proc/kafl_vuln", O_WRONLY | O_SYNC, 0);
37 | kAFL_hypercall(HYPERCALL_KAFL_GET_PAYLOAD, (uint64_t)payload_buffer);
38 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_CR3, 0);
39 | while(1){
40 | kAFL_hypercall(HYPERCALL_KAFL_NEXT_PAYLOAD, 0);
41 | kAFL_hypercall(HYPERCALL_KAFL_ACQUIRE, 0);
42 | write(kafl_vuln_fd, payload_buffer->data, payload_buffer->size);
43 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
44 | }
45 | return 0;
46 | }
47 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/linux_x86_64/info/info.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include "../../kafl_user.h"
28 |
29 | #ifndef SIZE_MAX
30 | #define SIZE_MAX ((size_t) - 1)
31 | #endif
32 |
33 | #define TMP_SIZE (64<<10)
34 | #define MOD_NAME_SIZE (256)
35 |
36 | static inline uint64_t get_address(char* identifier)
37 | {
38 | FILE * fp;
39 | char * line = NULL;
40 | ssize_t read;
41 | ssize_t len;
42 | char *tmp;
43 | uint64_t address = 0x0;
44 | uint8_t identifier_len = strlen(identifier);
45 |
46 | fp = fopen("/proc/kallsyms", "r");
47 | if (fp == NULL){
48 | return address;
49 | }
50 |
51 | while ((read = getline(&line, &len, fp)) != -1) {
52 | if(strlen(line) > identifier_len && !strcmp(line + strlen(line) - identifier_len, identifier)){
53 | address = strtoull(strtok(line, " "), NULL, 16);
54 | break;
55 | }
56 | }
57 |
58 | fclose(fp);
59 | if (line){
60 | free(line);
61 | }
62 | return address;
63 | }
64 |
65 | int main(int argc, char** argv){
66 | char key[] = "(OE)";
67 | char key2[] = "(O)";
68 | char data[TMP_SIZE];
69 | char module_name[MOD_NAME_SIZE];
70 | uint64_t start;
71 | uint64_t offset;
72 | char * pch;
73 | int counter;
74 | int pos = 0;
75 |
76 | void* info_buffer = mmap((void*)NULL, INFO_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
77 | memset(info_buffer, 0xff, INFO_SIZE);
78 |
79 | FILE* f = fopen("/proc/modules", "r");
80 | fread(data, 1, TMP_SIZE, f);
81 | fclose(f);
82 |
83 | counter = 0;
84 | int i;
85 | for(i = 0; i < strlen(data); i++){
86 | if (data[i] == '\n'){
87 | counter++;
88 | }
89 | }
90 |
91 | pos += sprintf(info_buffer + pos, "kAFL Linux x86-64 Kernel Addresses (%d Modules)\n\n", counter);
92 | printf("kAFL Linux x86-64 Kernel Addresses (%d Modules)\n\n", counter);
93 | pos += sprintf(info_buffer + pos, "START-ADDRESS\t\tEND-ADDRESS\t\tDRIVER\n");
94 | printf("START-ADDRESS\t\tEND-ADDRESS\t\tDRIVER\n");
95 |
96 | pch = strtok(data, " \n");
97 | counter = 0;
98 | while (pch != NULL)
99 | {
100 | if(strcmp(key, pch) && strcmp(key2, pch)){
101 | switch((counter++) % 6){
102 | case 0:
103 | strncpy(module_name, pch, MOD_NAME_SIZE);
104 | break;
105 | case 1:
106 | offset = strtoull(pch, NULL, 10);
107 | break;
108 | case 5:
109 | start = strtoull(pch, NULL, 16);
110 | pos += sprintf(info_buffer + pos, "0x%016lx\t0x%016lx\t%s\n", start, start+offset, module_name);
111 | printf("0x%016lx\t0x%016lx\t%s\n", start, start+offset, module_name);
112 | break;
113 | }
114 | }
115 | pch = strtok (NULL, " \n");
116 | }
117 |
118 | pos += sprintf(info_buffer + pos, "0x%016lx\t0x%016lx\t%s\n\n", get_address("T startup_64\n"), get_address("r __param_str_debug\n"), "Kernel Core");
119 |
120 | kAFL_hypercall(HYPERCALL_KAFL_INFO, (uint64_t)info_buffer);
121 | return 0;
122 | }
123 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/linux_x86_64/loader/loader.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of QEMU-PT (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #define _GNU_SOURCE
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include "../../kafl_user.h"
31 |
32 | static inline uint64_t get_address(char* identifier)
33 | {
34 | FILE * fp;
35 | char * line = NULL;
36 | ssize_t read;
37 | ssize_t len;
38 | char *tmp;
39 | uint64_t address = 0x0;
40 | uint8_t identifier_len = strlen(identifier);
41 |
42 | fp = fopen("/proc/kallsyms", "r");
43 | if (fp == NULL){
44 | return address;
45 | }
46 |
47 | while ((read = getline(&line, &len, fp)) != -1) {
48 | if(strlen(line) > identifier_len && !strcmp(line + strlen(line) - identifier_len, identifier)){
49 | address = strtoull(strtok(line, " "), NULL, 16);
50 | break;
51 | }
52 | }
53 |
54 | fclose(fp);
55 | if (line){
56 | free(line);
57 | }
58 | return address;
59 | }
60 |
61 |
62 | static inline void load_programm(void* buf){
63 | int payload_file;
64 | char* newenviron[] = {NULL};
65 | char* newargv[] = {TARGET_FILE, NULL};
66 |
67 | payload_file = open(TARGET_FILE, O_RDWR | O_CREAT | O_SYNC, 0777);
68 | write(payload_file, buf, PROGRAM_SIZE);
69 | close(payload_file);
70 | payload_file = open(TARGET_FILE, O_RDONLY);
71 | fexecve(payload_file, newargv, newenviron);
72 | }
73 |
74 | int main(int argc, char** argv)
75 | {
76 | uint64_t panic_handler = 0x0;
77 | uint64_t kasan_handler = 0x0;
78 | void* program_buffer;
79 |
80 | if(geteuid()){
81 | printf("<< kAFL Usermode Load for Linux x86-64 >>\n");
82 | printf("Loader requires root privileges...\n");
83 | return 1;
84 | }
85 |
86 | panic_handler = get_address("T panic\n");
87 | printf("Kernel Panic Handler Address:\t%lx\n", panic_handler);
88 |
89 | kasan_handler = get_address("t kasan_report_error\n");
90 | if (kasan_handler){
91 | printf("Kernel KASAN Handler Address:\t%lx\n", kasan_handler);
92 | }
93 |
94 | /* allocate 4MB contiguous virtual memory to hold fuzzer program; data is provided by the fuzzer */
95 | program_buffer = mmap((void*)0xabcd0000, PROGRAM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
96 | /* ensure that the virtual memory is *really* present in physical memory... */
97 | memset(program_buffer, 0xff, PROGRAM_SIZE);
98 |
99 | /* this hypercall will generate a VM snapshot for the fuzzer and subsequently terminate QEMU */
100 | kAFL_hypercall(HYPERCALL_KAFL_LOCK, 0);
101 |
102 |
103 | /***** Fuzzer Entrypoint *****/
104 |
105 |
106 | /* initial fuzzer handshake */
107 | kAFL_hypercall(HYPERCALL_KAFL_ACQUIRE, 0);
108 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
109 | /* submit panic address */
110 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_PANIC, panic_handler);
111 | /* submit KASan address */
112 | if (kasan_handler){
113 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_KASAN, kasan_handler);
114 | }
115 | /* submit virtual address of program buffer and wait for data (*blocking*) */
116 | kAFL_hypercall(HYPERCALL_KAFL_GET_PROGRAM, (uint64_t)program_buffer);
117 | /* execute fuzzer program */
118 | load_programm(program_buffer);
119 | /* bye */
120 | return 0;
121 | }
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/macOS_x86_64/compile.sh:
--------------------------------------------------------------------------------
1 | if [[ "$OSTYPE" == "darwin"* ]]; then
2 | printf "\tCompiling info executable...\n"
3 | gcc -o info/info info/info.c
4 | printf "\tCompiling loader...\n"
5 | gcc -o loader/loader loader/loader.c # -D DEBUG_MODE
6 | printf "\tCompiling loader (autoreload)...\n"
7 | gcc -o loader/loader_autoreload loader/loader.c -D AUTORELOAD
8 | printf "\tCompiling vuln_driver fuzzer...\n"
9 | gcc -o fuzzer/vuln_test fuzzer/vuln_test.c # -D DEBUG_MODE
10 | else
11 | printf "\tError: Cannont compile macOS userspace components on this plattform! Please use macOS instead!\n"
12 | fi
13 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/macOS_x86_64/fuzzer/vuln_test.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of kAFL Fuzzer (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include "../../kafl_user.h"
30 |
31 | int main(int argc, char** argv)
32 | {
33 | int kafl_vuln_fd;
34 | kAFL_payload* payload_buffer = mmap((void*)0xabcd0000, PAYLOAD_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
35 | memset(payload_buffer, 0xff, PAYLOAD_SIZE);
36 | kafl_vuln_fd = open("/dev/vuln", O_WRONLY, 0);
37 | kAFL_hypercall(HYPERCALL_KAFL_GET_PAYLOAD, (uint64_t)payload_buffer);
38 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_CR3, 0);
39 | while(1){
40 | kAFL_hypercall(HYPERCALL_KAFL_NEXT_PAYLOAD, 0);
41 | kAFL_hypercall(HYPERCALL_KAFL_ACQUIRE, 0);
42 | write(kafl_vuln_fd, payload_buffer->data, payload_buffer->size);
43 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
44 | }
45 | return 0;
46 | }
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/macOS_x86_64/loader/loader.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of kAFL Fuzzer (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include "../../kafl_user.h"
31 |
32 | static inline void execute_program(){
33 | char* newenviron[] = {NULL};
34 | char* newargv[] = {TARGET_FILE, NULL};
35 | #ifndef AUTORELOAD
36 | pid_t cpid;
37 | int status;
38 | cpid = fork();
39 | while(1){
40 | if (!cpid){
41 | execve(TARGET_FILE, newargv, newenviron);
42 | }
43 | else{
44 | waitpid(-1, &status, 0);
45 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
46 | cpid = fork();
47 | }
48 | }
49 | #else
50 | execve(TARGET_FILE, newargv, newenviron);
51 | #endif
52 | }
53 |
54 | static inline void load_program(void* buf){
55 | int payload_file;
56 | #ifdef DEBUG_MODE
57 | fflush(stdout);
58 | #endif
59 | payload_file = open(TARGET_FILE, O_RDWR | O_CREAT | O_SYNC, 0777);
60 | write(payload_file, buf, PROGRAM_SIZE);
61 | close(payload_file);
62 |
63 | execute_program();
64 | }
65 |
66 | #ifdef DEBUG_MODE
67 | void readfile(void* buffer){
68 | FILE *fileptr;
69 | long filelen;
70 |
71 | fileptr = fopen("test", "rb");
72 | fseek(fileptr, 0, SEEK_END);
73 | filelen = ftell(fileptr);
74 | rewind(fileptr);
75 |
76 | fread(buffer, filelen, 1, fileptr);
77 | fclose(fileptr);
78 | }
79 | #endif
80 |
81 | static inline uint64_t get_kernel_symbol_addr(char* target){
82 | char cmd[256];
83 | FILE *fp = NULL;
84 | char addr[17];
85 |
86 | /* classy cmd-injection...hell yeah! */
87 | snprintf(cmd, 256, "nm /System/Library/Kernels/kernel | grep \"%s\"$", target);
88 |
89 | fp = popen(cmd, "r");
90 | fgets(addr, 17, fp);
91 | pclose(fp);
92 | return (uint64_t)strtoull(addr, NULL, 16);
93 | }
94 |
95 | int main(int argc, char** argv)
96 | {
97 | uint64_t panic_handler = 0x0;
98 | uint64_t panic_handler64 = 0x0;
99 | void* program_buffer;
100 |
101 | printf("<< kAFL Usermode Loader for macOS x86-64 >>\n");
102 |
103 | panic_handler = get_kernel_symbol_addr("T _panic");
104 | panic_handler64 = get_kernel_symbol_addr("T _panic_64");
105 |
106 | printf("panic_handler\t%llx\n", panic_handler);
107 | printf("panic_handler64\t%llx\n", panic_handler64);
108 |
109 | /* allocate 4MB contiguous virtual memory to hold fuzzer program; data is provided by the fuzzer */
110 | program_buffer = mmap((void*)0xabcd0000, PROGRAM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
111 | /* ensure that the virtual memory is *really* present in physical memory... */
112 |
113 | memset(program_buffer, 0xff, PROGRAM_SIZE);
114 |
115 | #ifdef DEBUG_MODE
116 | readfile(program_buffer);
117 | load_program(program_buffer);
118 | return 0;
119 | #endif
120 |
121 | /* this hypercall will generate a VM snapshot for the fuzzer and subsequently terminate QEMU */
122 | kAFL_hypercall(HYPERCALL_KAFL_LOCK, 0);
123 |
124 |
125 | /***** Fuzzer Entrypoint *****/
126 |
127 |
128 | /* initial fuzzer handshake */
129 | kAFL_hypercall(HYPERCALL_KAFL_ACQUIRE, 0);
130 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
131 |
132 | /* submit panic addresses */
133 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_PANIC, panic_handler);
134 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_PANIC, panic_handler64);
135 |
136 | /* submit virtual address of program buffer and wait for data (*blocking*) */
137 | kAFL_hypercall(HYPERCALL_KAFL_GET_PROGRAM, (uint64_t)program_buffer);
138 | /* execute fuzzer program */
139 | load_program(program_buffer);
140 | /* bye */
141 | return 0;
142 | }
143 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/windows_x86_64/compile.sh:
--------------------------------------------------------------------------------
1 | if [[ "$OSTYPE" == "linux-gnu" ]]; then
2 | if x86_64-w64-mingw32-gcc -v 2> /dev/null && x86_64-w64-mingw32-g++ -v 2> /dev/null; then
3 | printf "\tCompiling loader...\n"
4 | x86_64-w64-mingw32-g++ info/info.cpp -o info/info.exe -lntdll -lpsapi
5 | printf "\tCompiling info executable...\n"
6 | x86_64-w64-mingw32-gcc loader/loader.c -o loader/loader.exe -Wall -lpsapi
7 | printf "\tCompiling vuln_driver fuzzer...\n"
8 | x86_64-w64-mingw32-gcc fuzzer/vuln_test.c -o fuzzer/vuln_test.exe
9 |
10 | else
11 | printf "\tError: x86_64-w64-mingw32-gcc/g++ not found. Please install x86_64-w64-mingw32-gcc/g++ (sudo apt install gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64)!\n"
12 | fi
13 | else
14 | printf "\tError: Cannont compile windows userspace components on this plattform!\n\tPlease use Linux instead!\n"
15 | fi
16 |
17 |
18 | # sudo apt install gcc-mingw-w64-x86-64
19 | # sudo apt install gcc-mingw-w64-x86-64
20 | # linux_x86-64-2$ x86_64-w64-mingw32-gcc -v
21 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/windows_x86_64/fuzzer/vuln_test.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Robert Gawlik
4 |
5 | This file is part of kAFL Fuzzer (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include "../../kafl_user.h"
25 |
26 | #define IOCTL_KAFL_INPUT (ULONG) CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
27 |
28 | int main(int argc, char** argv)
29 | {
30 | kAFL_payload* payload_buffer = (kAFL_payload*)VirtualAlloc(0, PAYLOAD_SIZE, MEM_COMMIT, PAGE_READWRITE);
31 | //LPVOID payload_buffer = (LPVOID)VirtualAlloc(0, PAYLOAD_SIZE, MEM_COMMIT, PAGE_READWRITE);
32 | memset(payload_buffer, 0xff, PAYLOAD_SIZE);
33 |
34 | /* open vulnerable driver */
35 | HANDLE kafl_vuln_handle = NULL;
36 | BOOL status = -1;
37 | kafl_vuln_handle = CreateFile((LPCSTR)"\\\\.\\testKafl",
38 | GENERIC_READ | GENERIC_WRITE,
39 | FILE_SHARE_READ | FILE_SHARE_WRITE,
40 | NULL,
41 | OPEN_EXISTING,
42 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
43 | NULL
44 | );
45 |
46 | if (kafl_vuln_handle == INVALID_HANDLE_VALUE) {
47 | printf("[-] KAFL test: Cannot get device handle: 0x%X\n", GetLastError());
48 | ExitProcess(0);
49 | }
50 |
51 | /* this hypercall submits the current CR3 value */
52 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_CR3, 0);
53 |
54 | /* submit the guest virtual address of the payload buffer */
55 | kAFL_hypercall(HYPERCALL_KAFL_GET_PAYLOAD, (UINT64)payload_buffer);
56 |
57 | while(1){
58 | kAFL_hypercall(HYPERCALL_KAFL_NEXT_PAYLOAD, 0);
59 | /* request new payload (*blocking*) */
60 | kAFL_hypercall(HYPERCALL_KAFL_ACQUIRE, 0);
61 |
62 | /* kernel fuzzing */
63 | DeviceIoControl(kafl_vuln_handle,
64 | IOCTL_KAFL_INPUT,
65 | (LPVOID)(payload_buffer->data),
66 | (DWORD)payload_buffer->size,
67 | NULL,
68 | 0,
69 | NULL,
70 | NULL
71 | );
72 |
73 | /* inform fuzzer about finished fuzzing iteration */
74 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
75 | }
76 |
77 | return 0;
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/windows_x86_64/info/info.cpp:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Sergej Schumilo
4 |
5 | This file is part of kAFL Fuzzer (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include "../../kafl_user.h"
28 |
29 | #define ARRAY_SIZE 1024
30 |
31 | PCSTR ntoskrnl = "C:\\Windows\\System32\\ntoskrnl.exe";
32 | PCSTR kernel_func = "PsCreateSystemThread";
33 |
34 | FARPROC KernGetProcAddress(HMODULE kern_base, LPCSTR function){
35 | HMODULE kernel_base_in_user_mode = LoadLibraryA(ntoskrnl);
36 | return (FARPROC)((PUCHAR)GetProcAddress(kernel_base_in_user_mode, function) - (PUCHAR)kernel_base_in_user_mode + (PUCHAR)kern_base);
37 | }
38 |
39 | typedef struct _RTL_PROCESS_MODULE_INFORMATION
40 | {
41 | HANDLE Section;
42 | PVOID MappedBase;
43 | PVOID ImageBase;
44 | ULONG ImageSize;
45 | ULONG Flags;
46 | USHORT LoadOrderIndex;
47 | USHORT InitOrderIndex;
48 | USHORT LoadCount;
49 | USHORT OffsetToFileName;
50 | UCHAR FullPathName[256];
51 | } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
52 |
53 | typedef struct _RTL_PROCESS_MODULES
54 | {
55 | ULONG NumberOfModules;
56 | RTL_PROCESS_MODULE_INFORMATION Modules[1];
57 | } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
58 |
59 | int main( void ){
60 |
61 | char* info_buffer = (char*)VirtualAlloc(0, INFO_SIZE, MEM_COMMIT, PAGE_READWRITE);
62 | memset(info_buffer, 0xff, INFO_SIZE);
63 | memset(info_buffer, 0x00, INFO_SIZE);
64 | int pos = 0;
65 |
66 | LPVOID drivers[ARRAY_SIZE];
67 | DWORD cbNeeded;
68 | int cDrivers, i;
69 | NTSTATUS status;
70 |
71 | if( EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers))
72 | {
73 | TCHAR szDriver[ARRAY_SIZE];
74 |
75 | cDrivers = cbNeeded / sizeof(drivers[0]);
76 | PRTL_PROCESS_MODULES ModuleInfo;
77 |
78 | ModuleInfo=(PRTL_PROCESS_MODULES)VirtualAlloc(NULL,1024*1024,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
79 |
80 | if(!ModuleInfo){
81 | goto fail;
82 | }
83 |
84 | if(!NT_SUCCESS(status=NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)11,ModuleInfo,1024*1024,NULL))){
85 | VirtualFree(ModuleInfo,0,MEM_RELEASE);
86 | goto fail;
87 | }
88 |
89 | pos += sprintf(info_buffer + pos, "kAFL Windows x86-64 Kernel Addresses (%d Drivers)\n\n", cDrivers);
90 | //_tprintf(TEXT("kAFL Windows x86-64 Kernel Addresses (%d Drivers)\n\n"), cDrivers);
91 | pos += sprintf(info_buffer + pos, "START-ADDRESS\t\tEND-ADDRESS\t\tDRIVER\n");
92 | //_tprintf(TEXT("START-ADDRESS\t\tEND-ADDRESS\t\tDRIVER\n"));
93 | for (i=0; i < cDrivers; i++ ){
94 | pos += sprintf(info_buffer + pos, "0x%p\t0x%p\t%s\n", drivers[i], ((UINT64)drivers[i]) + ModuleInfo->Modules[i].ImageSize, ModuleInfo->Modules[i].FullPathName+ModuleInfo->Modules[i].OffsetToFileName);
95 | //_tprintf(TEXT("0x%p\t0x%p\t%s\n"), drivers[i], drivers[i]+ModuleInfo->Modules[i].ImageSize, ModuleInfo->Modules[i].FullPathName+ModuleInfo->Modules[i].OffsetToFileName);
96 | }
97 | }
98 | else {
99 | goto fail;
100 | }
101 |
102 | fail:
103 | kAFL_hypercall(HYPERCALL_KAFL_INFO, (UINT64)info_buffer);
104 | return 0;
105 | }
106 |
107 |
108 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/agents/windows_x86_64/loader/loader.c:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (C) 2017 Robert Gawlik
4 |
5 | This file is part of kAFL Fuzzer (kAFL).
6 |
7 | QEMU-PT is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | QEMU-PT is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with QEMU-PT. If not, see .
19 |
20 | */
21 |
22 | #include
23 | #include
24 | #include "../../kafl_user.h"
25 |
26 | char target_file[MAX_PATH] = { 0 };
27 |
28 | /* get KeBugCheck */
29 | /* -------------- */
30 |
31 | #include
32 | #define ARRAY_SIZE 1024
33 |
34 | PCSTR ntoskrnl = "C:\\Windows\\System32\\ntoskrnl.exe";
35 | PCSTR kernel_func1 = "KeBugCheck";
36 | PCSTR kernel_func2 = "KeBugCheckEx";
37 |
38 | FARPROC KernGetProcAddress(HMODULE kern_base, LPCSTR function){
39 | // error checking? bah...
40 | HMODULE kernel_base_in_user_mode = LoadLibraryA(ntoskrnl);
41 | return (FARPROC)((PUCHAR)GetProcAddress(kernel_base_in_user_mode, function) - (PUCHAR)kernel_base_in_user_mode + (PUCHAR)kern_base);
42 | }
43 |
44 |
45 | /* force termination on AVs */
46 | void WINAPI nuke(){
47 | TerminateProcess((HANDLE)-1, 0x41);
48 | }
49 |
50 |
51 | LONG CALLBACK catch_all(struct _EXCEPTION_POINTERS *ExceptionInfo) {
52 | ExceptionInfo->ContextRecord->Rip = (DWORD64)nuke;
53 | return EXCEPTION_CONTINUE_EXECUTION; // return -1;
54 | }
55 |
56 |
57 | UINT64 resolve_KeBugCheck(PCSTR kfunc){
58 | LPVOID drivers[ARRAY_SIZE];
59 | DWORD cbNeeded;
60 | FARPROC KeBugCheck = NULL;
61 | int cDrivers, i;
62 |
63 | if( EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)){
64 | TCHAR szDriver[ARRAY_SIZE];
65 | cDrivers = cbNeeded / sizeof(drivers[0]);
66 | for (i=0; i < cDrivers; i++){
67 | if(GetDeviceDriverFileName(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0]))){
68 | // assuming ntoskrnl.exe is first entry seems save (FIXME)
69 | if (i == 0){
70 | KeBugCheck = KernGetProcAddress((HMODULE)drivers[i], kfunc);
71 | if (!KeBugCheck){
72 | printf("[-] w00t?");
73 | ExitProcess(0);
74 | }
75 | break;
76 | }
77 | }
78 | }
79 | }
80 | else{
81 | printf("[-] EnumDeviceDrivers failed; array size needed is %d\n", (UINT32)(cbNeeded / sizeof(LPVOID)));
82 | ExitProcess(0);
83 | }
84 |
85 | return (UINT64) KeBugCheck;
86 | }
87 | /* -------------- */
88 |
89 | static inline void run_program(void* target){
90 | PROCESS_INFORMATION p1;
91 | STARTUPINFOA s1;
92 |
93 | ZeroMemory(&p1, sizeof(p1));
94 | ZeroMemory(&s1, sizeof(s1));
95 | s1.cb = sizeof(s1);
96 |
97 | printf("[+] LOADER: Starting fuzzing target\n");
98 | BOOL success = CreateProcessA(NULL, target, NULL, NULL, FALSE,
99 | 0, NULL, NULL, &s1, &p1);
100 | if (!success){
101 | printf("[-] LOADER: cannot start fuzzing target\n");
102 | getchar();
103 | ExitProcess(0);
104 | }
105 | TerminateProcess((HANDLE)-1,0x41);
106 | }
107 |
108 | static inline void load_program(void* buf){
109 | HANDLE payload_file_handle = NULL;
110 | DWORD dwWritten;
111 |
112 | memset(target_file, 0x00, MAX_PATH);
113 | DWORD tmp_path_len = GetTempPathA(MAX_PATH, target_file);
114 | memcpy(target_file + tmp_path_len, "\x5c", 1);
115 | memcpy(target_file + tmp_path_len + 1, TARGET_FILE_WIN, strlen(TARGET_FILE_WIN));
116 |
117 | payload_file_handle = CreateFile((LPCSTR)target_file,
118 | GENERIC_READ | GENERIC_WRITE,
119 | FILE_SHARE_READ | FILE_SHARE_WRITE,
120 | NULL,
121 | CREATE_ALWAYS,
122 | FILE_ATTRIBUTE_NORMAL,
123 | NULL
124 | );
125 |
126 | BOOL result = WriteFile(
127 | payload_file_handle,
128 | buf,
129 | PROGRAM_SIZE,
130 | &dwWritten,
131 | NULL
132 | );
133 | if (result == 0){
134 | printf("[+] Cannot write usermode fuzzer (%ld)\n", GetLastError());
135 | /* blocks */
136 | getchar();
137 | }
138 |
139 | printf("[+] LOADER: Executing target: %s\n", target_file);
140 | CloseHandle(payload_file_handle);
141 | run_program(target_file);
142 | }
143 |
144 | static inline UINT64 hex_to_bin(char* str){
145 | return (UINT64)strtoull(str, NULL, 16);
146 | }
147 |
148 | int main(int argc, char** argv){
149 | UINT64 panic_handler1 = 0x0;
150 | UINT64 panic_handler2 = 0x0;
151 | void* program_buffer;
152 |
153 | if (AddVectoredExceptionHandler(1, catch_all) == 0){
154 | printf("[+] Cannot add veh handler %u\n", (UINT32)GetLastError());
155 | ExitProcess(0);
156 | }
157 |
158 |
159 | panic_handler1 = resolve_KeBugCheck(kernel_func1);
160 | panic_handler2 = resolve_KeBugCheck(kernel_func2);
161 |
162 | /* allocate 4MB contiguous virtual memory to hold fuzzer program; data is provided by the fuzzer */
163 | program_buffer = (void*)VirtualAlloc(0, PROGRAM_SIZE, MEM_COMMIT, PAGE_READWRITE);
164 | /* ensure that the virtual memory is *really* present in physical memory... */
165 | memset(program_buffer, 0xff, PROGRAM_SIZE);
166 |
167 | /* this hypercall will generate a VM snapshot for the fuzzer and subsequently terminate QEMU */
168 | kAFL_hypercall(HYPERCALL_KAFL_LOCK, 0);
169 |
170 |
171 | /***** Fuzzer Entrypoint *****/
172 |
173 |
174 | /* initial fuzzer handshake */
175 | kAFL_hypercall(HYPERCALL_KAFL_ACQUIRE, 0);
176 | kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0);
177 | /* submit panic address */
178 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_PANIC, panic_handler1);
179 | kAFL_hypercall(HYPERCALL_KAFL_SUBMIT_PANIC, panic_handler2);
180 | /* submit virtual address of program buffer and wait for data (*blocking*) */
181 | kAFL_hypercall(HYPERCALL_KAFL_GET_PROGRAM, (UINT64)program_buffer);
182 | /* execute fuzzer program */
183 | load_program(program_buffer);
184 | /* bye */
185 | return 0;
186 | }
187 |
188 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/common/__init__.py
--------------------------------------------------------------------------------
/kAFL-Fuzzer/common/debug.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import sys
21 | from datetime import timedelta
22 | import time
23 | import collections
24 | from multiprocessing import Manager
25 |
26 |
27 | __author__ = 'sergej'
28 |
29 | def hexdump(src, length=16):
30 | hexdump_filter = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)])
31 | lines = []
32 | for c in xrange(0, len(src), length):
33 | chars = src[c:c+length]
34 | hex_value = ' '.join(["%02x" % ord(x) for x in chars])
35 | printable = ''.join(["%s" % ((ord(x) <= 127 and hexdump_filter[ord(x)]) or '.') for x in chars])
36 | lines.append("%04x %-*s %s\n" % (c, length*3, hex_value, printable))
37 | return ''.join(lines)
38 |
39 |
40 | logging_is_enabled = False
41 | output_file = None
42 | init_time = 0.0
43 |
44 | manager = Manager()
45 | shared_list = manager.list()
46 |
47 | def __init_logger():
48 | global output_file, init_time
49 | init_time = time.time()
50 | output_file = open("debug.log", 'w')
51 |
52 | def logger(msg):
53 | global logging_is_enabled, output_file, init_time, shared_list
54 |
55 | try:
56 | if(len(shared_list) >= 9):
57 | shared_list.pop(0)
58 | shared_list.append(msg.replace("\n", " "))
59 | except:
60 | pass
61 | if logging_is_enabled:
62 | if not output_file:
63 | __init_logger()
64 | output_file.write("[" + str(timedelta(seconds=time.time()-init_time)) + "] " + msg + "\n")
65 | output_file.flush()
66 |
67 | def get_rbuf_content():
68 | global shared_list
69 | try:
70 | return list(shared_list)
71 | except:
72 | return None
73 |
74 | def enable_logging():
75 | global logging_is_enabled
76 | logging_is_enabled = True
77 |
78 | def log_master(msg):
79 | logger("[MASTER] " + msg)
80 |
81 | def log_mapserver(msg):
82 | logger("[MAPSERV] " + msg)
83 |
84 | def log_update(msg):
85 | logger("[UPDATE] " + msg)
86 |
87 | def log_slave(msg, qid):
88 | if qid < 10:
89 | logger("[SLAVE " + str(qid) + "] " + msg)
90 | elif qid > 10 and qid < 100:
91 | logger("[SLAVE " + str(qid) + "] " + msg)
92 | else:
93 | logger("[SLAVE " + str(qid) + "] " + msg)
94 |
95 | def log_tree(msg):
96 | logger("[TREE] " + msg)
97 |
98 | def log_eval(msg):
99 | logger("[EVAL] " + msg)
100 |
101 | def log_qemu(msg, qid):
102 | if qid < 10:
103 | logger("[QEMU " + str(qid) + "] " + msg)
104 | elif qid > 10 and qid < 100:
105 | logger("[QEMU " + str(qid) + "] " + msg)
106 | else:
107 | logger("[QEMU " + str(qid) + "] " + msg)
108 |
109 | def log_core(msg):
110 | logger("[CORE] " + msg)
111 |
112 | def log_info(msg):
113 | logger("[INFO] " + msg)
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/common/evaluation.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import time, os
21 | from common.debug import log_eval
22 |
23 | class Evaluation:
24 |
25 | def __init__(self, config):
26 | self.config = config
27 | if self.config.argument_values['e']:
28 | self.start_time = time.time()
29 | if os.path.exists(self.config.argument_values['work_dir'] + "/evaluation/data.csv"):
30 | last = ""
31 | with open(self.config.argument_values['work_dir'] + "/evaluation/data.csv", "rb") as f:
32 | first = f.readline()
33 | f.seek(-2, 2)
34 | while f.read(1) != b"\n":
35 | f.seek(-2, 1)
36 | last = f.readline()
37 | self.time_offset = float(last.split(";")[0])
38 | log_eval("[EVAL]\tTime offset for evaluation file is " + str(self.time_offset))
39 | self.performance_file = open(self.config.argument_values['work_dir'] + "/evaluation/data.csv", "a")
40 | else:
41 | self.time_offset = 0.0
42 | self.performance_file = open(self.config.argument_values['work_dir'] + "/evaluation/data.csv", "w")
43 | self.__write_plot_file()
44 | self.__write_converter_file()
45 | self.enabled = True
46 | else:
47 | self.enabled = False
48 |
49 | def __del__(self):
50 | self.performance_file.close()
51 |
52 | def __write_converter_file(self):
53 | script = "require 'csv'\n" +\
54 | "last_time = nil\n" +\
55 | "first_time = nil\n" +\
56 | "acc = nil\n" +\
57 | "count = 0\n" +\
58 | "CSV.open('converted.csv', 'wb') do |csv|\n" +\
59 | " CSV.foreach('data.csv',col_sep: \";\") do |row|\n" +\
60 | " time,*data = *row\n" +\
61 | " time = time.to_i\n" +\
62 | " data = data.map(&:to_i)\n" +\
63 | " first_time = time unless first_time\n" +\
64 | " acc ||= data.map{0}\n" +\
65 | " acc.each_index{|i| acc[i]+=data[i]}\n" +\
66 | " count += 1\n" +\
67 | " if !last_time || time - last_time > 2\n" +\
68 | " csv << [time-first_time, *(acc.map{|v| v/count.to_f})]\n" +\
69 | " last_time = time\n" +\
70 | " acc = acc.map{0}\n" +\
71 | " count = 0\n" +\
72 | " end\n" +\
73 | " end\n" +\
74 | "end\n"
75 |
76 | f = open(self.config.argument_values['work_dir'] + "/evaluation/convert.rb", "w")
77 | f.write(script)
78 | f.close()
79 |
80 | def __write_plot_file(self):
81 |
82 | script = "reset\n" +\
83 | "system(\"ruby convert.rb\")\n" +\
84 | "set terminal wxt size 1200,800\n" +\
85 | "set multiplot\n" +\
86 | "set grid xtics linetype 0 linecolor rgb '#d0d0d0'\n" +\
87 | "set grid ytics linetype 0 linecolor rgb '#d0d0d0'\n" +\
88 | "set border linecolor rgb '#50c0f0'\n" +\
89 | "set tics textcolor rgb '#000000'\n" +\
90 | "set key outside\n" +\
91 | "set size 1, 0.25\n" +\
92 | "set datafile separator ','\n" +\
93 | "set xdata time\n" +\
94 | "set format x \"Day %j\\n %H:%M\"\n" +\
95 | "set timefmt '%s'\n" +\
96 | "set style line 2\n" +\
97 | "set style data line\n" +\
98 | "set origin 0.0,0.75\n" +\
99 | "plot 'converted.csv' using 1:2 title 'Performance' with line linecolor rgb '#0090ff' linewidth 2 smooth bezier, \\\n" +\
100 | "'' using 1:2 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder,\n" +\
101 | "set origin 0.0,0.5\n" +\
102 | "plot 'converted.csv' \\\n" +\
103 | " using 1:4 title 'Pending' with lines linecolor rgb '#404040' linewidth 3, \\\n" +\
104 | "'' using 1:14 title 'Pending Favs' with lines linecolor rgb '#808080' linewidth 3, \\\n" +\
105 | "'' using 1:3 title 'Findings' with lines linecolor rgb '#C0C0C0' linewidth 2, \\\n" +\
106 | "'' using 1:5 title 'Favorites' with lines linecolor rgb '#FF0000' linewidth 2, \\\n" +\
107 | "'' using 1:3 with filledcurve x1 title '' linecolor rgb '#C0C0C0' fillstyle transparent solid 0.3 noborder, \\\n" +\
108 | "'' using 1:4 with filledcurve x1 title '' linecolor rgb '#808080' fillstyle transparent solid 0.5 noborder, \\\n" +\
109 | "'' using 1:14 with filledcurve x1 title '' linecolor rgb '#404040' fillstyle transparent solid 0.5 noborder\n" +\
110 | "set origin 0.0,0.25\n" +\
111 | "plot 'converted.csv' \\\n" +\
112 | " using 1:7 title 'Unique Panics' with lines, \\\n" +\
113 | "'' using 1:9 title 'KASan Unique' with lines, \\\n" +\
114 | "'' using 1:11 title 'Timeout Unique' with lines\n" +\
115 | "set origin 0.0,0.0\n" +\
116 | "plot 'converted.csv' using 0:15 title 'Blacklisted BB' with lines\n" +\
117 | "pause 2\n" +\
118 | "unset multiplot\n" +\
119 | "reread\n"
120 |
121 | f = open(self.config.argument_values['work_dir'] + "/evaluation/plot.gnu", "w")
122 | f.write(script)
123 | f.close()
124 |
125 |
126 | def write_data(self, state, blacklisted):
127 | # Format: Time; Performance; Paths, Pending; Favorites; Panics; Panics Unique; Kasan; Kasan Unique; Timeout; Timeout Unique; Level; Cycles
128 | if self.enabled:
129 | self.performance_file.write(\
130 | str(((time.time()-self.start_time)+self.time_offset)) + ";" + \
131 | str(state.get_performance()) + ";" + \
132 | str(state.hashes) + ";" + \
133 | str(state.path_pending) + ";" + \
134 | str(state.favorites) + ";" + \
135 | str(state.panics) + ";" + \
136 | str(state.panics_unique) + ";" + \
137 | str(state.kasan) + ";" + \
138 | str(state.kasan_unique) + ";" + \
139 | str(state.reloads) + ";" + \
140 | str(state.reloads_unique) + ";" +\
141 | str(state.level) + ";" +\
142 | str(state.cycles) + ";" +\
143 | str(state.fav_pending) + ";" +\
144 | str(blacklisted)+ "\n")
145 | self.performance_file.flush()
146 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/common/self_check.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | from fcntl import ioctl
21 | import sys, os, subprocess
22 |
23 | error_prefix = "[Error] "
24 |
25 | def check_version():
26 | if sys.version_info < (2, 7, 0) or sys.version_info >= (3, 0, 0):
27 | print('\033[93m' + error_prefix + "This script requires python 2.7 or higher (except for python 3.x)!" + '\033[0m')
28 | return False
29 | return True
30 |
31 | def check_packages():
32 | try:
33 | import mmh3
34 | except ImportError:
35 | print('\033[91m' + error_prefix + "Package 'mmh3' is missing!" + '\033[0m')
36 | return False
37 |
38 | try:
39 | import lz4
40 | except ImportError:
41 | print('\033[91m' + error_prefix + "Package 'lz4' is missing!" + '\033[0m')
42 | return False
43 |
44 | try:
45 | import psutil
46 | except ImportError:
47 | print('\033[91m' + error_prefix + "Package 'psutil' is missing!" + '\033[0m')
48 | return False
49 |
50 | try:
51 | import pygraphviz
52 | except ImportError:
53 | print('\033[91m' + error_prefix + "Package 'pygraphviz' is missing!" + '\033[0m')
54 | return False
55 |
56 | return True
57 |
58 | def check_vmx_pt():
59 | from fcntl import ioctl
60 |
61 | KVMIO = 0xAE
62 | KVM_VMX_PT_SUPPORTED = KVMIO << (8) | 0xe4
63 |
64 | try:
65 | fd = open("/dev/kvm", "wb")
66 | except:
67 | print('\033[91m' + error_prefix + "KVM is not loaded!" + '\033[0m')
68 | return False
69 |
70 | try:
71 | ret = ioctl(fd, KVM_VMX_PT_SUPPORTED, 0)
72 | except IOError:
73 | print('\033[91m' + error_prefix + "VMX_PT is not loaded!" + '\033[0m')
74 | return False
75 | fd.close()
76 |
77 | if ret == 0:
78 | print('\033[91m' + error_prefix + "Intel PT is not supported on this CPU!" + '\033[0m')
79 | return False
80 |
81 | return True
82 |
83 | def check_apple_osk(config):
84 | if config.argument_values["macOS"]:
85 | if config.config_values["APPLE-SMC-OSK"] == "":
86 | print('\033[91m' + error_prefix + "APPLE SMC OSK is missing in kafl.ini!" + '\033[0m')
87 | return False
88 | return True
89 |
90 | def check_apple_ignore_msrs(config):
91 | if config.argument_values["macOS"]:
92 | try:
93 | f = open("/sys/module/kvm/parameters/ignore_msrs")
94 | if not 'Y' in f.read(1):
95 | print('\033[91m' + error_prefix + "KVM is not properly configured! Please execute the following command:" + '\033[0m' + "\n\n\tsudo su\n\techo 1 > /sys/module/kvm/parameters/ignore_msrs\n")
96 | return False
97 | else:
98 | return True
99 | except:
100 | pass
101 | finally:
102 | f.close()
103 | print('\033[91m' + error_prefix + "KVM is not ready?!" + '\033[0m')
104 | return False
105 | return True
106 |
107 | def check_qemu_version(config):
108 | if not config.config_values["QEMU_KAFL_LOCATION"] or config.config_values["QEMU_KAFL_LOCATION"] == "":
109 | print('\033[91m' + error_prefix + "QEMU_KAFL_LOCATION is not set in kafl.ini!" + '\033[0m')
110 | return False
111 |
112 | if not os.path.exists(config.config_values["QEMU_KAFL_LOCATION"]):
113 | print('\033[91m' + error_prefix + "QEMU-PT executable does not exists..." + '\033[0m')
114 | return False
115 |
116 | output = ""
117 | try:
118 | proc = subprocess.Popen([config.config_values["QEMU_KAFL_LOCATION"], "-version"],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
119 | output = proc.stdout.readline()
120 | except:
121 | print('\033[91m' + error_prefix + "Binary is not executable...?" + '\033[0m')
122 | return False
123 | if not("QEMU-PT" in output and "(kAFL)" in output):
124 | print('\033[91m' + error_prefix + "Wrong QEMU-PT executable..." + '\033[0m')
125 | return False
126 | return True
127 |
128 | def self_check():
129 | if not check_version():
130 | return False
131 | if not check_packages():
132 | return False
133 | if not check_vmx_pt():
134 | return False
135 | return True
136 |
137 | def post_self_check(config):
138 | if not check_apple_ignore_msrs(config):
139 | return False
140 | if not check_apple_osk(config):
141 | return False
142 | if not check_qemu_version(config):
143 | return False
144 | return True
--------------------------------------------------------------------------------
/kAFL-Fuzzer/dict/http_sys.dict:
--------------------------------------------------------------------------------
1 | #
2 | # kAFL dictionary for HTTP.SYS
3 | # -------------------------------------------
4 | #
5 | # Created by Sergej Schumilo
6 | # Inspired by
7 | #
8 |
9 | http_tag_0="PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
10 | http_tag_1="GET"
11 | http_tag_2="PUT"
12 | http_tag_3="POST"
13 | http_tag_4="DELETE"
14 | http_tag_5="CONNECT"
15 | http_tag_6="OPTIONS"
16 | http_tag_7="TRACE"
17 | http_tag_8="PATCH"
18 | http_tag_9="PROPFIND"
19 | http_tag_10="PROPPATCH"
20 | http_tag_11="MKCOL"
21 | http_tag_12="COPY"
22 | http_tag_13="MOVE"
23 | http_tag_14="LOCK"
24 | http_tag_15="UNLOCK"
25 | http_tag_16="VERSION-CONTROL"
26 | http_tag_17="CHECKOUT"
27 | http_tag_18="UNCHECKOUT"
28 | http_tag_19="CHECKIN"
29 | http_tag_20="UPDATE"
30 | http_tag_21="LABEL"
31 | http_tag_22="REPORT"
32 | http_tag_23="MKWORKSPACE"
33 | http_tag_24="MKACTIVITY"
34 | http_tag_25="BASELINE-CONTROL"
35 | http_tag_26="MERGE"
36 | http_tag_27="/"
37 | http_tag_28="/index.html"
38 | http_tag_29="HTTP"
39 | http_tag_30="HTTP/"
40 | http_tag_31="HTTP/1.0"
41 | http_tag_32="AAAAAAAAAAAAAAAAA=BBBBBBBBBBBBBBBBBB&CCCCCCCCCCCCCCCCCC=DDDDDDDDDDDDDDDD"
42 | http_tag_33=","
43 | http_tag_34="\n"
44 | http_tag_35="\r"
45 | http_tag_36="\r\n"
46 | http_tag_37="\r\n\r\n"
47 | http_tag_38=":"
48 | http_tag_39=": "
49 | http_tag_40="ETag:"
50 | http_tag_41="Timeout:"
51 | http_tag_42="Accept:"
52 | http_tag_43="Accept-Charset:"
53 | http_tag_44="Accept-Encoding:"
54 | http_tag_45="Transfer-Encoding:"
55 | http_tag_46="Accept-Language:"
56 | http_tag_47="Accept-Datetime:"
57 | http_tag_48="Authorization:"
58 | http_tag_49="Cache-Control:"
59 | http_tag_50="Connection:"
60 | http_tag_51="Cookie:"
61 | http_tag_52="Set-Cookie:"
62 | http_tag_53="Set-Cookie2:"
63 | http_tag_54="Server:"
64 | http_tag_55="Alt-Svc:"
65 | http_tag_56="Cookie2:"
66 | http_tag_57="Content-Length:"
67 | http_tag_58="Content-MD5:"
68 | http_tag_59="Content-Type:"
69 | http_tag_60="Date:"
70 | http_tag_61="Expires:"
71 | http_tag_62="Destination:"
72 | http_tag_63="Digest"
73 | http_tag_64="Expect:"
74 | http_tag_65="From:"
75 | http_tag_66="Host:"
76 | http_tag_67="Vary:"
77 | http_tag_68="If-Match:"
78 | http_tag_69="If-Modified-Since:"
79 | http_tag_70="If-None-Match:"
80 | http_tag_71="If-Range:"
81 | http_tag_72="If-Unmodified-Since:"
82 | http_tag_73="Max-Forwards:"
83 | http_tag_74="Origin:"
84 | http_tag_75="Pragma:"
85 | http_tag_76="Proxy-Authorization:"
86 | http_tag_77="Range:"
87 | http_tag_78="Request-Range:"
88 | http_tag_79="Referer:"
89 | http_tag_80="TE:"
90 | http_tag_81="User-Agent:"
91 | http_tag_82="Upgrade:"
92 | http_tag_83="URI:"
93 | http_tag_84="Via:"
94 | http_tag_85="Warning:"
95 | http_tag_86="Proxy-Connection:"
96 | http_tag_87="Fowarded:"
97 | http_tag_88="Transfer-Encoding: chunked"
98 | http_tag_89="TE: chunked"
99 | http_tag_90="novary"
100 | http_tag_91="NULL"
101 | http_tag_92="null"
102 | http_tag_93="127.0.0.1"
103 | http_tag_94="[2002:abcd:abcd::1]"
104 | http_tag_95="text/plain"
105 | http_tag_96="text/html"
106 | http_tag_97="utf-8"
107 | http_tag_98="iso8859-2"
108 | http_tag_99="iso-8859-2"
109 | http_tag_100="gzip"
110 | http_tag_101="x-gzip"
111 | http_tag_102="identity"
112 | http_tag_103="ratio"
113 | http_tag_104="input"
114 | http_tag_105="output"
115 | http_tag_106="gzip"
116 | http_tag_107="identity"
117 | http_tag_108="deflate"
118 | http_tag_109="en-US"
119 | http_tag_110="pl"
120 | http_tag_111="base64"
121 | http_tag_112="Basic"
122 | http_tag_113="Basic realm=""
123 | http_tag_114="QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
124 | http_tag_115="Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
125 | http_tag_116="no-cache"
126 | http_tag_117="no-store"
127 | http_tag_118="no-transform"
128 | http_tag_119="must-revalidate"
129 | http_tag_120="never"
130 | http_tag_121="only-if-cached"
131 | http_tag_122="none"
132 | http_tag_123="keep-alive"
133 | http_tag_124="close"
134 | http_tag_125="trailer"
135 | http_tag_126="Upgrade"
136 | http_tag_127="STARTTLS"
137 | http_tag_128="SSL"
138 | http_tag_129="$Version=1; Skin=new;"
139 | http_tag_130="2147483648"
140 | http_tag_131="-2147483648"
141 | http_tag_132="-2147483647"
142 | http_tag_133="2147483647"
143 | http_tag_134="-1"
144 | http_tag_135="0"
145 | http_tag_136="1"
146 | http_tag_137="4294967295"
147 | http_tag_138="-4294967295"
148 | http_tag_139="4294967296"
149 | http_tag_140="-4294967296"
150 | http_tag_141="9223372036854775808"
151 | http_tag_142="-9223372036854775808"
152 | http_tag_143="9223372036854775807"
153 | http_tag_144="-9223372036854775808"
154 | http_tag_145="4611686018427387904"
155 | http_tag_146="-4611686018427387904"
156 | http_tag_147="4611686018427387903"
157 | http_tag_148="-4611686018427387904"
158 | http_tag_149="application/x-www-form-urlencoded"
159 | http_tag_150="Tue, 15 Nov 1994 08:12:31 GMT"
160 | http_tag_151="100-continue"
161 | http_tag_152="user@example.com"
162 | http_tag_153="en.wikipedia.org:80"
163 | http_tag_154="737060cd8c284d8af7ad3082f209582d"
164 | http_tag_155="Sat, 29 Oct 1994 19:43:31 GMT"
165 | http_tag_156="bytes=000000000000000000000000000000000000000500-000000000000000000000000000999"
166 | http_tag_157="Content-Range:"
167 | http_tag_158="Last-Modified:"
168 | http_tag_159="chunked"
169 | http_tag_160="Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0"
170 | http_tag_161="HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11"
171 | http_tag_162="HTTP/1.0"
172 | http_tag_163="HTTP/2.0"
173 | http_tag_164="HTTP/0.9"
174 | http_tag_165="1.0 fred, 1.1 example.com (Apache/1.1)"
175 | http_tag_166="199 Miscellaneous warning"
176 | http_tag_167="TLS/1.0"
177 | http_tag_168="Connection: Upgrade\r\n"
178 | http_tag_169="Upgrade: h2c\r\n"
179 | http_tag_170="Upgrade: h2\r\n"
180 | http_tag_171="HTTP2-Settings: 321323212321321321321321321321321322133213\r\n"
181 | http_tag_172="Upgrade:"
182 | http_tag_173="h2"
183 | http_tag_174="h2c"
184 | http_tag_175="HTTP2-Settings: "
--------------------------------------------------------------------------------
/kAFL-Fuzzer/dict/vuln.dict:
--------------------------------------------------------------------------------
1 | #
2 | # kAFL dictionary for Vuln Driver
3 | # -------------------------------------------
4 | #
5 | # Created by Sergej Schumilo
6 | #
7 |
8 | tag_result1="SERGEJ"
9 | tag_result2="KASAN"
10 | tag_result3="KERNELAFL"
11 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/communicator.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import multiprocessing
21 | import os
22 | import mmap
23 | import Queue
24 | from common.debug import logger
25 |
26 | class Communicator:
27 | def __init__(self, num_processes=1, tasks_per_requests=1, bitmap_size=(64 << 10)):
28 | self.to_update_queue = multiprocessing.Queue()
29 | self.to_master_queue = multiprocessing.Queue()
30 | self.to_master_from_mapserver_queue = multiprocessing.Queue()
31 | self.to_master_from_slave_queue = multiprocessing.Queue()
32 | self.to_mapserver_queue = multiprocessing.Queue()
33 |
34 | self.to_slave_queues = []
35 | for i in range(num_processes):
36 | self.to_slave_queues.append(multiprocessing.Queue())
37 |
38 | self.slave_locks_A = []
39 | self.slave_locks_B = []
40 | for i in range(num_processes):
41 | self.slave_locks_A.append(multiprocessing.Lock())
42 | self.slave_locks_B.append(multiprocessing.Lock())
43 | self.slave_locks_B[i].acquire()
44 |
45 | self.reload_semaphore = multiprocessing.Semaphore(multiprocessing.cpu_count()/2)
46 | self.num_processes = num_processes
47 | self.tasks_per_requests = tasks_per_requests
48 |
49 | self.stage_abortion_notifier = multiprocessing.Value('b', False)
50 | self.slave_termination = multiprocessing.Value('b', False, lock=False)
51 | self.sampling_failed_notifier = multiprocessing.Value('b', False)
52 | self.effector_mode = multiprocessing.Value('b', False)
53 |
54 | self.files = ["/dev/shm/kafl_fuzzer_master_", "/dev/shm/kafl_fuzzer_mapserver_", "/dev/shm/kafl_fuzzer_bitmap_"]
55 | self.sizes = [(65 << 10), (65 << 10), bitmap_size]
56 | self.tmp_shm = [{}, {}, {}]
57 |
58 | def get_master_payload_shm(self, slave_id):
59 | return self.__get_shm(0, slave_id)
60 |
61 | def get_mapserver_payload_shm(self, slave_id):
62 | return self.__get_shm(1, slave_id)
63 |
64 | def get_bitmap_shm(self, slave_id):
65 | return self.__get_shm(2, slave_id)
66 |
67 | def get_master_payload_shm_size(self):
68 | return self.sizes[0]
69 |
70 | def get_mapserver_payload_shm_size(self):
71 | return self.sizes[1]
72 |
73 | def get_bitmap_shm_size(self):
74 | return self.sizes[2]
75 |
76 | def create_shm(self):
77 | for j in range(len(self.files)):
78 | for i in range(self.num_processes):
79 | shm_f = os.open(self.files[j]+str(i), os.O_CREAT | os.O_RDWR | os.O_SYNC)
80 | os.ftruncate(shm_f, self.sizes[j]*self.tasks_per_requests)
81 | os.close(shm_f)
82 |
83 | def __get_shm(self, type_id, slave_id):
84 | if slave_id in self.tmp_shm[type_id]:
85 | shm = self.tmp_shm[type_id][slave_id]
86 | else:
87 | shm_fd = os.open(self.files[type_id] + str(slave_id), os.O_RDWR | os.O_SYNC)
88 | shm = mmap.mmap(shm_fd, self.sizes[type_id]*self.tasks_per_requests, mmap.MAP_SHARED, mmap.PROT_WRITE | mmap.PROT_READ)
89 | self.tmp_shm[type_id][slave_id] = shm
90 | return shm
91 |
92 |
93 | class Message():
94 | def __init__(self, tag, data, source=None):
95 | self.tag = tag
96 | self.data = data
97 | self.source = source
98 |
99 | def msg_pending(queue):
100 | return queue.empty()
101 |
102 | def send_msg(tag, data, queue, source=None):
103 | msg = Message(tag, data, source=source)
104 | queue.put(msg)
105 |
106 | def recv_msg(queue, timeout=None):
107 | if timeout:
108 | try:
109 | return queue.get(timeout=timeout)
110 | except Queue.Empty:
111 | return None
112 | return queue.get()
113 |
114 | def recv_tagged_msg(queue, tag):
115 | tmp_list = []
116 | tmp_obj = None
117 |
118 | while True:
119 | tmp_obj = recv_msg(queue)
120 | if tmp_obj.tag == tag:
121 | return tmp_obj
122 | else:
123 | queue.put(tmp_obj)
124 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/core.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import multiprocessing
21 | import time
22 | import os
23 | import signal
24 | from fuzzer.communicator import Communicator
25 | from process.mapserver import mapserver_loader
26 | from process.master import MasterProcess
27 | from process.slave import slave_loader
28 | from process.update import update_loader
29 | from common.debug import log_core, enable_logging
30 | from common.qemu import qemu
31 | from common.util import prepare_working_dir, copy_seed_files, print_fail, \
32 | check_if_old_state_exits, print_exit_msg, check_state_exists, print_pre_exit_msg, ask_for_purge, print_warning
33 | from common.config import FuzzerConfiguration
34 | from common.self_check import post_self_check
35 |
36 |
37 | __author__ = 'Sergej Schumilo'
38 |
39 |
40 | def start():
41 | config = FuzzerConfiguration()
42 |
43 | if not post_self_check(config):
44 | return -1
45 |
46 | if config.argument_values['v']:
47 | enable_logging()
48 |
49 | num_processes = config.argument_values['p']
50 |
51 | if config.argument_values['Purge'] and check_if_old_state_exits(config.argument_values['work_dir']):
52 | print_warning("Old workspace found!")
53 | if ask_for_purge("PURGE"):
54 | print_warning("Wiping old workspace...")
55 | prepare_working_dir(config.argument_values['work_dir'], purge=config.argument_values['Purge'])
56 | time.sleep(2)
57 | else:
58 | print_fail("Aborting...")
59 | return 0
60 |
61 | if not check_if_old_state_exits(config.argument_values['work_dir']):
62 | if not prepare_working_dir(config.argument_values['work_dir'], purge=config.argument_values['Purge']):
63 | print_fail("Working directory is weired or corrupted...")
64 | return 1
65 | if not copy_seed_files(config.argument_values['work_dir'], config.argument_values['seed_dir']):
66 | print_fail("Seed directory is empty...")
67 | return 1
68 | config.save_data()
69 | else:
70 | log_core("Old state exist -> loading...")
71 | config.load_data()
72 |
73 | comm = Communicator(num_processes=num_processes, tasks_per_requests=config.argument_values['t'], bitmap_size=config.config_values["BITMAP_SHM_SIZE"])
74 | comm.create_shm()
75 |
76 | master = MasterProcess(comm)
77 |
78 | update_process = multiprocessing.Process(name='UPDATE', target=update_loader, args=(comm, ))
79 | mapserver_process = multiprocessing.Process(name='MAPSERVER', target=mapserver_loader, args=(comm, ))
80 |
81 | slaves = []
82 | for i in range(num_processes):
83 | slaves.append(multiprocessing.Process(name='SLAVE' + str(i), target=slave_loader, args=(comm, i, )))
84 | slaves[i].start()
85 |
86 | update_process.start()
87 | mapserver_process.start()
88 |
89 | try:
90 | master.loop()
91 | except KeyboardInterrupt:
92 | master.save_data()
93 | log_core("Date saved!")
94 |
95 | signal.signal( signal.SIGINT, signal.SIG_IGN)
96 |
97 | counter = 0
98 | print_pre_exit_msg(counter, clrscr=True)
99 | for slave in slaves:
100 | while True:
101 | counter += 1
102 | print_pre_exit_msg(counter)
103 | slave.join(timeout=0.25)
104 | if not slave.is_alive():
105 | break
106 | print_exit_msg()
107 | return 0
108 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/process/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/process/update.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import os
21 | import time
22 |
23 | from fuzzer.communicator import recv_msg, Communicator
24 | from threading import Thread
25 | from common.config import FuzzerConfiguration
26 | from common.debug import log_update
27 | from common.ui import *
28 | from common.evaluation import Evaluation
29 |
30 | __author__ = 'Sergej Schumilo'
31 |
32 |
33 | def update_loader(comm):
34 | log_update("PID: " + str(os.getpid()))
35 | slave_process = UpdateProcess(comm)
36 | try:
37 | slave_process.loop()
38 | except KeyboardInterrupt:
39 | log_update("Exiting...")
40 |
41 | class UpdateProcess:
42 | def __init__(self, comm):
43 | self.comm = comm
44 | self.config = FuzzerConfiguration()
45 | self.timeout = self.config.config_values['UI_REFRESH_RATE']
46 |
47 |
48 | def blacklist_updater(self, ui):
49 | while True:
50 | try:
51 | counter = 0
52 | with open("/dev/shm/kafl_filter0", "rb") as f:
53 | while True:
54 | byte = f.read(1)
55 | if not byte:
56 | break
57 | if byte != '\x00':
58 | counter += 1
59 | ui.blacklist_counter = counter
60 |
61 | counter = 0
62 | with open("/dev/shm/kafl_tfilter", "rb") as f:
63 | while True:
64 | byte = f.read(1)
65 | if not byte:
66 | break
67 | if byte != '\x00':
68 | counter += 1
69 | ui.blacklist_tcounter = counter
70 |
71 | except:
72 | pass
73 | time.sleep(2)
74 |
75 | def __update_ui(self, ui, ev, update, msg):
76 | if msg:
77 | update = msg.data
78 | ui.update_state(update)
79 | ev.write_data(update, ui.blacklist_counter)
80 | elif update:
81 | update.performance_rb.append(0)
82 | ui.update_state(update)
83 | ev.write_data(update, ui.blacklist_counter)
84 | ui.refresh()
85 |
86 |
87 | def loop(self):
88 | ui = FuzzerUI(self.comm.num_processes, fancy=self.config.argument_values['f'], inline_log=self.config.argument_values['l'])
89 | ev = Evaluation(self.config)
90 | ui.install_sighandler()
91 | Thread(target=self.blacklist_updater, args=(ui,)).start()
92 | update = None
93 | while True:
94 | msg = recv_msg(self.comm.to_update_queue, timeout=self.timeout)
95 | self.__update_ui(ui, ev, update, msg)
96 | while not self.comm.to_update_queue.empty():
97 | msg = recv_msg(self.comm.to_update_queue)
98 | self.__update_ui(ui, ev, update, msg)
99 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/protocol.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | class FuzzingResult:
21 | def __init__(self, pos, crash, timeout, kasan, affected_bytes, slave_id, performance, reloaded=False, new_bits=True, qid=0):
22 | self.pos = pos
23 | self.crash = crash
24 | self.timeout = timeout
25 | self.kasan = kasan
26 | self.affected_bytes = affected_bytes
27 | self.slave_id = slave_id
28 | self.reloaded = reloaded
29 | self.performance = performance
30 | self.new_bits = new_bits
31 | self.qid = qid
32 |
33 | KAFL_TAG_REQ = 0
34 | KAFL_TAG_JOB = 1
35 | KAFL_TAG_OUTPUT = 2
36 | KAFL_TAG_START = 3
37 | KAFL_TAG_RESULT = 4
38 | KAFL_TAG_MAP_INFO = 5
39 | KAFL_TAG_NXT_FIN = 6
40 | KAFL_TAG_NXT_UNFIN = 7
41 | KAFL_TAG_UNTOUCHED_NODES = 8
42 | KAFL_TAG_REQ_BITMAP = 9
43 | KAFL_TAG_REQ_EFFECTOR = 10
44 | KAFL_TAG_GET_EFFECTOR = 11
45 | KAFL_INIT_BITMAP = 12
46 | KAFL_TAG_REQ_SAMPLING = 13
47 | KAFL_TAG_REQ_BENCHMARK = 14
48 | KAFL_TAG_ABORT_REQ = 15
49 |
50 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/state.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import time
21 | import base64
22 | from collections import deque
23 |
24 | class MapserverState:
25 | def __init__(self):
26 | self.level = 1
27 | self.timeout = 0
28 | self.unique_timeout = 0
29 | self.kasan = 0
30 | self.unique_kasan = 0
31 | self.crashes = 0
32 | self.unique = 0
33 | self.timeout = 0
34 | self.hashes = 0
35 | self.pending = 0
36 | self.cycles = 0
37 | self.favorites = 0
38 | self.last_hash_time = None
39 |
40 | self.ratio_coverage = 0.0
41 | self.ratio_bits = 0.0
42 |
43 | self.path_pending = 0
44 | self.path_unfinished = 0
45 | self.fav_pending = 0
46 | self.fav_unfinished = 0
47 |
48 | def save_data(self):
49 | tmp = {}
50 | for key, value in self.__dict__.iteritems():
51 | if key == "last_hash_time":
52 | if value:
53 | tmp[key] = (time.time() - value)
54 | else:
55 | tmp[key] = value
56 | return tmp
57 |
58 | def load_data(self, data):
59 | for key, value in data.iteritems():
60 | if key == "last_hash_time":
61 | setattr(self, key, (time.time() - value))
62 | else:
63 | setattr(self, key, value)
64 |
65 |
66 | class State:
67 | def __init__(self):
68 |
69 | self.loading = True
70 | self.reload = False
71 | self.slaves_ready = 0
72 |
73 | self.interface_str = ""
74 | self.target_str = ""
75 | self.technique = ""
76 | self.total = 0
77 | self.performance = 0
78 | self.performance_rb = deque(maxlen=5)
79 | self.max_performance_rb = deque(maxlen=100)
80 | self.runtime = time.time()
81 | self.last_hash_time = time.time()
82 | self.level = 0
83 | self.max_level = 0
84 | self.cycles = 0
85 | self.hashes = 0
86 | self.favorites = 0
87 | self.pending = 0
88 | self.payload_size = 0
89 |
90 | self.panics = 0
91 | self.panics_unique = 0
92 |
93 | self.kasan = 0
94 | self.kasan_unique = 0
95 |
96 | self.reloads = 0
97 | self.reloads_unique = 0
98 |
99 | self.progress_bitflip = 0
100 | self.progress_arithmetic = 0
101 | self.progress_interesting = 0
102 | self.progress_havoc = 0
103 | self.progress_specific = 0
104 |
105 | self.progress_requeen_amount = 0
106 | self.progress_bitflip_amount = 0
107 | self.progress_arithmetic_amount = 0
108 | self.progress_interesting_amount = 0
109 | self.progress_havoc_amount = 0
110 | self.progress_specific_amount = 0
111 |
112 | self.ratio_coverage = 0.0
113 | self.ratio_bits = 0.0
114 |
115 | self.path_pending = 0
116 | self.path_unfinished = 0
117 | self.fav_pending = 0
118 | self.fav_unfinished = 0
119 |
120 | self.payload = ""
121 |
122 | def get_performance(self):
123 | if len(self.performance_rb) == 0:
124 | return 0
125 | else:
126 | return (sum(self.performance_rb)/len(self.performance_rb))
127 |
128 | def get_max_performance(self):
129 | if len(self.max_performance_rb) == 0:
130 | return 0
131 | else:
132 | return (sum(self.max_performance_rb)/len(self.max_performance_rb))
133 |
134 | def save_data(self):
135 | tmp = {}
136 | for key, value in self.__dict__.iteritems():
137 | if key == "runtime" or key == "last_hash_time":
138 | tmp[key] = (time.time() - value)
139 | elif key == "performance_rb" or key == "max_performance_rb":
140 | tmp[key] = list(value)
141 | elif key == "payload":
142 | tmp[key] = base64.b64encode(value)
143 | elif not str(key).startswith("progress"):
144 | tmp[key] = value
145 | return tmp
146 |
147 | def load_data(self, data):
148 | for key, value in data.iteritems():
149 | if key == "runtime" or key == "last_hash_time":
150 | setattr(self, key, (time.time() - value))
151 | elif key == "performance_rb":
152 | for element in value:
153 | self.performance_rb.append(element)
154 | elif key == "max_performance_rb":
155 | for element in value:
156 | self.max_performance_rb.append(element)
157 | elif key == "payload":
158 | setattr(self, key, base64.b64decode(value))
159 | elif not str(key).startswith("progress"):
160 | setattr(self, key, value)
161 | self.slaves_ready = 0
162 |
163 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/technique/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/technique/bitflip.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
3 | def bitflip_range(data, skip_null=False, effector_map=None):
4 | if len(data) == 0:
5 | return 0
6 |
7 | if effector_map:
8 | effector_map = effector_map[:len(data)]
9 | data_len = sum(x is True for x in effector_map)
10 | data_tmp = ""
11 | for i in range(len(data)):
12 | if effector_map[i]:
13 | data_tmp += data[i]
14 | else:
15 | data_len = len(data)
16 | data_tmp = data
17 | num = data_len*8
18 | num += data_len*7
19 | num += data_len*5
20 | num += data_len
21 | if effector_map:
22 | byte_count = 0
23 | for i in range(len(data)):
24 | if effector_map[i]:
25 | byte_count += 1
26 | if byte_count >= 2:
27 | num += 1
28 | if byte_count >= 4:
29 | num += 1
30 |
31 | else:
32 | byte_count = 0
33 | else:
34 | if data_len > 1:
35 | num += data_len - 1
36 | if data_len > 3:
37 | num += data_len - 3
38 | return num
39 |
40 | def bitflip8_range(data, skip_null=False, effector_map=None):
41 | if effector_map:
42 | effector_map = effector_map[:len(data)]
43 | data_len = sum(x is True for x in effector_map)
44 | data_tmp = ""
45 | for i in range(len(data)):
46 | if effector_map[i]:
47 | data_tmp += data[i]
48 | else:
49 | data_len = len(data)
50 | data_tmp = data
51 | num = data_len*8
52 | return num
53 |
54 | def mutate_seq_walking_bits_array(data, func, skip_null=False, kafl_state=None, effector_map=None):
55 | if kafl_state:
56 | if skip_null:
57 | kafl_state.technique = "BIT-FLIP 1 S0"
58 | else:
59 | kafl_state.technique = "BIT-FLIP 1"
60 |
61 | for i in range(len(data)*8):
62 | if effector_map:
63 | if not effector_map[i/8]:
64 | continue
65 | if data[i/8] == 0x00 and skip_null:
66 | func(None, no_data=True)
67 | continue
68 | data[i/8] ^= (0x80 >> (i % 8))
69 | func(data.tostring(), affected_bytes=[(i/8)])
70 | data[i/8] ^= (0x80 >> (i % 8))
71 |
72 | def mutate_seq_two_walking_bits_array(data, func, skip_null=False, kafl_state=None, effector_map=None):
73 | if kafl_state:
74 | if skip_null:
75 | kafl_state.technique = "BIT-FLIP 2 S0"
76 | else:
77 | kafl_state.technique = "BIT-FLIP 2"
78 |
79 | for i in range((len(data)*7)):
80 | if effector_map:
81 | if not effector_map[i/7]:
82 | continue
83 | if data[i/7] == 0x00 and skip_null:
84 | func(None, no_data=True)
85 | continue
86 | data[i/7] ^= (0xC0 >> (i % 7))
87 | func(data.tostring(), affected_bytes=[(i/7)])
88 | data[i/7] ^= (0xC0 >> (i % 7))
89 |
90 | def mutate_seq_four_walking_bits_array(data, func, skip_null=False, kafl_state=None, effector_map=None):
91 | if kafl_state:
92 | if skip_null:
93 | kafl_state.technique = "BIT-FLIP 4 S0"
94 | else:
95 | kafl_state.technique = "BIT-FLIP 4"
96 |
97 | for i in range((len(data)*5)):
98 | if effector_map:
99 | if not effector_map[i/5]:
100 | continue
101 | if data[i/5] == 0x00 and skip_null:
102 | func(None, no_data=True)
103 | continue
104 | data[i/5] ^= (0xF0 >> (i % 5))
105 | func(data.tostring(), affected_bytes=[(i/5)])
106 | data[i/5] ^= (0xF0 >> (i % 5))
107 |
108 | def mutate_seq_walking_byte_array(data, func, skip_null=False, kafl_state=None, effector_map=None):
109 | if kafl_state:
110 | if skip_null:
111 | kafl_state.technique = "BIT-FLIP 8 S0"
112 | else:
113 | kafl_state.technique = "BIT-FLIP 8"
114 |
115 | for i in range((len(data))):
116 | if effector_map:
117 | if not effector_map[i]:
118 | continue
119 | if data[i] == 0x00 and skip_null:
120 | func(None, no_data=True)
121 | continue
122 | data[i] ^= 0xFF
123 | func(data.tostring(), affected_bytes=[i])
124 | data[i] ^= 0xFF
125 |
126 | def mutate_seq_two_walking_bytes_array(data, func, kafl_state=None, effector_map=None):
127 | if kafl_state:
128 | kafl_state.technique = "BIT-FLIP 16"
129 |
130 | if len(data) > 1:
131 | data[0] ^= 0xFF
132 | for i in range(1, ((len(data)))):
133 | if effector_map:
134 | if not effector_map[i] or not effector_map[i-1]:
135 | continue
136 | data[i] ^= 0xFF
137 | func(data.tostring(), affected_bytes=[i-1, i])
138 | data[i-1] ^= 0xFF
139 | data[len(data)-1] ^= 0xFF
140 |
141 | def mutate_seq_four_walking_bytes_array(data, func, kafl_state=None, effector_map=None):
142 | if kafl_state:
143 | kafl_state.technique = "BIT-FLIP 32"
144 |
145 | if len(data) > 3:
146 | data[0] ^= 0xFF
147 | data[1] ^= 0xFF
148 | data[2] ^= 0xFF
149 | for i in range(3, (len(data))):
150 | if effector_map:
151 | if not effector_map[i] or not effector_map[i-1] or not effector_map[i-2] or not effector_map[i-3]:
152 | continue
153 | data[i] ^= 0xFF
154 | func(data.tostring(), affected_bytes=[i-3, i-2, i-1, i])
155 | data[i-3] ^= 0xFF
156 | data[len(data)-1] ^= 0xFF
157 | data[len(data)-2] ^= 0xFF
158 | data[len(data)-3] ^= 0xFF
159 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/technique/debug.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
3 | def mutate_seq_debug_array(data, func, skip_null=False, kafl_state=None):
4 | kafl_state.technique = "DEBUG"
5 | for i in range(len(data)*0xff):
6 | #tmp = data[i/0xff]
7 | #data[i/0xff] = (i % 0xff)
8 | func(data.tostring())
9 | #data[i/0xff] = tmp
10 |
11 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/technique/havoc.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
3 | from array import array
4 | from fuzzer.technique.helper import *
5 | from fuzzer.technique.havoc_handler import *
6 | from common.config import FuzzerConfiguration
7 | from common.debug import logger
8 |
9 | def load_dict(file_name):
10 | f = open(file_name)
11 | dict_entries = []
12 | for line in f:
13 | if not line.startswith("#"):
14 | try:
15 | dict_entries.append((line.split("=\"")[1].split("\"\n")[0]).decode("string_escape"))
16 | except:
17 | pass
18 | f.close()
19 | return dict_entries
20 |
21 | if FuzzerConfiguration().argument_values["I"]:
22 | set_dict(load_dict(FuzzerConfiguration().argument_values["I"]))
23 | append_handler(havoc_dict)
24 | append_handler(havoc_dict)
25 |
26 | location_findings = FuzzerConfiguration().argument_values['work_dir'] + "/findings/"
27 | location_corpus = FuzzerConfiguration().argument_values['work_dir'] + "/corpus/"
28 |
29 | def havoc_range(perf_score):
30 |
31 | max_iterations = int(perf_score * 2.5)
32 |
33 | if max_iterations < AFL_HAVOC_MIN:
34 | max_iterations = AFL_HAVOC_MIN
35 |
36 | return max_iterations
37 |
38 |
39 | def mutate_seq_havoc_array(data, func, max_iterations, stacked=True, resize=False, files_to_splice=None):
40 |
41 | reseed()
42 | if resize:
43 | copy = array('B', data.tostring() + data.tostring())
44 | else:
45 | copy = array('B', data.tostring())
46 |
47 | cnt = 0
48 | for i in range(max_iterations):
49 | if resize:
50 | copy = array('B', data.tostring() + data.tostring())
51 | else:
52 | copy = array('B', data.tostring())
53 |
54 | value = RAND(AFL_HAVOC_STACK_POW2)
55 | if files_to_splice:
56 | copy = havoc_splicing(data, files_to_splice)
57 | value = RAND(AFL_HAVOC_STACK_POW2)*3
58 |
59 | for j in range(1 << (1 + value)):
60 | handler = random.choice(havoc_handler)
61 | if not stacked:
62 | if resize:
63 | copy = array('B', data.tostring() + data.tostring())
64 | else:
65 | copy = array('B', data.tostring())
66 | copy = handler(copy[:(64<<10)], func)
67 | cnt += 1
68 | if cnt >= max_iterations:
69 | return
70 |
71 | pass
72 |
73 |
74 | def mutate_seq_splice_array(data, func, max_iterations, kafl_state, stacked=True, resize=False):
75 | files = []
76 | for i in range(kafl_state.panics_unique):
77 | files.append(location_findings + "/panic/panic_" + str(i+1))
78 | for i in range(kafl_state.kasan_unique):
79 | files.append(location_findings + "/kasan/kasan_" + str(i+1))
80 | for i in range(kafl_state.reloads_unique):
81 | files.append(location_findings + "/timeout/timeout_" + str(i+1))
82 |
83 | for i in range(kafl_state.hashes):
84 | files.append(location_corpus + "payload_" + str(i))
85 |
86 | random.shuffle(files)
87 | mutate_seq_havoc_array(data, func, max_iterations, stacked=stacked, resize=resize, files_to_splice=files)
88 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/technique/helper.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
3 | import random
4 | import os
5 | from common.config import FuzzerConfiguration
6 |
7 | KAFL_MAX_FILE = 1 << 15
8 |
9 | AFL_HAVOC_BLK_LARGE = 1500
10 | AFL_ARITH_MAX = 35
11 | AFL_HAVOC_MIN = 2000
12 | AFL_HAVOC_CYCLES = 5000
13 | AFL_HAVOC_STACK_POW2 = 3# 7
14 |
15 | interesting_8_Bit = [128, 255, 0, 1, 16, 32, 64, 100, 127]
16 | interesting_16_Bit = [65535, 32897, 128, 255, 256, 512, 1000, 1024, 4096, 32767]
17 | interesting_32_Bit = [4294967295, 2248146693, 2147516417, 32768, 65535, 65536, 100663045, 2147483647]
18 |
19 | random.seed(os.urandom(4))
20 |
21 | # Todo
22 | def AFL_choose_block_len(limit):
23 | min_value = 1
24 | max_value = 32
25 |
26 | if min_value >= limit:
27 | min_value = 1
28 |
29 | return min_value + RAND(MIN(max_value, limit) - min_value + 1)
30 |
31 | def MIN(value_a, value_b):
32 | if value_a > value_b:
33 | return value_b
34 | else:
35 | return value_a
36 |
37 | def reseed():
38 | random.seed(os.urandom(4))
39 |
40 | def RAND(value):
41 | if value == 0:
42 | return value
43 | return random.randint(0, value-1)
44 |
45 | def load_8(value, pos):
46 | return value[pos]
47 |
48 |
49 | def load_16(value, pos):
50 | return (value[pos] << 8) + (value[pos+1] % 0xff)
51 |
52 |
53 | def load_32(value, pos):
54 | return (value[pos] << 24) + (value[pos+1] << 16) + (value[pos+2] << 8) + (value[pos+3] % 0xff)
55 |
56 |
57 | def store_8(data, pos, value):
58 | data[pos] = in_range_8(value)
59 |
60 |
61 | def store_16(data, pos, value):
62 | value = in_range_16(value)
63 | data[pos] = (value & 0xff00) >> 8
64 | data[pos+1] = (value & 0x00ff)
65 |
66 |
67 | def store_32(data, pos, value):
68 | value = in_range_32(value)
69 | data[pos] = (value & 0xff000000) >> 24
70 | data[pos+1] = (value & 0x00ff0000) >> 16
71 | data[pos+2] = (value & 0x0000ff00) >> 8
72 | data[pos+3] = (value & 0x000000ff)
73 |
74 |
75 | def in_range_8(value):
76 | return value & 0xff
77 |
78 |
79 | def in_range_16(value):
80 | return value & 0xffff
81 |
82 |
83 | def in_range_32(value):
84 | return value & 0xffffffff
85 |
86 |
87 | def swap_16(value):
88 | return (((value & 0xff00) >> 8) +
89 | ((value & 0xff) << 8))
90 |
91 |
92 | def swap_32(value):
93 | return ((value & 0x000000ff) << 24) + \
94 | ((value & 0x0000ff00) << 8) + \
95 | ((value & 0x00ff0000) >> 8) + \
96 | ((value & 0xff000000) >> 24)
97 |
98 |
99 | def bytes_to_str_8(value):
100 | return chr((value & 0xff))
101 |
102 |
103 | def bytes_to_str_16(value):
104 | return chr((value & 0xff00) >> 8) + \
105 | chr((value & 0x00ff))
106 |
107 |
108 | def bytes_to_str_32(value):
109 | return chr((value & 0xff000000) >> 24) + \
110 | chr((value & 0x00ff0000) >> 16) + \
111 | chr((value & 0x0000ff00) >> 8) + \
112 | chr((value & 0x000000ff))
113 |
114 |
115 | def to_string_16(value):
116 | return chr((value >> 8) & 0xff) + \
117 | chr(value & 0xff)
118 |
119 |
120 | def to_string_32(value):
121 | return chr((value >> 24) & 0xff) + \
122 | chr((value >> 16) & 0xff) + \
123 | chr((value >> 8) & 0xff) + \
124 | chr(value & 0xff)
125 |
126 |
127 | def is_not_bitflip(value):
128 | return True
129 | if value == 0:
130 | return False
131 |
132 | sh = 0
133 | while (value & 1) == 0:
134 | sh += 1
135 | value >>= 1
136 |
137 | if value == 1 or value == 3 or value == 15:
138 | return False
139 |
140 | if (sh & 7) != 0:
141 | return True
142 |
143 | if value == 0xff or value == 0xffff or value == 0xffffffff:
144 | return False
145 |
146 | return True
147 |
148 |
149 | def is_not_arithmetic(value, new_value, num_bytes, set_arith_max=None):
150 | if value == new_value:
151 | return False
152 |
153 | if not set_arith_max:
154 | set_arith_max = AFL_ARITH_MAX
155 |
156 | diffs = 0
157 | ov = 0
158 | nv = 0
159 | for i in range(num_bytes):
160 | a = value >> (8 * i)
161 | b = new_value >> (8 * i)
162 | if a != b:
163 | diffs += 1
164 | ov = a
165 | nv = b
166 |
167 | if diffs == 1:
168 | if in_range_8(ov - nv) <= set_arith_max or in_range_8(nv-ov) <= set_arith_max:
169 | return False
170 |
171 | if num_bytes == 1:
172 | return True
173 |
174 | diffs = 0
175 | for i in range(num_bytes / 2):
176 | a = value >> (16 * i)
177 | b = new_value >> (16 * i)
178 |
179 | if a != b:
180 | diffs += 1
181 | ov = a
182 | nv = b
183 |
184 | if diffs == 1:
185 | if in_range_16(ov - nv) <= set_arith_max or in_range_16(nv - ov) <= set_arith_max:
186 | return False
187 |
188 | ov = swap_16(ov)
189 | nv = swap_16(nv)
190 |
191 | if in_range_16(ov - nv) <= set_arith_max or in_range_16(nv - ov) <= set_arith_max:
192 | return False
193 |
194 | if num_bytes == 4:
195 | if in_range_32(value - new_value) <= set_arith_max or in_range_32(new_value - value) <= set_arith_max:
196 | return False
197 |
198 | value = swap_32(value)
199 | new_value = swap_32(new_value)
200 |
201 | if in_range_32(value - new_value) <= set_arith_max or in_range_32(new_value - value) <= set_arith_max:
202 | return False
203 |
204 | return True
205 |
206 |
207 | def is_not_interesting(value, new_value, num_bytes, le):
208 | if value == new_value:
209 | return False
210 |
211 | for i in range(num_bytes):
212 | for j in range(len(interesting_8_Bit)):
213 | tval = (value & ~(0xff << (i * 8))) | (interesting_8_Bit[j] << (i * 8))
214 | if new_value == tval:
215 | return False
216 |
217 | if num_bytes == 2 and not le:
218 | return True
219 |
220 | for i in range(num_bytes - 1):
221 | for j in range(len(interesting_16_Bit)):
222 | tval = (value & ~(0xffff << (i * 8)) | (interesting_16_Bit[j] << (i * 8)))
223 | #print(" -> " + str(value) + " - " + str(new_value) + " - " + str(tval))
224 | if new_value == tval:
225 | return False
226 |
227 | #if num_bytes > 2:
228 | tval = (value & ~(0xffff << (i * 8))) | (swap_16(interesting_16_Bit[j]) << (i * 8));
229 | if new_value == tval:
230 | return False
231 |
232 | if num_bytes == 4 and le:
233 | for j in range(len(interesting_32_Bit)):
234 | if new_value == interesting_32_Bit[j]:
235 | return False
236 |
237 | return True
238 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/fuzzer/technique/interesting_values.py:
--------------------------------------------------------------------------------
1 | from fuzzer.technique.helper import *
2 | from array import array
3 | __author__ = 'sergej'
4 |
5 |
6 | def interesting_range(data, skip_null=False, effector_map=None):
7 |
8 | if effector_map:
9 | data_len = sum(x is True for x in effector_map)
10 | data_tmp = ""
11 | for i in range(len(data)):
12 | if effector_map[i]:
13 | data_tmp += data[i]
14 | else:
15 | data_len = len(data)
16 | data_tmp = data
17 | if skip_null:
18 | num_of_non_null_bytes = data_len - data_tmp.count('\x00')
19 | num = num_of_non_null_bytes * len(interesting_8_Bit)
20 | num += ((num_of_non_null_bytes-1) * (len(interesting_16_Bit)))*2
21 | num += ((num_of_non_null_bytes-3) * (len(interesting_32_Bit)))*2
22 | else:
23 | num = data_len * len(interesting_8_Bit)
24 | if data_len > 1:
25 | num += ((data_len-1) * (len(interesting_16_Bit)))*2
26 | if data_len > 3:
27 | num += ((data_len-3) * (len(interesting_32_Bit)))*2
28 | if num < 0:
29 | return 0
30 |
31 | return num
32 |
33 |
34 | def mutate_seq_8_bit_interesting_array(data, func, skip_null=False, kafl_state=None, effector_map=None):
35 | if kafl_state:
36 | kafl_state.technique = "INTERST 8"
37 |
38 | for i in range(0, len(data)):
39 | if effector_map:
40 | if not effector_map[i]:
41 | continue
42 | byte = data[i]
43 | for j in range(len(interesting_8_Bit)):
44 | if skip_null and byte == 0:
45 | continue
46 | interesting_value = in_range_8(interesting_8_Bit[j])
47 | if is_not_bitflip(byte ^ interesting_value):
48 | func(data[:i].tostring() + bytes_to_str_8(interesting_value) + data[(i+1):].tostring())
49 | else:
50 | func(None, no_data=True)
51 | data[i] = byte
52 |
53 | def mutate_seq_16_bit_interesting_array(data, func, skip_null=False, kafl_state=None, effector_map=None, set_arith_max=None):
54 | if kafl_state:
55 | kafl_state.technique = "INTERST 16"
56 |
57 | for i in range(len(data) - 1):
58 | if effector_map:
59 | if not effector_map[i] or not effector_map[i+1]:
60 | continue
61 |
62 | byte1 = data[i]
63 | byte2 = data[i + 1]
64 | value = (byte1 << 8) + byte2
65 |
66 | for j in range(len(interesting_16_Bit)):
67 | if skip_null and value == 0:
68 | continue
69 | interesting_value = in_range_16(interesting_16_Bit[j])
70 | swapped_value = swap_16(interesting_value)
71 |
72 | if is_not_bitflip(value ^ interesting_value) and is_not_arithmetic(value, interesting_value, 2, set_arith_max=set_arith_max) and is_not_interesting(value, interesting_value, 2, False):
73 | func(data[:i].tostring() + bytes_to_str_16(interesting_value) + data[(i + 2):].tostring())
74 | else:
75 | func(None, no_data=True)
76 |
77 | if interesting_value != swapped_value and is_not_bitflip(value ^ swapped_value) and is_not_arithmetic(value, swapped_value, 2, set_arith_max=set_arith_max) and is_not_interesting(value, swapped_value, 2, False):
78 | func(data[:i].tostring() + bytes_to_str_16(swapped_value) + data[(i+2):].tostring())
79 | else:
80 | func(None, no_data=True)
81 | data[i] = byte1
82 | data[i + 1] = byte2
83 |
84 | def mutate_seq_32_bit_interesting_array(data, func, skip_null=False, kafl_state=None, effector_map=None, set_arith_max=None):
85 | if kafl_state:
86 | kafl_state.technique = "INTERST 32"
87 |
88 | for i in range(len(data) - 3):
89 | if effector_map:
90 | if not effector_map[i] or not effector_map[i + 1] or not effector_map[i + 2] or not effector_map[i + 3]:
91 | continue
92 | byte1 = data[i]
93 | byte2 = data[i + 1]
94 | byte3 = data[i + 2]
95 | byte4 = data[i + 3]
96 | value = (byte1 << 24) + (byte2 << 16) + (byte3 << 8) + byte4
97 | for j in range(len(interesting_32_Bit)):
98 | if skip_null and value == 0:
99 | continue
100 | interesting_value = in_range_32(interesting_32_Bit[j])
101 | swapped_value = swap_32(interesting_value)
102 | if is_not_bitflip(value ^ interesting_value) and is_not_arithmetic(value, interesting_value, 4, set_arith_max=set_arith_max) and is_not_interesting(value, interesting_value, 4, False):
103 | func(data[:i].tostring() + bytes_to_str_32(interesting_value) + data[(i+4):].tostring())
104 | else:
105 | func(None, no_data=True)
106 |
107 | if interesting_value != swapped_value and is_not_bitflip(value ^ swapped_value) and is_not_arithmetic(value, swapped_value, 4, set_arith_max=set_arith_max) and is_not_interesting(value, swapped_value, 4, True):
108 | func(data[:i].tostring() + bytes_to_str_32(swapped_value) + data[(i+4):].tostring())
109 | else:
110 | func(None, no_data=True)
111 | data[i] = byte1
112 | data[i + 1] = byte2
113 | data[i + 2] = byte3
114 | data[i + 3] = byte4
115 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/help.txt:
--------------------------------------------------------------------------------
1 | __ __ ___ ________
2 | / /_____ _________ ___ / / / | / ____/ /
3 | / //_/ _ \/ ___/ __ \/ _ \/ / / /| | / /_ / /
4 | / ,< / __/ / / / / / __/ / / ___ |/ __/ / /___
5 | /_/|_|\___/_/ /_/ /_/\___/_/ /_/ |_/_/ /_____/
6 | ===================================================
7 |
8 | kernel AFL: A feedback-driven general purpose ring-0 interface fuzzer for x86-64 operating systems.
9 |
10 | Sergej Schumilo
11 | Cornelius Aschermann
12 | Robert Gawlik
13 |
14 | Version: 0.1
15 |
16 | (C) 2017
17 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/info/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/info/core.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import time
21 | import os
22 | from common.config import InfoConfiguration
23 | from common.qemu import qemu
24 | from common.debug import log_info, enable_logging
25 | from common.self_check import post_self_check
26 |
27 | __author__ = 'Sergej Schumilo'
28 |
29 | def start():
30 | config = InfoConfiguration()
31 |
32 | if not post_self_check(config):
33 | return -1
34 |
35 | if config.argument_values['v']:
36 | enable_logging()
37 |
38 | log_info("Dumping kernel addresses...")
39 | if os.path.exists("/tmp/kAFL_info.txt"):
40 | os.remove("/tmp/kAFL_info.txt")
41 | q = qemu(0, config)
42 | q.start()
43 | q.__del__()
44 | try:
45 | for line in open("/tmp/kAFL_info.txt"):
46 | print line,
47 | os.remove("/tmp/kAFL_info.txt")
48 | except:
49 | pass
50 | return 0
51 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/kafl.ini:
--------------------------------------------------------------------------------
1 | [Fuzzer]
2 | UI_REFRESH_RATE: 0.15
3 | MASTER_SHM_PREFIX: kafl_master_
4 | MAPSERV_SHM_PREFIX: kafl_mapserver_
5 | BITMAP_SHM_PREFIX: kafl_bitmap_
6 | PAYLOAD_SHM_SIZE: 66560
7 | BITMAP_SHM_SIZE: 65536
8 | #BITMAP_SHM_SIZE: 32768
9 | #BITMAP_SHM_SIZE: 131072
10 | #BITMAP_SHM_SIZE: 262144
11 | QEMU_KAFL_LOCATION: qemu/x86_64-softmmu/qemu-system-x86_64
12 | FINDING_RINGBUF_SIZE: 50
13 | ABORTION_TRESHOLD: 5
14 | TIMEOUT_TICK_FACTOR: 5.0
15 | ARITHMETIC_MAX: 35
16 | APPLE-SMC-OSK: ""
17 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/kafl_fuzz.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Copyright (C) 2017 Sergej Schumilo
5 |
6 | This file is part of kAFL Fuzzer (kAFL).
7 |
8 | QEMU-PT is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 2 of the License, or
11 | (at your option) any later version.
12 |
13 | QEMU-PT is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with QEMU-PT. If not, see .
20 | """
21 |
22 | import sys
23 | from common.self_check import self_check
24 |
25 | __author__ = 'sergej'
26 |
27 |
28 | def main():
29 | f = open("help.txt")
30 | for line in f:
31 | print(line.replace("\n", ""))
32 | f.close()
33 |
34 | print("<< " + '\033[1m' + '\033[92m' + sys.argv[0] + ": Kernel Fuzzer " + '\033[0m' + ">>\n")
35 |
36 | if not self_check():
37 | return 1
38 |
39 | from fuzzer.core import start
40 | return start()
41 |
42 |
43 | if __name__ == "__main__":
44 | main()
45 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/kafl_info.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Copyright (C) 2017 Sergej Schumilo
5 |
6 | This file is part of kAFL Fuzzer (kAFL).
7 |
8 | QEMU-PT is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 2 of the License, or
11 | (at your option) any later version.
12 |
13 | QEMU-PT is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with QEMU-PT. If not, see .
20 | """
21 |
22 | import sys
23 | from common.self_check import self_check
24 |
25 | __author__ = 'sergej'
26 |
27 | def main():
28 | f = open("help.txt")
29 | for line in f:
30 | print(line.replace("\n", ""))
31 | f.close()
32 |
33 | print("<< " + '\033[1m' + '\033[92m' + sys.argv[0] + ": Kernel Address Dumper " + '\033[0m' + ">>\n")
34 |
35 | if not self_check():
36 | return 1
37 |
38 | from info.core import start
39 | return start()
40 |
41 |
42 | if __name__ == "__main__":
43 | main()
44 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/run_test.sh:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017 Sergej Schumilo
2 | #
3 | # This file is part of kAFL Fuzzer (kAFL).
4 | #
5 | # QEMU-PT is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation, either version 2 of the License, or
8 | # (at your option) any later version.
9 | #
10 | # QEMU-PT is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with QEMU-PT. If not, see .
17 |
18 |
19 | trial -e test.py
20 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/ext4/ext4.img:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/ext4/ext4.img
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/fat/fat_a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/fat/fat_a
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/fat/fat_b:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/fat/fat_b
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/fat/fat_c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/fat/fat_c
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/fat/fat_d:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/fat/fat_d
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/fat/fat_e:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/fat/fat_e
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/kafl_vulntest/seed_file:
--------------------------------------------------------------------------------
1 | AAAAAAAAAAAAAAAAAAAAA
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/ntfs/ntfs64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/ntfs/ntfs64
--------------------------------------------------------------------------------
/kAFL-Fuzzer/seed/ntfs_win/ntfs_header_64k:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RUB-SysSec/kAFL/1ece095a7a835887477393b2bba88247b1536d4f/kAFL-Fuzzer/seed/ntfs_win/ntfs_header_64k
--------------------------------------------------------------------------------
/kAFL-Fuzzer/test.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import unittest
21 | from testing.deterministic_techniques import *
22 | from testing.deterministic_input_generation import *
23 | from testing.queue import *
24 |
25 | if __name__ == '__main__':
26 | unittest.main()
27 |
28 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/testing/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'sergej'
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/testing/queue.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2017 Sergej Schumilo
3 |
4 | This file is part of kAFL Fuzzer (kAFL).
5 |
6 | QEMU-PT is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | QEMU-PT is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with QEMU-PT. If not, see .
18 | """
19 |
20 | import unittest, os
21 | from common.config import FuzzerConfiguration
22 | from fuzzer.tree import KaflTree
23 | from common.util import prepare_working_dir
24 | import time
25 |
26 | from subprocess import Popen
27 |
28 |
29 | class QueueTest(unittest.TestCase):
30 |
31 | def test_simple(self):
32 | args = dict()
33 | args['ram_file'] = "/tmp/kafl_unittest_ram_file"
34 | args['overlay_dir'] = "/tmp/kafl_unittest_overlay_dir/"
35 | args['executable'] = "/tmp/kafl_unittest_exec_file"
36 | args['work_dir'] = "/tmp/kafl_unittest_work_dir/"
37 | args['mem'] = 300
38 | args['ip_filter'] = (0x0000,0xffff)
39 | FuzzerConfiguration(emulated_arguments=args)
40 |
41 | if not os.path.isdir(args['work_dir']):
42 | os.makedirs(args['work_dir'])
43 | prepare_working_dir(args['work_dir'], purge=True)
44 |
45 | seed = \
46 | [ \
47 | ["ABC", [chr(0), chr(1), chr(1)]], \
48 | ["DEF", [chr(0), chr(1), chr(0)]] \
49 | ]
50 |
51 | kt = KaflTree(seed, enable_graphviz=True)
52 | kt.draw()
53 | p = Popen("xdot /tmp/kafl_unittest_work_dir/graph.dot".split(" "))
54 | time.sleep(2)
55 | for i in range(10):
56 | print(kt.get_next(100))
57 | kt.draw()
58 | time.sleep(1)
59 | p.terminate()
60 | self.assertTrue(True)
61 |
62 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/json/linux_x86-64/Makefile:
--------------------------------------------------------------------------------
1 | obj-m += kafl_vuln_test_json.o
2 |
3 | all:
4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5 |
6 | clean:
7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
8 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/json/macOS_x86-64/compile.sh:
--------------------------------------------------------------------------------
1 | xcodebuild -project vuln.xcodeproj
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/json/macOS_x86-64/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | schumilo.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | KEXT
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | OSBundleLibraries
24 |
25 | com.apple.kpi.bsd
26 | 10.0
27 | com.apple.kpi.libkern
28 | 10.0
29 | com.apple.kpi.unsupported
30 | 10.0
31 |
32 |
33 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/json/macOS_x86-64/load.sh:
--------------------------------------------------------------------------------
1 | sudo chown -R root:wheel build/Release/vuln.kext
2 | sudo kextutil build/Release/vuln.kext
3 | sudo chown -R `id -un`:`id -gn` build/Release/vuln.kext
4 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/linux_x86-64/Makefile:
--------------------------------------------------------------------------------
1 | obj-m += kafl_vuln_test.o
2 |
3 | all:
4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5 |
6 | clean:
7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/linux_x86-64/kafl_vuln_test.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | MODULE_LICENSE("GPL");
11 | MODULE_AUTHOR("Sergej Schumilo");
12 | MODULE_DESCRIPTION("kAFL Test Module");
13 |
14 | #define MAX_LEN 128
15 | #define NAME "kafl_vuln"
16 |
17 | ssize_t write_info(struct file *filp, const char __user *buff, size_t len, loff_t *data);
18 |
19 | struct proc_dir_entry *proc_file_entry;
20 |
21 | static const struct file_operations proc_file_fops = {
22 | .owner = THIS_MODULE,
23 | .write = write_info,
24 | };
25 |
26 | int init_mod( void )
27 | {
28 | proc_file_entry = proc_create(NAME, 0666, NULL, &proc_file_fops);
29 | if(proc_file_entry == NULL)
30 | return -ENOMEM;
31 | return 0;
32 | }
33 |
34 | void cleanup_mod( void )
35 | {
36 | remove_proc_entry(NAME, NULL);
37 | printk(KERN_INFO "/proc/%s removed.\n", NAME);
38 | }
39 |
40 | module_init(init_mod);
41 | module_exit(cleanup_mod);
42 |
43 | ssize_t write_info(struct file *filp, const char __user *buff, size_t len, loff_t *data) {
44 | char input[256];
45 | int *array = (int *)kmalloc(1332, GFP_KERNEL);
46 |
47 | if (len >= 256){
48 | return -EFAULT;
49 | }
50 |
51 | if (copy_from_user(input, buff, len)) {
52 | return -EFAULT;
53 | }
54 |
55 | if(input[0] == 'K')
56 | if(input[1] == 'E')
57 | if(input[2] == 'R')
58 | if(input[3] == 'N')
59 | if(input[4] == 'E')
60 | if(input[5] == 'L')
61 | if(input[6] == 'A')
62 | if(input[7] == 'F')
63 | if(input[8] == 'L')
64 | panic(KERN_INFO "KAFL...\n"); /* boom! bug incoming... */
65 | if(input[0] == 'S')
66 | if(input[1] == 'E')
67 | if(input[2] == 'R')
68 | if(input[3] == 'G')
69 | if(input[4] == 'E')
70 | if(input[5] == 'J')
71 | panic(KERN_INFO "SERGEJ...\n");
72 |
73 | if(input[0] == 'K'){
74 | if(input[1] == 'A'){
75 | if(input[2] == 'S'){
76 | if(input[3] == 'A'){
77 | if(input[4] == 'N'){
78 | kfree(array);
79 | array[0] = 1234;
80 | }
81 | }
82 | }
83 | }
84 | }
85 | kfree(array);
86 | return len;
87 |
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/linux_x86-64/load.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [[ $UID != 0 ]]; then
3 | echo "Please run this script as root!"
4 | exit 1
5 | else
6 | make
7 | insmod kafl_vuln_test.ko
8 | echo "done"
9 | exit 0
10 | fi
11 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/macOS_x86-64/compile.sh:
--------------------------------------------------------------------------------
1 | xcodebuild -project vuln.xcodeproj
2 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/macOS_x86-64/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | schumilo.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | KEXT
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | OSBundleLibraries
24 |
25 | com.apple.kpi.bsd
26 | 10.0
27 | com.apple.kpi.libkern
28 | 10.0
29 | com.apple.kpi.unsupported
30 | 10.0
31 |
32 |
33 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/macOS_x86-64/load.sh:
--------------------------------------------------------------------------------
1 | sudo chown -R root:wheel build/Release/vuln.kext
2 | sudo kextutil build/Release/vuln.kext
3 | sudo chown -R `id -un`:`id -gn` build/Release/vuln.kext
4 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/macOS_x86-64/vuln.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | #define BUFFERSIZE 255
12 | #define PANIC *((char*)(0x0)) = '0'
13 |
14 | static const char *device_name = "vuln";
15 | static int device_major;
16 | static void *device_handle;
17 |
18 | kern_return_t vuln_start(kmod_info_t *ki, void *d);
19 | kern_return_t vuln_stop(kmod_info_t *ki, void *d);
20 | static int vuln_open(dev_t dev, int flags, int type, struct proc *p);
21 | static int vuln_close(dev_t dev, int flags, int type, struct proc *p);
22 | static int vuln_write(dev_t dev, uio_t uio, int flags);
23 |
24 | static int vuln_open(dev_t dev, int flags, int type, struct proc *p)
25 | {
26 | return KERN_SUCCESS;
27 | }
28 |
29 | static int vuln_close(dev_t dev, int flags, int type, struct proc *p)
30 | {
31 | return KERN_SUCCESS;
32 | }
33 |
34 | static int vuln_write(dev_t dev, uio_t uio, int flags){
35 |
36 | char buffer[BUFFERSIZE+1];
37 | user_addr_t ioaddr = uio_curriovbase(uio);
38 | user_size_t iosize = uio_curriovlen(uio);
39 |
40 | //printf("KERNEL DRIVER!!!!!\n");
41 |
42 | if(iosize >= BUFFERSIZE){
43 | //printf("truncating input...\n");
44 | iosize = BUFFERSIZE;
45 | }
46 |
47 | if(copyin(ioaddr, buffer, iosize)){
48 | //printf("copyin failed!\n");
49 | return -1;
50 | }
51 |
52 | if(buffer[0] == 'K'){
53 | if(buffer[1] == 'E'){
54 | if(buffer[2] == 'R'){
55 | if(buffer[3] == 'N'){
56 | if(buffer[4] == 'E'){
57 | if(buffer[5] == 'L'){
58 | if(buffer[6] == 'A'){
59 | if(buffer[7] == 'F'){
60 | if(buffer[8] == 'L'){
61 | PANIC;
62 | }}}}}}}}}
63 |
64 | if(buffer[0] == 'm'){
65 | if(buffer[1] == 'a'){
66 | if(buffer[2] == 'c'){
67 | if(buffer[3] == 'O'){
68 | if(buffer[4] == 'S'){
69 | if(buffer[5] == '!'){
70 | PANIC;
71 | }}}}}}
72 |
73 | //printf("It works! \n");
74 | return 0;
75 | }
76 |
77 | static struct cdevsw device_fops = {
78 | .d_open = vuln_open,
79 | .d_close = vuln_close,
80 | .d_write = vuln_write,
81 | };
82 |
83 | kern_return_t vuln_start(kmod_info_t *ki, void *d)
84 | {
85 | device_major = cdevsw_add(-1, &device_fops);
86 | if (device_major < 0) {
87 | printf("cdevsw_add failed\n");
88 | return KERN_FAILURE;
89 | }
90 | device_handle = devfs_make_node(makedev(device_major, 0), DEVFS_CHAR, 0, 0, 0660, "%s", device_name);
91 | if (device_handle == NULL) {
92 | printf("devfs_make_node failed\n");
93 | return KERN_FAILURE;
94 | }
95 | return KERN_SUCCESS;
96 | }
97 |
98 | kern_return_t vuln_stop(kmod_info_t *ki, void *d)
99 | {
100 | devfs_remove(device_handle);
101 | cdevsw_remove(device_major, &device_fops);
102 | return KERN_SUCCESS;
103 | }
104 |
--------------------------------------------------------------------------------
/kAFL-Fuzzer/vuln_drivers/simple/win10_x86-64/Driver.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define DEVICE_NAME L"\\Device\\testKafl"
4 | #define DOS_DEVICE_NAME L"\\DosDevices\\testKafl"
5 | #define IOCTL_KAFL_INPUT (ULONG) CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
6 |
7 | NTSTATUS crashMe(IN PIO_STACK_LOCATION IrpStack){
8 | SIZE_T size = 0;
9 | PCHAR userBuffer = NULL;
10 |
11 | userBuffer = IrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
12 | size = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
13 |
14 | if (size < 0xe){
15 | return STATUS_SUCCESS;
16 | }
17 |
18 | if (userBuffer[0] == 'P'){
19 | if (userBuffer[1] == 'w'){
20 | if (userBuffer[2] == 'n'){
21 | if (userBuffer[3] == 'T'){
22 | if (userBuffer[4] == 'o'){
23 | if (userBuffer[5] == 'w'){
24 | if (userBuffer[6] == 'n'){
25 | DbgPrint("[+] KAFL vuln drv -- SETEIP");
26 | /* hell yeah */
27 | ((VOID(*)())0x0)();
28 | }
29 | }
30 | }
31 | }
32 | }
33 | }
34 | }
35 |
36 | if (userBuffer[0] == 'w'){
37 | DbgPrint("[+] KAFL vuln drv -- ONE");
38 | if (userBuffer[1] == '0'){
39 | DbgPrint("[+] KAFL vuln drv -- TWO");
40 | if (userBuffer[2] == '0'){
41 | DbgPrint("[+] KAFL vuln drv -- THREE");
42 | if (userBuffer[3] == 't'){
43 | DbgPrint("[+] KAFL vuln drv -- CRASH");
44 | size = *((PSIZE_T)(0x0));
45 | }
46 | }
47 | }
48 | }
49 |
50 | return STATUS_SUCCESS;
51 | }
52 |
53 |
54 | NTSTATUS handleIrp(IN PDEVICE_OBJECT DeviceObj, IN PIRP pIrp){
55 | PIO_STACK_LOCATION irpStack = 0;
56 | ULONG ioctl;
57 |
58 | irpStack = IoGetCurrentIrpStackLocation(pIrp);
59 |
60 | pIrp->IoStatus.Information = 0;
61 | pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
62 |
63 | UNREFERENCED_PARAMETER(DeviceObj);
64 | PAGED_CODE();
65 |
66 | switch(irpStack->MajorFunction){
67 | case IRP_MJ_DEVICE_CONTROL:
68 | ioctl = irpStack->Parameters.DeviceIoControl.IoControlCode;
69 | switch(ioctl){
70 | case IOCTL_KAFL_INPUT:
71 | DbgPrint("[+] KAFL vuln drv -- crash attempt\n");
72 | pIrp->IoStatus.Status = crashMe(irpStack);
73 | break;
74 | default:
75 | pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
76 | break;
77 | }
78 | break;
79 | case IRP_MJ_CREATE:
80 | case IRP_MJ_CLOSE:
81 | pIrp->IoStatus.Status = STATUS_SUCCESS;
82 | break;
83 | };
84 |
85 | IoCompleteRequest(pIrp, IO_NO_INCREMENT);
86 | return pIrp->IoStatus.Status;
87 | }
88 |
89 |
90 | void DriverUnload(PDRIVER_OBJECT pDriverObject){
91 | UNICODE_STRING dosDeviceName = { 0 };
92 | RtlInitUnicodeString(&dosDeviceName, DOS_DEVICE_NAME);
93 | IoDeleteSymbolicLink(&dosDeviceName);
94 | IoDeleteDevice(pDriverObject->DeviceObject);
95 | DbgPrint("[+] KAFL vuln drv -- unloaded");
96 | }
97 |
98 |
99 | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObj, IN PUNICODE_STRING RegPath){
100 | UINT32 i = 0;
101 | NTSTATUS ntstatus;
102 | PDEVICE_OBJECT deviceObject = NULL;
103 | UNICODE_STRING deviceName, dosDeviceName = { 0 };
104 |
105 | UNREFERENCED_PARAMETER(RegPath);
106 | PAGED_CODE();
107 |
108 | RtlInitUnicodeString(&deviceName, DEVICE_NAME);
109 | RtlInitUnicodeString(&dosDeviceName, DOS_DEVICE_NAME);
110 |
111 | ntstatus = IoCreateDevice(DriverObj, 0, &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);
112 | if(!NT_SUCCESS(ntstatus)){
113 | DbgPrint("[-] KAFL vuln drv -- IoCreateDevice failed: 0x%X\n", ntstatus);
114 | IoDeleteDevice(DriverObj->DeviceObject);
115 | return ntstatus;
116 | }
117 |
118 | for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++){
119 | DriverObj->MajorFunction[i] = handleIrp;
120 | }
121 |
122 | DriverObj->DriverUnload = DriverUnload;
123 | deviceObject->Flags |= DO_DIRECT_IO;
124 | deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
125 | ntstatus = IoCreateSymbolicLink(&dosDeviceName, &deviceName);
126 |
127 | DbgPrint("[+] KAFL vuln drv -- loaded");
128 | return ntstatus;
129 | }
130 |
131 |
--------------------------------------------------------------------------------