免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Godbach
打印 上一主题 下一主题

Linux下实现劫持系统调用的总结 [复制链接]

论坛徽章:
0
21 [报告]
发表于 2009-12-05 00:18 |只看该作者
本帖最后由 Godbach 于 2010-08-30 11:45 编辑

unsigned long
get_syscall_from_kallsyms(arch_t arch)
{
    unsigned long          syscall_entry;
    struct nameidata     nd;
    const  char        *path_str = "/proc/kallsyms";
    const  char        *symbol_str;
    struct vfsmount        *old_mnt;
    struct dentry        *old_dentry;
    int             err = 0;
    void            *p;
    struct seq_file        *m;
    struct kallsym_iter    *iter;
    struct file        *kallsyms_file;
    loff_t             index = 0;
    void            *old_buf;
            
    switch(arch) {
    case ARCH_X86_64:
        symbol_str = "system_call";
        break;
    case ARCH_X86:
        symbol_str = "ia32_syscall";
        break;
    default:
        return 0;
    }
   
    old_mnt         = current->fs->rootmnt;
    old_dentry   = current->fs->root;
   
    nd.mnt         = mntget(current->fs->rootmnt);
    nd.dentry    = dget(current->fs->root);
    nd.last_type = LAST_ROOT;
    nd.flags     = LOOKUP_FOLLOW | LOOKUP_NOALT;
    nd.depth     = 0;

    if ((err = path_walk(path_str, &nd)) == 0) {
        kallsyms_file = dentry_open(nd.dentry, nd.mnt, O_RDWR);
        if (kallsyms_file == NULL) {
            printk("[%s] can not open kallsyms file\n",
                   __FUNCTION__);
            syscall_entry = -EIO;
            goto out;
        }
        
        m = kallsyms_file->private_data;
        m->version = kallsyms_file->f_version;
            
        mutex_lock(&m->lock);
            
        old_buf = m->buf;

        m->buf = kmalloc(m->size = KSYM_SYMBOL_LEN, GFP_KERNEL);
        iter = m->private;
            
        while (1) {
            p = m->op->start(m, &index);
            err = PTR_ERR(p);
            if (!p || IS_ERR(p)) {
                syscall_entry = err;
                break;
            }
            m->count = 0;
            m->op->show(m, p);

            if (!strncmp(m->buf + sizeof("%s+%#lx/%#lx [%s]") + 1,
                     symbol_str,
                     strlen(symbol_str))) {
                m->buf[2 * sizeof(void *)] = 0;
                sscanf(m->buf, "%lx", &syscall_entry);
                break;
            }
            m->op->stop(m, p);
            index++;
        }
        
        m->op->stop(m, p);
        m->count = 0;
        m->size = 0;
        kfree(m->buf);
        m->buf = old_buf;
            
        mutex_unlock(&m->lock);
        filp_close(kallsyms_file, NULL);
    } else {
        printk("[%s] path_walk failed %d\n", __FUNCTION__, err);
    }

out:
    dput(old_dentry);
    mntput(old_mnt);

    return syscall_entry;
}

论坛徽章:
0
22 [报告]
发表于 2009-12-05 00:19 |只看该作者
本帖最后由 Godbach 于 2010-08-30 11:46 编辑

typedef enum {
    ARCH_X86 = 0,
    ARCH_X86_64,
} arch_t;

论坛徽章:
0
23 [报告]
发表于 2009-12-05 00:19 |只看该作者
本帖最后由 Godbach 于 2010-08-30 11:46 编辑

.macro LOAD_SYSCALL_ARGS
    movq 8(%rsp),  %r11
    movq 16(%rsp), %r10
    movq 24(%rsp), %r9
    movq 32(%rsp), %r8
    movq 56(%rsp), %rdx
    movq 64(%rsp), %rsi
    movq 72(%rsp), %rdi
    movq %r10,     %rcx
.endm

论坛徽章:
0
24 [报告]
发表于 2009-12-05 00:24 |只看该作者
以上是64位系统调用劫持代码,支持 Xen dom0,如果是 domU,那就看运气了,目前流行的发行版缺省都采用了 kallsyms。kvm/vmware和物理机没区别。

如果在调用原始的系统调用例程之前做了很多事情会改变寄存器值,需要执行一下那一小段汇编代码。

P.S 这坨东西应该是 CU 首发,要转载请注明转载自 CU。

[ 本帖最后由 vupiggy 于 2009-12-4 17:27 编辑 ]

论坛徽章:
0
25 [报告]
发表于 2009-12-05 02:21 |只看该作者
GOD 兄, 我来提下意见:
你的第一贴和第二贴似乎没啥关系啊. 第一贴用的是KPROBE. 它是内核已经做好的监测内核运行行为的工具. 可以监视任何内核函数.  第二贴讲的是传统的改SYSTEM CALL TABLE的方法. 而KPROBE用的不是这种方法. 关于KPROBE的解释可以看下面2个帖子:
http://www.ibm.com/developerworks/cn/linux/l-kprobes.html
http://www.maycode.com/index.php ... /1072-memcache.html
看你的帖子,似乎想说KPROBE就是用的改SYSTEM CALL TABLE的方法. 这点是不对的.

PS: 我只是大概看了下, 不对的地方多包涵.

论坛徽章:
0
26 [报告]
发表于 2009-12-05 09:45 |只看该作者
学习了,希望好贴连篇!

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
27 [报告]
发表于 2009-12-05 10:08 |只看该作者
GOD 兄, 我来提下意见:
你的第一贴和第二贴似乎没啥关系啊. 第一贴用的是KPROBE. 它是内核已经做好的监测内核运行行为的工具. 可以监视任何内核函数.  第二贴讲的是传统的改SYSTEM CALL TABLE的方法. 而KPROBE用的不是这种方法. 关于KPROBE的解释可以看下面2个帖子:


多谢accessory兄提意见。

我第一帖最开始就提到时使用了albcamus兄提供的代码,他本身就是使用KPROBE的。但是我这里展示的代码,应经屏蔽了相关的代码。
你可以看到#if 0的条件宏的。我保留了传统的那种方式,也就是我2楼中分析的那个流程:从获取idtr到最后获取系统调用表,然后替换系统调用,实例中替换的就是open系统调用。

论坛徽章:
0
28 [报告]
发表于 2009-12-05 10:15 |只看该作者
强人!

论坛徽章:
0
29 [报告]
发表于 2009-12-05 10:55 |只看该作者
不错不错,Godbach出品必属精品!不过现在一般都不用劫持系统调用这一招了,因为rkhunter这些软件很容易发现是否被劫持了!
现在如adore-ng这些当红软件都是用的VFS那一套。
可以看看
rootkit学习笔记
Adore-ng-0.56源码分析

论坛徽章:
0
30 [报告]
发表于 2009-12-05 14:17 |只看该作者

回复 #1 Godbach 的帖子

很好很强大。
不过,如果单是想跟踪一下系统调用的话,用systemtap是不是更简单便捷一些?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP