metasm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,54 @@
|
|
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
|
+
#
|
9
|
+
# this script scans directories recursively for ELF files which have a PT_GNU_STACK rwe or absent
|
10
|
+
# usage : scan_pt_gnu_stack.rb <dir> [<dir>]
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'metasm'
|
14
|
+
|
15
|
+
def _puts(a)
|
16
|
+
puts a.to_s.ljust(60)
|
17
|
+
end
|
18
|
+
def _printadv(a)
|
19
|
+
$stderr.print a.to_s.ljust(60)[-60, 60] + "\r"
|
20
|
+
end
|
21
|
+
|
22
|
+
# the recursive scanning procedure
|
23
|
+
iter = lambda { |f|
|
24
|
+
if File.symlink? f
|
25
|
+
elsif File.directory? f
|
26
|
+
# show where we are & recurse
|
27
|
+
_printadv f
|
28
|
+
Dir[ File.join(f, '*') ].each { |ff|
|
29
|
+
iter[ff]
|
30
|
+
}
|
31
|
+
else
|
32
|
+
# interpret any file as a ELF
|
33
|
+
begin
|
34
|
+
elf = Metasm::ELF.decode_file_header(f)
|
35
|
+
next if not elf.segments or elf.header.type == 'REL'
|
36
|
+
seg = elf.segments.find { |seg_| seg_.type == 'GNU_STACK' }
|
37
|
+
if not seg
|
38
|
+
_puts "PT_GNU_STACK absent : #{f}"
|
39
|
+
elsif seg.flags.include? 'X'
|
40
|
+
_puts "PT_GNU_STACK RWE : #{f}"
|
41
|
+
else
|
42
|
+
_puts "#{f} : #{seg.inspect}" if $VERBOSE
|
43
|
+
end
|
44
|
+
rescue
|
45
|
+
# the file is not a valid ELF
|
46
|
+
_puts "E: #{f} #{$!}" if $VERBOSE
|
47
|
+
end
|
48
|
+
end
|
49
|
+
}
|
50
|
+
|
51
|
+
# go
|
52
|
+
ARGV.each { |dir| iter[dir] }
|
53
|
+
|
54
|
+
_printadv ''
|
@@ -0,0 +1,62 @@
|
|
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 scans a directory for PE files which export a given symbol name (regexp case-insensitive)
|
8
|
+
# usage : ruby scanpeexports.rb <dir> <pattern>
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'metasm'
|
12
|
+
|
13
|
+
if not base = ARGV.shift
|
14
|
+
puts 'base dir ?'
|
15
|
+
base = gets.chomp
|
16
|
+
end
|
17
|
+
if not pat = ARGV.shift
|
18
|
+
puts 'pattern ?'
|
19
|
+
pat = gets.chomp
|
20
|
+
puts 'searching...'
|
21
|
+
end
|
22
|
+
|
23
|
+
def _puts(a)
|
24
|
+
puts a.to_s.ljust(60)
|
25
|
+
end
|
26
|
+
def _printadv(a)
|
27
|
+
$stderr.print a.to_s.ljust(60)[-60, 60] + "\r"
|
28
|
+
end
|
29
|
+
|
30
|
+
# the recursive scanning procedure
|
31
|
+
iter = lambda { |f, match|
|
32
|
+
if File.directory? f
|
33
|
+
# show where we are & recurse
|
34
|
+
_printadv f
|
35
|
+
Dir[ File.join(f, '*') ].each { |ff|
|
36
|
+
iter[ff, match]
|
37
|
+
}
|
38
|
+
else
|
39
|
+
# interpret any file as a PE
|
40
|
+
begin
|
41
|
+
pe = Metasm::PE.decode_file_header(f)
|
42
|
+
pe.decode_exports
|
43
|
+
next if not pe.export
|
44
|
+
# scan the export directory for the symbol pattern, excluding forwarders
|
45
|
+
pe.export.exports.each { |exp|
|
46
|
+
if exp.name =~ /#{match}/i and not exp.forwarder_lib
|
47
|
+
_puts f + " : " + exp.name
|
48
|
+
end
|
49
|
+
}
|
50
|
+
rescue
|
51
|
+
# the file is not a valid PE
|
52
|
+
end
|
53
|
+
end
|
54
|
+
}
|
55
|
+
|
56
|
+
# go
|
57
|
+
iter[base, pat]
|
58
|
+
|
59
|
+
if RUBY_PLATFORM =~ /win32/i
|
60
|
+
_puts "press [enter] to exit"
|
61
|
+
gets
|
62
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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
|
+
# in this exemple we can write a shellcode using a C function
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'metasm'
|
13
|
+
|
14
|
+
# load and decode the file
|
15
|
+
sc = Metasm::Shellcode.new(Metasm::Ia32.new)
|
16
|
+
sc.parse <<EOS
|
17
|
+
jmp c_func
|
18
|
+
|
19
|
+
some_func:
|
20
|
+
mov eax, 42
|
21
|
+
ret
|
22
|
+
EOS
|
23
|
+
|
24
|
+
cp = sc.cpu.new_cparser
|
25
|
+
cp.parse <<EOS
|
26
|
+
void some_func(void);
|
27
|
+
/* __declspec(naked) */ void c_func() {
|
28
|
+
int i;
|
29
|
+
for (i=0 ; i<10 ; ++i)
|
30
|
+
some_func();
|
31
|
+
}
|
32
|
+
EOS
|
33
|
+
asm = sc.cpu.new_ccompiler(cp, sc).compile
|
34
|
+
|
35
|
+
sc.parse asm
|
36
|
+
sc.assemble
|
37
|
+
|
38
|
+
sc.encode_file 'shellcode.raw'
|
39
|
+
|
40
|
+
puts Metasm::Shellcode.load_file('shellcode.raw', Metasm::Ia32.new).disassemble
|
@@ -0,0 +1,146 @@
|
|
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
|
+
# this script compiles a source file (asm or C) into a shellcode that will
|
7
|
+
# dynamically resolve the address of functions it uses
|
8
|
+
# windows only, supposes the shellcode is run in the address space of a process
|
9
|
+
# whose PEB allows to find all required libraries.
|
10
|
+
|
11
|
+
require 'metasm'
|
12
|
+
|
13
|
+
sc = Metasm::Shellcode.new(Metasm::Ia32.new)
|
14
|
+
|
15
|
+
case ARGV[0]
|
16
|
+
when /\.c(pp)?$/i
|
17
|
+
src_c = File.read(ARGV[0])
|
18
|
+
sc.assemble 'jmp main'
|
19
|
+
sc.compile_c src_c
|
20
|
+
when /\.asm$/i
|
21
|
+
src = File.read(ARGV[0])
|
22
|
+
sc.assemble src
|
23
|
+
when nil; abort "need sourcefile"
|
24
|
+
else abort "unknown srcfile extension"
|
25
|
+
end
|
26
|
+
|
27
|
+
# find external symbols needed by the shellcode
|
28
|
+
ext_syms = sc.encoded.reloc_externals
|
29
|
+
|
30
|
+
# resolver code
|
31
|
+
sc.parse <<EOS
|
32
|
+
get_libbase:
|
33
|
+
mov eax, fs:[0x30] // peb
|
34
|
+
mov eax, [eax+12] // peb_ldr
|
35
|
+
add eax, 12 // &inloadorder
|
36
|
+
libbase_loop:
|
37
|
+
mov eax, [eax] // next
|
38
|
+
mov edx, [eax+12*4] // basename ptr
|
39
|
+
mov cl, [edx+6]
|
40
|
+
shl ecx, 8
|
41
|
+
mov cl, [edx+4]
|
42
|
+
shl ecx, 8
|
43
|
+
mov cl, [edx+2]
|
44
|
+
shl ecx, 8
|
45
|
+
mov cl, [edx]
|
46
|
+
or ecx, 0x20202020 // downcase
|
47
|
+
cmp ecx, [esp+4]
|
48
|
+
jnz libbase_loop
|
49
|
+
mov eax, [eax+6*4] // baseaddr
|
50
|
+
ret 4
|
51
|
+
|
52
|
+
hash_name:
|
53
|
+
push ecx
|
54
|
+
push edx
|
55
|
+
xor eax, eax
|
56
|
+
xor ecx, ecx
|
57
|
+
mov edx, [esp+12]
|
58
|
+
dec edx
|
59
|
+
hash_loop:
|
60
|
+
ror eax, 0dh
|
61
|
+
add eax, ecx
|
62
|
+
inc edx
|
63
|
+
mov cl, [edx]
|
64
|
+
test cl, cl
|
65
|
+
jnz hash_loop
|
66
|
+
pop edx
|
67
|
+
pop ecx
|
68
|
+
ret 4
|
69
|
+
|
70
|
+
resolve_proc:
|
71
|
+
push ecx
|
72
|
+
push edx
|
73
|
+
push ebp
|
74
|
+
push dword ptr [esp+0x14] // arg_2
|
75
|
+
call get_libbase
|
76
|
+
mov ebp, eax // imagebase
|
77
|
+
add eax, [eax+0x3c] // coffhdr
|
78
|
+
mov edx, [eax+0x78] // exportdirectory
|
79
|
+
add edx, ebp
|
80
|
+
or ecx, -1
|
81
|
+
resolve_loop:
|
82
|
+
inc ecx
|
83
|
+
mov eax, [edx+0x20] // name
|
84
|
+
add eax, ebp
|
85
|
+
mov eax, [eax+4*ecx]
|
86
|
+
add eax, ebp
|
87
|
+
push eax
|
88
|
+
call hash_name
|
89
|
+
cmp eax, [esp+0x10] // cmp hash(name[i]), arg_1
|
90
|
+
jnz resolve_loop
|
91
|
+
mov eax, [edx+0x24] // ord
|
92
|
+
add eax, ebp
|
93
|
+
movzx ecx, word ptr [eax+2*ecx]
|
94
|
+
mov eax, [edx+0x1c] // func
|
95
|
+
add eax, ebp
|
96
|
+
mov eax, [eax+4*ecx] // func[ord[i]]
|
97
|
+
add eax, ebp
|
98
|
+
pop ebp
|
99
|
+
pop edx
|
100
|
+
pop ecx
|
101
|
+
ret 8
|
102
|
+
EOS
|
103
|
+
|
104
|
+
def hash_name(sym)
|
105
|
+
hash = 0
|
106
|
+
sym.each_byte { |char|
|
107
|
+
hash = (((hash >> 0xd) | (hash << (32-0xd))) + char) & 0xffff_ffff
|
108
|
+
}
|
109
|
+
hash
|
110
|
+
end
|
111
|
+
|
112
|
+
def lib_name(sym)
|
113
|
+
raise "unknown libname for #{sym}" if not lib = Metasm::WindowsExports::EXPORT[sym]
|
114
|
+
n = lib.downcase[0, 4].unpack('C*')
|
115
|
+
n[0] + (n[1]<<8) + (n[2] << 16) + (n[3] << 24)
|
116
|
+
end
|
117
|
+
|
118
|
+
# encode stub for each symbol
|
119
|
+
ext_syms.uniq.each { |sym|
|
120
|
+
next if sym == 'next_payload'
|
121
|
+
sc.parse <<EOS
|
122
|
+
#{sym}:
|
123
|
+
push #{lib_name(sym)}
|
124
|
+
push #{hash_name(sym)}
|
125
|
+
call resolve_proc
|
126
|
+
jmp eax
|
127
|
+
EOS
|
128
|
+
}
|
129
|
+
|
130
|
+
# marker to the next payload if the payload is a stager
|
131
|
+
sc.assemble "next_payload:"
|
132
|
+
|
133
|
+
# output to a file
|
134
|
+
sc.encode_file 'shellcode-dynlink.raw'
|
135
|
+
|
136
|
+
__END__
|
137
|
+
// sample payload
|
138
|
+
|
139
|
+
extern __stdcall int MessageBoxA(int, char*, char*, int);
|
140
|
+
extern void next_payload(void);
|
141
|
+
|
142
|
+
int main(void)
|
143
|
+
{
|
144
|
+
MessageBoxA(0, "Hello, world !", "Hi", 0);
|
145
|
+
next_payload();
|
146
|
+
}
|
data/samples/source.asm
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
.pt_gnu_stack rw // elf-specific instruction
|
2
|
+
//.interp none // request minimal elf, no section/dynamic/interpreter
|
3
|
+
|
4
|
+
#define __i386__
|
5
|
+
#include <asm/unistd.h> // can use the C preprocessor
|
6
|
+
|
7
|
+
stdout equ 1 // 'equ' constant definition
|
8
|
+
|
9
|
+
syscall macro nr // asm-style macros
|
10
|
+
mov eax, nr ; the syscall number goes in eax
|
11
|
+
int 80h
|
12
|
+
endm
|
13
|
+
|
14
|
+
#define syscall1(nr, arg) mov ebx, arg syscall(__NR_##nr) // c++-style macros
|
15
|
+
#define syscall3(nr, arg1, arg2, arg3) mov edx, arg3 mov ecx, arg2 syscall1(nr, arg1)
|
16
|
+
|
17
|
+
.entrypoint // the elf entrypoint
|
18
|
+
nop nop
|
19
|
+
call 1f // 1f is the first label named '1' found forward
|
20
|
+
toto_str db "toto\n"
|
21
|
+
toto_str_len equ $ - toto_str // $ is the address of the start of the current instruction/data
|
22
|
+
|
23
|
+
1:
|
24
|
+
pop ebp
|
25
|
+
|
26
|
+
syscall3(write, stdout, ebp, toto_str_len)
|
27
|
+
|
28
|
+
/*
|
29
|
+
; hang forever
|
30
|
+
jmp $
|
31
|
+
*/
|
32
|
+
|
33
|
+
syscall1(exit, 0)
|
34
|
+
hlt
|
@@ -0,0 +1,47 @@
|
|
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 usage of the C parser to compute the offset of members of a given structure
|
8
|
+
# usage: struct_offset.rb <c file> <struct name>
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'metasm'
|
12
|
+
include Metasm
|
13
|
+
|
14
|
+
require 'optparse'
|
15
|
+
opts = { :hdrs => [], :defs => {}, :path => [], :cpu => 'X86', :offbase => 16 }
|
16
|
+
OptionParser.new { |opt|
|
17
|
+
opt.on('-o outfile') { |f| opts[:outfile] = f }
|
18
|
+
opt.on('-H additional_header') { |f| opts[:hdrs] << f }
|
19
|
+
opt.on('-I path', '--includepath path') { |f| opts[:path] << f }
|
20
|
+
opt.on('-D var') { |f| k, v = f.split('=', 2) ; opts[:defs].update k => (v || '') }
|
21
|
+
opt.on('-d') { opts[:offbase] = 10 }
|
22
|
+
opt.on('--cpu CpuClass') { |c| opts[:cpu] = c }
|
23
|
+
opt.on('--gcc') { opts[:gcc] = true }
|
24
|
+
opt.on('--vs', '--visualstudio') { opts[:vs] = true }
|
25
|
+
}.parse!(ARGV)
|
26
|
+
|
27
|
+
cp = Metasm.const_get(opts[:cpu]).new.new_cparser
|
28
|
+
|
29
|
+
cp.prepare_gcc if opts[:gcc]
|
30
|
+
cp.prepare_visualstudio if opts[:vs]
|
31
|
+
|
32
|
+
pp = cp.lexer
|
33
|
+
pp.warn_redefinition = false
|
34
|
+
pp.include_search_path[0, 0] = opts[:path]
|
35
|
+
opts[:defs].each { |k, v| pp.define k, v }
|
36
|
+
|
37
|
+
cp.parse opts[:hdrs].map { |h| "#include <#{h}>" }.join("\n")
|
38
|
+
|
39
|
+
abort 'need source + struct name' unless ARGV.length >= 2
|
40
|
+
|
41
|
+
cp.parse_file(ARGV.shift)
|
42
|
+
|
43
|
+
$stdout.reopen File.open(opts[:outfile], 'w') if opts[:outfile]
|
44
|
+
|
45
|
+
ARGV.each { |structname|
|
46
|
+
puts cp.alloc_c_struct(structname)
|
47
|
+
}
|
data/samples/testpe.rb
ADDED
@@ -0,0 +1,32 @@
|
|
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
|
+
# a sample application
|
10
|
+
#
|
11
|
+
|
12
|
+
|
13
|
+
require 'metasm'
|
14
|
+
|
15
|
+
pe = Metasm::PE.assemble Metasm::Ia32.new, <<EOS
|
16
|
+
.entrypoint
|
17
|
+
push 0
|
18
|
+
push title
|
19
|
+
push message
|
20
|
+
push 0
|
21
|
+
call messagebox
|
22
|
+
|
23
|
+
xor eax, eax
|
24
|
+
ret
|
25
|
+
|
26
|
+
.import 'user32' MessageBoxA messagebox
|
27
|
+
|
28
|
+
.data
|
29
|
+
message db 'kikoo lol', 0
|
30
|
+
title db 'blaaa', 0
|
31
|
+
EOS
|
32
|
+
pe.encode_file 'testpe.exe'
|
data/samples/testraw.rb
ADDED
@@ -0,0 +1,45 @@
|
|
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
|
+
# usage: test.rb < source.asm
|
10
|
+
|
11
|
+
require 'metasm'
|
12
|
+
|
13
|
+
|
14
|
+
dump = ARGV.delete '--dump'
|
15
|
+
|
16
|
+
source = ARGF.read
|
17
|
+
|
18
|
+
cpu = Metasm::Ia32.new
|
19
|
+
shellcode = Metasm::Shellcode.assemble(cpu, source).encode_string
|
20
|
+
shellstring = shellcode.unpack('C*').map { |b| '\\x%02x' % b }.join
|
21
|
+
|
22
|
+
if dump
|
23
|
+
puts shellstring
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
|
27
|
+
File.open('test-testraw.c', 'w') { |fd|
|
28
|
+
fd.puts <<EOS
|
29
|
+
unsigned char sc[] = "#{shellstring}";
|
30
|
+
int main(void)
|
31
|
+
{
|
32
|
+
((void (*)())sc)();
|
33
|
+
return 42;
|
34
|
+
}
|
35
|
+
EOS
|
36
|
+
}
|
37
|
+
|
38
|
+
system 'gcc -W -Wall -o test-testraw test-testraw.c'
|
39
|
+
system 'chpax -psm test-testraw'
|
40
|
+
|
41
|
+
puts "running"
|
42
|
+
system './test-testraw'
|
43
|
+
puts "done"
|
44
|
+
#File.unlink 'test-testraw'
|
45
|
+
File.unlink 'test-testraw.c'
|