├── 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 | --------------------------------------------------------------------------------