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
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
3
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
4
|
+
#
|
|
5
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# this script reads a list of elf files, and lists its dependencies recursively
|
|
10
|
+
# libraries are searched in LD_LIBRARY_PATH, /usr/lib and /lib
|
|
11
|
+
# includes the elf interpreter
|
|
12
|
+
# can be useful when chrooting a binary
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
require 'metasm'
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
paths = ENV['LD_LIBRARY_PATH'].to_s.split(':') + %w[/usr/lib /lib]
|
|
19
|
+
todo = ARGV.map { |file| (file[0] == ?/) ? file : "./#{file}" }
|
|
20
|
+
done = []
|
|
21
|
+
while src = todo.shift
|
|
22
|
+
puts src
|
|
23
|
+
# could do a simple ELF.decode_file, but this is quicker
|
|
24
|
+
elf = Metasm::ELF.decode_file_header(src)
|
|
25
|
+
|
|
26
|
+
if s = elf.segments.find { |s_| s_.type == 'INTERP' }
|
|
27
|
+
interp = elf.encoded[s.offset, s.filesz].data.chomp("\0")
|
|
28
|
+
if not done.include? interp
|
|
29
|
+
puts interp
|
|
30
|
+
done << interp
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
elf.decode_tags
|
|
35
|
+
elf.decode_segments_tags_interpret
|
|
36
|
+
deps = elf.tag['NEEDED'].to_a - done
|
|
37
|
+
done.concat deps
|
|
38
|
+
|
|
39
|
+
deps.each { |dep|
|
|
40
|
+
if not path = paths.find { |path_| File.exist? File.join(path_, dep) }
|
|
41
|
+
$stderr.puts "cannot find #{dep} for #{src}"
|
|
42
|
+
else
|
|
43
|
+
todo << File.join(path, dep)
|
|
44
|
+
end
|
|
45
|
+
}
|
|
46
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
# this script takes a list of dll filenames as arguments, and outputs each lib export
|
|
8
|
+
# libname, followed by the list of the exported symbol names, in a format usable
|
|
9
|
+
# by the Elf class autoimport functionnality (see metasm/os/linux.rb)
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
require 'metasm'
|
|
13
|
+
|
|
14
|
+
bd = 'GLOBAL'
|
|
15
|
+
bd = 'WEAK' if ARGV.delete '--weak'
|
|
16
|
+
obj = true if ARGV.delete '--obj'
|
|
17
|
+
|
|
18
|
+
ARGV.each { |f|
|
|
19
|
+
e = Metasm::ELF.decode_file(f)
|
|
20
|
+
next if not e.tag['SONAME']
|
|
21
|
+
puts e.tag['SONAME']
|
|
22
|
+
line = ''
|
|
23
|
+
e.symbols.find_all { |s|
|
|
24
|
+
s.name and (obj ? s.type != 'FUNC' : s.type == 'FUNC') and s.shndx != 'UNDEF' and s.bind == bd
|
|
25
|
+
}.map { |s| ' ' << s.name }.sort.each { |s|
|
|
26
|
+
if line.length + s.length >= 160
|
|
27
|
+
puts line
|
|
28
|
+
line = ''
|
|
29
|
+
end
|
|
30
|
+
line << s
|
|
31
|
+
}
|
|
32
|
+
puts line if not line.empty?
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
4
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
5
|
+
#
|
|
6
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
7
|
+
|
|
8
|
+
require 'metasm'
|
|
9
|
+
$opts = { :execlass => Metasm::ELF, :exetype => :lib }
|
|
10
|
+
load File.join(File.dirname(__FILE__), 'exeencode.rb')
|
|
11
|
+
|
|
12
|
+
__END__
|
|
13
|
+
.pt_gnu_stack rw
|
|
14
|
+
// .nointerp // to disable the dynamic section, eg for stuff with int80 only
|
|
15
|
+
.text
|
|
16
|
+
.entrypoint
|
|
17
|
+
push bla
|
|
18
|
+
push fmt
|
|
19
|
+
call printf
|
|
20
|
+
push 0
|
|
21
|
+
call exit
|
|
22
|
+
|
|
23
|
+
.data
|
|
24
|
+
bla db "world", 0
|
|
25
|
+
fmt db "Hello, %s !\n", 0
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
3
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
4
|
+
#
|
|
5
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# this sample shows how to compile an executable file from source
|
|
9
|
+
# use --exe PE to compile a PE/ELF/MachO etc
|
|
10
|
+
# use --cpu MIPS/--16/--be to change the CPU
|
|
11
|
+
# the arg is a source file (c or asm) (some arch may not yet support C compiling)
|
|
12
|
+
# defaults to encoding a shellcode, use --exe to override (or the scripts samples/{elf,pe}encode)
|
|
13
|
+
# to compile a shellcode to a cstring, use --cstring
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
require 'metasm'
|
|
17
|
+
require 'optparse'
|
|
18
|
+
|
|
19
|
+
$opts ||= {}
|
|
20
|
+
$opts = {
|
|
21
|
+
:execlass => Metasm::Shellcode,
|
|
22
|
+
:cpu => Metasm::Ia32.new,
|
|
23
|
+
:exetype => :bin,
|
|
24
|
+
:macros => {}
|
|
25
|
+
}.merge($opts)
|
|
26
|
+
|
|
27
|
+
OptionParser.new { |opt|
|
|
28
|
+
opt.on('-o file', 'output filename') { |f| $opts[:outfilename] = f }
|
|
29
|
+
opt.on('-f') { $opts[:overwrite_outfile] = true }
|
|
30
|
+
opt.on('--c', 'parse source as a C file') { $opts[:srctype] = 'c' }
|
|
31
|
+
opt.on('--asm', 'parse asm as an ASM file') { $opts[:srctype] = 'asm' }
|
|
32
|
+
opt.on('--stdin', 'parse source on stdin') { ARGV << '-' }
|
|
33
|
+
opt.on('-v', '-W', 'verbose') { $VERBOSE=true }
|
|
34
|
+
opt.on('-d', 'debug') { $DEBUG=$VERBOSE=true }
|
|
35
|
+
opt.on('-D var=val', 'define a preprocessor macro') { |v| v0, v1 = v.split('=', 2) ; $opts[:macros][v0] = v1 }
|
|
36
|
+
opt.on('--cstring', 'encode output as a C string') { $opts[:to_string] = :c }
|
|
37
|
+
opt.on('--jsstring', 'encode output as a js string') { $opts[:to_string] = :js }
|
|
38
|
+
opt.on('--string', 'encode output as a string to stdout') { $opts[:to_string] = :inspect }
|
|
39
|
+
opt.on('--varname name', 'the variable name for string output') { |v| $opts[:varname] = v }
|
|
40
|
+
opt.on('-e class', '--exe class', 'use a specific ExeFormat class') { |c| $opts[:execlass] = Metasm.const_get(c) }
|
|
41
|
+
opt.on('--cpu cpu', 'use a specific CPU class') { |c| $opts[:cpu] = Metasm.const_get(c).new }
|
|
42
|
+
# must come after --cpu in commandline
|
|
43
|
+
opt.on('--16', 'set cpu in 16bit mode') { $opts[:cpu].size = 16 }
|
|
44
|
+
opt.on('--le', 'set cpu in little-endian mode') { $opts[:cpu].endianness = :little }
|
|
45
|
+
opt.on('--be', 'set cpu in big-endian mode') { $opts[:cpu].endianness = :big }
|
|
46
|
+
opt.on('--fno-pic', 'generate position-dependant code') { $opts[:cpu].generate_PIC = false }
|
|
47
|
+
opt.on('--shared', 'generate shared library') { $opts[:exetype] = :lib }
|
|
48
|
+
opt.on('--ruby-module-hack', 'use the dynldr module hack to use any ruby lib available for ruby symbols') { $opts[:dldrhack] = true }
|
|
49
|
+
}.parse!
|
|
50
|
+
|
|
51
|
+
src = $opts[:macros].map { |k, v| "#define #{k} #{v}\n" }.join
|
|
52
|
+
|
|
53
|
+
if file = ARGV.shift
|
|
54
|
+
$opts[:srctype] ||= 'c' if file =~ /\.c$/
|
|
55
|
+
if file == '-'
|
|
56
|
+
src << $stdin.read
|
|
57
|
+
else
|
|
58
|
+
src << File.read(file)
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
$opts[:srctype] ||= $opts[:srctype_data]
|
|
62
|
+
src << DATA.read # the text after __END__ in this file
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if $opts[:outfilename] and not $opts[:overwrite_outfile] and File.exist?($opts[:outfilename])
|
|
66
|
+
abort "Error: target file exists !"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if $opts[:srctype] == 'c'
|
|
70
|
+
exe = $opts[:execlass].compile_c($opts[:cpu], src, file)
|
|
71
|
+
else
|
|
72
|
+
exe = $opts[:execlass].assemble($opts[:cpu], src, file)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if $opts[:to_string]
|
|
76
|
+
str = exe.encode_string
|
|
77
|
+
|
|
78
|
+
$opts[:varname] ||= File.basename(file.to_s)[/^\w+/] || 'sc' # derive varname from filename
|
|
79
|
+
case $opts[:to_string]
|
|
80
|
+
when :inspect
|
|
81
|
+
str = "#{$opts[:varname]} = #{str.inspect}"
|
|
82
|
+
when :c
|
|
83
|
+
str = ["unsigned char #{$opts[:varname]}[#{str.length}] = "] + str.scan(/.{1,19}/m).map { |l|
|
|
84
|
+
'"' + l.unpack('C*').map { |c| '\\x%02x' % c }.join + '"'
|
|
85
|
+
}
|
|
86
|
+
str.last << ?;
|
|
87
|
+
when :js
|
|
88
|
+
str << 0 if str.length & 1 != 0
|
|
89
|
+
str = ["#{$opts[:varname]} = "] + str.scan(/.{2,20}/m).map { |l|
|
|
90
|
+
'"' + l.unpack($opts[:cpu].endianness == :little ? 'v*' : 'n*').map { |c| '%%u%04x' % c }.join + '"+'
|
|
91
|
+
}
|
|
92
|
+
str.last[-1] = ?;
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
if of = $opts[:outfilename]
|
|
96
|
+
abort "Error: target file #{of.inspect} exists !" if File.exists? of and not $opts[:overwrite_outfile]
|
|
97
|
+
File.open(of, 'w') { |fd| fd.puts str }
|
|
98
|
+
puts "saved to file #{of.inspect}"
|
|
99
|
+
else
|
|
100
|
+
puts str
|
|
101
|
+
end
|
|
102
|
+
else
|
|
103
|
+
of = $opts[:outfilename] ||= 'a.out'
|
|
104
|
+
abort "Error: target file #{of.inspect} exists !" if File.exists? of and not $opts[:overwrite_outfile]
|
|
105
|
+
Metasm::DynLdr.compile_binary_module_hack(exe) if $opts[:dldrhack]
|
|
106
|
+
exe.encode_file(of, $opts[:exetype])
|
|
107
|
+
puts "saved to file #{of.inspect}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
__END__
|
|
111
|
+
#include <asm/unistd.h>
|
|
112
|
+
jmp getip
|
|
113
|
+
gotip:
|
|
114
|
+
mov eax, __NR_write
|
|
115
|
+
mov ebx, 1
|
|
116
|
+
pop ecx
|
|
117
|
+
mov edx, strend-str
|
|
118
|
+
int 80h
|
|
119
|
+
|
|
120
|
+
mov eax, __NR_exit
|
|
121
|
+
mov ebx, 1
|
|
122
|
+
int 80h
|
|
123
|
+
|
|
124
|
+
getip:
|
|
125
|
+
call gotip
|
|
126
|
+
|
|
127
|
+
str db "Hello, world!", 0xa
|
|
128
|
+
strend:
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
# this exemple illustrates the use of the cparser/preprocessor #factorize functionnality:
|
|
8
|
+
# it generates code that references to the functions imported by an ELF executable
|
|
9
|
+
# usage: factorize-imports.rb <exe> [<path to include dir>] [<additional func names>... !<func to exclude>]
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
require 'metasm'
|
|
13
|
+
include Metasm
|
|
14
|
+
|
|
15
|
+
require 'optparse'
|
|
16
|
+
opts = { :hdrs => [], :defs => {}, :path => [] }
|
|
17
|
+
OptionParser.new { |opt|
|
|
18
|
+
opt.on('-o outfile') { |f| opts[:outfile] = f }
|
|
19
|
+
opt.on('-H additional_header') { |f| opts[:hdrs] << f }
|
|
20
|
+
opt.on('--exe executable') { |f| opts[:exe] = f }
|
|
21
|
+
opt.on('-I path', '--includepath path') { |f| opts[:path] << f }
|
|
22
|
+
opt.on('-D var') { |f| k, v = f.split('=', 2) ; opts[:defs].update k => (v || '') }
|
|
23
|
+
opt.on('--gcc') { opts[:gcc] = true }
|
|
24
|
+
opt.on('--vs', '--visualstudio') { opts[:vs] = true }
|
|
25
|
+
}.parse!(ARGV)
|
|
26
|
+
|
|
27
|
+
exe = AutoExe.decode_file_header(opts[:exe] || ARGV.shift)
|
|
28
|
+
opts[:path] ||= [ARGV.shift] if not ARGV.empty?
|
|
29
|
+
|
|
30
|
+
case exe
|
|
31
|
+
when PE
|
|
32
|
+
exe.decode_imports
|
|
33
|
+
funcnames = exe.imports.map { |id| id.imports.map { |i| i.name } }
|
|
34
|
+
when ELF
|
|
35
|
+
exe.decode_segments_dynamic
|
|
36
|
+
funcnames = exe.symbols.map { |s| s.name if s.shndx == 'UNDEF' and s.type == 'FUNC' }
|
|
37
|
+
opts[:hdrs] << 'stdio.h' << 'stdlib.h' << 'unistd.h'
|
|
38
|
+
opts[:gcc] = true if not opts[:vs]
|
|
39
|
+
else raise "unsupported #{exe.class}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
funcnames = funcnames.flatten.compact.uniq.sort
|
|
43
|
+
|
|
44
|
+
ARGV.each { |n|
|
|
45
|
+
if n[0] == ?!
|
|
46
|
+
funcnames.delete n[1..-1]
|
|
47
|
+
else
|
|
48
|
+
funcnames |= [n]
|
|
49
|
+
end
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
src = opts[:hdrs].map { |h| "#include <#{h}>" }.join("\n")
|
|
53
|
+
|
|
54
|
+
parser = Ia32.new.new_cparser
|
|
55
|
+
parser.prepare_gcc if opts[:gcc]
|
|
56
|
+
parser.prepare_visualstudio if opts[:vs]
|
|
57
|
+
pp = parser.lexer
|
|
58
|
+
pp.warn_redefinition = false
|
|
59
|
+
pp.include_search_path[0, 0] = opts[:path]
|
|
60
|
+
opts[:defs].each { |k, v| pp.define k, v }
|
|
61
|
+
parser.factorize_init
|
|
62
|
+
parser.parse src
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# delete imports not present in the header files
|
|
66
|
+
funcnames.delete_if { |f|
|
|
67
|
+
if not parser.toplevel.symbol[f]
|
|
68
|
+
puts "// #{f.inspect} is not defined in the headers"
|
|
69
|
+
true
|
|
70
|
+
end
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
parser.parse "void *fnptr[] = { #{funcnames.map { |f| '&'+f }.join(', ')} };"
|
|
74
|
+
|
|
75
|
+
outfd = (opts[:outfile] ? File.open(opts[:outfile], 'w') : $stdout)
|
|
76
|
+
outfd.puts parser.factorize_final
|
|
77
|
+
outfd.close
|
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
# this exemple illustrates the use of the cparser/preprocessor #factorize functionnality:
|
|
8
|
+
# it generates code that references to the functions imported by a windows executable
|
|
9
|
+
# usage: factorize-imports.rb <exe> <exe2> <path to visual studio installation> [<additional func names>... ^<func to exclude>]
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
require 'metasm'
|
|
13
|
+
include Metasm
|
|
14
|
+
|
|
15
|
+
require 'optparse'
|
|
16
|
+
opts = { :hdrs => [], :defs => {}, :path => [], :exe => [] }
|
|
17
|
+
OptionParser.new { |opt|
|
|
18
|
+
opt.on('-o outfile') { |f| opts[:outfile] = f }
|
|
19
|
+
opt.on('-H additional_header') { |f| opts[:hdrs] << f }
|
|
20
|
+
opt.on('-e exe', '--exe executable') { |f| opts[:exe] << f }
|
|
21
|
+
opt.on('-I path', '--includepath path') { |f| opts[:path] << f }
|
|
22
|
+
opt.on('-D var') { |f| k, v = f.split('=', 2) ; opts[:defs].update k => (v || '') }
|
|
23
|
+
opt.on('--ddk') { opts[:ddk] = true }
|
|
24
|
+
opt.on('--vspath path') { |f| opts[:vspath] = f }
|
|
25
|
+
}.parse!(ARGV)
|
|
26
|
+
|
|
27
|
+
ARGV.delete_if { |e|
|
|
28
|
+
next if not File.file? e
|
|
29
|
+
opts[:exe] << e
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if opts[:vspath] ||= ARGV.shift
|
|
33
|
+
opts[:vspath] = opts[:vspath].tr('\\', '/')
|
|
34
|
+
opts[:vspath] = opts[:vspath].chop if opts[:vspath][-1] == ?/
|
|
35
|
+
if opts[:ddk]
|
|
36
|
+
opts[:path] << (opts[:vspath]+'/ddk') << (opts[:vspath]+'/api') << (opts[:vspath]+'/crt')
|
|
37
|
+
else
|
|
38
|
+
opts[:vspath] = opts[:vspath][0...-3] if opts[:vspath][-3..-1] == '/VC'
|
|
39
|
+
opts[:path] << (opts[:vspath]+'/VC/platformsdk/include') << (opts[:vspath]+'/VC/include')
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
funcnames = opts[:exe].map { |e|
|
|
44
|
+
pe = PE.decode_file_header(e)
|
|
45
|
+
pe.decode_imports
|
|
46
|
+
if not pe.imports
|
|
47
|
+
puts "#{e} has no imports"
|
|
48
|
+
next
|
|
49
|
+
end
|
|
50
|
+
pe.imports.map { |id| id.imports.map { |i| i.name } }
|
|
51
|
+
}.flatten.compact.uniq.sort
|
|
52
|
+
|
|
53
|
+
ARGV.each { |n|
|
|
54
|
+
if n[0] == ?! or n[0] == ?- or n[0] == ?^
|
|
55
|
+
funcnames.delete n[1..-1]
|
|
56
|
+
else
|
|
57
|
+
funcnames |= [n]
|
|
58
|
+
end
|
|
59
|
+
}
|
|
60
|
+
exit if funcnames.empty?
|
|
61
|
+
|
|
62
|
+
src = <<EOS + opts[:hdrs].to_a.map { |h| "#include <#{h}>\n" }.join
|
|
63
|
+
#ifdef DDK
|
|
64
|
+
#define NO_INTERLOCKED_INTRINSICS
|
|
65
|
+
typedef struct _CONTEXT CONTEXT; // needed by ntddk.h, but this will pollute the factorized output..
|
|
66
|
+
typedef CONTEXT *PCONTEXT;
|
|
67
|
+
#define dllimport stdcall // wtff
|
|
68
|
+
#define SORTPP_PASS // C_ASSERT proprocessor assert..
|
|
69
|
+
#define _MSC_EXTENSIONS // __volatile stuff
|
|
70
|
+
#include <ntddk.h>
|
|
71
|
+
#include <stdio.h>
|
|
72
|
+
#else
|
|
73
|
+
#define WIN32_LEAN_AND_MEAN
|
|
74
|
+
#include <windows.h>
|
|
75
|
+
#include <winternl.h>
|
|
76
|
+
#endif
|
|
77
|
+
EOS
|
|
78
|
+
|
|
79
|
+
parser = Ia32.new.new_cparser
|
|
80
|
+
parser.prepare_visualstudio
|
|
81
|
+
pp = parser.lexer
|
|
82
|
+
pp.warn_redefinition = false
|
|
83
|
+
pp.define('_WIN32_WINNT', '0x0600')
|
|
84
|
+
pp.define('DDK') if opts[:ddk]
|
|
85
|
+
pp.define_strong('IN', '__attribute__((in))')
|
|
86
|
+
pp.define_strong('__in', '__attribute__((in))')
|
|
87
|
+
pp.define_strong('OUT', '__attribute__((out))')
|
|
88
|
+
pp.define_strong('__out', '__attribute__((out))')
|
|
89
|
+
pp.include_search_path = opts[:path]
|
|
90
|
+
opts[:defs].each { |k, v| pp.define k, v }
|
|
91
|
+
parser.factorize_init
|
|
92
|
+
parser.parse src
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
outfd = (opts[:outfile] ? File.open(opts[:outfile], 'w') : $stdout)
|
|
96
|
+
|
|
97
|
+
# delete imports not present in the header files
|
|
98
|
+
funcnames.delete_if { |f|
|
|
99
|
+
if not parser.toplevel.symbol[f]
|
|
100
|
+
puts "// #{f.inspect} is not defined in the headers"
|
|
101
|
+
outfd.puts "// #{f.inspect} is not defined in the headers" if opts[:outfile]
|
|
102
|
+
true
|
|
103
|
+
end
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
parser.parse "void *fnptr[] = { #{funcnames.map { |f| '&'+f }.join(', ')} };"
|
|
107
|
+
|
|
108
|
+
outfd.puts parser.factorize_final
|
|
109
|
+
outfd.close
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
# this exemple illustrates the use of the cparser/preprocessor #factorize functionnality:
|
|
8
|
+
# we write some code using standard headers, and the factorize call on CParser
|
|
9
|
+
# gives us back the macro/C definitions that we use in our code, so that we can
|
|
10
|
+
# get rid of the header
|
|
11
|
+
# Argument: C file to factorize, [path to visual studio installation]
|
|
12
|
+
# with a single argument, uses GCC standard headers
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
require 'metasm'
|
|
16
|
+
include Metasm
|
|
17
|
+
|
|
18
|
+
abort 'target needed' if not file = ARGV.shift
|
|
19
|
+
|
|
20
|
+
visualstudiopath = ARGV.shift
|
|
21
|
+
if visualstudiopath
|
|
22
|
+
stub = <<EOS
|
|
23
|
+
// add the path to the visual studio std headers
|
|
24
|
+
#ifdef __METASM__
|
|
25
|
+
#pragma include_dir #{(visualstudiopath+'/platformsdk/include').inspect}
|
|
26
|
+
#pragma include_dir #{(visualstudiopath+'/include').inspect}
|
|
27
|
+
#pragma prepare_visualstudio
|
|
28
|
+
#pragma no_warn_redefinition
|
|
29
|
+
#endif
|
|
30
|
+
EOS
|
|
31
|
+
else
|
|
32
|
+
stub = <<EOS
|
|
33
|
+
#ifdef __METASM__
|
|
34
|
+
#pragma prepare_gcc
|
|
35
|
+
#endif
|
|
36
|
+
EOS
|
|
37
|
+
end
|
|
38
|
+
stub << "#line 0\n"
|
|
39
|
+
|
|
40
|
+
# to trace only pp macros (using eg an asm source), use Preprocessor#factorize instead
|
|
41
|
+
|
|
42
|
+
puts Ia32.new.new_cparser.factorize(stub + File.read(file), file)
|
|
43
|
+
|