NCPrePatcher 0.2.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/ncpp/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
2
  module NCPP
3
- VERSION = '0.2.0'
3
+ VERSION = '0.3.2'
4
4
  end
data/lib/ncpp.rb CHANGED
@@ -1,6 +1,8 @@
1
- require_relative 'nitro/nitro.rb'
2
- require_relative 'unarm/unarm.rb'
3
- require_relative 'ncpp/interpreter.rb'
1
+ require_relative 'nitro/nitro'
2
+ require_relative 'unarm/unarm'
3
+ require_relative 'unicorn/unicorn'
4
+ require_relative 'keystone/keystone'
5
+ require_relative 'ncpp/interpreter'
4
6
 
5
7
  require 'json'
6
8
  require 'optparse'
@@ -15,6 +17,10 @@ module NCPP
15
17
 
16
18
  alias $rom $clean_rom # In most cases the clean rom will be desired
17
19
 
20
+ $emu = nil
21
+ $arm_assembler = nil
22
+ $thumb_assembler = nil
23
+
18
24
  $config = nil
19
25
 
20
26
  NCP_CONFIG_FILE_PATH = 'ncpatcher.json'
@@ -141,6 +147,11 @@ module NCPP
141
147
 
142
148
  Unarm.load_symbols9(cfg['symbols9'].gsub(/\$\{env:([^}]+)\}/) { ENV[$1] }) unless cfg['symbols9'].empty?
143
149
  Unarm.load_symbols7(cfg['symbols7'].gsub(/\$\{env:([^}]+)\}/) { ENV[$1] }) unless cfg['symbols7'].empty?
150
+
151
+ $emu = Uc::Emu.new
152
+ $emu.load_arm9
153
+ $arm_assembler = Ks::Assembler.new
154
+ $thumb_assembler = Ks::Assembler.new(mode: Ks::KS_MODE_THUMB)
144
155
  end
145
156
 
146
157
  def self.uninstall(cfg_path = CONFIG_FILE_PATH)
@@ -426,20 +437,6 @@ module NCPP
426
437
  end
427
438
  end
428
439
 
429
- # interpreter = CFileInterpreter.new(
430
- # files, $config['gen_path'], $config['command_prefix'], extra_commands, extra_variables,
431
- # safe: safe_mode, puritan: puritan_mode
432
- # )
433
- # interpreter.run(verbose: !quiet)
434
- # lines_parsed += interpreter.lines_parsed
435
-
436
- # unless interpreter.incomplete_files.empty?
437
- # interpreter.incomplete_files.each do |file|
438
- # timestamp_cache.delete(file)
439
- # success = false
440
- # end
441
- # end
442
-
443
440
  end
444
441
 
445
442
  timestamp_cache['NCPP_VERSION'] = VERSION
@@ -447,9 +444,6 @@ module NCPP
447
444
  FileUtils.mkdir_p(File.dirname(timestamp_cache_path))
448
445
  File.write(timestamp_cache_path, JSON.generate(timestamp_cache))
449
446
 
450
- # FileUtils.mkdir_p(File.dirname(cmd_cache_path))
451
- # File.write(cmd_cache_path, JSON.generate(command_cache))
452
-
453
447
  unless quiet
454
448
  if lines_parsed > 0
455
449
  msg = "\nParsed #{lines_parsed} line#{'s' if lines_parsed != 1} across " \
data/lib/nitro/nitro.rb CHANGED
@@ -13,6 +13,7 @@ module NitroBind
13
13
  typedef :pointer, :codebin_handle
14
14
  typedef :pointer, :ovte_handle
15
15
  typedef :pointer, :module_params_handle
16
+ typedef :pointer, :autoload_entry_handle
16
17
 
17
18
  attach_function :nitroRom_alloc, [], :rom_handle
18
19
  attach_function :nitroRom_release, [:rom_handle], :void
@@ -48,12 +49,15 @@ module NitroBind
48
49
  attach_function :codeBin_readCString, [:codebin_handle, :uint32], :string
49
50
  attach_function :codeBin_getSize, [:codebin_handle], :uint32
50
51
  attach_function :codeBin_getStartAddress, [:codebin_handle], :uint32
52
+ attach_function :codeBin_getSectPtr, [:codebin_handle, :uint32, :size_t], :pointer
51
53
 
52
54
  attach_function :armBin_alloc, [], :codebin_handle
53
55
  attach_function :armBin_release, [:codebin_handle], :void
54
56
  attach_function :armBin_load, [:codebin_handle, :string, :uint32, :uint32, :uint32, :bool], :bool
55
57
  attach_function :armBin_getEntryPointAddress, [:codebin_handle], :uint32
