find socket - extreme way文摘出处:http://www.linuxforum.net/forum/showflat.php?Cat=&Board=security&Number=524627&page=0&view=collapsed&sb=5&o=31&fpart=
coolq
/*******************************************
* Name   : sock_find.c (PoC)              *
* Author : CoolQ                          *
* Version: 0.0.1                          *
* Kernel : 2.6(general)/RedHat FC2        *
* Usage  : insmod sock_find.ko            *
* Warning: this is ONLY a PoC prog. it    *
*          tranverse the tcp_sock, you    *
*          can write your own prog handle *
*          about udp_sock, raw_sock, etc  *
* Also   : if you have ipv6 support, if   *
*          you are listening on port 23,  *
*          you should find the spicified  *
*          entry in tcp6_sock, not tcp_   *
*          sock!                          *
******************************************/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/tcp.h>
#include <asm/string.h>
#include <asm/types.h>
struct array_cache {
        unsigned int avail;
        unsigned int limit;
        unsigned int batchcount;
        unsigned int touched;
};
struct kmem_list3 {
        struct list_head        slabs_partial;  /* partial list first, better asm code*/
        struct list_head        slabs_full;
        struct list_head        slabs_free;
        unsigned long   free_objects;
        int             free_touched;
        unsigned long   next_reap;
        struct array_cache      *shared;
};
struct kmem_cache_s {
/* 1) per-cpu data, touched during every alloc/free */
        struct array_cache      *array[NR_CPUS];
        unsigned int            batchcount;
        unsigned int            limit;
/* 2) touched by every alloc & free from the backend */
        struct kmem_list3       lists;
        /* NUMA: kmem_3list_t   *nodelists[MAX_NUMNODES] */
        unsigned int            objsize;
        unsigned int            flags;  /* constant flags */
        unsigned int            num;    /* # of objs per slab */
        unsigned int            free_limit; /* upper limit of objects in the lists */
        spinlock_t              spinlock;
/* 3) cache_grow/shrink */
        /* order of pgs per slab (2^n) */
        unsigned int            gfporder;
        /* force GFP flags, e.g. GFP_DMA */
        unsigned int            gfpflags;
        size_t                  colour;         /* cache colouring range */
        unsigned int            colour_off;     /* colour offset */
        unsigned int            colour_next;    /* cache colouring */
        kmem_cache_t            *slabp_cache;
        unsigned int            slab_size;
        unsigned int            dflags;         /* dynamic flags */
        /* constructor func */
        void (*ctor)(void *, kmem_cache_t *, unsigned long);
        /* de-constructor func */
        void (*dtor)(void *, kmem_cache_t *, unsigned long);
/* 4) cache creation/removal */
        const char              *name;
        struct list_head        next;
/* 5) statistics */
#if STATS
        unsigned long           num_active;
        unsigned long           num_allocations;
        unsigned long           high_mark;
        unsigned long           grown;
        unsigned long           reaped;
        unsigned long           errors;
        unsigned long           max_freeable;
        atomic_t                allochit;
        atomic_t                allocmiss;
        atomic_t                freehit;
        atomic_t                freemiss;
#endif
#if DEBUG
        int                     dbghead;
        int                     reallen;
#endif
};
/*****************************************
* the kmem_bufctl_t definition is quite *
* differente between FC2 kernel and the *
* general one, FC2 is uint, but the     *
* general kernel is ushort!             *
* **************************************/
typedef unsigned int kmem_bufctl_t;  /* !! for RC2 !! */
#define BUFCTL_END    (((kmem_bufctl_t)(~0U))-0)
#define BUFCTL_FREE    (((kmem_bufctl_t)(~0U))-1)
#define    SLAB_LIMIT    (((kmem_bufctl_t)(~0U))-2)
struct slab{
        struct list_head        list;
        unsigned long           colouroff;
        void                    *s_mem;         /* including colour offset */
        unsigned int            inuse;          /* num of objs active in slab */
        kmem_bufctl_t           free;
};
static struct kmem_cache_s *dummy_cachep;
static int      my_array[128];
static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)
{
        return (kmem_bufctl_t *)(slabp+1);
}
static int mod_init(void)
{
        struct list_head        *p, *q;
        struct kmem_cache_s     *cachep;
        struct slab             *slabp;
    struct tcp_sock        *tcp_sk;
        int                     i;
        
        
    /*************************************************************
     * the way we use here is to tranverse the tcp_sock slab,    *
     * get all the active slab objs. there are 3 lists, slabs_   *
     * free, slabs_full, slabs_partial. you can get active objs  *
     * from the full and partial lists.                          *
     * Tip: first we must get the symbol tcp_sock, unfortunately *
     *      the kernel doesn't EXPORT this symbol. we can use    *
     *      the System.map file located in /boot, but Redhat FC2 *
     *      doesn't have such entry ( whereas the general has )! *
     *      so, we can create a dummy cache discriptor , use     *
     *      double linked list (kmem_cache_s->next) to get all   *
     *      the cache symbols.                                   *
     ************************************************************/
    
        dummy_cachep = kmem_cache_create("dummy_cachep", 128, ARCH_MIN_TASKALIGN,SLAB_PANIC, NULL, NULL);
        list_for_each(p, dummy_cachep->next.prev){
                cachep = list_entry(p, struct kmem_cache_s, next);
                if(cachep->name){
                        spin_lock(&cachep->spinlock);
            if(!strcmp(cachep->name, "tcp_sock")){
                /*------------ slabs full ---------------*/
                list_for_each(q, &(cachep->lists.slabs_full)){
                    slabp = list_entry(q, struct slab, list);
                    for(i = 0; i < cachep->num; i++){
                        tcp_sk = slabp->s_mem + i * cachep->objsize;
                        printk("port:%d, ip:%x, state:%d\n",
                            tcp_sk->inet.sport, 
                            tcp_sk->inet.saddr, 
                            tcp_sk->sk.sk_state);
                    }
                }
                /*---------- slabs partial --------------*/
                list_for_each(q, &(cachep->lists.slabs_partial)){
                    slabp = list_entry(q, struct slab, list);
                    for(i = 0; i < cachep->num; i++)
                        my_array[i] = 0;
                    i = slabp->free;
                    
                    /* get all free objs and store the num in my_array */
                    do{
                        my_array[i] = 1;
                        i = slab_bufctl(slabp)[i];
                    }while(i != BUFCTL_END);
                    
                    for(i = 0; i < cachep->num; i++){
                        if(!my_array[i]){
                            tcp_sk = slabp->s_mem + i * cachep->objsize;
                            printk("port-s:%x, ip:%x, state:%d\n",
                                ntohs(tcp_sk->inet.sport),
                                tcp_sk->inet.saddr,
                                tcp_sk->sk.sk_state);
                        }
                    }
                }
            }
                        spin_unlock(&cachep->spinlock); 
                }
        }        
        return 0;
}
static void mod_exit(void)
{
        kmem_cache_destroy(dummy_cachep);
}
module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("qufuping<at>ercist.iscas.ac.cn");