metasm 1.0.1 → 1.0.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.
Files changed (235) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hgtags +3 -0
  4. data/Gemfile +1 -0
  5. data/INSTALL +61 -0
  6. data/LICENCE +458 -0
  7. data/README +29 -21
  8. data/Rakefile +10 -0
  9. data/TODO +10 -12
  10. data/doc/code_organisation.txt +2 -0
  11. data/doc/core/DynLdr.txt +247 -0
  12. data/doc/core/ExeFormat.txt +43 -0
  13. data/doc/core/Expression.txt +220 -0
  14. data/doc/core/GNUExports.txt +27 -0
  15. data/doc/core/Ia32.txt +236 -0
  16. data/doc/core/SerialStruct.txt +108 -0
  17. data/doc/core/VirtualString.txt +145 -0
  18. data/doc/core/WindowsExports.txt +61 -0
  19. data/doc/core/index.txt +1 -0
  20. data/doc/style.css +6 -3
  21. data/doc/usage/debugger.txt +327 -0
  22. data/doc/usage/index.txt +1 -0
  23. data/doc/use_cases.txt +2 -2
  24. data/metasm.gemspec +22 -0
  25. data/{lib/metasm.rb → metasm.rb} +11 -3
  26. data/{lib/metasm → metasm}/compile_c.rb +13 -7
  27. data/metasm/cpu/arc.rb +8 -0
  28. data/metasm/cpu/arc/decode.rb +425 -0
  29. data/metasm/cpu/arc/main.rb +191 -0
  30. data/metasm/cpu/arc/opcodes.rb +588 -0
  31. data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
  32. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  33. data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
  34. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  35. data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
  36. data/metasm/cpu/arm/opcodes.rb +324 -0
  37. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  38. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  39. data/metasm/cpu/arm64.rb +15 -0
  40. data/metasm/cpu/arm64/debug.rb +38 -0
  41. data/metasm/cpu/arm64/decode.rb +289 -0
  42. data/metasm/cpu/arm64/encode.rb +41 -0
  43. data/metasm/cpu/arm64/main.rb +105 -0
  44. data/metasm/cpu/arm64/opcodes.rb +232 -0
  45. data/metasm/cpu/arm64/parse.rb +20 -0
  46. data/metasm/cpu/arm64/render.rb +95 -0
  47. data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
  48. data/metasm/cpu/bpf/decode.rb +142 -0
  49. data/metasm/cpu/bpf/main.rb +60 -0
  50. data/metasm/cpu/bpf/opcodes.rb +81 -0
  51. data/metasm/cpu/bpf/render.rb +41 -0
  52. data/metasm/cpu/cy16.rb +9 -0
  53. data/metasm/cpu/cy16/decode.rb +253 -0
  54. data/metasm/cpu/cy16/main.rb +63 -0
  55. data/metasm/cpu/cy16/opcodes.rb +78 -0
  56. data/metasm/cpu/cy16/render.rb +41 -0
  57. data/metasm/cpu/dalvik.rb +11 -0
  58. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
  59. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
  60. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
  61. data/metasm/cpu/ia32.rb +17 -0
  62. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
  63. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
  64. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
  65. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
  66. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  67. data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
  68. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  69. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
  70. data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
  71. data/metasm/cpu/mips.rb +14 -0
  72. data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
  73. data/metasm/cpu/mips/debug.rb +42 -0
  74. data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
  75. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  76. data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
  77. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
  78. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  79. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  80. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  81. data/metasm/cpu/msp430/decode.rb +247 -0
  82. data/metasm/cpu/msp430/main.rb +62 -0
  83. data/metasm/cpu/msp430/opcodes.rb +101 -0
  84. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  85. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  86. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  87. data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
  88. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
  89. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  90. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  91. data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
  92. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
  93. data/metasm/cpu/ppc/parse.rb +55 -0
  94. data/metasm/cpu/python.rb +8 -0
  95. data/metasm/cpu/python/decode.rb +136 -0
  96. data/metasm/cpu/python/main.rb +36 -0
  97. data/metasm/cpu/python/opcodes.rb +180 -0
  98. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  99. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
  100. data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
  101. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  102. data/metasm/cpu/x86_64.rb +15 -0
  103. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
  104. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  105. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
  106. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
  107. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
  108. data/metasm/cpu/x86_64/opcodes.rb +136 -0
  109. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
  110. data/metasm/cpu/x86_64/render.rb +35 -0
  111. data/metasm/cpu/z80.rb +9 -0
  112. data/metasm/cpu/z80/decode.rb +313 -0
  113. data/metasm/cpu/z80/main.rb +67 -0
  114. data/metasm/cpu/z80/opcodes.rb +224 -0
  115. data/metasm/cpu/z80/render.rb +59 -0
  116. data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
  117. data/{lib/metasm → metasm}/decode.rb +35 -4
  118. data/{lib/metasm → metasm}/decompile.rb +15 -16
  119. data/{lib/metasm → metasm}/disassemble.rb +201 -45
  120. data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
  121. data/{lib/metasm → metasm}/dynldr.rb +220 -133
  122. data/{lib/metasm → metasm}/encode.rb +10 -1
  123. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  124. data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
  125. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  126. data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
  127. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
  128. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
  129. data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
  130. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  131. data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
  132. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
  133. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
  134. data/metasm/exe_format/gb.rb +65 -0
  135. data/metasm/exe_format/javaclass.rb +424 -0
  136. data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
  137. data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
  138. data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
  139. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  140. data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
  141. data/metasm/exe_format/pyc.rb +167 -0
  142. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  143. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  144. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  145. data/metasm/exe_format/swf.rb +205 -0
  146. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  147. data/metasm/exe_format/zip.rb +335 -0
  148. data/metasm/gui.rb +13 -0
  149. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  150. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  151. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
  152. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  153. data/metasm/gui/dasm_graph.rb +1695 -0
  154. data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
  155. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  156. data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
  157. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  158. data/{lib/metasm → metasm}/gui/debug.rb +93 -27
  159. data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
  160. data/{lib/metasm → metasm}/gui/qt.rb +12 -2
  161. data/{lib/metasm → metasm}/gui/win32.rb +179 -42
  162. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  163. data/{lib/metasm → metasm}/main.rb +389 -264
  164. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  165. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  166. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  167. data/metasm/os/main.rb +330 -0
  168. data/{lib/metasm → metasm}/os/windows.rb +132 -42
  169. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  170. data/{lib/metasm → metasm}/parse.rb +26 -24
  171. data/{lib/metasm → metasm}/parse_c.rb +221 -116
  172. data/{lib/metasm → metasm}/preprocessor.rb +55 -40
  173. data/{lib/metasm → metasm}/render.rb +14 -38
  174. data/misc/hexdump.rb +2 -1
  175. data/misc/lint.rb +58 -0
  176. data/misc/txt2html.rb +9 -7
  177. data/samples/bindiff.rb +3 -4
  178. data/samples/dasm-plugins/bindiff.rb +15 -0
  179. data/samples/dasm-plugins/bookmark.rb +133 -0
  180. data/samples/dasm-plugins/c_constants.rb +57 -0
  181. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  182. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  183. data/samples/dasm-plugins/dasm_all.rb +70 -0
  184. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  185. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  186. data/samples/dasm-plugins/dump_text.rb +35 -0
  187. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  188. data/samples/dasm-plugins/findgadget.rb +75 -0
  189. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  190. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  191. data/samples/dasm-plugins/imm2off.rb +34 -0
  192. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  193. data/samples/dasm-plugins/patch_file.rb +95 -0
  194. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  195. data/samples/dasm-plugins/scanxrefs.rb +26 -0
  196. data/samples/dasm-plugins/selfmodify.rb +197 -0
  197. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  198. data/samples/dasmnavig.rb +1 -1
  199. data/samples/dbg-apihook.rb +24 -9
  200. data/samples/dbg-plugins/heapscan.rb +283 -0
  201. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  202. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  203. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  204. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  205. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  206. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  207. data/samples/dbg-plugins/trace_func.rb +214 -0
  208. data/samples/disassemble-gui.rb +35 -5
  209. data/samples/disassemble.rb +31 -6
  210. data/samples/dump_upx.rb +24 -12
  211. data/samples/dynamic_ruby.rb +12 -3
  212. data/samples/exeencode.rb +6 -5
  213. data/samples/factorize-headers-peimports.rb +1 -1
  214. data/samples/lindebug.rb +175 -381
  215. data/samples/metasm-shell.rb +1 -2
  216. data/samples/peldr.rb +2 -2
  217. data/tests/all.rb +1 -1
  218. data/tests/arc.rb +26 -0
  219. data/tests/dynldr.rb +22 -4
  220. data/tests/expression.rb +55 -0
  221. data/tests/graph_layout.rb +285 -0
  222. data/tests/ia32.rb +79 -26
  223. data/tests/mips.rb +9 -2
  224. data/tests/x86_64.rb +66 -18
  225. metadata +330 -218
  226. data/lib/metasm/arm/opcodes.rb +0 -177
  227. data/lib/metasm/gui.rb +0 -23
  228. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  229. data/lib/metasm/ia32.rb +0 -14
  230. data/lib/metasm/ia32/opcodes.rb +0 -873
  231. data/lib/metasm/ppc/parse.rb +0 -52
  232. data/lib/metasm/x86_64.rb +0 -12
  233. data/lib/metasm/x86_64/opcodes.rb +0 -118
  234. data/samples/gdbclient.rb +0 -583
  235. data/samples/rubstop.rb +0 -399
@@ -20,10 +20,10 @@ class ELF
20
20
  @phoff ||= elf.segments.empty? ? 0 : elf.new_label('phdr')
21
21
  @shoff ||= elf.sections.length <= 1 ? 0 : elf.new_label('shdr')
22
22
  @flags ||= []
23
- @ehsize ||= Header.size(elf)
24
- @phentsize ||= Segment.size(elf)
23
+ @ehsize ||= Header.sizeof(elf)
24
+ @phentsize ||= Segment.sizeof(elf)
25
25
  @phnum ||= elf.segments.length
26
- @shentsize ||= Section.size(elf)
26
+ @shentsize ||= Section.sizeof(elf)
27
27
  @shnum ||= elf.sections.length
28
28
 
29
29
  super(elf)
@@ -47,8 +47,8 @@ class ELF
47
47
  # defines the @name_p field from @name and elf.section[elf.header.shstrndx]
48
48
  # creates .shstrtab if needed
49
49
  def make_name_p elf
50
- return 0 if not name or @name == ''
51
- if elf.header.shstrndx.to_i == 0
50
+ return 0 if not name or @name == '' or elf.header.shnum == 0
51
+ if elf.header.shstrndx.to_i == 0 or not elf.sections[elf.header.shstrndx]
52
52
  sn = Section.new
