root/framework3/trunk/msfopcode

Revision 5392, 9.7 kB (checked in by hdm, 8 months ago)

Merged revisions 5386-5391 via svnmerge from
svn+ssh://metasploit.com/home/svn/framework3/branches/framework-3.1

........

r5391 | hdm | 2008-02-02 15:26:48 -0600 (Sat, 02 Feb 2008) | 3 lines


Prepend a library directory to the search path, if MSF_LOCAL_LIB is set. This lets folks maintain a set of modified libraries that will be used instead of the official ones. Documentation updates as well.

........

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/env ruby
2 #
3 # This user interface provides a command line interface to the Metasploit
4 # Opcode Database.  It provides users with the ability to search for opcodes
5 # and to display information about modules.
6 #
7
8 msfbase = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
9 $:.unshift(File.join(File.dirname(msfbase), 'lib'))
10 $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
11
12 require 'rex'
13 require 'rex/ui'
14 require 'rex/exploitation/opcodedb'
15
16 if (ARGV.length == 0)
17         $stderr.puts("\n" + "    Usage: #{File.basename($0)} command <options>\n\n" +
18                 "SUPPORTED COMMANDS\n\n" +
19                 "   stats       Display database statistics\n" +
20                 "   locales     Display supported locales\n" +
21                 "   metatypes   Display supported opcode meta types (Ex: jmp reg)\n" +
22                 "   groups      Display supported opcode groups (Ex: esp => eip)\n" +
23                 "   types       Display supported opcode types (Ex: jmp esp)\n" +
24                 "   platforms   Display supported platforms\n" +
25                 "   modules     Display information about specific modules\n" +
26                 "   search      Search for opcodes given a set of criteria\n" +
27                 "\n")
28         exit
29 end
30
31 # Command-specific argument parser instances
32 $platform_args = Rex::Parser::Arguments.new(
33         "-p" => [ true,  "A comma separated list of operating system names to filter" ],
34         "-h" => [ false, "Help banner"                                                ])
35
36 $module_args = Rex::Parser::Arguments.new(
37         "-p" => [ true,  "A comma separated list of operating system names to filter (Ex: 2000,XP)" ],
38         "-l" => [ true,  "A comma separated list of locales to filter (Ex: English)" ],
39         "-m" => [ true,  "A comma separated list of module names to filter (Ex: kernel32.dll,user32.dll)" ],
40         "-d" => [ false, "Display detailed output" ],
41         "-S" => [ false, "Include module segment information" ],
42         "-I" => [ false, "Include module import information" ],
43         "-E" => [ false, "Include module export information" ],
44         "-x" => [ false, "Dump the raw XML response" ],
45         "-h" => [ false, "Help banner" ])
46
47 $search_args = Rex::Parser::Arguments.new(
48         "-p" => [ true,  "A comma separated list of operating system names to filter (Ex: 2000,XP)" ],
49         "-l" => [ true,  "A comma separated list of locales to filter (Ex: English)" ],
50         "-m" => [ true,  "A comma separated list of module names to filter (Ex: kernel32.dll,user32.dll)" ],
51         "-t" => [ true,  "A semi-colon separated list of opcode types to filter (Ex: jmp esp,call esp)" ],
52         "-g" => [ true,  "A comma separated list of opcode groups to filter (Ex: esp => eip)" ],
53         "-M" => [ true,  "A comma separated list of opcode meta types to filter (Ex: jmp reg)" ],
54         "-a" => [ true,  "A comma separated list of addresses to filter (Ex: 0x41424344)" ],
55         "-P" => [ false, "Results must span more than one operating system version" ],
56         "-x" => [ false, "Dump the raw XML response" ],
57         "-h" => [ false, "Help banner"])
58
59 # Command specific option argument parsing association
60 cmd_args =
61 {
62         "platforms" =>
63                 [
64                         $platform_args,
65                         Proc.new { |opt, val|
66                                 case opt
67                                         when "-p"
68                                                 $filter['Names'] = val.split(/,/)
69                                         when "-x"
70                                                 $dump_xml = true
71                                         when "-h"
72                                                 $stderr.puts("\n    Usage: #{File.basename($0)} platforms <options>\n" + $platform_args.usage)
73                                                 exit
74                                 end
75                         }
76                 ],
77         "modules" =>
78                 [
79                         $module_args,
80                         Proc.new { |opt, val|
81                                 case opt
82                                         when "-p"
83                                                 $filter['PlatformNames'] = val.split(/,/)
84                                         when "-l"
85                                                 $filter['LocaleNames'] = val.split(/,/)
86                                         when "-m"
87                                                 $filter['ModuleNames'] = val.split(/,/)
88                                         when "-S"
89                                                 $filter['Segments'] = true
90                                         when "-I"
91                                                 $filter['Imports'] = true
92                                         when "-E"
93                                                 $filter['Exports'] = true
94                                         when "-d"
95                                                 $filter['Detailed'] = true
96                                         when "-x"
97                                                 $dump_xml = true
98                                         when "-h"
99                                                 $stderr.puts("\n    Usage: #{File.basename($0)} modules <options>\n" + $module_args.usage)
100                                                 exit
101                                 end
102                         }
103                 ],
104         "search" =>
105                 [
106                         $search_args,
107                         Proc.new { |opt, val|
108                                 case opt
109                                         when "-p"
110                                                 $filter['PlatformNames'] = val.split(/,/)
111                                         when "-l"
112                                                 $filter['LocaleNames'] = val.split(/,/)
113                                         when "-m"
114                                                 $filter['ModuleNames'] = val.split(/,/)
115                                         when "-t"
116                                                 $filter['TypeNames'] = val.split(/;/)
117                                         when "-g"
118                                                 $filter['GroupNames'] = val.split(/,/)
119                                         when "-M"
120                                                 $filter['MetaTypeNames'] = val.split(/,/)
121                                         when "-a"
122                                                 $filter['Addresses'] = val.split(/,/).map { |e| e.hex }
123                                         when "-P"
124                                                 $filter['Portable'] = true
125                                         when "-x"
126                                                 $dump_xml = true
127                                         when "-h"
128                                                 $stderr.puts("\n    Usage: #{File.basename($0)} search <options>\n" + $search_args.usage)
129                                                 exit
130                                 end
131                         }
132                 ],
133 }
134
135 # Default to not dumping the XML contents
136 $dump_xml = false
137
138 # Extract the command
139 cmd = ARGV.shift
140
141 # Create the opcode client instance
142 client = Rex::Exploitation::OpcodeDb::Client.new
143
144 # Initializes the filter to an empty hash
145 $filter = {}
146
147 # Parse the command specific arguments as necessary
148 if (args = cmd_args[cmd])
149         args[0].parse(ARGV) { |opt, idx, val|
150                 args[1].call(opt, val)
151         }
152 end
153
154 # Process the specific command
155 case cmd
156         when "stats"
157                 stats = client.statistics
158
159                 puts(
160                         "\n" +
161                         "Last Updated             : #{stats.last_update.to_s}\n" +
162                         "Number of Opcodes        : #{stats.opcodes}\n" +
163                         "Number of Opcode Types   : #{stats.opcode_types}\n" +
164                         "Number of Platforms      : #{stats.platforms}\n" +
165                         "Number of Architectures  : #{stats.architectures}\n" +
166                         "Number of Modules        : #{stats.modules}\n" +
167                         "Number of Module Segments: #{stats.module_segments}\n" +
168                         "Number of Module Imports : #{stats.module_imports}\n" +
169                         "Number of Module Exports : #{stats.module_exports}\n\n")
170         when "locales"
171                 client.locales.each { |locale| puts "#{locale.name}" }
172         when "metatypes"
173                 client.meta_types.each { |mt| puts "#{mt.name}" }
174         when "groups"
175                 client.groups.each { |g| puts "#{g.name}" }
176         when "types"
177                 client.types.each { |g| puts "#{g.name}" }
178         when "platforms"
179                 client.platforms($filter).each { |p| puts "#{p.desc}" }
180         when "modules"
181                 if (ARGV.length == 0)
182                         $stderr.puts("Filter criteria required -- specify '-h' for help.")
183                         exit
184                 end
185
186                 modules = client.modules($filter)
187
188                 if ($dump_xml)
189                         puts client.last_xml
190                         exit
191                 end
192
193                 # If we're displaying extra information on a per-module basis, then we
194                 # need to not display in a single table format.
195                 if ($filter['Segments'] or $filter['Imports'] or $filter['Exports'] or $filter['Detailed'])
196
197                         modules.each { |mod|
198                                 puts(
199                                         ".-============================================\n\n" +
200                                         "  Name        : #{mod.name}\n" +
201                                         "  Base Address: #{"0x%.8x" % mod.base_address}\n" +
202                                         "  Size        : #{mod.image_size}\n" +
203                                         "  Version     : #{mod.maj_maj_ver}.#{mod.maj_min_ver}.#{mod.min_maj_ver}.#{mod.min_min_ver}\n" +
204                                         "  Timestamp   : #{mod.timestamp.to_s}\n" +
205                                         "  Locale      : #{mod.locale.name}\n" +
206                                         "  Platforms   : \n\n" +
207                                         "#{mod.platforms.map { |p| "    " + p.desc }.join("\n")}\n\n")
208
209                                 # Display module segments
210                                 if ($filter['Segments'])
211                                         tbl = Rex::Ui::Text::Table.new(
212                                                 'Indent'  => 4,
213                                                 'Columns' =>
214                                                         [
215                                                                 "Type",
216                                                                 "Base Address",
217                                                                 "Size",
218                                                                 "Permissions"
219                                                         ])
220
221                                         mod.segments.each { |seg|
222                                                 tbl << [
223                                                         seg.type,
224                                                         "0x%.8x" % seg.base_address,
225                                                         seg.size.to_s,
226                                                         (((seg.readable == true) ? "r" : "") +
227                                                          ((seg.writable == true) ? "w" : "") +
228                                                          ((seg.executable == true) ? "x" : ""))
229                                                 ]
230                                         }
231
232                                         puts("\n  Module segments:\n\n" + tbl.to_s + "\n")
233                                 end
234
235                                 # Display module imports
236                                 if ($filter['Imports'])
237                                         tbl = Rex::Ui::Text::Table.new(
238                                                 'Indent'  => 4,
239                                                 'Columns' =>
240                                                         [
241                                                                 "Ordinal",
242                                                                 "Address",
243                                                                 "Name",
244                                                         ])
245
246                                         mod.imports.each { |imp|
247                                                 tbl << [
248                                                         imp.ordinal.to_s,
249                                                         "0x%.8x" % imp.address,
250                                                         imp.name
251                                                 ]
252                                         }
253
254                                         puts("\n  Module imports:\n\n" + tbl.to_s + "\n")
255                                 end
256
257                                 # Display module exports
258                                 if ($filter['Exports'])
259                                         tbl = Rex::Ui::Text::Table.new(
260                                                 'Indent'  => 4,
261                                                 'Columns' =>
262                                                         [
263                                                                 "Ordinal",
264                                                                 "Address",
265                                                                 "Name",
266                                                         ])
267
268                                         mod.exports.each { |exp|
269                                                 tbl << [
270                                                         exp.ordinal.to_s,
271                                                         "0x%.8x" % exp.address,
272                                                         exp.name
273                                                 ]
274                                         }
275
276                                         puts("\n  Module exports:\n\n" + tbl.to_s + "\n")
277
278                                 end
279                         }
280
281                 else
282                         tbl = Rex::Ui::Text::Table.new(
283                                 'Indent'  => 4,
284                                 'Header'  => "Matching Modules",
285                                 'Columns' =>
286                                         [
287                                                 "Name",
288                                                 "Base Address",
289                                                 "Size",
290                                                 "Version",
291                                                 "Timestamp",
292                                                 "Locale",
293                                         ])
294
295                         modules.each { |mod|
296                                 tbl << [
297                                         mod.name,
298                                         "0x%.8x" % mod.base_address,
299                                         mod.image_size,
300                                         "#{mod.maj_maj_ver}.#{mod.maj_min_ver}.#{mod.min_maj_ver}.#{mod.min_min_ver}",
301                                         mod.timestamp.to_s,
302                                         mod.locale.name,
303                                 ]
304                         }
305
306                         puts("\n" + tbl.to_s + "\n")
307                 end
308         when "search"
309                 if (ARGV.length == 0)
310                         $stderr.puts("Filter criteria required -- specify '-h' for help.")
311                         exit
312                 end
313
314                 opcodes = client.search($filter)
315
316                 if ($dump_xml)
317                         puts client.last_xml
318                         exit
319                 end
320
321                 tbl = Rex::Ui::Text::Table.new(
322                         'Indent'  => 4,
323                         'Header'  => "Opcodes",
324                         'Columns' =>
325                                 [
326                                         "Address",
327                                         "Type",
328                                         "OS"
329                                 ])
330
331                 opcodes.each { |opcode|
332                         tbl << [
333                                 "0x%.8x" % opcode.address,
334                                 opcode.type.name,
335                                 opcode.modules[0].platforms[0].desc  + " (#{opcode.modules[0].name})"
336                         ]
337
338                         midx = 0
339                         pidx = 1
340
341                         until (opcode.modules[midx] == nil)
342                                 tbl << [ '', '', '' ] if (midx >= 1)
343
344                                 if (opcode.modules[midx].platforms.length > 1)
345        
346                                         until (opcode.modules[midx].platforms[pidx] == nil)
347                                                 tbl << [
348                                                         '', '',
349                                                         opcode.modules[midx].platforms[pidx].desc + " (#{opcode.modules[midx].name})"
350                                                 ]
351        
352                                                 pidx += 1
353                                         end
354        
355                                         pidx = 0
356                                 end
357
358                                 midx += 1
359                         end
360                 }
361
362                 puts("\n" + tbl.to_s + "\n")
363         else
364                 $stderr.puts("Unsupported command: #{cmd}")
365 end
366
Note: See TracBrowser for help on using the browser.