kinsmod.c

Module insertion without native support
NAME : kinsmod.c
AUTHOR : Silvio Cesare
DESCRIPTION : This is a very nice program which allows us to insert LKMs on system with no native module support.
LINK : found it by a search on http://www.antisearch.com

/**********needed include file*/
#ifndef KMEM_H
#define KMEM_H

#include <linux/module.h>
#include <unistd.h>
#include <fcntl.h>

/*
these functions are anologous to standard file routines.
*/

#define kopen(mode) open("/dev/kmem", (mode))
#define kclose(kd) close((kd))

ssize_t kread(int kd, int pos, void *buf, size_t size);
ssize_t kwrite(int kd, int pos, void *buf, size_t size);

/*
ksyms initialization and cleanup
*/

int ksyms_init(const char *map);
void ksyms_cleanup(void);

/*
print the ksym table
*/

void ksyms_print(void);

/*
return the ksym of name 'name' or NULL if no symbol exists
*/

struct kernel_sym *ksyms_find(const char *name);

#endif

/**********KMEM functions*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/module.h>
#include <linux/unistd.h>
#include "kmem.h"
struct ksymlist
            {
            struct ksymlist* next;
            struct kernel_sym ksym;
            };

struct ksymlisthead
            {
            struct ksymlist* next;
            };

/*
the hash size must be an integral power of two
*/

#define KSYM_HASH_SIZE 512
struct ksymlisthead ksymhash[KSYM_HASH_SIZE];

/*
these functions are anologous to standard file routines.
*/

ssize_t kread(int kd, int pos, void *buf, size_t size)
            {
            int retval;
            retval = lseek(kd, pos, SEEK_SET);
            if (retval != pos)
                        return retval;
            return read(kd, buf, size);
            }

ssize_t kwrite(int kd, int pos, void *buf, size_t size)
            {
            int retval;
            retval = lseek(kd, pos, SEEK_SET);
            if (retval != pos)
                        return retval;
            return write(kd, buf, size);
            }

void ksyms_print(void)
            {
            int i;

            for (i = 0; i < KSYM_HASH_SIZE; i++)
                        {
                        struct ksymlist *head = (struct ksymlist *)&ksymhash[i];
                        struct ksymlist *current = ksymhash[i].next;
                        while (current != head)
                                   {
                                   printf(
                                               "name: %s addr: %lx\n",
                                               current->ksym.name,
                                               current->ksym.value
                                               );
                                   current = current->next;
                                   }
                        }
            }

void ksyms_cleanup(void)
            {
            int i;

            for (i = 0; i < KSYM_HASH_SIZE; i++)
                        {
                        struct ksymlist *head = (struct ksymlist *)&ksymhash[i];
                        struct ksymlist *current = head->next;
                        while (current != head)
                                   {
                                   struct ksymlist *next = current->next;
                                   free(current);
                                   current = next;
                                   }
                        }
            }

int hash(const char *name)
            {
            unsigned long h;
            const char *p;

            for (h = 0, p = name; *p; h += (unsigned char)*p, p++);
                        return h & (KSYM_HASH_SIZE - 1);
            }

int ksyminsert(struct kernel_sym *ksym)
            {
            struct ksymlist *node;
            struct ksymlisthead *head;

            node = (struct ksymlist *)malloc(sizeof(struct ksymlist));
            if (node == NULL) return -1;
                        head = &ksymhash[hash(ksym->name)];
            memcpy(&node->ksym, ksym, sizeof(*ksym));
            node->next = (struct ksymlist *)head->next;
            head->next = node;

            return 0;
            }

int ksyms_init(const char *map)
            {
            char s[512];
            FILE *f;
            int i;

            for (i = 0; i < KSYM_HASH_SIZE; i++)
                        ksymhash[i].next = (struct ksymlist *)&ksymhash[i];
            f = fopen(map, "r");
            if (f == NULL) return -1;
                        while (fgets(s, sizeof(s), f) != NULL)
                                   {
                                   struct kernel_sym ksym;
                                   char *n, *p;
                                   ksym.value = strtoul(s, &n, 16);
                                   if (n == s || *n == 0) goto error;
                                               p = n;
                                   while (*p && isspace(*p))
                                               ++p;
                                   if (*p == 0 || p[1] == 0 || p[2] == 0)
                                               goto error;
                                   p += 2;
                                   n = p;
                                   while (*p && !isspace(*p))
                                               ++p;
                                   if (*p) *p = 0;
                                               strncpy(ksym.name, n, 60);
                                   if (ksyminsert(&ksym) < 0)
                                               goto error;
                                   }
            fclose(f);
            return 0;
            error:
            fclose(f);
            ksyms_cleanup();
            printf("--> %s\n", s);
            return -1;
            }