53
53
  sn.name = '.shstrtab'
54
54
  sn.type = 'STRTAB'
@@ -140,6 +140,9 @@ class ELF
140
140
  srank = rank[s]
141
141
  nexts = @sections.find { |sec| rank[sec] > srank } # find section with rank superior
142
142
  nexts = nexts ? @sections.index(nexts) : -1 # if none, last
143
+ if @header.shstrndx.to_i != 0 and nexts != -1 and @header.shstrndx >= nexts
144
+ @header.shstrndx += 1
145
+ end
143
146
  @sections.insert(nexts, s) # insert section
144
147
  end
145
148
 
@@ -196,6 +199,8 @@ class ELF
196
199
 
197
200
  # encodes the symbol dynamic hash table in the .hash section, updates the HASH tag
198
201
  def encode_hash
202
+ return if @symbols.length <= 1
203
+
199
204
  if not hash = @sections.find { |s| s.type == 'HASH' }
200
205
  hash = Section.new
201
206
  hash.name = '.hash'
@@ -236,11 +241,13 @@ class ELF
236
241
  # encodes the symbol table
237
242
  # should have a stable self.sections array (only append allowed after this step)
238
243
  def encode_segments_symbols(strtab)
244
+ return if @symbols.length <= 1
245
+
239
246
  if not dynsym = @sections.find { |s| s.type == 'DYNSYM' }
240
247
  dynsym = Section.new
241
248
  dynsym.name = '.dynsym'
242
249
  dynsym.type = 'DYNSYM'
243
- dynsym.entsize = Symbol.size(self)
250
+ dynsym.entsize = Symbol.sizeof(self)
244
251
  dynsym.addralign = 4
245
252
  dynsym.flags = ['ALLOC']
246
253
  dynsym.info = @symbols[1..-1].find_all { |s| s.bind == 'LOCAL' }.length + 1
@@ -251,7 +258,7 @@ class ELF
251
258
  @symbols.each { |s| dynsym.encoded << s.encode(self, strtab.encoded) } # needs all section indexes, as will be in the final section header
252
259
 
253
260
  @tag['SYMTAB'] = label_at(dynsym.encoded, 0)
254
- @tag['SYMENT'] = Symbol.size(self)
261
+ @tag['SYMENT'] = Symbol.sizeof(self)
255
262
 
256
263
  encode_check_section_size dynsym
257
264
 
@@ -261,7 +268,7 @@ class ELF
261
268
  # encodes the relocation tables
262
269
  # needs a complete self.symbols array
263
270
  def encode_segments_relocs
264
- return if not @relocations
271
+ return if not @relocations or @relocations.empty?
265
272
 
266
273
  arch_preencode_reloc_func = "arch_#{@header.machine.downcase}_preencode_reloc"
267
274
  send arch_preencode_reloc_func if respond_to? arch_preencode_reloc_func
@@ -287,7 +294,7 @@ class ELF
287
294
  @tag['JMPREL'] = label_at(relplt.encoded, 0)
288
295
  @tag['PLTRELSZ'] = relplt.encoded.virtsize
289
296
  @tag['PLTREL'] = relplt.type = stype
290
- @tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.size(self) : RelocationAddend.size(self))
297
+ @tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.sizeof(self) : RelocationAddend.sizeof(self))
291
298
  encode_check_section_size relplt
292
299
  end
293
300
 
@@ -305,13 +312,13 @@ class ELF
305
312
  rel.name = '.rel.dyn'
306
313
  rel.type = 'REL'
307
314
  rel.flags = ['ALLOC']
308
- rel.entsize = rel.addralign = Relocation.size(self)
315
+ rel.entsize = rel.addralign = Relocation.sizeof(self)
309
316
  encode_add_section rel
310
317
  end
311
318
  rel.encoded = EncodedData.new
312
319
  list.each { |r| rel.encoded << r.encode(self) }
313
320
  @tag['REL'] = label_at(rel.encoded, 0)
314
- @tag['RELENT'] = Relocation.size(self)
321
+ @tag['RELENT'] = Relocation.sizeof(self)
315
322
  @tag['RELSZ'] = rel.encoded.virtsize
316
323
  encode_check_section_size rel
317
324
  end
@@ -323,13 +330,13 @@ class ELF
323
330
  rela.name = '.rela.dyn'
324
331
  rela.type = 'RELA'
325
332
  rela.flags = ['ALLOC']
326
- rela.entsize = rela.addralign = RelocationAddend.size(self)
333
+ rela.entsize = rela.addralign = RelocationAddend.sizeof(self)
327
334
  encode_add_section rela
328
335
  end
329
336
  rela.encoded = EncodedData.new
330
337
  list.each { |r| rela.encoded << r.encode(self) }
331
338
  @tag['RELA'] = label_at(rela.encoded, 0)
332
- @tag['RELAENT'] = RelocationAddend.size(self)
339
+ @tag['RELAENT'] = RelocationAddend.sizeof(self)
333
340
  @tag['RELASZ'] = rela.encoded.virtsize
334
341
  encode_check_section_size rela
335
342
  end
@@ -337,6 +344,8 @@ class ELF
337
344
 
338
345
  # creates the .plt/.got from the @relocations
339
346
  def arch_386_preencode_reloc
347
+ return if @relocations.empty?
348
+
340
349
  # if .got.plt does not exist, the dynamic loader segfaults
341
350
  if not gotplt = @sections.find { |s| s.type == 'PROGBITS' and s.name == '.got.plt' }
342
351
  gotplt = Section.new
@@ -358,7 +367,7 @@ class ELF
358
367
  when 'PC32'
359
368
  next if not r.symbol
360
369
 
361
- if r.symbol.type != 'FUNC'
370
+ if r.symbol.type != 'FUNC'
362
371
  # external data xref: generate a GOT entry
363
372
  # XXX reuse .got.plt ?
364
373
  if not got ||= @sections.find { |s| s.type == 'PROGBITS' and s.name == '.got' }
@@ -385,7 +394,7 @@ class ELF
385
394
  else
386
395
  @relocations.delete r
387
396
  end
388
-
397
+
389
398
  # prevoffset is label_section_start + int_section_offset
390
399
  target_s = @sections.find { |s| s.encoded and s.encoded.export[prevoffset.lexpr] == 0 }
391
400
  rel = target_s.encoded.reloc[prevoffset.rexpr]
@@ -411,12 +420,12 @@ class ELF
411
420
  #
412
421
  # [.got.plt header]
413
422
  # dd _DYNAMIC
414
- # dd 0 # rewritten to GOTPLT? by ld-linux
423
+ # dd 0 # rewritten to GOTPLT? by ld-linux
415
424
  # dd 0 # rewritten to dlresolve_inplace by ld-linux
416
425
  #
417
426
  # [.got.plt + func_got_offset]
418
427
  # dd some_func_got_default # lazily rewritten to the real addr of some_func by jmp dlresolve_inplace
419
- # # base_relocated ?
428
+ # # base_relocated ?
420
429
 
421
430
  # in the PIC case, _dlresolve imposes us to use the ebx register (which may not be saved by the calling function..)
422
431
  # also geteip trashes eax, which may interfere with regparm(3)
@@ -448,7 +457,7 @@ class ELF
448
457
  plt.encoded << shellcode["jmp [#{base} + #{gotplt.encoded.length}]"]
449
458
  plt.encoded.add_export r.symbol.name+'_plt_default', plt.encoded.length
450
459
  reloffset = @relocations.find_all { |rr| rr.type == 'JMP_SLOT' }.length
451
- reloffset *= Relocation.size(self) if @bitsize == 32
460
+ reloffset *= Relocation.sizeof(self) if @bitsize == 32
452
461
  plt.encoded << shellcode["push #{reloffset}\njmp metasm_plt_start"]
453
462
 
454
463
  # transform the reloc PC32 => JMP_SLOT
@@ -531,7 +540,7 @@ class ELF
531
540
 
532
541
  # fill these later, but create the base relocs now
533
542
  arch_create_reloc_func = "arch_#{@header.machine.downcase}_create_reloc"
534
- next if not respond_to?(arch_create_reloc_func)
543
+ next if not respond_to?(arch_create_reloc_func)
535
544
  curaddr = label_at(@encoded, 0, 'elf_start')
536
545
  fkbind = {}
