metasm 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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