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.
- data/BUGS +11 -0
- data/CREDITS +17 -0
- data/README +270 -0
- data/TODO +114 -0
- data/doc/code_organisation.txt +146 -0
- data/doc/const_missing.txt +16 -0
- data/doc/core_classes.txt +75 -0
- data/doc/feature_list.txt +53 -0
- data/doc/index.txt +59 -0
- data/doc/install_notes.txt +170 -0
- data/doc/style.css +3 -0
- data/doc/use_cases.txt +18 -0
- data/lib/metasm.rb +80 -0
- data/lib/metasm/arm.rb +12 -0
- data/lib/metasm/arm/debug.rb +39 -0
- data/lib/metasm/arm/decode.rb +167 -0
- data/lib/metasm/arm/encode.rb +77 -0
- data/lib/metasm/arm/main.rb +75 -0
- data/lib/metasm/arm/opcodes.rb +177 -0
- data/lib/metasm/arm/parse.rb +130 -0
- data/lib/metasm/arm/render.rb +55 -0
- data/lib/metasm/compile_c.rb +1457 -0
- data/lib/metasm/dalvik.rb +8 -0
- data/lib/metasm/dalvik/decode.rb +196 -0
- data/lib/metasm/dalvik/main.rb +60 -0
- data/lib/metasm/dalvik/opcodes.rb +366 -0
- data/lib/metasm/decode.rb +213 -0
- data/lib/metasm/decompile.rb +2659 -0
- data/lib/metasm/disassemble.rb +2068 -0
- data/lib/metasm/disassemble_api.rb +1280 -0
- data/lib/metasm/dynldr.rb +1329 -0
- data/lib/metasm/encode.rb +333 -0
- data/lib/metasm/exe_format/a_out.rb +194 -0
- data/lib/metasm/exe_format/autoexe.rb +82 -0
- data/lib/metasm/exe_format/bflt.rb +189 -0
- data/lib/metasm/exe_format/coff.rb +455 -0
- data/lib/metasm/exe_format/coff_decode.rb +901 -0
- data/lib/metasm/exe_format/coff_encode.rb +1078 -0
- data/lib/metasm/exe_format/dex.rb +457 -0
- data/lib/metasm/exe_format/dol.rb +145 -0
- data/lib/metasm/exe_format/elf.rb +923 -0
- data/lib/metasm/exe_format/elf_decode.rb +979 -0
- data/lib/metasm/exe_format/elf_encode.rb +1375 -0
- data/lib/metasm/exe_format/macho.rb +827 -0
- data/lib/metasm/exe_format/main.rb +228 -0
- data/lib/metasm/exe_format/mz.rb +164 -0
- data/lib/metasm/exe_format/nds.rb +172 -0
- data/lib/metasm/exe_format/pe.rb +437 -0
- data/lib/metasm/exe_format/serialstruct.rb +246 -0
- data/lib/metasm/exe_format/shellcode.rb +114 -0
- data/lib/metasm/exe_format/xcoff.rb +167 -0
- data/lib/metasm/gui.rb +23 -0
- data/lib/metasm/gui/cstruct.rb +373 -0
- data/lib/metasm/gui/dasm_coverage.rb +199 -0
- data/lib/metasm/gui/dasm_decomp.rb +369 -0
- data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
- data/lib/metasm/gui/dasm_graph.rb +1354 -0
- data/lib/metasm/gui/dasm_hex.rb +543 -0
- data/lib/metasm/gui/dasm_listing.rb +599 -0
- data/lib/metasm/gui/dasm_main.rb +906 -0
- data/lib/metasm/gui/dasm_opcodes.rb +291 -0
- data/lib/metasm/gui/debug.rb +1228 -0
- data/lib/metasm/gui/gtk.rb +884 -0
- data/lib/metasm/gui/qt.rb +495 -0
- data/lib/metasm/gui/win32.rb +3004 -0
- data/lib/metasm/gui/x11.rb +621 -0
- data/lib/metasm/ia32.rb +14 -0
- data/lib/metasm/ia32/compile_c.rb +1523 -0
- data/lib/metasm/ia32/debug.rb +193 -0
- data/lib/metasm/ia32/decode.rb +1167 -0
- data/lib/metasm/ia32/decompile.rb +564 -0
- data/lib/metasm/ia32/encode.rb +314 -0
- data/lib/metasm/ia32/main.rb +233 -0
- data/lib/metasm/ia32/opcodes.rb +872 -0
- data/lib/metasm/ia32/parse.rb +327 -0
- data/lib/metasm/ia32/render.rb +91 -0
- data/lib/metasm/main.rb +1193 -0
- data/lib/metasm/mips.rb +11 -0
- data/lib/metasm/mips/compile_c.rb +7 -0
- data/lib/metasm/mips/decode.rb +253 -0
- data/lib/metasm/mips/encode.rb +51 -0
- data/lib/metasm/mips/main.rb +72 -0
- data/lib/metasm/mips/opcodes.rb +443 -0
- data/lib/metasm/mips/parse.rb +51 -0
- data/lib/metasm/mips/render.rb +43 -0
- data/lib/metasm/os/gnu_exports.rb +270 -0
- data/lib/metasm/os/linux.rb +1112 -0
- data/lib/metasm/os/main.rb +1686 -0
- data/lib/metasm/os/remote.rb +527 -0
- data/lib/metasm/os/windows.rb +2027 -0
- data/lib/metasm/os/windows_exports.rb +745 -0
- data/lib/metasm/parse.rb +876 -0
- data/lib/metasm/parse_c.rb +3938 -0
- data/lib/metasm/pic16c/decode.rb +42 -0
- data/lib/metasm/pic16c/main.rb +17 -0
- data/lib/metasm/pic16c/opcodes.rb +68 -0
- data/lib/metasm/ppc.rb +11 -0
- data/lib/metasm/ppc/decode.rb +264 -0
- data/lib/metasm/ppc/decompile.rb +251 -0
- data/lib/metasm/ppc/encode.rb +51 -0
- data/lib/metasm/ppc/main.rb +129 -0
- data/lib/metasm/ppc/opcodes.rb +410 -0
- data/lib/metasm/ppc/parse.rb +52 -0
- data/lib/metasm/preprocessor.rb +1277 -0
- data/lib/metasm/render.rb +130 -0
- data/lib/metasm/sh4.rb +8 -0
- data/lib/metasm/sh4/decode.rb +336 -0
- data/lib/metasm/sh4/main.rb +292 -0
- data/lib/metasm/sh4/opcodes.rb +381 -0
- data/lib/metasm/x86_64.rb +12 -0
- data/lib/metasm/x86_64/compile_c.rb +1025 -0
- data/lib/metasm/x86_64/debug.rb +59 -0
- data/lib/metasm/x86_64/decode.rb +268 -0
- data/lib/metasm/x86_64/encode.rb +264 -0
- data/lib/metasm/x86_64/main.rb +135 -0
- data/lib/metasm/x86_64/opcodes.rb +118 -0
- data/lib/metasm/x86_64/parse.rb +68 -0
- data/misc/bottleneck.rb +61 -0
- data/misc/cheader-findpppath.rb +58 -0
- data/misc/hexdiff.rb +74 -0
- data/misc/hexdump.rb +55 -0
- data/misc/metasm-all.rb +13 -0
- data/misc/objdiff.rb +47 -0
- data/misc/objscan.rb +40 -0
- data/misc/pdfparse.rb +661 -0
- data/misc/ppc_pdf2oplist.rb +192 -0
- data/misc/tcp_proxy_hex.rb +84 -0
- data/misc/txt2html.rb +440 -0
- data/samples/a.out.rb +31 -0
- data/samples/asmsyntax.rb +77 -0
- data/samples/bindiff.rb +555 -0
- data/samples/compilation-steps.rb +49 -0
- data/samples/cparser_makestackoffset.rb +55 -0
- data/samples/dasm-backtrack.rb +38 -0
- data/samples/dasmnavig.rb +318 -0
- data/samples/dbg-apihook.rb +228 -0
- data/samples/dbghelp.rb +143 -0
- data/samples/disassemble-gui.rb +102 -0
- data/samples/disassemble.rb +133 -0
- data/samples/dump_upx.rb +95 -0
- data/samples/dynamic_ruby.rb +1929 -0
- data/samples/elf_list_needed.rb +46 -0
- data/samples/elf_listexports.rb +33 -0
- data/samples/elfencode.rb +25 -0
- data/samples/exeencode.rb +128 -0
- data/samples/factorize-headers-elfimports.rb +77 -0
- data/samples/factorize-headers-peimports.rb +109 -0
- data/samples/factorize-headers.rb +43 -0
- data/samples/gdbclient.rb +583 -0
- data/samples/generate_libsigs.rb +102 -0
- data/samples/hotfix_gtk_dbg.rb +59 -0
- data/samples/install_win_env.rb +78 -0
- data/samples/lindebug.rb +924 -0
- data/samples/linux_injectsyscall.rb +95 -0
- data/samples/machoencode.rb +31 -0
- data/samples/metasm-shell.rb +91 -0
- data/samples/pe-hook.rb +69 -0
- data/samples/pe-ia32-cpuid.rb +203 -0
- data/samples/pe-mips.rb +35 -0
- data/samples/pe-shutdown.rb +78 -0
- data/samples/pe-testrelocs.rb +51 -0
- data/samples/pe-testrsrc.rb +24 -0
- data/samples/pe_listexports.rb +31 -0
- data/samples/peencode.rb +19 -0
- data/samples/peldr.rb +494 -0
- data/samples/preprocess-flatten.rb +19 -0
- data/samples/r0trace.rb +308 -0
- data/samples/rubstop.rb +399 -0
- data/samples/scan_pt_gnu_stack.rb +54 -0
- data/samples/scanpeexports.rb +62 -0
- data/samples/shellcode-c.rb +40 -0
- data/samples/shellcode-dynlink.rb +146 -0
- data/samples/source.asm +34 -0
- data/samples/struct_offset.rb +47 -0
- data/samples/testpe.rb +32 -0
- data/samples/testraw.rb +45 -0
- data/samples/win32genloader.rb +132 -0
- data/samples/win32hooker-advanced.rb +169 -0
- data/samples/win32hooker.rb +96 -0
- data/samples/win32livedasm.rb +33 -0
- data/samples/win32remotescan.rb +133 -0
- data/samples/wintrace.rb +92 -0
- data/tests/all.rb +8 -0
- data/tests/dasm.rb +39 -0
- data/tests/dynldr.rb +35 -0
- data/tests/encodeddata.rb +132 -0
- data/tests/ia32.rb +82 -0
- data/tests/mips.rb +116 -0
- data/tests/parse_c.rb +239 -0
- data/tests/preprocessor.rb +269 -0
- data/tests/x86_64.rb +62 -0
- metadata +255 -0
data/samples/wintrace.rb
ADDED
|
@@ -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
|
data/tests/all.rb
ADDED
data/tests/dasm.rb
ADDED
|
@@ -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
|
+
|
data/tests/dynldr.rb
ADDED
|
@@ -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
|
data/tests/ia32.rb
ADDED
|
@@ -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
|
data/tests/mips.rb
ADDED
|
@@ -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
|