struct kernel_sym *ksyms_find(const char *name)
            {
            struct ksymlist *head = (struct ksymlist *)&ksymhash[hash(name)];
            struct ksymlist *current = head->next;

            while (current != head)
                        {
                        if (!strncmp(current->ksym.name, name, 60))
                                   return &current->ksym;
                        current = current->next;
                        }
            return NULL;
            }

/**********MAIN PROGRAM : kinsmod.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <elf.h>
#include <getopt.h>
#include "kmem.h"

static char system_map[] = "System.kmap";
static int error = 0;
static int run = 0;
static int force = 0;

struct _module
            {
            Elf32_Ehdr ehdr;
            Elf32_Shdr* shdr;
            unsigned long maddr;
            int maxlen;
            int len;
            int strtabidx;
            char** section;
            };

Elf32_Sym *local_sym_find(Elf32_Sym *symtab, int n, char *strtab, const char *name)
            {
            int i;

            for (i = 0; i < n; i++)
                        {
                        if (!strcmp(&strtab[symtab[i].st_name], name))
                                   return &symtab[i];
                        }
            return NULL;
            }

Elf32_Sym *localall_sym_find(struct _module *module, const char *name)
            {
            char *strtab = module->section[module->strtabidx];
            int i;

            for (i = 0; i < module->ehdr.e_shnum; i++)
                        {
                        Elf32_Shdr *shdr = &module->shdr[i];
                        if (shdr->sh_type == SHT_SYMTAB)
                                   {
                                   Elf32_Sym *sym;
                                   sym = local_sym_find(
                                                           (Elf32_Sym *)module->section[i],
                                                           shdr->sh_size/sizeof(Elf32_Sym),
                                                           strtab,
                                                           name
                                                           );
                                   if (sym != NULL) return sym;
                                   }
                        }
            return NULL;
            }

void check_module(struct _module *module, int fd)
            {
            Elf32_Ehdr *ehdr = &module->ehdr;

            if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr))
                        {
                        perror("read");
                        exit(1);
                        }
            /* ELF checks */
            if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG))
                        {
                        fprintf(stderr, "File not ELF\n");
                        exit(1);
                        }
            if (ehdr->e_type != ET_REL)
                        {
                        fprintf(stderr, "ELF type not ET_REL\n");
                        exit(1);
                        }
            if (ehdr->e_machine != EM_386 && ehdr->e_machine != EM_486)
                        {
                        fprintf(stderr, "ELF machine type not EM_386 or EM_486\n");
                        exit(1);
                        }
            if (ehdr->e_version != EV_CURRENT)
                        {
                        fprintf(stderr, "ELF version not current\n");
                        exit(1);
                        }
            }

void load_section(char **p, int fd, Elf32_Shdr *shdr)
            {
            if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0)
                        {
                        perror("lseek");
                        exit(1);
                        }
            *p = (char *)malloc(shdr->sh_size);
            if (*p == NULL)
                        {
                        perror("malloc");
                        exit(1);
                        }
            if (read(fd, *p, shdr->sh_size) != shdr->sh_size)
                        {
                        perror("read");
                        exit(1);
                        }
            }

void load_module(struct _module *module, int fd)
            {
            Elf32_Ehdr *ehdr;
            Elf32_Shdr *shdr;
            char **sectionp;
            int slen;
            int i;

            check_module(module, fd);
            ehdr = &module->ehdr;
            slen = sizeof(Elf32_Shdr)*ehdr->e_shnum;
            module->shdr = (Elf32_Shdr *)malloc(slen);
            if (module->shdr == NULL)
                        {
                        perror("malloc");
                        exit(1);
                        }
            module->section = (char **)malloc(sizeof(char **)*ehdr->e_shnum);
            if (module->section == NULL)
                        {
                        perror("malloc");
                        exit(1);
                        }

            if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0)
                        {
                        perror("lseek");
                        exit(1);
                        }

