Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | |
Nguyen Anh Quynh | 5feee40 | 2014-03-04 12:26:51 +0800 | [diff] [blame] | 3 | # Simple fuzzing tool by disassembling random code. By Nguyen Anh Quynh, 2014 |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 4 | # Syntax: |
Nguyen Anh Quynh | 5feee40 | 2014-03-04 12:26:51 +0800 | [diff] [blame] | 5 | # ./suite/fuzz.py --> Fuzz all archs |
| 6 | # ./suite/fuzz.py x86 --> Fuzz all X86 (all 16bit, 32bit, 64bit) |
| 7 | # ./suite/fuzz.py x86-16 --> Fuzz X86-32 arch only |
| 8 | # ./suite/fuzz.py x86-32 --> Fuzz X86-32 arch only |
| 9 | # ./suite/fuzz.py x86-64 --> Fuzz X86-64 arch only |
| 10 | # ./suite/fuzz.py arm --> Fuzz all ARM (arm, thumb) |
| 11 | # ./suite/fuzz.py aarch64 --> Fuzz ARM-64 |
| 12 | # ./suite/fuzz.py mips --> Fuzz all Mips (32bit, 64bit) |
| 13 | # ./suite/fuzz.py ppc --> Fuzz PPC |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 14 | |
| 15 | from capstone import * |
| 16 | |
| 17 | from time import time |
| 18 | from random import randint |
| 19 | import sys |
| 20 | |
| 21 | |
| 22 | # file providing code to disassemble |
| 23 | FILE = '/usr/bin/python' |
| 24 | |
| 25 | TIMES = 64 |
Nguyen Anh Quynh | d9ee9b1 | 2014-03-04 15:32:28 +0800 | [diff] [blame] | 26 | INTERVALS = (4, 5, 7, 9, 11, 13) |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 27 | |
| 28 | all_tests = ( |
| 29 | (CS_ARCH_X86, CS_MODE_16, "X86-16bit (Intel syntax)", 0), |
| 30 | (CS_ARCH_X86, CS_MODE_16, "X86-16bit (ATT syntax)", CS_OPT_SYNTAX_ATT), |
| 31 | (CS_ARCH_X86, CS_MODE_32, "X86-32 (Intel syntax)", 0), |
| 32 | (CS_ARCH_X86, CS_MODE_32, "X86-32 (ATT syntax)", CS_OPT_SYNTAX_ATT), |
| 33 | (CS_ARCH_X86, CS_MODE_64, "X86-64 (Intel syntax)", 0), |
Nguyen Anh Quynh | 0586a74 | 2014-03-04 16:27:23 +0800 | [diff] [blame] | 34 | (CS_ARCH_X86, CS_MODE_64, "X86-64 (ATT syntax)", CS_OPT_SYNTAX_ATT), |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 35 | (CS_ARCH_ARM, CS_MODE_ARM, "ARM", 0), |
| 36 | (CS_ARCH_ARM, CS_MODE_THUMB, "THUMB (ARM)", 0), |
| 37 | (CS_ARCH_MIPS, CS_MODE_32 + CS_MODE_BIG_ENDIAN, "MIPS-32 (Big-endian)", 0), |
| 38 | (CS_ARCH_MIPS, CS_MODE_64 + CS_MODE_LITTLE_ENDIAN, "MIPS-64-EL (Little-endian)", 0), |
| 39 | (CS_ARCH_ARM64, CS_MODE_ARM, "ARM-64 (AArch64)", 0), |
| 40 | (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, "PPC", 0), |
| 41 | (CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, "PPC, print register with number only", CS_OPT_SYNTAX_NOREGNAME), |
Nguyen Anh Quynh | 61b7a72 | 2014-03-10 15:44:48 +0800 | [diff] [blame] | 42 | (CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, "Sparc", 0), |
Nguyen Anh Quynh | 61aaabb | 2014-03-23 22:56:38 +0800 | [diff] [blame] | 43 | (CS_ARCH_SYSZ, 0, "SystemZ", 0), |
Nguyen Anh Quynh | 7ae389e | 2014-06-17 18:17:59 +0800 | [diff] [blame] | 44 | (CS_ARCH_XCORE, 0, "XCore", 0), |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 45 | ) |
| 46 | |
| 47 | |
| 48 | # for debugging |
| 49 | def to_hex(s): |
| 50 | return " ".join("0x" + "{0:x}".format(ord(c)).zfill(2) for c in s) # <-- Python 3 is OK |
| 51 | |
Nguyen Anh Quynh | 3a61483 | 2014-03-04 12:41:01 +0800 | [diff] [blame] | 52 | |
| 53 | # read @size bytes from @f & return data. |
| 54 | # return None when there is not enough data |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 55 | def get_code(f, size): |
| 56 | code = f.read(size) |
| 57 | if len(code) != size: # reached end-of-file? |
| 58 | # then reset file position to begin-of-file |
| 59 | f.seek(0) |
| 60 | return None |
| 61 | |
| 62 | return code |
| 63 | |
| 64 | |
| 65 | def cs(md, code): |
| 66 | insns = md.disasm(code, 0) |
| 67 | for i in insns: |
| 68 | if i.address == 0x100000: |
| 69 | print i |
| 70 | |
| 71 | |
| 72 | def cs_lite(md, code): |
| 73 | insns = md.disasm_lite(code, 0) |
| 74 | for (addr, size, mnem, ops) in insns: |
| 75 | if addr == 0x100000: |
| 76 | print i |
| 77 | |
| 78 | |
| 79 | cfile = open(FILE) |
| 80 | |
| 81 | for (arch, mode, comment, syntax) in all_tests: |
| 82 | try: |
| 83 | request = sys.argv[1] |
| 84 | if not request in comment.lower(): |
| 85 | continue |
| 86 | except: |
| 87 | pass |
| 88 | |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 89 | try: |
| 90 | md = Cs(arch, mode) |
| 91 | md.detail = True |
| 92 | |
| 93 | if syntax != 0: |
| 94 | md.syntax = syntax |
| 95 | |
| 96 | # test disasm() |
Nguyen Anh Quynh | d9ee9b1 | 2014-03-04 15:32:28 +0800 | [diff] [blame] | 97 | print("\nFuzzing disasm() @platform: %s" %comment) |
| 98 | for ii in INTERVALS: |
| 99 | print("Interval: %u" %ii) |
| 100 | for j in xrange(1, TIMES): |
| 101 | while (True): |
| 102 | code = get_code(cfile, j * ii) |
| 103 | if code is None: |
| 104 | # EOF? break |
| 105 | break |
| 106 | #print to_hex(code) |
| 107 | cs(md, code) |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 108 | |
| 109 | # test disasm_lite() |
Nguyen Anh Quynh | 1cf70fe | 2014-03-04 14:23:41 +0800 | [diff] [blame] | 110 | print("Fuzzing disasm_lite() @platform: %s" %comment) |
Nguyen Anh Quynh | d9ee9b1 | 2014-03-04 15:32:28 +0800 | [diff] [blame] | 111 | for ii in INTERVALS: |
| 112 | print("Interval: %u" %ii) |
| 113 | for j in xrange(1, TIMES): |
| 114 | while (True): |
| 115 | code = get_code(cfile, j * ii) |
| 116 | if code is None: |
| 117 | # EOF? break |
| 118 | break |
| 119 | #print to_hex(code) |
| 120 | cs_lite(md, code) |
Nguyen Anh Quynh | 301e831 | 2014-03-04 12:20:25 +0800 | [diff] [blame] | 121 | |
| 122 | except CsError as e: |
| 123 | print("ERROR: %s" %e) |