metasm 1.0.0

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