¡¡¡¡¡¡¡¡if (read(fd, module->shdr, slen) != slen)
                        {
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡perror("read");
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡exit(1);
¡¡¡¡¡¡¡¡}

            for (i = 0, sectionp = module->section, shdr = module->shdr;i < ehdr->e_shnum;i++, sectionp++)
                        {
                        switch (shdr->sh_type)
                                   {
                                   case SHT_NULL:
                                   case SHT_NOTE:
                                   case SHT_NOBITS:
                                   break;

                                   case SHT_STRTAB:
                                   load_section(sectionp, fd, shdr);
                                   if (i != ehdr->e_shstrndx)
                                               module->strtabidx = i;
                                   break;

                                   case SHT_SYMTAB:
                                   case SHT_PROGBITS:
                                   case SHT_REL:
                                   load_section(sectionp, fd, shdr);
                                   break;

                                   default:
                                   fprintf(stderr,"No handler for section (type): %i\n",shdr->sh_type);
                                   exit(1);
                                   }
                        ++shdr;
                        }
            }

void relocate(struct _module *module, Elf32_Rel *rel, Elf32_Shdr *shdr)
            {
            Elf32_Sym *symtab = (Elf32_Sym *)module->section[shdr->sh_link];
            Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
            Elf32_Addr addr;
            Elf32_Shdr *targshdr = &module->shdr[shdr->sh_info];
            Elf32_Addr dot = targshdr->sh_addr + rel->r_offset;
            Elf32_Addr *loc = (Elf32_Addr *)(
            module->section[shdr->sh_info] + rel->r_offset
            );

char *name = &module->section[module->strtabidx][sym->st_name];
if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL)
            {
            struct kernel_sym *ksym;

            if (force)
                        {
                        char novname[60];
                        int len;

                        len = strlen(name);
                        if (len > 10 && !strncmp(name + len - 10, "_R", 2))
                                   {
                                   strncpy(novname, name, len - 10);
                                   novname[len - 10] = 0;
                                   ksym = ksyms_find(novname);
                                   }
                        else
                                   ksym = ksyms_find(name);
                        }
            else
                        ksym = ksyms_find(name);
            if (ksym != NULL)
                        {
                        addr = ksym->value;
                        #ifdef DEBUG
                        printf("Extern symbol is (%s:%lx)\n",ksym->name,(unsigned long)addr);
                        #endif
                        goto next;
                        }
            if (sym->st_shndx == 0 ||sym->st_shndx > module->ehdr.e_shnum)
                        {
                        fprintf(stderr,"ERROR: undefined symbol (%s)\n", name);
                        ++error;
                        return;
                        }
            }
            addr = sym->st_value + module->shdr[sym->st_shndx].sh_addr;

            #ifdef DEBUG
            printf("Symbol (%s:%lx) is local\n", name, (unsigned long)addr);
            #endif

            next:
            if (targshdr->sh_type == SHT_SYMTAB)
                        return;
            if (targshdr->sh_type != SHT_PROGBITS)
                        {
                        fprintf(stderr,"Rel not PROGBITS or SYMTAB (type: %i)\n",targshdr->sh_type);
                        exit(1);
                        }
            switch (ELF32_R_TYPE(rel->r_info))
                        {
                        case R_386_NONE:
                        break;

                        case R_386_PLT32:
                        case R_386_PC32:
                        *loc -= dot; /* *loc += addr - dot */

                        case R_386_32:
                        *loc += addr;
                        break;

                        default:
                        fprintf(stderr, "No handler for Relocation (type): %i",ELF32_R_TYPE(rel->r_info));
                        exit(1);
                        }
            }

void relocate_module(struct _module *module)
            {
            int i;

            for (i = 0; i < module->ehdr.e_shnum; i++)
                        {
                        if (module->shdr[i].sh_type == SHT_REL)
                                   {
                                    int j;
                                   Elf32_Rel *relp = (Elf32_Rel *)module->section[i];
                                   for (j = 0;j < module->shdr[i].sh_size/sizeof(Elf32_Rel);j++)
                                               {
                                               relocate(module,relp,&module->shdr[i]);
                                               ++relp;
                                               }
                                   }
                        }
            }

void print_symaddr(struct _module *module, const char *symbol)
            {
            Elf32_Sym *sym;

            sym = localall_sym_find(module, symbol);
            if (sym == NULL)
                        {
                        fprintf(stderr, "No symbol (%s)\n", symbol);
                        ++error;
                        return;
                        }
            printf("%s: 0x%lx\n",symbol,(unsigned long)module->shdr[sym->st_shndx].sh_addr+ sym->st_value);
            }

