metasm 1.0.0

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 (192) hide show
  1. data/BUGS +11 -0
  2. data/CREDITS +17 -0
  3. data/README +270 -0
  4. data/TODO +114 -0
  5. data/doc/code_organisation.txt +146 -0
  6. data/doc/const_missing.txt +16 -0
  7. data/doc/core_classes.txt +75 -0
  8. data/doc/feature_list.txt +53 -0
  9. data/doc/index.txt +59 -0
  10. data/doc/install_notes.txt +170 -0
  11. data/doc/style.css +3 -0
  12. data/doc/use_cases.txt +18 -0
  13. data/lib/metasm.rb +80 -0
  14. data/lib/metasm/arm.rb +12 -0
  15. data/lib/metasm/arm/debug.rb +39 -0
  16. data/lib/metasm/arm/decode.rb +167 -0
  17. data/lib/metasm/arm/encode.rb +77 -0
  18. data/lib/metasm/arm/main.rb +75 -0
  19. data/lib/metasm/arm/opcodes.rb +177 -0
  20. data/lib/metasm/arm/parse.rb +130 -0
  21. data/lib/metasm/arm/render.rb +55 -0
  22. data/lib/metasm/compile_c.rb +1457 -0
  23. data/lib/metasm/dalvik.rb +8 -0
  24. data/lib/metasm/dalvik/decode.rb +196 -0
  25. data/lib/metasm/dalvik/main.rb +60 -0
  26. data/lib/metasm/dalvik/opcodes.rb +366 -0
  27. data/lib/metasm/decode.rb +213 -0
  28. data/lib/metasm/decompile.rb +2659 -0
  29. data/lib/metasm/disassemble.rb +2068 -0
  30. data/lib/metasm/disassemble_api.rb +1280 -0
  31. data/lib/metasm/dynldr.rb +1329 -0
  32. data/lib/metasm/encode.rb +333 -0
  33. data/lib/metasm/exe_format/a_out.rb +194 -0
  34. data/lib/metasm/exe_format/autoexe.rb +82 -0
  35. data/lib/metasm/exe_format/bflt.rb +189 -0
  36. data/lib/metasm/exe_format/coff.rb +455 -0
  37. data/lib/metasm/exe_format/coff_decode.rb +901 -0
  38. data/lib/metasm/exe_format/coff_encode.rb +1078 -0
  39. data/lib/metasm/exe_format/dex.rb +457 -0
  40. data/lib/metasm/exe_format/dol.rb +145 -0
  41. data/lib/metasm/exe_format/elf.rb +923 -0
  42. data/lib/metasm/exe_format/elf_decode.rb +979 -0
  43. data/lib/metasm/exe_format/elf_encode.rb +1375 -0
  44. data/lib/metasm/exe_format/macho.rb +827 -0
  45. data/lib/metasm/exe_format/main.rb +228 -0
  46. data/lib/metasm/exe_format/mz.rb +164 -0
  47. data/lib/metasm/exe_format/nds.rb +172 -0
  48. data/lib/metasm/exe_format/pe.rb +437 -0
  49. data/lib/metasm/exe_format/serialstruct.rb +246 -0
  50. data/lib/metasm/exe_format/shellcode.rb +114 -0
  51. data/lib/metasm/exe_format/xcoff.rb +167 -0
  52. data/lib/metasm/gui.rb +23 -0
  53. data/lib/metasm/gui/cstruct.rb +373 -0
  54. data/lib/metasm/gui/dasm_coverage.rb +199 -0
  55. data/lib/metasm/gui/dasm_decomp.rb +369 -0
  56. data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
  57. data/lib/metasm/gui/dasm_graph.rb +1354 -0
  58. data/lib/metasm/gui/dasm_hex.rb +543 -0
  59. data/lib/metasm/gui/dasm_listing.rb +599 -0
  60. data/lib/metasm/gui/dasm_main.rb +906 -0
  61. data/lib/metasm/gui/dasm_opcodes.rb +291 -0
  62. data/lib/metasm/gui/debug.rb +1228 -0
  63. data/lib/metasm/gui/gtk.rb +884 -0
  64. data/lib/metasm/gui/qt.rb +495 -0
  65. data/lib/metasm/gui/win32.rb +3004 -0
  66. data/lib/metasm/gui/x11.rb +621 -0
  67. data/lib/metasm/ia32.rb +14 -0
  68. data/lib/metasm/ia32/compile_c.rb +1523 -0
  69. data/lib/metasm/ia32/debug.rb +193 -0
  70. data/lib/metasm/ia32/decode.rb +1167 -0
  71. data/lib/metasm/ia32/decompile.rb +564 -0
  72. data/lib/metasm/ia32/encode.rb +314 -0
  73. data/lib/metasm/ia32/main.rb +233 -0
  74. data/lib/metasm/ia32/opcodes.rb +872 -0
  75. data/lib/metasm/ia32/parse.rb +327 -0
  76. data/lib/metasm/ia32/render.rb +91 -0
  77. data/lib/metasm/main.rb +1193 -0
  78. data/lib/metasm/mips.rb +11 -0
  79. data/lib/metasm/mips/compile_c.rb +7 -0
  80. data/lib/metasm/mips/decode.rb +253 -0
  81. data/lib/metasm/mips/encode.rb +51 -0
  82. data/lib/metasm/mips/main.rb +72 -0
  83. data/lib/metasm/mips/opcodes.rb +443 -0
  84. data/lib/metasm/mips/parse.rb +51 -0
  85. data/lib/metasm/mips/render.rb +43 -0
  86. data/lib/metasm/os/gnu_exports.rb +270 -0
  87. data/lib/metasm/os/linux.rb +1112 -0
  88. data/lib/metasm/os/main.rb +1686 -0
  89. data/lib/metasm/os/remote.rb +527 -0
  90. data/lib/metasm/os/windows.rb +2027 -0
  91. data/lib/metasm/os/windows_exports.rb +745 -0
  92. data/lib/metasm/parse.rb +876 -0
  93. data/lib/metasm/parse_c.rb +3938 -0
  94. data/lib/metasm/pic16c/decode.rb +42 -0
  95. data/lib/metasm/pic16c/main.rb +17 -0
  96. data/lib/metasm/pic16c/opcodes.rb +68 -0
  97. data/lib/metasm/ppc.rb +11 -0
  98. data/lib/metasm/ppc/decode.rb +264 -0
  99. data/lib/metasm/ppc/decompile.rb +251 -0
  100. data/lib/metasm/ppc/encode.rb +51 -0
  101. data/lib/metasm/ppc/main.rb +129 -0
  102. data/lib/metasm/ppc/opcodes.rb +410 -0
  103. data/lib/metasm/ppc/parse.rb +52 -0
  104. data/lib/metasm/preprocessor.rb +1277 -0
  105. data/lib/metasm/render.rb +130 -0
  106. data/lib/metasm/sh4.rb +8 -0
  107. data/lib/metasm/sh4/decode.rb +336 -0
  108. data/lib/metasm/sh4/main.rb +292 -0
  109. data/lib/metasm/sh4/opcodes.rb +381 -0
  110. data/lib/metasm/x86_64.rb +12 -0
  111. data/lib/metasm/x86_64/compile_c.rb +1025 -0
  112. data/lib/metasm/x86_64/debug.rb +59 -0
  113. data/lib/metasm/x86_64/decode.rb +268 -0
  114. data/lib/metasm/x86_64/encode.rb +264 -0
  115. data/lib/metasm/x86_64/main.rb +135 -0
  116. data/lib/metasm/x86_64/opcodes.rb +118 -0
  117. data/lib/metasm/x86_64/parse.rb +68 -0
  118. data/misc/bottleneck.rb +61 -0
  119. data/misc/cheader-findpppath.rb +58 -0
  120. data/misc/hexdiff.rb +74 -0
  121. data/misc/hexdump.rb +55 -0
  122. data/misc/metasm-all.rb +13 -0
  123. data/misc/objdiff.rb +47 -0
  124. data/misc/objscan.rb +40 -0
  125. data/misc/pdfparse.rb +661 -0
  126. data/misc/ppc_pdf2oplist.rb +192 -0
  127. data/misc/tcp_proxy_hex.rb +84 -0
  128. data/misc/txt2html.rb +440 -0
  129. data/samples/a.out.rb +31 -0
  130. data/samples/asmsyntax.rb +77 -0
  131. data/samples/bindiff.rb +555 -0
  132. data/samples/compilation-steps.rb +49 -0
  133. data/samples/cparser_makestackoffset.rb +55 -0
  134. data/samples/dasm-backtrack.rb +38 -0
  135. data/samples/dasmnavig.rb +318 -0
  136. data/samples/dbg-apihook.rb +228 -0
  137. data/samples/dbghelp.rb +143 -0
  138. data/samples/disassemble-gui.rb +102 -0
  139. data/samples/disassemble.rb +133 -0
  140. data/samples/dump_upx.rb +95 -0
  141. data/samples/dynamic_ruby.rb +1929 -0
  142. data/samples/elf_list_needed.rb +46 -0
  143. data/samples/elf_listexports.rb +33 -0
  144. data/samples/elfencode.rb +25 -0
  145. data/samples/exeencode.rb +128 -0
  146. data/samples/factorize-headers-elfimports.rb +77 -0
  147. data/samples/factorize-headers-peimports.rb +109 -0
  148. data/samples/factorize-headers.rb +43 -0
  149. data/samples/gdbclient.rb +583 -0
  150. data/samples/generate_libsigs.rb +102 -0
  151. data/samples/hotfix_gtk_dbg.rb +59 -0
  152. data/samples/install_win_env.rb +78 -0
  153. data/samples/lindebug.rb +924 -0
  154. data/samples/linux_injectsyscall.rb +95 -0
  155. data/samples/machoencode.rb +31 -0
  156. data/samples/metasm-shell.rb +91 -0
  157. data/samples/pe-hook.rb +69 -0
  158. data/samples/pe-ia32-cpuid.rb +203 -0
  159. data/samples/pe-mips.rb +35 -0
  160. data/samples/pe-shutdown.rb +78 -0
  161. data/samples/pe-testrelocs.rb +51 -0
  162. data/samples/pe-testrsrc.rb +24 -0
  163. data/samples/pe_listexports.rb +31 -0
  164. data/samples/peencode.rb +19 -0
  165. data/samples/peldr.rb +494 -0
  166. data/samples/preprocess-flatten.rb +19 -0
  167. data/samples/r0trace.rb +308 -0
  168. data/samples/rubstop.rb +399 -0
  169. data/samples/scan_pt_gnu_stack.rb +54 -0
  170. data/samples/scanpeexports.rb +62 -0
  171. data/samples/shellcode-c.rb +40 -0
  172. data/samples/shellcode-dynlink.rb +146 -0
  173. data/samples/source.asm +34 -0
  174. data/samples/struct_offset.rb +47 -0
  175. data/samples/testpe.rb +32 -0
  176. data/samples/testraw.rb +45 -0
  177. data/samples/win32genloader.rb +132 -0
  178. data/samples/win32hooker-advanced.rb +169 -0
  179. data/samples/win32hooker.rb +96 -0
  180. data/samples/win32livedasm.rb +33 -0
  181. data/samples/win32remotescan.rb +133 -0
  182. data/samples/wintrace.rb +92 -0
  183. data/tests/all.rb +8 -0
  184. data/tests/dasm.rb +39 -0
  185. data/tests/dynldr.rb +35 -0
  186. data/tests/encodeddata.rb +132 -0
  187. data/tests/ia32.rb +82 -0
  188. data/tests/mips.rb +116 -0
  189. data/tests/parse_c.rb +239 -0
  190. data/tests/preprocessor.rb +269 -0
  191. data/tests/x86_64.rb +62 -0
  192. metadata +255 -0
