从FileObject中取得文件完整路径

2014-8-21 Nie.Meining Coding

好久没更新了……最近太忙……

以前写的某物体,需要从FileObject中取得完整路径,方法是 FileObject->DeviceObject->Dirver_Letter + FileObject->RelatedFileObject->FileName + FileObject->FileName。最近发现这个物体取得的文件名中间偶尔会重复一截。

找出FileMon源码研究了一下,发现这一段:

codes.png

原来RelatedFileObject不能乱拼的……

评论(0) 浏览(18009)

内核呓语系列7 —— DPC与APC

2014-2-15 Nie.Meining Coding

今天接着讲中断后端。前面已经说过了,中断处理例程的优先级太高,有很多限制,尤其是不能让出处理器影响机器响应能力,因此,为了让中断例程处理尽可能少的的工作,Linux和Windows都采用了一些方法把次要工作延后到中断处理例程之外的中断后端去处理。Windows采用的方式是插入DPC,Linux中常用的方式有以下几种:
1. BH接口:最古老的方式。系统中总共只能有32个BH(用一个32位变量做mark),每个BH都是全局同步的(即使在多核环境中),因此很不灵活且效率很低,已经被取缔了;
2. task queues:内核定义了一堆task queue,驱动可以在合适的queue中注册他们的中断后端。依然不灵活、性能低,已取缔;
3. softirq: 一组静态定义(编译时静态分配)的中断后端,能在不同的处理器上并行执行(即使是两个相同类型的softirq),因此常用于对性能要求很高的情况。softirq不会被另一个softirq抢占,但会被中断处理例程抢占;
4. tasklet: 动态添加的中断后端,在softirq的基础上实现,能在不同的处理器上并行执行,但两个相同类型的tasklet不能并行执行。因此虽然性能略低于softirq,但性价比最高,是最常用的中断后端方式;
5. work queues:将任务排队到进程上下文中执行,每个cpu有一个event/n内核线程worker threads,复制处理排队的任务。这个跟Windows的work item机制(ExQueueWorkItem)很像。Windows系统中的System进程中有一个系统辅助线程池,池中的系统辅助线程专门处理排队的work item。因此有时候IRQL过高时,可以将任务以work item的形式排队给系统辅助线程在PASSIVE_LEVEL上执行。

阅读全文>>

评论(0) 浏览(1313)

内核呓语系列6 —— 中断和异常

2014-1-21 Nie.Meining Coding

前面讲了系统调用对于一些不支持快速系统调用的情况,实际上就是通过中断进入内核的。linux是int 80h,windows是int 2eh。然后通过IDT中指定的中断服务例程(例如KiSystemService)进行系统服务分发。

中断和异常,一个主要是异步触发(如硬件I/O中断,当然也不排斥int 2eh这种软件中断),一个主要是同步触发(如除0异常),但由于系统的处理方式是相同的,所以经常被看作是一个东西。通常32及以上的中断号留给了中断,32以下的除了2号是NMI不可屏蔽中断以外,都留给了异常。这一篇不对中断的硬件原理做说明,仅围绕内核相关的东西展开介绍。

首先需要说明的是,对于多核处理器,每个核都有自己的IDT,因此无论是添加新的中断还是做IDT hook都得注意这个问题。此外还需要注意由于中断的优先级很高,不少操作是受限的。这里就涉及到IRQL的问题了。相信很多写驱动的朋友都碰到过IRQL_NOT_LESS_OR_EQUAL蓝屏的问题……

Windows将APIC的中断优先级映射到了自己的一套IRQL中断请求级上。任何时刻CPU都必然处于某个级别:

阅读全文>>

评论(8) 浏览(22401)

内核呓语系列5 —— 系统调用Hook

2014-1-10 Nie.Meining Coding

上次写了一堆系统调用的相关东西,相信不少研究过rootkit或主动防御的朋友都是从SSDT/ShadowSSDT hook开始的,本篇就针对系统调用监控这方面展开讲讲。

主动防御技术一般通过拦截系统调用实现,在Windows中特别流行,Linux中比较少。除了Windows用户多,需求量大以外,还有一个原因是Linux中做系统调用监控其实不太方便提取上层行为,因为Linux把一切都的当作文件的理念导致你极有可能拦截到一大堆sys_read/sys_write,却很难知道样本究竟在干什么。尤其是一些以linux为内核的其它操作系统,往往在样本行为和系统调用之间还夹了一层虚拟机,例如Android的Dalvik。最初做Android监控时就遇到了这个问题,因此不得不采用了一些特别的手段。截图说明一下:

nhyy5_1.png

阅读全文>>

评论(0) 浏览(41315)

内核呓语系列4 —— 系统调用

2014-1-6 Nie.Meining Coding

内核通过系统调用向应用层提供接口,应用层代码通过中断(Windows int 0x2e,Linux int 0x80)或sysenter的形式进入系统调用。相信很多玩过rootkit的朋友最初就是从ssdt hook开始的,网上也有大量介绍ssdt的文章,因此本篇也不对ssdt的原理、调用流程什么的进行说明了,就挑一些有意思的周边东西讲讲。

首先Windows和Linux都有一张SSDT表,Linux的SSDT表中各个函数的地址可以在编译内核后的system.map文件中找到。Windows由于子系统集成到了内核中,因此win32k.sys还扩展了一张Shadow SSDT表。win32k.sys模块并不常驻内存,Shadow SSDT地址也未导出,因此hook其中的函数需要多做一些工作。关于子系统的问题可以参见本系列的前两篇文章。

此外,来自应用层的东西通常是不可信的,所以系统调用必须进行参数检查。可能为了效率问题,Windows引入了PreviousMode的概念。通常只在KeGetPreviousMode() != KernelMode时进行参数检查。写过驱动的朋友应该知道,Windows执行体中同样功能的函数通常有两套,NtXXX和ZwXXX。其实NtXXX才是真正完成功能的函数,而调用ZwXXX的目的就是改变PreviousMode为KernerMode再调用NtXXX,省去参数检查的麻烦。可以找个函数验证一下:

阅读全文>>

评论(0) 浏览(30347)

Powered by emlog