56
58
  attach_function :armBin_getModuleParams, [:codebin_handle], :module_params_handle
59
+ attach_function :armBin_getAutoloadEntry, [:codebin_handle, :size_t], :autoload_entry_handle
60
+ attach_function :armBin_getAutoloadEntryCount, [:codebin_handle], :size_t
57
61
  attach_function :armBin_sanityCheckAddress, [:codebin_handle, :uint32], :bool
58
62
 
59
63
  attach_function :overlayBin_alloc, [], :codebin_handle
@@ -176,7 +180,7 @@ module Nitro
176
180
  raise ArgumentError, 'step must be 1, 2, 4, or 8 (bytes)' unless [1,2,4,8].include? step
177
181
  raise ArgumentError, 'range must be a Range' unless range.is_a? Range
178
182
 
179
- clamped = Range.new([range.begin || start_addr, start_addr].max, [range.end || end_addr, end_addr].min)
183
+ clamped = Range.new(range.begin || start_addr, [range.end || end_addr, end_addr].min)
180
184
 
181
185
  clamped.step(step).map { |addr| [send(:"read#{step * 8}", addr), addr] }
182
186
  end
@@ -211,17 +215,25 @@ module Nitro
211
215
  end
212
216
  end
213
217
 
214
- def read_cstring(start_addr)
215
- codeBin_readCString(@ptr, start_addr)
218
+ def read_cstring(addr)
219
+ codeBin_readCString(@ptr, addr)
216
220
  end
217
221
  alias_method :read_cstr, :read_cstring
218
222
 
223
+ def get_section_ptr(addr, sect_size)
224
+ ptr = FFI::MemoryPointer.new(:pointer, 1)
225
+ ptr.write_pointer(codeBin_getSectPtr(@ptr, addr, sect_size))
226
+ raise "Could not read #{sect_size} bytes from address #{addr.to_hex}" if ptr.read_pointer == FFI::Pointer::NULL
227
+ ptr.read_pointer
228
+ end
229
+ alias_method :get_sect_ptr, :get_section_ptr
230
+
219
231
  end
220
232
 
221
233
  class ArmBin < CodeBin
222
234
  include NitroBind
223
235
 
224
- attr_reader :module_params
236
+ attr_reader :module_params, :autoload_entries
225
237
 
226
238
  class ModuleParams < FFI::Struct
227
239
  layout :autoload_list_start, :uint32,
@@ -235,10 +247,17 @@ module Nitro
235
247
  :nitro_code_le, :uint32
236
248
  end
237
249
 
250
+ class AutoLoadEntry < FFI::Struct
251
+ layout :address, :uint32,
252
+ :size, :uint32,
253
+ :bss_size, :uint32,
254
+ :data_offset, :uint32
255
+ end
256
+
238
257
  def initialize(args = {})
239
258
  if args.has_key? :file_path
240
259
  @ptr = FFI::AutoPointer.new(armBin_alloc, method(:armBin_release))
241
- if not File.exist? args[:file_path]
260
+ if !File.exist?(args[:file_path])
242
261
  puts "Error: #{args[:file_path]} does not exist"
243
262
  raise 'ArmBin initialization failed'
244
263
  end
@@ -253,6 +272,9 @@ module Nitro
253
272
  end
254
273
 
255
274
  @module_params = ModuleParams.new(armBin_getModuleParams(@ptr))
275
+ @autoload_entries = []
276
+ autoload_entry_count = armBin_getAutoloadEntryCount(@ptr)
277
+ autoload_entry_count.times {|id| autoload_entries << AutoLoadEntry.new(armBin_getAutoloadEntry(@ptr,id)) }
256
278
  end
257
279
 
258
280
  def entry_point_address
@@ -0,0 +1,196 @@
1
+ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.rb]
2
+
3
+ module UnicornEngine
4
+
5
+ # ARM CPU
6
+
7
+ UC_CPU_ARM_926 = 0
8
+ UC_CPU_ARM_946 = 1
9
+ UC_CPU_ARM_1026 = 2
10
+ UC_CPU_ARM_1136_R2 = 3
11
+ UC_CPU_ARM_1136 = 4
12
+ UC_CPU_ARM_1176 = 5
13
+ UC_CPU_ARM_11MPCORE = 6
14
+ UC_CPU_ARM_CORTEX_M0 = 7
15
+ UC_CPU_ARM_CORTEX_M3 = 8
16
+ UC_CPU_ARM_CORTEX_M4 = 9
17
+ UC_CPU_ARM_CORTEX_M7 = 10
18
+ UC_CPU_ARM_CORTEX_M33 = 11
19
+ UC_CPU_ARM_CORTEX_R5 = 12
20
+ UC_CPU_ARM_CORTEX_R5F = 13
21
+ UC_CPU_ARM_CORTEX_A7 = 14
22
+ UC_CPU_ARM_CORTEX_A8 = 15
23
+ UC_CPU_ARM_CORTEX_A9 = 16
24
+ UC_CPU_ARM_CORTEX_A15 = 17
25
+ UC_CPU_ARM_TI925T = 18
26
+ UC_CPU_ARM_SA1100 = 19
27
+ UC_CPU_ARM_SA1110 = 20
28
+ UC_CPU_ARM_PXA250 = 21
29
+ UC_CPU_ARM_PXA255 = 22
30
+ UC_CPU_ARM_PXA260 = 23
31
+ UC_CPU_ARM_PXA261 = 24
32
+ UC_CPU_ARM_PXA262 = 25
33
+ UC_CPU_ARM_PXA270 = 26
34
+ UC_CPU_ARM_PXA270A0 = 27
35
+ UC_CPU_ARM_PXA270A1 = 28
36
+ UC_CPU_ARM_PXA270B0 = 29
37
+ UC_CPU_ARM_PXA270B1 = 30
38
+ UC_CPU_ARM_PXA270C0 = 31
39
+ UC_CPU_ARM_PXA270C5 = 32
40
+ UC_CPU_ARM_MAX = 33
41
+ UC_CPU_ARM_ENDING = 34
42
+
43
+ # ARM registers
44
+
45
+ UC_ARM_REG_INVALID = 0
46
+ UC_ARM_REG_APSR = 1
47
+ UC_ARM_REG_APSR_NZCV = 2
48
+ UC_ARM_REG_CPSR = 3
49
+ UC_ARM_REG_FPEXC = 4
50
+ UC_ARM_REG_FPINST = 5
51
+ UC_ARM_REG_FPSCR = 6
52
+ UC_ARM_REG_FPSCR_NZCV = 7
53
+ UC_ARM_REG_FPSID = 8
54
+ UC_ARM_REG_ITSTATE = 9
55
+ UC_ARM_REG_LR = 10
56
+ UC_ARM_REG_PC = 11
57
+ UC_ARM_REG_SP = 12
58
+ UC_ARM_REG_SPSR = 13
59
+ UC_ARM_REG_D0 = 14
60
+ UC_ARM_REG_D1 = 15
61
+ UC_ARM_REG_D2 = 16
62
+ UC_ARM_REG_D3 = 17
63
+ UC_ARM_REG_D4 = 18
64
+ UC_ARM_REG_D5 = 19
65
+ UC_ARM_REG_D6 = 20
66
+ UC_ARM_REG_D7 = 21
67
+ UC_ARM_REG_D8 = 22
68
+ UC_ARM_REG_D9 = 23
69
+ UC_ARM_REG_D10 = 24
70
+ UC_ARM_REG_D11 = 25
71
+ UC_ARM_REG_D12 = 26
72
+ UC_ARM_REG_D13 = 27
73
+ UC_ARM_REG_D14 = 28
74
+ UC_ARM_REG_D15 = 29
75
+ UC_ARM_REG_D16 = 30
76
+ UC_ARM_REG_D17 = 31
77
+ UC_ARM_REG_D18 = 32
78
+ UC_ARM_REG_D19 = 33
79
+ UC_ARM_REG_D20 = 34
80
+ UC_ARM_REG_D21 = 35
81
+ UC_ARM_REG_D22 = 36
82
+ UC_ARM_REG_D23 = 37
83
+ UC_ARM_REG_D24 = 38
84
+ UC_ARM_REG_D25 = 39
85
+ UC_ARM_REG_D26 = 40
86
+ UC_ARM_REG_D27 = 41
87
+ UC_ARM_REG_D28 = 42
88
+ UC_ARM_REG_D29 = 43
89
+ UC_ARM_REG_D30 = 44
90
+ UC_ARM_REG_D31 = 45
91
+ UC_ARM_REG_FPINST2 = 46
92
+ UC_ARM_REG_MVFR0 = 47
93
+ UC_ARM_REG_MVFR1 = 48
94
+ UC_ARM_REG_MVFR2 = 49
95
+ UC_ARM_REG_Q0 = 50
96
+ UC_ARM_REG_Q1 = 51
97
+ UC_ARM_REG_Q2 = 52
98
+ UC_ARM_REG_Q3 = 53
99
+ UC_ARM_REG_Q4 = 54
100
+ UC_ARM_REG_Q5 = 55
101
+ UC_ARM_REG_Q6 = 56
102
+ UC_ARM_REG_Q7 = 57
103
+ UC_ARM_REG_Q8 = 58
104
+ UC_ARM_REG_Q9 = 59
105
+ UC_ARM_REG_Q10 = 60
106
+ UC_ARM_REG_Q11 = 61
107
+ UC_ARM_REG_Q12 = 62
108
+ UC_ARM_REG_Q13 = 63
109
+ UC_ARM_REG_Q14 = 64
110
+ UC_ARM_REG_Q15 = 65
111
+ UC_ARM_REG_R0 = 66
112
+ UC_ARM_REG_R1 = 67
113
+ UC_ARM_REG_R2 = 68
114
+ UC_ARM_REG_R3 = 69
115
+ UC_ARM_REG_R4 = 70
116
+ UC_ARM_REG_R5 = 71
117
+ UC_ARM_REG_R6 = 72
118
+ UC_ARM_REG_R7 = 73
119
+ UC_ARM_REG_R8 = 74
120
+ UC_ARM_REG_R9 = 75
121
+ UC_ARM_REG_R10 = 76
122
+ UC_ARM_REG_R11 = 77
123
+ UC_ARM_REG_R12 = 78
124
+ UC_ARM_REG_S0 = 79
125
+ UC_ARM_REG_S1 = 80
126
+ UC_ARM_REG_S2 = 81
127
+ UC_ARM_REG_S3 = 82
128
+ UC_ARM_REG_S4 = 83
129
+ UC_ARM_REG_S5 = 84
130
+ UC_ARM_REG_S6 = 85
131
+ UC_ARM_REG_S7 = 86
132
+ UC_ARM_REG_S8 = 87
133
+ UC_ARM_REG_S9 = 88
134
+ UC_ARM_REG_S10 = 89
135
+ UC_ARM_REG_S11 = 90
136
+ UC_ARM_REG_S12 = 91
137
+ UC_ARM_REG_S13 = 92
138
+ UC_ARM_REG_S14 = 93
139
+ UC_ARM_REG_S15 = 94
140
+ UC_ARM_REG_S16 = 95
141
+ UC_ARM_REG_S17 = 96
142
+ UC_ARM_REG_S18 = 97
143
+ UC_ARM_REG_S19 = 98
144
+ UC_ARM_REG_S20 = 99
145
+ UC_ARM_REG_S21 = 100
146
+ UC_ARM_REG_S22 = 101
147
+ UC_ARM_REG_S23 = 102
148
+ UC_ARM_REG_S24 = 103
149
+ UC_ARM_REG_S25 = 104
150
+ UC_ARM_REG_S26 = 105
151
+ UC_ARM_REG_S27 = 106
152
+ UC_ARM_REG_S28 = 107
153
+ UC_ARM_REG_S29 = 108
154
+ UC_ARM_REG_S30 = 109
155
+ UC_ARM_REG_S31 = 110
156
+ UC_ARM_REG_C1_C0_2 = 111
157
+ UC_ARM_REG_C13_C0_2 = 112
158
+ UC_ARM_REG_C13_C0_3 = 113
159
+ UC_ARM_REG_IPSR = 114
160
+ UC_ARM_REG_MSP = 115
161
+ UC_ARM_REG_PSP = 116
162
+ UC_ARM_REG_CONTROL = 117
163
+ UC_ARM_REG_IAPSR = 118
164
+ UC_ARM_REG_EAPSR = 119
165
+ UC_ARM_REG_XPSR = 120
166
+ UC_ARM_REG_EPSR = 121
167
+ UC_ARM_REG_IEPSR = 122
168
+ UC_ARM_REG_PRIMASK = 123
169
+ UC_ARM_REG_BASEPRI = 124
170
+ UC_ARM_REG_BASEPRI_MAX = 125
171
+ UC_ARM_REG_FAULTMASK = 126
172
+ UC_ARM_REG_APSR_NZCVQ = 127
173
+ UC_ARM_REG_APSR_G = 128
174
+ UC_ARM_REG_APSR_NZCVQG = 129
175
+ UC_ARM_REG_IAPSR_NZCVQ = 130
176
+ UC_ARM_REG_IAPSR_G = 131
177
+ UC_ARM_REG_IAPSR_NZCVQG = 132
178
+ UC_ARM_REG_EAPSR_NZCVQ = 133
179
+ UC_ARM_REG_EAPSR_G = 134
180
+ UC_ARM_REG_EAPSR_NZCVQG = 135
181
+ UC_ARM_REG_XPSR_NZCVQ = 136
182
+ UC_ARM_REG_XPSR_G = 137
183
+ UC_ARM_REG_XPSR_NZCVQG = 138
184
+ UC_ARM_REG_CP_REG = 139
185
+ UC_ARM_REG_ESR = 140
186
+ UC_ARM_REG_ENDING = 141
187
+
188
+ # alias registers
189
+ UC_ARM_REG_R13 = 12
190
+ UC_ARM_REG_R14 = 10
191
+ UC_ARM_REG_R15 = 11
192
+ UC_ARM_REG_SB = 75
193
+ UC_ARM_REG_SL = 76
194
+ UC_ARM_REG_FP = 77
195
+ UC_ARM_REG_IP = 78
196
+ end
@@ -0,0 +1,204 @@
1
+ require 'ffi'
2
+
3
+ require_relative 'arm_const'
4
+ require_relative 'unicorn_const'
5
+
6
+ include UnicornEngine
7
+
8
+ module UnicornBind
9
+ extend FFI::Library
10
+ ffi_lib [
11
+ File.expand_path("unicorn", __dir__),
12
+ File.expand_path("unicorn.dylib", __dir__),
13
+ File.expand_path("unicorn.so", __dir__),
14
+ ]
15
+
16
+ typedef :pointer, :uc_engine # ptr to uc_engine instance
17
+ typedef :pointer, :uc_engine_handle # ptr to a uc_engine ptr
18
+ typedef :pointer, :reg_val_ptr
19
+ typedef :pointer, :reg_val_ptr_arr
20
+ typedef :pointer, :reg_id_arr
21
+ typedef :uint64, :addr
22
+ typedef :uint, :uc_arch
23
+ typedef :uint, :uc_mode
24
+ typedef :uint, :uc_err
25
+ typedef :uint, :uc_query_type
26
+ typedef :uint, :uc_control_type
27
+ typedef :int, :reg_id
28
+
29
+ attach_function :uc_version, [:pointer,:pointer], :uint
30
+ attach_function :uc_arch_supported, [:uc_arch], :bool
31
+ attach_function :uc_open, [:uc_arch, :uc_mode, :uc_engine_handle], :uc_err
32
+ attach_function :uc_close, [:uc_engine], :uc_err
33
+ attach_function :uc_query, [:uc_engine, :uc_query_type, :pointer], :uc_err
34
+ attach_function :uc_ctl, [:uc_engine, :uc_control_type, :varargs], :uc_err
35
+ attach_function :uc_errno, [:uc_engine], :uc_err
36
+ attach_function :uc_strerror, [:uc_err], :string
37
+ attach_function :uc_reg_write, [:uc_engine, :reg_id, :reg_val_ptr], :uc_err
38
+ attach_function :uc_reg_read, [:uc_engine, :reg_id, :reg_val_ptr], :uc_err
39
+ attach_function :uc_reg_write_batch, [:uc_engine, :reg_id_arr, :reg_val_ptr_arr, :int], :uc_err
40
+ attach_function :uc_reg_read_batch, [:uc_engine, :reg_id_arr, :reg_val_ptr_arr, :int], :uc_err
41
+ attach_function :uc_mem_write, [:uc_engine, :addr, :pointer, :uint64], :uc_err
42
+ attach_function :uc_mem_read, [:uc_engine, :addr, :pointer, :uint64], :uc_err
43
+ attach_function :uc_emu_start, [:uc_engine, :addr, :addr, :uint64, :size_t], :uc_err
44
+ attach_function :uc_emu_stop, [:uc_engine], :uc_err
45
+ attach_function :uc_mem_map, [:uc_engine, :addr, :uint64, :uint32], :uc_err
46
+ attach_function :uc_mem_map_ptr, [:uc_engine, :addr, :uint64, :uint32, :pointer], :uc_err
47
+ attach_function :uc_mem_unmap, [:uc_engine, :addr, :uint64], :uc_err
48
+ attach_function :uc_mem_protect, [:uc_engine, :addr, :uint64, :uint32], :uc_err
49
+
50
+ REG_ID = {
51
+ r0: UC_ARM_REG_R0,
52
+ r1: UC_ARM_REG_R1,
53
+ r2: UC_ARM_REG_R2,
54
+ r3: UC_ARM_REG_R3,
55
+ r4: UC_ARM_REG_R4,
56
+ r5: UC_ARM_REG_R5,
57
+ r6: UC_ARM_REG_R6,
58
+ r7: UC_ARM_REG_R7,
59
+ r8: UC_ARM_REG_R8,
60
+ r9: UC_ARM_REG_R9,
61
+ r10: UC_ARM_REG_R10,
62
+ r11: UC_ARM_REG_R11,
63
+ r12: UC_ARM_REG_R12,
64
+ sp: UC_ARM_REG_SP,
65
+ lr: UC_ARM_REG_LR,
66
+ pc: UC_ARM_REG_PC,
67
+ cpsr: UC_ARM_REG_CPSR,
68
+ spsr: UC_ARM_REG_SPSR
69
+ }.freeze
70
+ end
71
+
72
+ module Unicorn
73
+ extend UnicornBind
74
+
75
+ class Region
76
+ attr_reader :addr, :size, :prot, :end_addr
77
+ def initialize(addr, size, prot = UC_PROT_ALL)
78
+ @addr = addr
79
+ @size = size
80
+ @prot = prot
81
+ @end_addr = addr + size
82
+ end
83
+ end
84
+
85
+ NDS_REGIONS = [
86
+ Region.new(0x1ff8000, 32*1024), # ITCM -> 32KB
87
+ Region.new(0x2000000, 4*1024*1024), # Main memory -> 4MB
88
+ Region.new(0x4000000, 64*1024*1024), # I/O and VRAM -> 64MB
89
+ Region.new(0xffff000, 32*1024) # BIOS -> 32KB
90
+ ].freeze
91
+
92
+ class Section
93
+ attr_reader :addr, :ptr, :size, :end_addr
94
+ def initialize(addr, ffi_ptr, size)
95
+ @addr = addr
96
+ @ptr = ffi_ptr
97
+ @size = size
98
+ @end_addr = addr + size
99
+ end
100
+ end
101
+ Sect = Section
102
+
103
+ class Emulator
104
+ include UnicornBind
105
+
106
+ def initialize(arch: UC_ARCH_ARM, mode: UC_MODE_ARM946, regions: NDS_REGIONS, sections: [], registers: {})
107
+
108
+ FFI::MemoryPointer.new(:pointer, 1) do |ptr|
109
+ safe_call(:uc_open, arch, mode, ptr)
110
+ @engine = FFI::AutoPointer.new(ptr.read_pointer, method(:uc_close))
111
+ end
112
+
113
+ regions.each { add_region(it) } unless regions.empty?
114
+ sections.each { add_sect(it) } unless sections.empty?
115
+ registers.each {|r,v| write_register(r,v) } unless registers.empty?
116
+ end
117
+
118
+ def run(from: nil, to: -1, timeout_ms: 0, max_ins: 0)
119
+ raise "The 'from' parameter must be specified" if from.nil?
120
+ if to == -1 && timeout_ms == 0 && max_ins == 0
121
+ raise "The 'to' parameter must be specified if 'timeout_ms' or 'max_ins' are not"
122
+ end
123
+ safe_call(:uc_emu_start, @engine, from, to, timeout_ms, max_ins)
124
+ end
125
+
126
+ def add_region(region)
127
+ safe_call(:uc_mem_map, @engine, region.addr, region.size, region.prot)
128
+ end
129
+
130
+ def add_section(sect)
131
+ safe_call(:uc_mem_write, @engine, sect.addr, sect.ptr, sect.size)
132
+ end
133
+ alias_method :add_sect, :add_section
134
+
135
+ def write_mem(addr, byte_str)
136
+ FFI::MemoryPointer.new(:uint8, byte_str.bytesize) do |ptr|
137
+ ptr.write_array_of_uint8(byte_str.bytes)
138
+ safe_call(:uc_mem_write, @engine, addr, ptr, byte_str.bytesize)
139
+ end
140
+ end
141
+
142
+ def read_mem(addr, size)
143
+ byte_str = nil
144
+ FFI::MemoryPointer.new(:uint8, size) do |ptr|
145
+ safe_call(:uc_mem_read, @engine, addr, ptr, size)
146
+ byte_str = ptr.read_array_of_uint8(size).pack('C*')
147
+ end
148
+ byte_str
149
+ end
150
+
151
+ def write_register(reg, val)
152
+ FFI::MemoryPointer.new(:int32, 1) do |pv|
153
+ pv.write_int(val)
154
+ safe_call(:uc_reg_write, @engine, REG_ID[reg], pv)
155
+ end
156
+ end
157
+ alias_method :write_reg, :write_register
158
+
159
+ def write_registers(regs_h)
160
+ regs_h.each {|r,v| write_register(r,v) }
161
+ end
162
+ alias_method :write_regs, :write_registers
163
+
164
+ REG_ID.each do |name, id|
165
+ define_method("write_#{name.to_s}".to_sym) do |val|
166
+ write_register(name, val)
167
+ end
168
+ end
169
+
170
+ def read_register(reg)
171
+ val = nil
172
+ FFI::MemoryPointer.new(:int32, 1) do |pv|
173
+ safe_call(:uc_reg_read, @engine, REG_ID[reg], pv)
174
+ val = pv.read_int32
175
+ end
176
+ val
177
+ end
178
+ alias_method :read_reg, :read_register
179
+
180
+ def read_registers(reg_names = REG_ID.keys)
181
+ regs_h = {}
182
+ reg_names.each {|r| regs_h[r] = read_register(r) }
183
+ regs_h
184
+ end
185
+ alias_method :read_regs, :read_registers
186
+
187
+ REG_ID.each do |name, id|
188
+ define_method("read_#{name.to_s}".to_sym) do
189
+ read_register(name)
190
+ end
191
+ end
192
+
193
+ private
194
+ def safe_call(meth_sym, *args)
195
+ err = send(meth_sym, *args)
196
+ raise "Error from #{meth_sym.to_s}: #{uc_strerror(err)}" if err != UC_ERR_OK
197
+ end
198
+ end
199
+
200
+ Emu = Emulator
201
+
202
+ end
203
+
204
+ Uc = Unicorn
@@ -0,0 +1,152 @@
1
+ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [unicorn_const.rb]
2
+
3
+ module UnicornEngine
4
+ UC_API_MAJOR = 2
5
+ UC_API_MINOR = 1
6
+ UC_API_PATCH = 4
7
+ UC_API_EXTRA = 255
8
+ UC_VERSION_MAJOR = 2
9
+ UC_VERSION_MINOR = 1
10
+ UC_VERSION_PATCH = 4
11
+ UC_VERSION_EXTRA = 255
12
+ UC_SECOND_SCALE = 1000000
13
+ UC_MILISECOND_SCALE = 1000
14
+ UC_ARCH_ARM = 1
15
+ UC_ARCH_ARM64 = 2
16
+ UC_ARCH_MIPS = 3
17
+ UC_ARCH_X86 = 4
18
+ UC_ARCH_PPC = 5
19
+ UC_ARCH_SPARC = 6
20
+ UC_ARCH_M68K = 7
21
+ UC_ARCH_RISCV = 8
22
+ UC_ARCH_S390X = 9
23
+ UC_ARCH_TRICORE = 10
24
+ UC_ARCH_MAX = 11
25
+
26
+ UC_MODE_LITTLE_ENDIAN = 0
27
+ UC_MODE_BIG_ENDIAN = 1073741824
28
+
29
+ UC_MODE_ARM = 0
30
+ UC_MODE_THUMB = 16
31
+ UC_MODE_MCLASS = 32
32
+ UC_MODE_V8 = 64
33
+ UC_MODE_ARMBE8 = 1024
34
+ UC_MODE_ARM926 = 128
35
+ UC_MODE_ARM946 = 256
36
+ UC_MODE_ARM1176 = 512
37
+ UC_MODE_MICRO = 16
38
+ UC_MODE_MIPS3 = 32
39
+ UC_MODE_MIPS32R6 = 64
40
+ UC_MODE_MIPS32 = 4
41
+ UC_MODE_MIPS64 = 8
42
+ UC_MODE_16 = 2
43
+ UC_MODE_32 = 4
44
+ UC_MODE_64 = 8
45
+ UC_MODE_PPC32 = 4
46
+ UC_MODE_PPC64 = 8
47
+ UC_MODE_QPX = 16
48
+ UC_MODE_SPARC32 = 4
49
+ UC_MODE_SPARC64 = 8
50
+ UC_MODE_V9 = 16
51
+ UC_MODE_RISCV32 = 4
52
+ UC_MODE_RISCV64 = 8
53
+
54
+ UC_ERR_OK = 0
55
+ UC_ERR_NOMEM = 1
56
+ UC_ERR_ARCH = 2
57
+ UC_ERR_HANDLE = 3
58
+ UC_ERR_MODE = 4
59
+ UC_ERR_VERSION = 5
60
+ UC_ERR_READ_UNMAPPED = 6
61
+ UC_ERR_WRITE_UNMAPPED = 7
62
+ UC_ERR_FETCH_UNMAPPED = 8
63
+ UC_ERR_HOOK = 9
64
+ UC_ERR_INSN_INVALID = 10
65
+ UC_ERR_MAP = 11
66
+ UC_ERR_WRITE_PROT = 12
67
+ UC_ERR_READ_PROT = 13
68
+ UC_ERR_FETCH_PROT = 14
69
+ UC_ERR_ARG = 15
70
+ UC_ERR_READ_UNALIGNED = 16
71
+ UC_ERR_WRITE_UNALIGNED = 17
72
+ UC_ERR_FETCH_UNALIGNED = 18
73
+ UC_ERR_HOOK_EXIST = 19
74
+ UC_ERR_RESOURCE = 20
75
+ UC_ERR_EXCEPTION = 21
76
+ UC_ERR_OVERFLOW = 22
77
+
78
+ UC_PROT_NONE = 0
79
+ UC_PROT_READ = 1
80
+ UC_PROT_WRITE = 2
81
+ UC_PROT_EXEC = 4
82
+ UC_PROT_ALL = 7
83
+ UC_MEM_READ = 16
84
+ UC_MEM_WRITE = 17
85
+ UC_MEM_FETCH = 18
86
+ UC_MEM_READ_UNMAPPED = 19
87
+ UC_MEM_WRITE_UNMAPPED = 20
88
+ UC_MEM_FETCH_UNMAPPED = 21
89
+ UC_MEM_WRITE_PROT = 22
90
+ UC_MEM_READ_PROT = 23
91
+ UC_MEM_FETCH_PROT = 24
92
+ UC_MEM_READ_AFTER = 25
93
+
94
+ UC_TCG_OP_SUB = 0
95
+ UC_TCG_OP_FLAG_CMP = 1
96
+ UC_TCG_OP_FLAG_DIRECT = 2
97
+ UC_HOOK_INTR = 1
98
+ UC_HOOK_INSN = 2
99
+ UC_HOOK_CODE = 4
100
+ UC_HOOK_BLOCK = 8
101
+ UC_HOOK_MEM_READ_UNMAPPED = 16
102
+ UC_HOOK_MEM_WRITE_UNMAPPED = 32
103
+ UC_HOOK_MEM_FETCH_UNMAPPED = 64
104
+ UC_HOOK_MEM_READ_PROT = 128
105
+ UC_HOOK_MEM_WRITE_PROT = 256
106
+ UC_HOOK_MEM_FETCH_PROT = 512
107
+ UC_HOOK_MEM_READ = 1024
108
+ UC_HOOK_MEM_WRITE = 2048
109
+ UC_HOOK_MEM_FETCH = 4096
110
+ UC_HOOK_MEM_READ_AFTER = 8192
111
+ UC_HOOK_INSN_INVALID = 16384
112
+ UC_HOOK_EDGE_GENERATED = 32768
113
+ UC_HOOK_TCG_OPCODE = 65536
114
+ UC_HOOK_TLB_FILL = 131072
115
+ UC_HOOK_MEM_UNMAPPED = 112
116
+ UC_HOOK_MEM_PROT = 896
117
+ UC_HOOK_MEM_READ_INVALID = 144
118
+ UC_HOOK_MEM_WRITE_INVALID = 288
119
+ UC_HOOK_MEM_FETCH_INVALID = 576
120
+ UC_HOOK_MEM_INVALID = 1008
121
+ UC_HOOK_MEM_VALID = 7168
122
+ UC_QUERY_MODE = 1
123
+ UC_QUERY_PAGE_SIZE = 2
124
+ UC_QUERY_ARCH = 3
125
+ UC_QUERY_TIMEOUT = 4
126
+
127
+ UC_CTL_IO_NONE = 0
128
+ UC_CTL_IO_WRITE = 1
129
+ UC_CTL_IO_READ = 2
130
+ UC_CTL_IO_READ_WRITE = 3
131
+
132
+ UC_TLB_CPU = 0
133
+ UC_TLB_VIRTUAL = 1
134
+
135
+ UC_CTL_UC_MODE = 0
136
+ UC_CTL_UC_PAGE_SIZE = 1
137
+ UC_CTL_UC_ARCH = 2
138
+ UC_CTL_UC_TIMEOUT = 3
139
+ UC_CTL_UC_USE_EXITS = 4
140
+ UC_CTL_UC_EXITS_CNT = 5
141
+ UC_CTL_UC_EXITS = 6
142
+ UC_CTL_CPU_MODEL = 7
143
+ UC_CTL_TB_REQUEST_CACHE = 8
144
+ UC_CTL_TB_REMOVE_CACHE = 9
145
+ UC_CTL_TB_FLUSH = 10
146
+ UC_CTL_TLB_FLUSH = 11
147
+ UC_CTL_TLB_TYPE = 12
148
+ UC_CTL_TCG_BUFFER_SIZE = 13
149
+ UC_CTL_CONTEXT_MODE = 14
150
+ UC_CTL_CONTEXT_CPU = 1
151
+ UC_CTL_CONTEXT_MEMORY = 2
152
+ end
@@ -0,0 +1,3 @@
1
+ module Unicorn
2
+ VERSION = "2.1.4"
3
+ end