void init_module(struct _module *module, unsigned long maddr)
            {
            int i;
            unsigned long len = 0;
            module->maddr = maddr;
            for (i = 0; i < module->ehdr.e_shnum; i++)
                        {
                        if (module->shdr[i].sh_type != SHT_PROGBITS)
                                   continue;
                        module->shdr[i].sh_addr = len + maddr;
                        len += module->shdr[i].sh_size;
                        }
            module->len = len;
            if (module->maxlen > 0 && module->len > module->maxlen)
                        {
                        fprintf(stderr,"Module too large: (modsz: %i)\n",module->len);
                        exit(1);
                        }
            printf("Module length: %i\n", module->len);
            relocate_module(module);
            print_symaddr(module, "init_module");
            print_symaddr(module, "cleanup_module");
            }

void do_module(struct _module *module, int fd)
            {
            int kd;
            int i;

            #ifdef DEBUG
            for (i = 0; i < module->ehdr.e_shnum; i++)
                        {
                        if (module->shdr[i].sh_type != SHT_PROGBITS) continue;
                                   if (lseek(fd, module->shdr[i].sh_offset, SEEK_SET) < 0)
                                               {
                                               perror("lseek");
                                               exit(1);
                                               }
                        if (
                        write(fd, module->section[i], module->shdr[i].sh_size) != module->shdr[i].sh_size)
                                   {
                                   perror("write");
                                   exit(1);
                                   }
                        }
            #else
                        kd = open("/dev/kmem", O_RDWR);
            if (kd < 0)
                        {
                        perror("open");
                        exit(1);
                        }
            if (lseek(kd, module->maddr, SEEK_SET) < 0)
                        {
                        perror("lseek");
                        exit(1);
                        }
            for (i = 0; i < module->ehdr.e_shnum; i++)
                        {
                        if (module->shdr[i].sh_type != SHT_PROGBITS)
                                   continue;
                        if (write(kd, module->section[i], module->shdr[i].sh_size) != module->shdr[i].sh_size)
                                   {
                                   perror("write");
                                    exit(1);
                                   }
                        }
            close(kd);
            #endif
            }

int main(int argc, char *argv[])
            {
            char *map = system_map;
            struct _module module;
            int fd;
            int ch;
            int retval = 0;

            while ((ch = getopt(argc, argv, "m:tf")) != EOF)
                        {
                        switch (ch)
                                   {
                                   case 'm':
                                   map = optarg;
                                   break;

                                   case 't':
                                   ++run;
                                   break;

                                   case 'f':
                                   ++force;
                                   break;
                                   }
                        }

            /*
            so we can move options in and out without changing the codes idea
            of what argv and argc look like.
            */
            --optind;
            argv += optind;
            argc -= optind;
            if (argc != 3 && argc != 4)
                        {
                        fprintf(stderr,"usage: k module [-t] [-m map] maddr(hex) [maxlen]\n");
                        exit(1);
                        }
            #ifdef DEBUG
                        fd = open(argv[1], O_RDWR);
            #else
                        fd = open(argv[1], O_RDONLY);
            #endif
            if (fd < 0)
                        {
                        perror("open");
                        exit(1);
                        }
            if (ksyms_init(map) < 0)
                        {
                        perror("ksyms_init");
                        exit(1);
                        }
            module.maxlen = (argc == 4 ? atoi(argv[3]) : -1);
            load_module(&module, fd);
            init_module(&module, strtoul(argv[2], NULL, 16));
            if (run == 0)
                        {
                        if (error == 0)
                                   {
                                   do_module(&module, fd);
                                   }
                        else
                                   {
                                   fprintf(stderr,"FAILED: (%i) errors. Exiting...\n", error);
                                   ++retval;
                                   }
                        }
            ksyms_cleanup();
            exit(retval);
            }



mot clé : ksym ksym table parfeu kinsmod table KMEM par feu voip KMEM_H ipv4 tcpip ipv6 firewall ip vpn

Copyright © 2011-2015 FrameIP TcpIP. Tous droits réservés. Les marques et marques commerciales mentionnées appartiennent à leurs propriétaires respectifs. L'utilisation de ce site Web TcpIP implique l'acceptation des conditions d'utilisation et du règlement sur le respect de la vie privée.
Sécurité entreprise Téléphonie entreprise Expert de votre Infrastructure Test ADSL Serinya Operateur Telecom