This commit overhauls much of the meterpreter timeouts and staging processes. This fixes a bug with concurrent session handling, reduces CPU load by caching a single SSL certificate for all sessions, increases all of the critical timeouts, and generally makes mass ownage work better. We still need to limit the maximum number of concurrent on_session() threads to something sane to prevent sesssion spikes from dragging out the process even longer. The C-side meterpreter change is minimal and will only help with future compatibility if we move to non-blocking fd's for the SSL socket.

git-svn-id: file:///home/svn/framework3/trunk@10595 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
HD Moore 2010-10-08 04:11:47 +00:00
parent e4a00b2fd1
commit 2e9138ebbc
21 changed files with 49 additions and 16 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -68,7 +68,7 @@ void real_dprintf(char *filename, int line, const char *function, char *format,
#ifdef _WIN32 #ifdef _WIN32
//#define DEBUGTRACE // #define DEBUGTRACE 1
#ifdef DEBUGTRACE #ifdef DEBUGTRACE
#define dprintf(...) real_dprintf(__VA_ARGS__) #define dprintf(...) real_dprintf(__VA_ARGS__)

View File

@ -252,6 +252,7 @@ static BOOL server_negotiate_ssl(Remote *remote)
BOOL success = TRUE; BOOL success = TRUE;
SOCKET fd = 0; SOCKET fd = 0;
DWORD ret = 0; DWORD ret = 0;
DWORD res = 0;
lock_acquire( remote->lock ); lock_acquire( remote->lock );
@ -274,12 +275,23 @@ static BOOL server_negotiate_ssl(Remote *remote)
break; break;
} }
do {
if( (ret = SSL_connect(remote->ssl)) != 1 ) if( (ret = SSL_connect(remote->ssl)) != 1 )
{ {
dprintf("[SERVER] connect failed %d\n", SSL_get_error(remote->ssl, ret)); res = SSL_get_error(remote->ssl, ret);
dprintf("[SERVER] connect failed %d\n", res);
if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) {
// Catch non-blocking socket errors and retry
continue;
}
success = FALSE; success = FALSE;
break; break;
} }
} while(ret != 1);
if (success == FALSE) break;
dprintf("[SERVER] Sending a HTTP GET request to the remote side..."); dprintf("[SERVER] Sending a HTTP GET request to the remote side...");

View File

@ -187,7 +187,6 @@ class Meterpreter < Rex::Post::Meterpreter::Client
# #
def load_stdapi() def load_stdapi()
original = console.disable_output original = console.disable_output
console.disable_output = true console.disable_output = true
console.run_single('use stdapi') console.run_single('use stdapi')
console.disable_output = original console.disable_output = original
@ -209,7 +208,7 @@ class Meterpreter < Rex::Post::Meterpreter::Client
# #
def load_session_info() def load_session_info()
begin begin
::Timeout.timeout(20) do ::Timeout.timeout(60) do
username = self.sys.config.getuid username = self.sys.config.getuid
sysinfo = self.sys.config.sysinfo sysinfo = self.sys.config.sysinfo
self.info = "#{username} @ #{sysinfo['Computer']}" self.info = "#{username} @ #{sysinfo['Computer']}"

View File

@ -44,7 +44,7 @@ module MeterpreterOptions
end end
begin begin
::Timeout.timeout(10) do ::Timeout.timeout(30) do
if session.railgun and session.railgun.shell32.IsUserAnAdmin()["return"] == true if session.railgun and session.railgun.shell32.IsUserAnAdmin()["return"] == true
session.load_priv session.load_priv
session.info += " (ADMIN)" session.info += " (ADMIN)"

View File

@ -161,10 +161,10 @@ module ReverseTcp
# Start a new thread and pass the client connection # Start a new thread and pass the client connection
# as the input and output pipe. Client's are expected # as the input and output pipe. Client's are expected
# to implement the Stream interface. # to implement the Stream interface.
conn_threads << Thread.new { conn_threads << Thread.new(client) { |client_copy|
begin begin
handle_connection(client) handle_connection(client_copy)
rescue rescue ::Exception
elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}") elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}")
end end
} }

View File

@ -41,6 +41,16 @@ class Client
# #
@@ext_hash = {} @@ext_hash = {}
#
# Cached SSL certificate (required to scale)
#
@@ssl_ctx = nil
#
# Mutex to synchronize class-wide operations
#
@@ssl_mutex = ::Mutex.new
# #
# Checks the extension hash to see if a class has already been associated # Checks the extension hash to see if a class has already been associated
# with the supplied extension name. # with the supplied extension name.
@ -133,6 +143,11 @@ class Client
end end
def generate_ssl_context def generate_ssl_context
@@ssl_mutex.synchronize do
if not @@ssl_ctx
wlog("Generating SSL certificate for Meterpreter sessions")
key = OpenSSL::PKey::RSA.new(1024){ } key = OpenSSL::PKey::RSA.new(1024){ }
cert = OpenSSL::X509::Certificate.new cert = OpenSSL::X509::Certificate.new
cert.version = 2 cert.version = 2
@ -175,7 +190,14 @@ class Client
ctx.session_id_context = Rex::Text.rand_text(16) ctx.session_id_context = Rex::Text.rand_text(16)
return ctx wlog("Generated SSL certificate for Meterpreter sessions")
@@ssl_ctx = ctx
end # End of if not @ssl_ctx
end # End of mutex.synchronize
@@ssl_ctx
end end
# #
@ -197,7 +219,7 @@ class Client
# waiting for a response. # waiting for a response.
# #
def Client.default_timeout def Client.default_timeout
return 30 return 300
end end
## ##