Implement a crash handler to ease debugging
git-svn-id: file:///home/svn/framework3/trunk@10416 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
3c99897115
commit
89b33c2cc7
|
@ -17,6 +17,10 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
|
#include <asm/sigcontext.h>
|
||||||
|
#include <asm/ucontext.h>
|
||||||
|
|
||||||
|
|
||||||
#include "linker.h"
|
#include "linker.h"
|
||||||
#include "linker_debug.h"
|
#include "linker_debug.h"
|
||||||
#include "linker_format.h"
|
#include "linker_format.h"
|
||||||
|
@ -133,23 +137,210 @@ int dlsocket(void *libc)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
extern soinfo *solist;
|
||||||
* 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
|
/*
|
||||||
* use bash / nc / whatever to put a socket on fd 5 for now.
|
* This can't handle PROT_WRITE only memory :-)
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void dump_memory(char **ptr, int *len, char *prefix, long unsigned int location, size_t count)
|
||||||
|
{
|
||||||
|
unsigned char discard[count];
|
||||||
|
|
||||||
|
int fds[2];
|
||||||
|
int rc;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if(pipe(fds) == -1) return;
|
||||||
|
|
||||||
|
if(write(fds[1], location, count) == count) {
|
||||||
|
if(read(fds[0], discard, count) == count) {
|
||||||
|
n = 0;
|
||||||
|
while(n < count) {
|
||||||
|
|
||||||
|
rc = format_buffer(*ptr, *len, "%s+%4d: %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",
|
||||||
|
prefix, n, discard[n + 0], discard[n + 1], discard[n + 2], discard[n + 3],
|
||||||
|
discard[n + 4], discard[n + 5], discard[n + 6], discard[n + 7],
|
||||||
|
discard[n + 8], discard[n + 9], discard[n + 10], discard[n + 11],
|
||||||
|
discard[n + 12], discard[n + 13], discard[n + 14], discard[n + 15]
|
||||||
|
);
|
||||||
|
|
||||||
|
*ptr += rc;
|
||||||
|
*len -= rc;
|
||||||
|
|
||||||
|
n += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = format_buffer(*ptr, *len, "\n");
|
||||||
|
*ptr += rc;
|
||||||
|
*len -= rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fds[0]);
|
||||||
|
close(fds[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *special_sig_stack;
|
||||||
|
|
||||||
|
void sigcrash(int signo, siginfo_t *info, void *context)
|
||||||
|
{
|
||||||
|
struct ucontext *uc = (struct ucontext *)(context);
|
||||||
|
struct sigcontext *sg = (struct sigcontext *)(& uc->uc_mcontext);
|
||||||
|
char buf[8192], *p;
|
||||||
|
int len, rc;
|
||||||
|
int fd;
|
||||||
|
soinfo *si;
|
||||||
|
|
||||||
|
char filename[64];
|
||||||
|
|
||||||
|
// reset signal handler, in case of another crash
|
||||||
|
signal(signo, SIG_DFL);
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
len = sizeof(buf);
|
||||||
|
|
||||||
|
rc = format_buffer(p, len, "\n[ meterpreter crash -- caught signal %d ]\n\n", signo);
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
|
||||||
|
rc = format_buffer(p, len, "Special registers:\nEIP: 0x%08x ESP: 0x%08x EBP: 0x%08x\n\n",
|
||||||
|
sg->eip, sg->esp, sg->ebp);
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
|
||||||
|
rc = format_buffer(p, len, "General registers:\nEAX: 0x%08x EBX: 0x%08x ECX: 0x%08x" \
|
||||||
|
" EDX: 0x%08x ESI: 0x%08x EDI: 0x%08x\n\n",
|
||||||
|
sg->eax, sg->ebx, sg->ecx, sg->edx, sg->esi, sg->edi);
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
|
||||||
|
rc = format_buffer(p, len, "Loaded libraries:\n");
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
|
||||||
|
for(si = solist; si; si = si->next) {
|
||||||
|
rc = format_buffer(p, len, "%s %08x - %08x", si->name, si->base, si->base + si->size);
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
|
||||||
|
if(sg->eip >= si->base && sg->eip <= (si->base + si->size)) {
|
||||||
|
rc = format_buffer(p, len, " [eip offset: %08x]", sg->eip - si->base);
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = format_buffer(p, len, "\n");
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = format_buffer(p, len, "\nRegister pointer contents:\n");
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
|
||||||
|
dump_memory(&p, &len, "EAX", sg->eax, 32);
|
||||||
|
dump_memory(&p, &len, "EBX", sg->ebx, 32);
|
||||||
|
dump_memory(&p, &len, "ECX", sg->ecx, 32);
|
||||||
|
dump_memory(&p, &len, "EDX", sg->edx, 32);
|
||||||
|
dump_memory(&p, &len, "ESI", sg->esi, 32);
|
||||||
|
dump_memory(&p, &len, "EDI", sg->edi, 32);
|
||||||
|
dump_memory(&p, &len, "EBP", sg->ebp, 64);
|
||||||
|
dump_memory(&p, &len, "ESP", sg->esp, 64);
|
||||||
|
dump_memory(&p, &len, "EIP", sg->eip, 16);
|
||||||
|
|
||||||
|
fd = open("/proc/self/maps", O_RDONLY);
|
||||||
|
if(fd != -1) {
|
||||||
|
rc = read(fd, p, len);
|
||||||
|
if(rc != -1) {
|
||||||
|
p += rc;
|
||||||
|
len -= rc;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(filename, 0, sizeof(filename));
|
||||||
|
format_buffer(filename, sizeof(filename) - 1, "/tmp/meterpreter.crash.%d", getpid());
|
||||||
|
|
||||||
|
fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644);
|
||||||
|
if(fd) {
|
||||||
|
write(fd, buf, 8192 - len);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(2, buf, 8192 - len);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void sigchld(int signo)
|
void sigchld(int signo)
|
||||||
{
|
{
|
||||||
waitpid(-1, NULL, WNOHANG);
|
waitpid(-1, NULL, WNOHANG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NEWSTKSIZE (4096 * 32)
|
||||||
|
|
||||||
|
|
||||||
|
void handle_crashes()
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
memset(&sa, 0, sizeof(struct sigaction));
|
||||||
|
sa.sa_sigaction = sigcrash;
|
||||||
|
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We set up a special signal handler stack on the chance that
|
||||||
|
* if our thread's esp is corrupt / too long, we can still execute
|
||||||
|
* the crash handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
special_sig_stack = mmap(NULL, NEWSTKSIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||||
|
|
||||||
|
if(special_sig_stack == MAP_FAILED) {
|
||||||
|
TRACE("[ (%s) unable to mmap for special stack. ]", __FUNCTION__);
|
||||||
|
|
||||||
|
sa.sa_flags &= ~SA_ONSTACK;
|
||||||
|
special_sig_stack = NULL;
|
||||||
|
} else {
|
||||||
|
stack_t newstk;
|
||||||
|
|
||||||
|
newstk.ss_sp = special_sig_stack;
|
||||||
|
newstk.ss_flags = 0;
|
||||||
|
newstk.ss_size = NEWSTKSIZE;
|
||||||
|
|
||||||
|
if(sigaltstack(&newstk, NULL) == -1) {
|
||||||
|
TRACE("[ (%s) unable to sigaltstack. errno = %d ]", __FUNCTION__, errno);
|
||||||
|
munmap(special_sig_stack, NEWSTKSIZE);
|
||||||
|
special_sig_stack = NULL;
|
||||||
|
sa.sa_flags &= ~SA_ONSTACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sigaction(SIGSEGV, &sa, NULL); sigaction(SIGILL, &sa, NULL);
|
||||||
|
sigaction(SIGFPE, &sa, NULL); sigaction(SIGSYS, &sa, NULL);
|
||||||
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the entry point for the meterpreter payload, either as a stand alone executable, or a
|
||||||
|
* payload executing on the remote machine.
|
||||||
|
*
|
||||||
|
* If executed as a stand alone, int fd will be invalid. Later on, once libc has been loaded,
|
||||||
|
* it will connect to the metasploit meterpreter server.
|
||||||
|
*/
|
||||||
|
|
||||||
void _start(int fd)
|
void _start(int fd)
|
||||||
{
|
{
|
||||||
signal(SIGCHLD, sigchld);
|
alarm(0); // clear out any pending alarms.
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
|
|
||||||
// we can't run ./msflinker directly. Use rtldtest to test the code
|
signal(SIGCHLD, sigchld); // reap pids
|
||||||
metsrv_rtld(fd);
|
signal(SIGPIPE, SIG_IGN); // ignore read/write pipe errors, make them return -1.
|
||||||
|
|
||||||
|
handle_crashes(); // try to make debugging a little easier.
|
||||||
|
|
||||||
|
metsrv_rtld(fd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ static int link_image(soinfo *si, unsigned wr_offset);
|
||||||
static int socount = 0;
|
static int socount = 0;
|
||||||
static soinfo sopool[SO_MAX];
|
static soinfo sopool[SO_MAX];
|
||||||
static soinfo *freelist = NULL;
|
static soinfo *freelist = NULL;
|
||||||
static soinfo *solist = &libdl_info;
|
soinfo *solist = &libdl_info;
|
||||||
static soinfo *sonext = &libdl_info;
|
static soinfo *sonext = &libdl_info;
|
||||||
#if ALLOW_SYMBOLS_FROM_MAIN
|
#if ALLOW_SYMBOLS_FROM_MAIN
|
||||||
static soinfo *somain; /* main process, always the one after libdl_info */
|
static soinfo *somain; /* main process, always the one after libdl_info */
|
||||||
|
|
Loading…
Reference in New Issue