linux内核hack-运行中动态添加系统调用

简介:

LINUX中每次添加一个系统调用都要完成重新编译内核,然后制作initrd等工作,不得不说这是一件繁重的工作,很多人本来已经构思好了自己的一个系统调用,要添加到内核,然后却被这些工作所中断,毫不夸张的说,制作initrd就很麻烦,虽然基于cpio的initrd可以利用几条命令完成,然而只要有一个错误,你就不得不重启系统。
     我们都知道,内核模块运行在内核态,可以访问所有的内存空间,那么能不能在系统运行期间,不用重新编译内核,而运用内核模块机制实现添加系统调用呢?答案是肯定的,因为一个基本原理:内核态能读写所有的内存,内存全部在我们手中,没有什么事情做不到, 那么怎么做到呢?
     如果我们了解了系统调用执行的过程,那么我们就知道在执行一个系统调用之前,有两个限制,第一就是系统调用数量在编译时定死,系统调用号必须在这个被允许的系统调用号区间内,第二就是系统调用表的地址未导出。 由于系统调用入口也是一种中断/异常,因此我们看一下代码,看个究竟,基于i386的内核代码在arch/i386/kernel/entry.S(基于2.6.8内核,虽然有点老,但能说明问题),我们看一下系统调用的入口

 
通过以上的代码可以看出,如果我们想添加一个新的系统调用,第一,它的系统调用号不能超过nr_syscalls,第二,它的地址必须在系统调用表地址加上系统调用号*4的位置处, 也就是说,满足这两个条件,内核逻辑就会将执行流路由到我们调用的系统调用服务程序。
     如果我们希望在系统运行期动态添加一个系统调用,那么就必须破除上述的两个神话。第一,我们必须修改nr_syscalls的值,第二,我们必须修改sys_call_table的值,并且新的sys_call_table内容值必须保留原有的sys_call_table内容值。 这个需求怎么做到呢?很简单,扫面二进制机器码!记住,内存在我们手中,还要记住,我们的这次行为不是攻击行为,只是为了调试一个新增加的系统调用而不想重新编译内核...!!! 
     到底怎么做到呢?首先,我们只需要修改掉system_call中的cmpl $(nr_syscalls), %eax语句中的nr_syscalls,我们首先从/proc/kallsym中取得system_call的地址,然后在其下面搜索cmpl $(nr_syscalls), %eax的机器码,搜到后将nr_syscalls修改;其次我们在/boot/Sysmap中取得sys_call_table的地址,然后在system_call的下面搜索这个地址的机器码,取得后我们将其修改为新的系统调用表的地址,需要指出的是,新的系统调用表的前nr_syscalls个字段必须和原始的系统调用表sys_call_table的相同。另外,如何获得sys_call_table的地址,这个技术值得商榷,其实有很多方法,本文使用最直接的方式,那就是从/boot/Sysmap中获取。
     有一个细节,那就是如何在system_call附近寻找匹配检测系统调用号范围的机器码呢?最简单的方式莫过于模拟,那就是写一个程序,调用cmpl $(nr_syscalls), %eax,其中nr_syscalls在2.6.8中为284,那么我们就写下面的代码:
 
编译后使用objdump得到了3d 1c 01 00 00 cmp    $0x11c,%eax这样的机器码/汇编码,于是我们可以断定,机器特征码为3d 1c 01 00 00 。类似的,sys_call_table的地址也可以这样来求得,不过记住,没有必要,既然你有root权限了,还有必要这样吗?
     那么到底怎么做到的呢?请看模块dynamic_add_syscall:
 
编译上述模块,然后加载:
insmod dynamic_add_syscall.ko entry_addr=0xc01061d8 table_addr=0xc02dad1c nowa_num=0x11c want_num=0x21c 
上述的地址信息都是从/boot/Sysmap以及/proc/kallsym以及内核源码中得到的。现在我们希望增加一个系统调用,该怎么办呢?
     很简单,再写一个模块newsyscall:
 