537
546
  @sections.each { |s|
@@ -557,6 +566,9 @@ class ELF
557
566
 
558
567
  encode_check_section_size strtab
559
568
 
569
+ # rm unused tag (shrink .nointerp binaries by allowing to skip the section entirely)
570
+ @tag.delete('STRTAB') if strtab.encoded.length == 1
571
+
560
572
  # XXX any order needed ?
561
573
  @tag.keys.each { |k|
562
574
  case k
@@ -581,7 +593,7 @@ class ELF
581
593
  encode_tag[k, @tag[k]]
582
594
  end
583
595
  }
584
- encode_tag['NULL', @tag['NULL'] || 0]
596
+ encode_tag['NULL', @tag['NULL'] || 0] unless @tag.empty?
585
597
 
586
598
  encode_check_section_size dynamic
587
599
  end
@@ -598,17 +610,13 @@ class ELF
598
610
  @sections.each { |s|
599
611
  next if not s.encoded
600
612
  s.encoded.reloc.each_value { |r|
601
- t = Expression[r.target.reduce]
602
- if t.op == :+ and t.rexpr.kind_of? Expression and t.rexpr.op == :- and not t.rexpr.lexpr and
603
- t.rexpr.rexpr.kind_of?(::String) and t.lexpr.kind_of?(::String)
604
- symname = t.lexpr
605
- else
606
- symname = t.reduce_rec
607
- end
608
- next if not dll = autoexports[symname]
613
+ et = r.target.externals
614
+ extern = et.find_all { |name| autoexports[name] }
615
+ next if extern.length != 1
616
+ symname = extern.first
609
617
  if not @symbols.find { |sym| sym.name == symname }
610
618
  @tag['NEEDED'] ||= []
611
- @tag['NEEDED'] |= [dll]
619
+ @tag['NEEDED'] |= [autoexports[symname]]
612
620
  sym = Symbol.new
613
621
  sym.shndx = 'UNDEF'
614
622
  sym.type = 'FUNC'
@@ -737,6 +745,55 @@ class ELF
737
745
  @relocations << r
738
746
  end
739
747
 
748
+ def arch_mips_create_reloc(section, off, binding, rel=nil)
749
+ rel ||= section.encoded.reloc[off]
750
+ startaddr = label_at(@encoded, 0)
751
+ r = Relocation.new
752
+ r.offset = Expression[label_at(section.encoded, 0, 'sect_start'), :+, off]
753
+ if Expression[rel.target, :-, startaddr].bind(binding).reduce.kind_of?(::Integer)
754
+ # this location is relative to the base load address of the ELF
755
+ r.type = 'REL32'
756
+ else
757
+ et = rel.target.externals
758
+ extern = et.find_all { |name| not binding[name] }
759
+ if extern.length != 1
760
+ puts "ELF: mips_create_reloc: ignoring reloc #{rel.target} in #{section.name}: #{extern.inspect} unknown" if $VERBOSE
761
+ return
762
+ end
763
+ if not sym = @symbols.find { |s| s.name == extern.first }
764
+ puts "ELF: mips_create_reloc: ignoring reloc #{rel.target} in #{section.name}: undefined symbol #{extern.first}" if $VERBOSE
765
+ return
766
+ end
767
+ r.symbol = sym
768
+ if Expression[rel.target, :-, sym.name].bind(binding).reduce.kind_of?(::Integer)
769
+ rel.target = Expression[rel.target, :-, sym.name]
770
+ r.type = '32'
771
+ elsif Expression[rel.target, :&, 0xffff0000].reduce.kind_of?(::Integer)
772
+ lo = Expression[rel.target, :&, 0xffff].reduce
773
+ lo = lo.lexpr if lo.kind_of?(Expression) and lo.op == :& and lo.rexpr == 0xffff
774
+ if lo.kind_of?(Expression) and lo.op == :>> and lo.rexpr == 16
775
+ r.type = 'HI16'
776
+ rel.target = Expression[rel.target, :&, 0xffff0000]
777
+ # XXX offset ?
778
+ elsif lo.kind_of?(String) or (lo.kind_of(Expression) and lo.op == :+)
779
+ r.type = 'LO16'
780
+ rel.target = Expression[rel.target, :&, 0xffff0000]
781
+ # XXX offset ?
782
+ else
783
+ puts "ELF: mips_create_reloc: ignoring reloc #{lo}: cannot find matching 16 reloc type" if $VERBOSE
784
+ return
785
+ end
786
+ #elsif Expression[rel.target, :+, label_at(section.encoded, 0)].bind(section.encoded.binding).reduce.kind_of? ::Integer
787
+ # rel.target = Expression[[rel.target, :+, label_at(section.encoded, 0)], :+, off]
788
+ # r.type = 'PC32'
789
+ else
790
+ puts "ELF: mips_create_reloc: ignoring reloc #{sym.name} + #{rel.target}: cannot find matching standard reloc type" if $VERBOSE
791
+ return
792
+ end
793
+ end
794
+ @relocations << r
795
+ end
796
+
740
797
  # resets the fields of the elf headers that should be recalculated, eg phdr offset
741
798
  def invalidate_header
742
799
  @header.shoff = @header.shnum = nil
@@ -817,9 +874,13 @@ class ELF
817
874
  end
818
875
 
819
876
  if @header.type == 'REL'
820
- raise 'ET_REL encoding not supported atm, come back later'
877
+ encode_rel
878
+ else
879
+ encode_elf
821
880
  end
881
+ end
822
882
 
883
+ def encode_elf
823
884
  @encoded = EncodedData.new
824
885
  if @header.type != 'EXEC' or @segments.find { |i| i.type == 'INTERP' }
825
886
  # create a .dynamic section unless we are an ET_EXEC with .nointerp
@@ -870,7 +931,7 @@ class ELF
870
931
  end
871
932
 
872
933
  # add dynamic segment
873
- if ds = @sections.find { |sec| sec.type == 'DYNAMIC' }
934
+ if ds = @sections.find { |sec| sec.type == 'DYNAMIC' } and ds.encoded.length > 1
874
935
  ds.set_default_values self
875
936
  seg = Segment.new
876
937
  seg.type = 'DYNAMIC'
@@ -979,6 +1040,36 @@ class ELF
979
1040
  @encoded.data
980
1041
  end
981
1042
 
1043
+ def encode_rel
1044
+ @encoded = EncodedData.new
1045
+ automagic_symbols
1046
+ create_relocations
1047
+
1048
+ @header.phoff = @header.phnum = @header.phentsize = 0
1049
+ @header.entry = 0
1050
+ @sections.each { |sec| sec.addr = 0 }
1051
+ st = @sections.inject(EncodedData.new) { |edata, sec| edata << sec.encode(self) }
1052
+
1053
+ binding = {}
1054
+ @encoded << @header.encode(self)
1055
+ @encoded.align 8
1056
+
1057
+ binding[@header.shoff] = @encoded.length
1058
+ @encoded << st
1059
+ @encoded.align 8
1060
+
1061
+ @sections.each { |sec|
1062
+ next if not sec.encoded
1063
+ binding[sec.offset] = @encoded.length
1064
+ sec.encoded.fixup sec.encoded.binding
1065
+ @encoded << sec.encoded
1066
+ @encoded.align 8
1067
+ }
1068
+
1069
+ @encoded.fixup! binding
1070
+ @encoded.data
1071
+ end
1072
+
982
1073
  def parse_init
983
1074
  # allow the user to specify a section, falls back to .text if none specified
984
1075
  if not defined? @cursource or not @cursource
@@ -0,0 +1,65 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/exe_format/main'
8
+ require 'metasm/encode'
9
+ require 'metasm/decode'
10
+
11
+
12
+ module Metasm
13
+ # GameBoy ROM file format
14
+ class GameBoyRom < ExeFormat
15
+ class Header < SerialStruct
16
+ # starts at 0x104 in the file
17
+ mem :logo, 0x30
18
+ str :title, 0x10
19
+ byte :sgb_flag
20
+ byte :cartridge_type
21
+ byte :rom_size # n => (n+1) * 32k bytes
22
+ byte :ram_size
23
+ byte :destination_code
24
+ byte :old_licensee_code
25
+ byte :mask_rom_version
26
+ byte :header_checksum
27
+ byte :checksum_hi
28
+ byte :checksum_lo
29
+ end
30
+
31
+ def encode_byte(val) Expression[val].encode(:u8, @endianness) end
32
+ def decode_byte(edata = @encoded) edata.decode_imm(:u8, @endianness) end
33
+ def sizeof_byte ; 1 ; end
34
+
35
+
36
+ attr_accessor :header
37
+
38
+ def initialize(cpu=nil)
39
+ @endianness = (cpu ? cpu.endianness : :little)
40
+ super(cpu)
41
+ end
42
+
43
+ def decode_header
44
+ @encoded.ptr = 0x104
45
+ @header = Header.decode(self)
46
+ end
47
+
48
+ def decode
49
+ decode_header
50
+ @encoded.add_export('entrypoint', 0x100)
51
+ end
52
+
53
+ def cpu_from_headers
54
+ Z80.new('gb')
55
+ end
56
+
57
+ def each_section
58
+ yield @encoded, 0
59
+ end
60
+
61
+ def get_default_entrypoints
62
+ ['entrypoint']
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,424 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+ require 'metasm/exe_format/main'
7
+ require 'metasm/encode'
8
+ require 'metasm/decode'
9
+
10
+ module Metasm
11
+
12
+ class JavaClass < ExeFormat
13
+ MAGIC = "\xCA\xFE\xBA\xBE"
14
+
15
+ CONSTANT_TAG = {0x1 => 'Utf8', 0x3 => 'Integer',
16
+ 0x4 => 'Float', 0x5 => 'Long',
17
+ 0x6 => 'Double', 0x7 => 'Class',
18
+ 0x8 => 'String', 0x9 => 'Fieldref',
19
+ 0xa => 'Methodref', 0xb => 'InterfaceMethodref',
20
+ 0xc => 'NameAndType' }
21
+
22
+ class SerialStruct < Metasm::SerialStruct
23
+ new_int_field :u1, :u2, :u4
24
+ end
25
+
26
+ class Header < SerialStruct
27
+ mem :magic, 4, MAGIC
28
+ u2 :minor_version
29
+ u2 :major_version
30
+ end
31
+
32
+ class ConstantPool < SerialStruct
33
+ u2 :constant_pool_count
34
+ attr_accessor :constant_pool
35
+
36
+ def decode(c)
37
+ super(c)
38
+
39
+ @constant_pool = [nil]
40
+
41
+ i = 1
42
+ while i < @constant_pool_count
43
+ entry = ConstantPoolInfo.decode(c)
44
+ entry.idx = i
45
+ @constant_pool << entry
46
+ i += 1
47
+
48
+ if entry.tag =~ /Long|Double/
49
+ # we must insert a phantom cell
50
+ # for long and double constants
51
+ @constant_pool << nil
52
+ i += 1
53
+ end
54
+ end
55
+ end
56
+
57
+ def encode(c)
58
+ cp = super(c)
59
+
60
+ @constant_pool.each { |entry|
61
+ next if entry.nil?
62
+ cp << entry.encode(c)
63
+ }
64
+ cp
65
+ end
66
+
67
+ def [](idx)
68
+ @constant_pool[idx]
69
+ end
70
+
71
+ def []=(idx, val)
72
+ raise 'cannot be used to add a cp entry' if @constant_pool[idx].nil?
73
+ @constant_pool[idx] = val
74
+ end
75
+ end
76
+
77
+ class ConstantPoolInfo < SerialStruct
78
+ u1 :tag
79
+ fld_enum :tag, CONSTANT_TAG
80
+ attr_accessor :info, :idx
81
+
82
+ def decode(c)
83
+ super(c)
84
+
85
+ case @tag
86
+ when 'Utf8'
87
+ @info = ConstantUtf8.decode(c)
88
+ when /Integer|Float/
89
+ @info = ConstantIntFloat.decode(c)
90
+ when /Long|Double/
91
+ @info = ConstantLongDouble.decode(c)
92
+ when /Class|String/
93
+ @info = ConstantIndex.decode(c)
94
+ when /ref$/
95
+ @info = ConstantRef.decode(c)
96
+ when 'NameAndType'
97
+ @info = ConstantNameAndType.decode(c)
98
+ else
99
+ raise 'unkown constant tag'
100
+ return
101
+ end
102
+ end
103
+
104
+ def encode(c)
105
+ super(c) << @info.encode(c)
106
+ end
107
+ end
108
+
109
+ class ConstantUtf8 < SerialStruct
110
+ u2 :length
111
+ attr_accessor :bytes
112
+
113
+ def decode(c)
114
+ super(c)
115
+ @bytes = c.encoded.read(@length)
116
+ end
117
+
118
+ def encode(c)
119
+ super(c) << @bytes
120
+ end
121
+ end
122
+
123
+ class ConstantIntFloat < SerialStruct
124
+ u4 :bytes
125
+ end
126
+
127
+ class ConstantLongDouble < SerialStruct
128
+ u4 :high_bytes
129
+ u4 :low_bytes
130
+ end
131
+
132
+ class ConstantIndex < SerialStruct
133
+ u2 :index
134
+ end
135
+
136
+ class ConstantRef < SerialStruct
137
+ u2 :class_index
138
+ u2 :name_and_type_index
139
+ end
140
+
141
+ class ConstantNameAndType < SerialStruct
142
+ u2 :name_index
143
+ u2 :descriptor_index
144
+ end
145
+
146
+ class ClassInfo < SerialStruct
147
+ u2 :access_flags
148
+ u2 :this_class
149
+ u2 :super_class
150
+ end
151
+
152
+ class Interfaces < SerialStruct
153
+ u2 :interfaces_count
154
+ attr_accessor :interfaces
155
+
156
+ def decode(c)
157
+ super(c)
158
+
159
+ @interfaces = []
160
+ @interfaces_count.times {
161
+ @interfaces << ConstantIndex.decode(c)
162
+ }
163
+ end
164
+
165
+ def encode(c)
166
+ ret = super(c)
167
+
168
+ @interfaces.each { |e|
169
+ ret << e.encode(c)
170
+ }
171
+ ret
172
+ end
173
+
174
+ def [](idx)
175
+ @interfaces[idx]
176
+ end
177
+ end
178
+
179
+ class Fields < SerialStruct
180
+ u2 :fields_count
181
+ attr_accessor :fields
182
+
183
+ def decode(c)
184
+ super(c)
185
+ @fields = []
186
+ @fields_count.times {
187
+ @fields << FieldMethodInfo.decode(c)
188
+ }
189
+ end
190
+
191
+ def encode(c)
192
+ ret = super(c)
193
+
194
+ @fields.each { |e|
195
+ ret << e.encode(c)
196
+ }
197
+ ret
198
+ end
199
+
200
+ def [](idx)
201
+ @fields[idx]
202
+ end
203
+ end
204
+
205
+ class Methods < SerialStruct
206
+ u2 :methods_count
207
+ attr_accessor :methods
208
+
209
+ def decode(c)
210
+ super(c)
211
+ @methods = []
212
+ @methods_count.times {
213
+ @methods << FieldMethodInfo.decode(c)
214
+ }
215
+ end
216
+
217
+ def encode(c)
218
+ ret = super(c)
219
+
220
+ @methods.each { |e|
221
+ ret << e.encode(c)
222
+ }
223
+ ret
224
+ end
225
+
226
+ def [](idx)
227
+ @methods[idx]
228
+ end
229
+ end
230
+
231
+ class FieldMethodInfo < SerialStruct
232
+ u2 :access_flags
233
+ u2 :name_index
234
+ u2 :descriptor_index
235
+ attr_accessor :attributes
236
+
237
+ def decode(c)
238
+ super(c)
239
+ @attributes = Attributes.decode(c)
240
+ end
241
+
242
+ def encode(c)
243
+ super(c) << @attributes.encode(c)
244
+ end
245
+ end
246
+
247
+ class Attributes < SerialStruct
248
+ u2 :attributes_count
249
+ attr_accessor :attributes
250
+
251
+ def decode(c)
252
+ super(c)
253
+
254
+ @attributes = []
255
+ @attributes_count.times { |i|
256
+ @attributes << AttributeInfo.decode(c)
257
+ }
258
+ end
259
+
260
+ def encode(c)
261
+ ret = super(c)
262
+
263
+ @attributes.each { |e|
264
+ ret << e.encode(c)
265
+ }
266
+ ret
267
+ end
268
+
269
+ def [](idx)
270
+ @attributes[idx]
271
+ end
272
+ end
273
+
274
+ class AttributeInfo < SerialStruct
275
+ u2 :attribute_name_index
276
+ u4 :attribute_length
277
+ attr_accessor :data
278
+
279
+ def decode(c)
280
+ super(c)
281
+ @data = c.encoded.read(@attribute_length)
282
+ end
283
+
284
+ def encode(c)
285
+ super(c) << @data
286
+ end
287
+ end
288
+
289
+ def encode_u1(val) Expression[val].encode(:u8, @endianness) end
290
+ def encode_u2(val) Expression[val].encode(:u16, @endianness) end
291
+ def encode_u4(val) Expression[val].encode(:u32, @endianness) end
292
+ def decode_u1(edata = @encoded) edata.decode_imm(:u8, @endianness) end
293
+ def decode_u2(edata = @encoded) edata.decode_imm(:u16, @endianness) end
294
+ def decode_u4(edata = @encoded) edata.decode_imm(:u32, @endianness) end
295
+ def sizeof_u1 ; 1 ; end
296
+ def sizeof_u2 ; 2 ; end
297
+ def sizeof_u4 ; 4 ; end
298
+
299
+ attr_accessor :header, :constant_pool, :class_info, :interfaces, :fields, :methods, :attributes
300
+
301
+ def initialize(endianness=:big)
302
+ @endianness = endianness
303
+ @encoded = EncodedData.new
304
+ super()
305
+ end
306
+
307
+ def decode
308
+ @header = Header.decode(self)
309
+ @constant_pool = ConstantPool.decode(self)
310
+ @class_info = ClassInfo.decode(self)
311
+ @interfaces = Interfaces.decode(self)
312
+ @fields = Fields.decode(self)
313
+ @methods = Methods.decode(self)
314
+ @attributes = Attributes.decode(self)
315
+ end
316
+
317
+ def encode
318
+ @encoded = EncodedData.new
319
+ @encoded << @header.encode(self)
320
+ @encoded << @constant_pool.encode(self)
321
+ @encoded << @class_info.encode(self)
322
+ @encoded << @interfaces.encode(self)
323
+ @encoded << @fields.encode(self)
324
+ @encoded << @methods.encode(self)
325
+ @encoded << @attributes.encode(self)
326
+ @encoded.data
327
+ end
328
+
329
+ def cpu_from_headers
330
+ raise 'JVM'
331
+ end
332
+
333
+ def each_section
334
+ raise 'n/a'
335
+ end
336
+
337
+ def get_default_entrypoints
338
+ []
339
+ end
340
+
341
+ def string_at(idx)
342
+ loop do
343
+ tmp = @constant_pool[idx].info
344
+ return tmp.bytes if tmp.kind_of? ConstantUtf8
345
+ idx = tmp.index
346
+ end
347
+ end
348
+
349
+ def decode_methodref(mref)
350
+ class_idx = mref.info.class_index
351
+ nt_idx = mref.info.name_and_type_index
352
+ name_idx = @constant_pool[nt_idx].info.name_index
353
+ desc_idx = @constant_pool[nt_idx].info.descriptor_index
354
+
355
+ string_at(class_idx) + '/' + string_at(name_idx) + string_at(desc_idx)
356
+ end
357
+
358
+ def cp_add(cpi, tag)
359
+ cpe = ConstantPoolInfo.new
360
+ cpe.tag = tag
361
+ cpe.info = cpi
362
+ cpe.idx = @constant_pool.constant_pool_count
363
+
364
+ @constant_pool.constant_pool << cpe
365
+ @constant_pool.constant_pool_count += 1
366
+ @constant_pool.constant_pool_count += 1 if tag =~ /Long|Double/
367
+
368
+ cpe.idx
369
+ end
370
+
371
+ def cp_find(tag)
372
+ constant_pool.constant_pool.each { |e|
373
+ next if !e or e.tag != tag
374
+ if yield(e.info)
375
+ return e.idx
376
+ end
377
+ }
378
+ nil
379
+ end
380
+
381
+
382
+ def cp_auto_utf8(string)
383
+ if idx = cp_find('Utf8') { |i| i.bytes == string }
384
+ return idx
385
+ end
386
+
387
+ cpi = ConstantUtf8.new
388
+ cpi.bytes = string
389
+ cpi.length = string.length
390
+ cp_add(cpi, 'Utf8')
391
+ end
392
+
393
+ def cp_auto_class(classname)
394
+ if idx = cp_find('Class') { |i| string_at(i.index) == classname }
395
+ return idx
396
+ end
397
+
398
+ cpi = ConstantIndex.new
399
+ cpi.index = cp_auto_utf8(classname)
400
+ cp_add(cpi, 'Class')
401
+ end
402
+
403
+ def cp_add_methodref(classname, name, descriptor)
404
+ nat = ConstantNameAndType.new
405
+ nat.name_index = cp_auto_utf8(name)
406
+ nat.descriptor_index = cp_auto_utf8(descriptor)
407
+ natidx = cp_add(nat, 'NameAndType')
408
+
409
+ cpi = ConstantRef.new
410
+ cpi.class_index = cp_auto_class(classname)
411
+ cpi.name_and_type_index = natidx
412
+
413
+ cp_add(cpi, 'Methodref')
414
+ end
415
+
416
+ def attribute_create(name, data)
417
+ a = AttributeInfo.new
418
+ a.attribute_name_index = cp_auto_utf8(name)
419
+ a.attribute_length = data.size
420
+ a.data = data
421
+ a
422
+ end
423
+ end
424
+ end