@@ -0,0 +1,92 @@
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
+ #
8
+ # this is a simple executable tracer for Windows using the
9
+ # Metasm windows debug api abstraction
10
+ # all callbacks are full ruby, so this is extremely slow !
11
+ #
12
+
13
+ require 'metasm'
14
+ Metasm.require 'samples/metasm-shell'
15
+
16
+ class Tracer < Metasm::WinDbgAPI
17
+ def initialize(*a)
18
+ super(*a)
19
+ @label = {}
20
+ @prog = Metasm::ExeFormat.new(Metasm::Ia32.new)
21
+ loop
22
+ puts 'finished'
23
+ end
24
+
25
+ def handler_newprocess(pid, tid, info)
26
+ hide_debugger(pid, tid, info)
27
+ Metasm::WinAPI::DBG_CONTINUE
28
+ end
29
+
30
+ def handler_newthread(pid, tid, info)
31
+ do_singlestep(pid, tid)
32
+ Metasm::WinAPI::DBG_CONTINUE
33
+ end
34
+
35
+ def handler_exception(pid, tid, info)
36
+ do_singlestep(pid, tid) if @hthread[pid] and @hthread[pid][tid]
37
+ case info.code
38
+ when Metasm::WinAPI::STATUS_SINGLE_STEP
39
+ Metasm::WinAPI::DBG_CONTINUE
40
+ else super(pid, tid, info)
41
+ end
42
+ end
43
+
44
+ def handler_loaddll(pid, tid, info)
45
+ # update @label with exported symbols
46
+ pe = Metasm::LoadedPE.load(@mem[pid][info.imagebase, 0x1000000])
47
+ pe.decode_header
48
+ pe.decode_exports
49
+ libname = read_str_indirect(pid, info.imagename, info.unicode)
50
+ if pe.export
51
+ libname = pe.export.libname if libname == ''
52
+ pe.export.exports.each { |e|
53
+ next if not r = pe.label_rva(e.target)
54
+ @label[info.imagebase + r] = libname + '!' + (e.name || "ord_#{e.ordinal}")
55
+ }
56
+ end
57
+ super(pid, tid, info)
58
+ end
59
+
60
+ # dumps the opcode at eip, sets the trace flag
61
+ def do_singlestep(pid, tid)
62
+ ctx = get_context(pid, tid)
63
+ eip = ctx[:eip]
64
+
65
+ if l = @label[eip]
66
+ puts l + ':'
67
+ end
68
+ if $VERBOSE
69
+ bin = @mem[pid][eip, 16]
70
+ di = @prog.cpu.decode_instruction(Metasm::EncodedData.new(bin), eip)
71
+ puts "#{'%08X' % eip} #{di.instruction}"
72
+ end
73
+
74
+ ctx[:eflags] |= 0x100
75
+ end
76
+
77
+ # resets the DebuggerPresent field of the PEB
78
+ def hide_debugger(pid, tid, info)
79
+ peb = @mem[pid][info.threadlocalbase + 0x30, 4].unpack('L').first
80
+ @mem[pid][peb + 2, 2] = [0].pack('S')
81
+ end
82
+ end
83
+
84
+ if $0 == __FILE__
85
+ Metasm::WinOS.get_debug_privilege
86
+ if ARGV.empty?
87
+ # display list of running processes if no target found
88
+ puts Metasm::WinOS.list_processes.sort_by { |pr_| pr_.pid }
89
+ abort 'target needed'
90
+ end
91
+ Tracer.new ARGV.shift.dup
92
+ end
@@ -0,0 +1,8 @@
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
+ Dir['tests/*.rb'].each { |f| require f }
8
+
@@ -0,0 +1,39 @@
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 'test/unit'
8
+ require 'metasm'
9
+
10
+ class TestPreproc < Test::Unit::TestCase
11
+ include Metasm
12
+
13
+ def asm_dasm(src)
14
+ @cpu ||= Ia32.new
15
+ raw = Shellcode.assemble(src, @cpu).encode_string
16
+ dasm = Shellcode.decode(raw, @cpu).disassembler
17
+ dasm.disassemble_fast(0)
18
+ dasm
19
+ end
20
+
21
+ def do_test_bd2(src, bd)
22
+ d = asm_dasm(src)
23
+ calc_bd = d.compose_bt_binding(*d.decoded[0].block.list)
24
+ calc_bd.delete_if { |k, v| k.to_s =~ /flag/ }
25
+ assert_equal bd, calc_bd
26
+ end
27
+
28
+ def test_compose_bt_binding
29
+ do_test_bd2 'mov eax, 1 mov ebx, 2', :eax => Expression[1], :ebx => Expression[2]
30
+ do_test_bd2 'mov eax, 1 push eax', :eax => Expression[1], Indirection[:esp, 4] => Expression[1], :esp => Expression[:esp, :+, -4]
31
+ do_test_bd2 'mov [eax], ebx mov [eax], ecx', Indirection[:eax, 4] => Expression[:ecx]
32
+ do_test_bd2 'add eax, 4 mov [eax], ecx', Indirection[:eax, 4] => Expression[:ecx], :eax => Expression[:eax, :+, 4]
33
+ do_test_bd2 'mov [eax], ecx mov ebx, eax', :ebx => Expression[:eax], Indirection[:eax, 4] => Expression[:ecx], Indirection[:ebx, 4] => Expression[:ecx]
34
+ do_test_bd2 'mov [eax], ecx add eax, 4', :eax => Expression[:eax, :+, 4], Indirection[[:eax, :+, -4], 4] => Expression[:ecx]
35
+ do_test_bd2 'mov [eax+4], ecx add eax, 4', :eax => Expression[:eax, :+, 4], Indirection[:eax, 4] => Expression[:ecx]
36
+ do_test_bd2 'push 1 push 2', :esp => Expression[:esp, :+, -8], Indirection[:esp, 4] => Expression[2], Indirection[[:esp, :+, 4], 4] => Expression[1]
37
+ end
38
+ end
39
+
@@ -0,0 +1,35 @@
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 'test/unit'
7
+ require 'metasm'
8
+
9
+ class TestDynldr < Test::Unit::TestCase
10
+
11
+ def test_dynldr
12
+ str = "1234"
13
+ d = Metasm::DynLdr
14
+ d.new_api_c('int memcpy(char*, char*, int)')
15
+ d.memcpy(str, "9999", 2)
16
+ assert_equal('9934', str)
17
+
18
+ c_src = <<EOS
19
+ int sprintf(char*, char*, ...);
20
+ void fufu(int i, char* ptr)
21
+ {
22
+ sprintf(ptr, "lolzor %i\\n", i);
23
+ }
24
+ EOS
25
+ buf = 'aaaaaaaaaaaaaaaaaa'
26
+ d.new_func_c(c_src) { d.fufu(42, buf) }
27
+ assert_equal("lolzor 42\n\000aaaaaaa", buf)
28
+
29
+ if d.host_cpu.shortname == 'ia32'
30
+ ret = d.new_func_asm('int __fastcall bla(int)', "lea eax, [ecx+1]\nret") { d.bla(42) }
31
+ assert_equal(43, ret)
32
+ assert_equal(false, d.respond_to?(:bla))
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,132 @@
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 'test/unit'
8
+ require 'metasm/exe_format/shellcode'
9
+
10
+ class TestEncodedData < Test::Unit::TestCase
11
+ def compile(src)
12
+ p = Metasm::Shellcode.assemble(Metasm::UnknownCPU.new(32, :little), src)
13
+ p.encoded
14
+ end
15
+
16
+ def test_basic
17
+ e = compile <<EOS
18
+ toto db 42
19
+ tutu db 48
20
+ dd bla
21
+ EOS
22
+ assert_equal(6, e.virtsize)
23
+ assert_equal(2, e.export.keys.length)
24
+ assert_equal(0, e.export['toto'])
25
+ assert_equal(1, e.reloc.keys.length)
26
+ assert_equal('bla', e.reloc[2].target.reduce.rexpr)
27
+ end
28
+
29
+ def test_slice
30
+ e = compile <<EOS
31
+ db 4 dup(1)
32
+ toto:
33
+ db 4 dup(2)
34
+ db 4 dup(?)
35
+ foo:
36
+ dd bla
37
+ tutu:
38
+ EOS
39
+ e1 = e[4, 8]
40
+ e2 = e[4..11]
41
+ e3 = e[4...12]
42
+ e4 = e['toto', 8]
43
+ e5 = e['toto'...'foo']
44
+ assert_equal([e1.data, e1.virtsize], [e2.data, e2.virtsize])
45
+ assert_equal([e1.data, e1.virtsize], [e3.data, e3.virtsize])
46
+ assert_equal([e1.data, e1.virtsize], [e4.data, e4.virtsize])
47
+ assert_equal([e1.data, e1.virtsize], [e5.data, e5.virtsize])
48
+ assert_equal(nil, e[53, 12])
49
+ assert_equal(2, e[2, 2].export['toto'])
50
+ assert_equal(4, e[0, 4].export['toto'])
51
+ assert_equal(1, e[0, 16].reloc.length)
52
+ assert_equal(0, e[0, 15].reloc.length)
53
+ assert_equal(0, e[13, 8].reloc.length)
54
+ assert_equal(1, e[12, 4].reloc.length)
55
+ assert_equal(16, e[0, 50].virtsize)
56
+ assert_equal(1, e[15, 50].virtsize)
57
+ e.align 5
58
+ assert_equal(20, e.virtsize)
59
+ e.align 5
60
+ assert_equal(20, e.virtsize)
61
+ e.fill 30
62
+ assert_equal(30, e.virtsize)
63
+ end
64
+
65
+ def test_slice2
66
+ e = compile <<EOS
67
+ db '1'
68
+ toto:
69
+ .pad
70
+ tutu:
71
+ db '0'
72
+ .offset toto+11
73
+ EOS
74
+ assert_equal(12, e.virtsize)
75
+ assert_equal(11, e.export['tutu'])
76
+ e[1..10] = 'abcdefghij'
77
+ assert_equal(12, e.virtsize)
78
+ assert_equal(2, e.export.length)
79
+ e[1, 10] = 'jihgfedcba'
80
+ assert_equal(12, e.virtsize)
81
+ e[1...11] = 'abcdefghij'
82
+ assert_equal(12, e.virtsize)
83
+ e.patch('toto', 'tutu', 'xxx')
84
+ assert_equal('1xxxdefghij0', e.data)
85
+ e[1..10] = 'z'
86
+ assert_equal(3, e.virtsize)
87
+ assert_equal(2, e.export['tutu'])
88
+ assert_raise(Metasm::EncodeError) { e.patch('toto', 'tutu', 'toolong') }
89
+
90
+ e = compile <<EOS
91
+ db '1'
92
+ dd rel
93
+ db '2'
94
+ EOS
95
+ assert_equal(1, e.reloc.length)
96
+ assert_equal(1, e[1, 4].reloc.length)
97
+ assert_equal(1, e[1..4].reloc.length)
98
+ assert_equal(1, e[1...5].reloc.length)
99
+ assert_equal(0, e[2, 8].reloc.length)
100
+ assert_equal(0, e[1, 3].reloc.length)
101
+ end
102
+
103
+ def test_fixup
104
+ e = compile <<EOS
105
+ db 1
106
+ db toto + tata
107
+ dd tutu
108
+ EOS
109
+ assert_equal(2, e.reloc.length)
110
+ e.fixup!('toto' => 42)
111
+ assert_raise(Metasm::EncodeError) { e.fixup('tata' => 192349129) }
112
+ e.fixup('tata' => -12)
113
+ assert_equal(30.chr[0], e.data[1])
114
+ assert_equal(1, e.reloc.length)
115
+ assert_equal(2, e.offset_of_reloc('tutu'))
116
+ assert_equal(2, e.offset_of_reloc(Metasm::Expression[:+, 'tutu']))
117
+ e.fixup('tutu' => 1024)
118
+ assert_equal("\1\x1e\0\4\0\0", e.data)
119
+
120
+ ee = Metasm::Expression[:+, 'bla'].encode(:u16, :big)
121
+ ee.fixup('bla' => 1024)
122
+ assert_equal("\4\0", ee.data)
123
+
124
+ eee = compile <<EOS
125
+ db abc - def
126
+ def:
127
+ db 12 dup(?, 3 dup('x'))
128
+ abc:
129
+ EOS
130
+ assert_equal((12*4).chr[0], eee.data[0])
131
+ end
132
+ end
@@ -0,0 +1,82 @@
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 'test/unit'
8
+ require 'metasm'
9
+
10
+ class TestIa32 < Test::Unit::TestCase
11
+ @@cpu32 = Metasm::Ia32.new
12
+ @@cpu16 = Metasm::Ia32.new(16)
13
+ def assemble(src, cpu=@@cpu32)
14
+ Metasm::Shellcode.assemble(cpu, src).encode_string
15
+ end
16
+
17
+ def assert_equal(a, b) super(b, a) end
18
+
19
+ def test_basic
20
+ assert_equal(assemble("nop"), "\x90")
21
+ assert_equal(assemble("push eax"), "\x50")
22
+ assert_equal(assemble("push 2"), "\x6a\x02")
23
+ assert_equal(assemble("push 142"), "\x68\x8e\0\0\0")
24
+ end
25
+
26
+ def test_sz
27
+ assert_equal(assemble("dec eax"), "\x48")
28
+ assert_equal(assemble("dec ax"), "\x66\x48")
29
+ assert_equal(assemble("dec al"), "\xfe\xc8")
30
+ assert_equal(assemble("arpl [edi+70h], bp"), "cop")
31
+ end
32
+
33
+ def test_16
34
+ assert_equal(assemble("push 142", @@cpu16), "\x68\x8e\0")
35
+ assert_equal(assemble("code16 push 142", @@cpu16), "\x68\x8e\0")
36
+ assert_equal(assemble("code16 push 142"), "\x68\x8e\0")
37
+ assert_equal(assemble("push.i16 142"), "\x66\x68\x8e\0")
38
+ assert_equal(assemble("mov eax, 42"), "\xb8\x2a\0\0\0")
39
+ assert_equal(assemble("code16 mov ax, 42"), "\xb8\x2a\0")
40
+ end
41
+
42
+ def test_jmp
43
+ assert_equal(assemble("jmp $"), "\xeb\xfe")
44
+ assert_equal(assemble("jmp.i32 $"), "\xe9\xfb\xff\xff\xff")
45
+ end
46
+
47
+ def test_mrmsz
48
+ assert_equal(assemble("mov [eax], ebx"), "\x89\x18")
49
+ assert_equal(assemble("mov [eax], bl"), "\x88\x18")
50
+ assert_equal(assemble("mov ebx, [eax]"), "\x8b\x18")
51
+ assert_equal(assemble("mov bl, [eax]"), "\x8a\x18")
52
+ assert_equal(assemble("mov bl, [bx]"), "\x67\x8a\x1f")
53
+ assert_equal(assemble("mov bl, [bx]", @@cpu16), "\x8a\x1f")
54
+ assert_equal(assemble("code16 mov bl, [bx]"), "\x8a\x1f")
55
+ assert_equal(assemble("mov bl, [0]"), "\x8a\x1d\0\0\0\0")
56
+ assert_equal(assemble("mov.a16 bl, [0]"), "\x67\x8a\x1e\0\0")
57
+ end
58
+
59
+ def test_err
60
+ assert_raise(Metasm::ParseError) { assemble("add eax") }
61
+ assert_raise(Metasm::ParseError) { assemble("add add, ebx") }
62
+ assert_raise(Metasm::ParseError) { assemble("add 42, ebx") }
63
+ assert_raise(Metasm::ParseError) { assemble("add [bx+ax]") }
64
+ end
65
+
66
+ def test_C
67
+ src = "int bla(void) { volatile int i=0; return ++i; }"
68
+ assert_equal(Metasm::Shellcode.compile_c(@@cpu32, src).encode_string,
69
+ ["5589E583EC04C745FC00000000FF45FC8B45FC89EC5DC3"].pack('H*'))
70
+ end
71
+
72
+ def disassemble(bin, cpu=@@cpu32)
73
+ Metasm::Shellcode.disassemble(cpu, bin)
74
+ end
75
+
76
+ def test_dasm
77
+ d = disassemble("\x90")
78
+ assert_equal(d.decoded[0].class, Metasm::DecodedInstruction)
79
+ assert_equal(d.decoded[0].opcode.name, "nop")
80
+ end
81
+
82
+ end
@@ -0,0 +1,116 @@
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 'test/unit'
7
+ require 'metasm'
8
+
9
+ class TestMips < Test::Unit::TestCase
10
+
11
+ def test_enc
12
+ sc = Metasm::Shellcode.assemble(Metasm::MIPS.new(:big), <<EOS)
13
+ ;
14
+ ; MIPS nul-free xor decoder
15
+ ;
16
+ ; (C) 2006 Julien TINNES
17
+ ; <julien at cr0.org>
18
+ ;
19
+ ; The first four bytes in encoded shellcode must be the xor key
20
+ ; This means that you have to put the xor key right after
21
+ ; this xor decoder
22
+ ; This key will be considered part of the encoded shellcode
23
+ ; by this decoder and will be xored, thus becoming 4NULs, meaning nop
24
+ ;
25
+ ; This is Linux-only because I use the cacheflush system call
26
+ ;
27
+ ; You can use shellforge to assemble this, but be sure to discard all
28
+ ; the nul bytes at the end (everything after x01\\x4a\\x54\\x0c)
29
+ ;
30
+ ; change 2 bytes in the first instruction's opcode with the number of passes
31
+ ; the number of passes is the number of xor operations to apply, which should be
32
+ ; 1 (for the key) + the number of 4-bytes words you have in your shellcode
33
+ ; you must encode ~(number_of_passes + 1) (to ensure that you're nul-free)
34
+
35
+
36
+ ;.text
37
+ ;.align 2
38
+ ;.globl main
39
+ ;.ent main
40
+ ;.type main,@function
41
+
42
+ main:
43
+
44
+ li $14, -5 ; 4 passes
45
+ nor $14, $14, $0 ; put number of passes in $14
46
+
47
+ li $11,-73 ; addend to calculated PC is 73
48
+ ;.set noreorder
49
+ next:
50
+ bltzal $8, next
51
+ ;.set reorder
52
+ slti $8, $0, 0x8282
53
+ nor $11, $11, $0 ; addend in $9
54
+ addu $25, $31, $11 ; $25 points to encoded shellcode +4
55
+ ; addu $16, $31, $11 ; $16 too (enable if you want to pass correct parameters to cacheflush
56
+
57
+ ; lui $2, 0xDDDD ; first part of the xor (old method)
58
+ slti $23, $0, 0x8282 ; store 0 in $23 (our counter)
59
+ ; ori $17, $2, 0xDDDD ; second part of the xor (old method)
60
+ lw $17, -4($25) ; load xor key in $17
61
+
62
+
63
+ li $13, -5
64
+ nor $13, $13, $0 ; 4 in $13
65
+
66
+ addi $15, $13, -3 ; 1 in $15
67
+ loop:
68
+ lw $8, -4($25)
69
+
70
+ addu $23, $23, $15 ; increment counter
71
+ xor $3, $8, $17
72
+ sltu $30, $23, $14 ; enough loops?
73
+ sw $3, -4($25)
74
+ addi $6, $13, -1 ; 3 in $6 (for cacheflush)
75
+ bne $0, $30, loop
76
+ addu $25, $25, $13 ; next instruction to decode :)
77
+
78
+
79
+ ; addiu $4, $16, -4 ; not checked by Linux
80
+ ; li $5,40 ; not checked by Linux
81
+ ; li $6,3 ; $6 is set above
82
+
83
+ ; .set noreorder
84
+ li $2, 4147 ; cacheflush
85
+ ;.ascii "\\x01JT\\x0c" ; nul-free syscall
86
+ syscall 0x52950
87
+ ; .set reorder
88
+
89
+
90
+ ; write last decoder opcode and decoded shellcode
91
+ ; li $4,1 ; stdout
92
+ ; addi $5, $16, -8
93
+ ; li $6,40 ; how much to write
94
+ ; .set noreorder
95
+ ; li $2, 4004 ; write
96
+ ; syscall
97
+ ; .set reorder
98
+
99
+
100
+ nop ; encoded shellcoded must be here (xor key right here ;)
101
+ ; $t9 (aka $25) points here
102
+ EOS
103
+ # ruby19 string.encoding. What a wonderful feature!
104
+ # if we use a "\x<80 or more>", the encoding is 8bits
105
+ # '' << "\x80" => 8bits
106
+ # '' << 0x80 => ascii
107
+ # Edata.data is ascii for now, so this is needed to make the test work.
108
+ str = ''
109
+ "\x24\x0e\xff\xfb\x01\xc0\x70\x27\x24\x0b\xff\xb7\x05\x10\xff\xff\x28\x08\x82\x82\x01\x60\x58\x27\x03\xeb\xc8\x21\x28\x17\x82\x82\x8f\x31\xff\xfc\x24\x0d\xff\xfb\x01\xa0\x68\x27\x21\xaf\xff\xfd\x8f\x28\xff\xfc\x02\xef\xb8\x21\x01\x11\x18\x26\x02\xee\xf0\x2b\xaf\x23\xff\xfc\x21\xa6\xff\xff\x17\xc0\xff\xf9\x03\x2d\xc8\x21\x24\x02\x10\x33\x01\x4a\x54\x0c\0\0\0\0".each_byte { |b| str << b }
110
+ assert_equal(str, sc.encoded.data)
111
+
112
+ dasm_src = Metasm::Shellcode.disassemble(Metasm::MIPS.new(:big), sc.encoded.data).to_s
113
+ lines = dasm_src.respond_to?(:lines) ? dasm_src.lines : dasm_src.to_a
114
+ assert_equal(28, lines.grep(/\S/).length)
115
+ end
116
+ end