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");