编译此模块,然后加载,为了测试我们新增加的系统调用sys_force,特写一个用户态程序:
 
编译为test,当我们执行test 284 123之后,用dmesg看一下,会发现最后一行打印:new sys----:123,表明成功,我们成功增加了一个系统调用,可喜!
后记: 
还是那句话,既然彻底理解了原理,那就没有什么是不可能的,我们不必为了实现一个系统调用而重新编译内核,完全没有必要,我们可以先使用上述的方式将新系统调用调试通过,然后最终再通过重新编译内核的方式添加进内核,OK?

         虽然修改内存机器码并不是可取的方式,不是常规的方式,然而再次重申,我们这不是在进行攻击,而是为了让自己添加和调试新的系统调用更方便,只要达到目的,有什么不可以呢?难道仅仅因为LKML上以及教科书上建议就非要重新编译内核吗?适合自己的才是最好的,我们需要的是提高工作效率! 
     还是那些人,然而还是那些人!有那么重要吗?信口开河!人要生活,而不仅仅是生存!


 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1271019



相关文章
|
16天前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
121 67
|
5天前
|
存储 Linux
Linux内核中的current机制解析
总的来说,current机制是Linux内核中进程管理的基础,它通过获取当前进程的task_struct结构的地址,可以方便地获取和修改进程的信息。这个机制在内核中的使用非常广泛,对于理解Linux内核的工作原理有着重要的意义。
27 11
|
1月前
|
自然语言处理 监控 Linux
Linux 内核源码分析---proc 文件系统
`proc`文件系统是Linux内核中一个灵活而强大的工具,提供了一个与内核数据结构交互的接口。通过本文的分析,我们深入探讨了 `proc`文件系统的实现原理,包括其初始化、文件的创建与操作、动态内容生成等方面。通过对这些内容的理解,开发者可以更好地利用 `proc`文件系统来监控和调试内核,同时也为系统管理提供了便利的工具。
73 16
|
2月前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
121 34
|
3月前
|
安全 Linux 测试技术
Intel Linux 内核测试套件-LKVS介绍 | 龙蜥大讲堂104期
《Intel Linux内核测试套件-LKVS介绍》(龙蜥大讲堂104期)主要介绍了LKVS的定义、使用方法、测试范围、典型案例及其优势。LKVS是轻量级、低耦合且高代码覆盖率的测试工具,涵盖20多个硬件和内核属性,已开源并集成到多个社区CICD系统中。课程详细讲解了如何使用LKVS进行CPU、电源管理和安全特性(如TDX、CET)的测试,并展示了其在实际应用中的价值。
|
3月前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
206 15
|
4月前
|
Ubuntu Linux Go
golang编译成Linux可运行文件
本文介绍了如何在 Linux 上编译和运行 Golang 程序,涵盖了本地编译和交叉编译的步骤。通过这些步骤,您可以轻松地将 Golang 程序编译成适合 Linux 平台的可执行文件,并在目标服务器上运行。掌握这些技巧,可以提高开发和部署 Golang 应用的效率。
557 14
|
5月前
|
负载均衡 算法 Linux
深入探索Linux内核调度器:公平与效率的平衡####
本文通过剖析Linux内核调度器的工作机制,揭示了其在多任务处理环境中如何实现时间片轮转、优先级调整及完全公平调度算法(CFS),以达到既公平又高效地分配CPU资源的目标。通过对比FIFO和RR等传统调度策略,本文展示了Linux调度器如何在复杂的计算场景下优化性能,为系统设计师和开发者提供了宝贵的设计思路。 ####
100 26
|
5月前
|
缓存 并行计算 Linux
深入解析Linux操作系统的内核优化策略
本文旨在探讨Linux操作系统内核的优化策略,包括内核参数调整、内存管理、CPU调度以及文件系统性能提升等方面。通过对这些关键领域的分析,我们可以理解如何有效地提高Linux系统的性能和稳定性,从而为用户提供更加流畅和高效的计算体验。
177 24
|
4月前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。