绕过CONFIG_MODVERSIONS
来源:互联网 发布:盟军苏军将领知乎 编辑:程序博客网 时间:2024/06/06 02:03
最近买了个手机乐视1pro,没有内核源码,想插入一些自己编译的模块来扩展内核,于是找到了硬件相近的一加2的内核源码,把编译得到的模块拷到手机上,发现无法加载。经过摸索,发现原因是内核开启了CONFIG_MODVERSIONS,但是没开启CONFIG_MODULE_FORCE_LOAD. 内核symbol有crc校验,不同源码树编译出来的内核,symbol的crc可能不一样。
要想编译出crc一致的模块,需要用到编译内核时生成的Module.symvers这个文件,厂商没有开放内核源码,更不可能提供这个文件给你了。不过,既然内核会对模块引用到的symbol验证crc,说明内核本身就保存有一份crc,我们只要提取出来就行了。
我们只要编写如下模块,就可完成提取工作:
symcrc.c
#include <linux/module.h>#include <linux/init.h>#include <linux/device.h>#include <linux/string.h>#include <linux/slab.h>static char symcrc[256];static ssize_t symcrc_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count){ const struct kernel_symbol *ksymbol; char *symname; struct module *owner; const unsigned long *crc = NULL; bool gplok = true; bool warn = true; symname = kstrndup(_buf,strlen(_buf)-1,GFP_KERNEL); ksymbol = find_symbol (symname, &owner, &crc, gplok, warn); if (ksymbol != NULL && crc != NULL) snprintf (symcrc, ARRAY_SIZE(symcrc), "0x%lx\t%s\tvmlinux\tEXPORT_SYMBOL\n", *crc, ksymbol->name); else{ symcrc[0] = '\0'; } kfree(symname); return _count;}static ssize_t symcrc_read(struct class *cls, struct class_attribute *attr, char *_buf){ return sprintf(_buf, "%s", symcrc);}static struct class *symcrc_class = NULL;static CLASS_ATTR(writesym, 0220, NULL, symcrc_write);static CLASS_ATTR(getcrc, 0440, symcrc_read, NULL);int __init find_symbol_init (void){ int ret; symcrc_class = class_create(THIS_MODULE, "symcrc"); if (IS_ERR(symcrc_class)) { printk("Create class symcrc_class failed.\n"); return -ENOMEM; } ret = class_create_file(symcrc_class, &class_attr_getcrc); ret = class_create_file(symcrc_class, &class_attr_writesym); return 0;}void __exitfind_symbol_exit (void){ class_remove_file(symcrc_class, &class_attr_getcrc); class_remove_file(symcrc_class, &class_attr_writesym); class_destroy(symcrc_class); symcrc_class = NULL;}module_init (find_symbol_init);module_exit (find_symbol_exit);MODULE_AUTHOR("Mr Pang");MODULE_LICENSE ("GPL");
编译这个模块,可以看到自动生成的symcrc.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 .arch = MODULE_ARCH_INIT,};static const struct modversion_info ____versions[]__used__attribute__((section("__versions"))) = { { 0x48f7bf25, __VMLINUX_SYMBOL_STR(module_layout) }, { 0xeb6cd1a5, __VMLINUX_SYMBOL_STR(class_destroy) }, { 0xe8efe986, __VMLINUX_SYMBOL_STR(class_remove_file) }, { 0x276c87ab, __VMLINUX_SYMBOL_STR(class_create_file) }, { 0x27e1a049, __VMLINUX_SYMBOL_STR(printk) }, { 0x8637fc77, __VMLINUX_SYMBOL_STR(__class_create) }, { 0x91715312, __VMLINUX_SYMBOL_STR(sprintf) }, { 0x37a0cba, __VMLINUX_SYMBOL_STR(kfree) }, { 0x28318305, __VMLINUX_SYMBOL_STR(snprintf) }, { 0x8b58b0d, __VMLINUX_SYMBOL_STR(find_symbol) }, { 0xaf6ae696, __VMLINUX_SYMBOL_STR(kstrndup) }, { 0x98cf60b3, __VMLINUX_SYMBOL_STR(strlen) },};static const char __module_depends[]__used__attribute__((section(".modinfo"))) ="depends=";
里面的static const struct modversion_info ____versions[]列举出了本模块引用到的symbol以及对应的crc。因为这个模块使用的是一加内核源码树编译的,所以部分crc与1pro内核的不一致,以至于无法加载。
为了解决这个问题,我们另外写一个模块,尽可能少的直接引用内核的symbol,
firststep.c
#include <linux/module.h>#include <linux/init.h>const struct kernel_symbol *(*find_symbol1)(const char *name, struct module **owner, const unsigned long **crc, bool gplok, bool warn) = (const struct kernel_symbol *(*)(const char *name, struct module **owner, const unsigned long **crc, bool gplok, bool warn))0xffffffc00027cab4;int (*printk1)(const char *fmt, ...) = (int (*)(const char *fmt, ...))0xffffffc000be3e94;static const char *sym_array[] = { "module_layout", "class_destroy", "class_remove_file", "class_create_file", "printk", "__class_create", "sprintf", "kfree", "up", "snprintf", "down", "find_symbol", "kstrndup", "strlen",};int __initfind_symbol_init (void){ const char *name; int index; const struct kernel_symbol *ksymbol; struct module *owner; const unsigned long *crc; bool gplok = true; bool warn = true; for (index = 0; index < ARRAY_SIZE (sym_array); index++) { name = sym_array[index]; ksymbol = find_symbol1 (name, &owner, &crc, gplok, warn); if (ksymbol != NULL) printk1 (" %s", ksymbol->name); else printk1 ("<0>Failed to find symbol %s\n", name); if (crc != NULL) printk1 ("*crc : 0x%lx\n", *crc); else printk1 ("\n"); } return 0;}void __exitfind_symbol_exit (void){}module_init (find_symbol_init);module_exit (find_symbol_exit);MODULE_LICENSE ("GPL");MODULE_AUTHOR("Mr Pang");
这个模块引用到的两个symbol是printk和find_symbol,我们通过其绝对地址来调用,就可以避免crc的问题了。绝对地址可以查看/proc/kallsyms获得,如果/proc/kallsyms地址全是0,可以echo 0 > /proc/sys/kernel/kptr_restrict
在我的手机上,find_symbol地址是0xffffffc00027cab4,printk地址是0xffffffc000be3e94.
static const char *sym_array[] 保存的是前一个模块symcrc引用到的symbol,可以查看symcrc.mod.c获得。
编译这个模块,查看自动生成的firststep.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 .arch = MODULE_ARCH_INIT,};static const struct modversion_info ____versions[]__used__attribute__((section("__versions"))) = { { 0x48f7bf25, __VMLINUX_SYMBOL_STR(module_layout) },};static const char __module_depends[]__used__attribute__((section(".modinfo"))) ="depends=";
发现这个模块依然引用了一个symbol–“module_layout”.这个symbol在所有模块上都可以查到,所以并不要紧,只需要提取手机上的任意一个模块,通过命令modprobe –show-modversions xxx.ko就可以找到module_layout的crc。人工修改firststep.mod.c文件,然后人工编译firststep.mod.c并人工链接firststep.ko。具体命令可以在编译模块时指定V=1查看。就两行长长的命令,复制粘贴而已。
此时生成的firststep.ko就是可以加载的了。加载之后通过dmesg查看打印出的crc,同样人工修改symcrc.mod.c里面的crc,再人工编译出symcrc.ko.
插入symcrc.ko之后,可以通过以下命令提取内核的Module.symvers:
for i in `cat /proc/kallsyms|awk '{print $3}'`;doecho $i > /sys/class/symcrc/writesym;cat /sys/class/symcrc/getcrc >> /sdcard/Module.symvers;done
拿到Module.symvers之后编译模块就方便多了。
首先要make clean
然后make nconfig选择需要编译的模块
然后通过make modules KBUILD_EXTRA_SYMBOLS=/path/to/Module.symvers
编译模块,生成的模块就是带有正确crc的模块,可以直接载入。
- 绕过CONFIG_MODVERSIONS
- Kernel Symbols and CONFIG_MODVERSIONS
- Kernel Symbols and CONFIG_MODVERSIONS
- Linux内核编译 CONFIG_MODVERSIONS 作用
- Linux内核编译 CONFIG_MODVERSIONS 作用
- LINUX内核中CONFIG_MODVERSIONS的作用
- 隔热噶热噶绕过绕过
- XSS绕过
- 上传绕过
- 热噶热狗绕过绕过人
- 如何绕过防火墙?
- Linux绕过root密码
- 成功绕过XP登陆密码
- 成功绕过XP登陆密码
- shellcode绕过kav6
- 绕过空格的注入
- 绕过杀毒软件之一
- 绕过杀毒软件之一续
- web开发乱码问题
- OracleOraDb11g_home1TNSListener服务启动后停止
- 剑指Offer-31-连续子数组的最大和
- 顺序折线遍历二维数组
- jQuery Mobile 学习四
- 绕过CONFIG_MODVERSIONS
- Axialis IconWorkshop破解版不能用了?看这个替换品
- APK动态加载框架(DL)解析
- shell 里执行sqlldr,not found
- nyoj--218--Dinner(语法)
- JBPM4.4业务流程管理框架详细解读
- 导出序列
- [Built-in Functions] - D
- Error: Could not create the Java Virtual Machine.