当前位置:七道奇文章资讯安全技术网络技术
日期:2010-04-29 02:35:00  来源:本站整理

对Linux Kernel vmsplice Exploit的解析[网络技术]

赞助商链接



  本文“对Linux Kernel vmsplice Exploit的解析[网络技术]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

首先解析一下造成溢出的缘由:
Vmsplice的作用是将一个文件描写符(必须是一个pipe)和一段内存衔接起来.这个功效的实现是通过 fs/splice.c的do_vmsplice()function来实现,在该function种,定义了两个数组:
struct page *pages[PIPE_BUFFERS];
struct partial_page partial[PIPE_BUFFERS];
PIPE_BUFFERS的值在存在溢出问题的版本中的是定义为16.这两个函数都传送到了 get_iovec_page_array()这个function中.
以2.6.22.14版本的源代码为例,看看在fs/splice.c的1565行开始的get_iovec_page_array函数.
在该函数中我们看到:
error = get_user(len, &iov->iov_len);
if (unlikely(!len))
break;
在这里仅仅判断len是正数就ok,而len是可以通过用户掌握的.
npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (npages > PIPE_BUFFERS - buffers)
npages = PIPE_BUFFERS – buffers;
error = get_user_pages(current, current->mm,
(unsigned long) base, npages, 0, 0,&pages[buffers], NULL);
npages的值是通过len计算得出,那么我们将len值设为UINT32_MAX的话,那么计算off+len+PAGE_SIZE的后果就会招致整 型数包裹(integer wrap),那么npages的将会是0,这是unexpected的.我们目前来解析get_user_pages在得到了unexpected的 npages值后,会有什么样的后果.get_user_pages是用来将用户空间中页(pages)映射(pin)入内存,并且得到他们页构造 (struct page)的指针.但是在get_user_pages()函数内部,处理页面时利用的do{}while()的末尾处是:
len--;
} while (len && start < vma->vm_end);
假如len的值是0的话(正如我们盼望的那样),那么这个循环将会至少循环一次,将len值减为-1后,持续在页面中错误地履行,直到履行到没有有效的 mapping的地址后,指针将会终止并返回.但是在这时,他大概已经在储了比他当时所分配的内存空间更多的内容,到其page数组中.也就是说在这种情 况下get_user_pages()将会溢出pages数组,写了不但仅是PIPE_BUFFERS(16)个指针到数组中.但是真正被溢出程序所操纵 数组是partial数组.
在do_vmsplice()中定义的partial数组一样被传送给了get_iovec_page_array().在partial数组中描写 了需求写入到管道中的页面的其他的部份.        在get_user_pages()返回后,紧随着一个循环语句:
for (i = 0; i < error; i++) {
const int plen = min_t(size_t, len, PAGE_SIZE - off);

partial[buffers].offset = off;
partial[buffers].len = plen;

off = 0;
len -= plen;
buffers++;
}
在这种情形下,因为全部页面都被写入,被计算的偏移量(offset)将会是zero,并且长度(length)值是PAGE_SIZE(4096).而 从get_user_pages()的返回值error,将会是在被溢出的情形下 被mapped的pages页的数目:46.那么实际上partial数组的一样是被定义为16个元素,因此上边的这个循环一样会招致溢出的发生.
这两个数组都是在vmsplice_to_page()中声明的.在内存分配中partial数组将会放在pages的下边,因此一点partial数组 被overflow,那么这个循环将会一样溢出放在上边的pages数组.因此pages数组的内容将会被改写为0,而不是先前的指向pages构造的指 针.
当这些完成后,掌握权返回到vmsplice_to_page()-溢出并不足以覆盖返回地址.针对splice_to_pipe()的调用目前看来要结 束了,但是一些风趣的事情发生了.在这个function的开始,有一个test:
if (!pipe->readers) {
send_sig(SIGPIPE, current, 0);
if (!ret)
ret = -EPIPE;
break;
}
假如我们看攻击代码的话,我们会看到
if (pipe(pi) < 0) die("pipe", errno);
close(pi[0]);
在调用vmsplice()之前,已经将pipe的读取端关闭了.因此splice_to_pipe将会当即退出,但是在退出时,将会履行以下操作:
while (page_nr < spd_pages)
page_cache_release(spd->pages[page_nr++]);
我们知道get_user_pages()函数的调用将会lock内存中的相关页,以便答应内查对其举行拜候;上边这两行是一段清理代码用来返回并 unlock先前锁住而目前不再利用的pages.但是在我们这个例子中,pages数组的内容已经被改写为0.那么接下来发生的事情,将会是内核拐骗 (kernel oops),因为pages数组中填充的内容并非合理的地址.溢出代码通过一些小办法,比方利用一些特定的mmap()调用,将会在内存地址的底部构造 肆意的内容.
当运行在内核情势,直接去取指向用户空间的指针的值固然大概会造成很多问题,但是确切可以被忍耐的.假如地址是有效的并且相关也驻留内存当中,那么直接的 取值也是可以成功的.因此当kernel开始工作在他认为是指向struct page空间的指针的内存时,并没有得到任何的错误提醒;而是得到了通过exploit程序所构造的数据内容.
kernle 普通情形下将每页page看为个体.但是在有些时刻,或有多个page构成的调集,被称为”compound pages”.这种情形发生在一段被kernel所需求的持续的空间的大小大于一个page的大小时;当这种调用发生时,一组compound pages被传送给调用者.对比分外的地方是,他们在被释放时,是会被拆脱离,因此就会有拆分的行动发生.因此compound pages会有一个普通pages所没有的属性:当pages被释放时,会调用destructor.
我们来看一下攻击程序

[1] [2]  下一页


  以上是“对Linux Kernel vmsplice Exploit的解析[网络技术]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • 巧用Ubuntu软件源对Linux在线更新
  • 加强对Linux网络服务器的管理 公道利用工具
  • 对linux服务器的一些安全设置
  • 对Linux Kernel vmsplice Exploit的解析
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .