我想用DDK写一个文件过滤驱动,禁止或允许EXE文件的运行。
在用户双击EXE文件运行时,会激发很多IRP请求,我想通过截获这些IRP请求,
控制EXE文件的运行。
请给个思路,最好有演示代码,谢谢!

解决方案 »

  1.   

    在Windows 2003中HOOK ZwCreateProcessEx创建时间:2005-03-09
    文章属性:原创
    文章提交:suei8423 (suei8423_at_163.com)作者:ZwelL工作需要,想控制进程的创建,于是HOOK了ZwCreateProcess,后来发现xp和2003中创建进程的都用NtCreateProcessEx(参见[1])。
    但是ZwCreateProcessEx未被ntoskrnl.exe导出,用softice的ntcall命令也没有看到,网上也没有找到相关代码。没办法,跟踪ntoskrnl!ZwCreateProcess
    >u ntoskrnl!ZwCreateProcessEx_ZwCreateProcess
    0008:804e7ae2    bb32000000    mov eax, 00000032但是ZwCreateProcessEx有9个参数,最后一个未知,4字节,猜成HANDLE型。
    原型如下:
    typedef NTSTATUS (*NTCREATEPROCESSEX)(
        OUT PHANDLE ProcessHandle,
        IN ACCESS_MASK DesiredAccess,
        IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
        IN HANDLE ParentProcess,
        IN BOOLEAN InheritObjectTable,
        IN HANDLE SectionHandle OPTIONAL,
        IN HANDLE DebugPort OPTIONAL,
        IN HANDLE ExceptionPort OPTIONAL,
        IN HANDLE Unknown );  
    最终用硬编码HOOK 成功,代码如下:
    #include "ntddk.h"
    #include "stdarg.h"
    #include "stdio.h"
    #include "ntiologc.h"#define DWORD unsigned long
    #define WORD unsigned short
    #define BOOL unsigned longtypedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
    } ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry;extern PServiceDescriptorTableEntry KeServiceDescriptorTable; typedef NTSTATUS (*NTCREATEPROCESSEX)(
    OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    IN HANDLE ParentProcess,
    IN BOOLEAN InheritObjectTable,
    IN HANDLE SectionHandle OPTIONAL,
    IN HANDLE DebugPort OPTIONAL,
    IN HANDLE ExceptionPort OPTIONAL,
    IN HANDLE Unknown );NTCREATEPROCESSEX    OldNtCreateProcessEx;// Length of process name (rounded up to next DWORD)
    #define PROCNAMELEN     20
    // Maximum length of NT process name
    #define NT_PROCNAMELEN  16
    ULONG gProcessNameOffset;void GetProcessNameOffset()
    {
        
        PEPROCESS curproc;
        int i;
        curproc = PsGetCurrentProcess();
        for( i = 0; i < 3*PAGE_SIZE; i++ ) 
        {
            if( !strncmp( "System", (PCHAR) curproc + i, strlen("System") ))
            {
                gProcessNameOffset = i;
            }
        }
    }BOOL GetProcessName( PCHAR theName )
    {
        PEPROCESS       curproc;
        char            *nameptr;
        ULONG           i;
        KIRQL           oldirql;    if( gProcessNameOffset ) 
        {
            curproc = PsGetCurrentProcess();
            nameptr   = (PCHAR) curproc + gProcessNameOffset;
            strncpy( theName, nameptr, NT_PROCNAMELEN );
            theName[NT_PROCNAMELEN] = 0; /* NULL at end */
            return TRUE;
        } 
        return FALSE;
    }NTSTATUS NewNtCreateProcessEx(
    OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    IN HANDLE ParentProcess,
    IN BOOLEAN InheritObjectTable,
    IN HANDLE SectionHandle OPTIONAL,
    IN HANDLE DebugPort OPTIONAL,
    IN HANDLE ExceptionPort OPTIONAL,
    IN HANDLE Unknown OPTIONAL)
    {
        CHAR aProcessName[PROCNAMELEN];
            
        GetProcessName( aProcessName );
        DbgPrint("rootkit: NewNtCreateProcessEx() from %s\n", aProcessName);
        //DbgPrint("ok");
        return OldNtCreateProcessEx(ProcessHandle,DesiredAccess,
                ObjectAttributes,ParentProcess,InheritObjectTable,SectionHandle,DebugPort,ExceptionPort,Unknown);
    }NTSTATUS
    OnStubDispatch(
        IN PDEVICE_OBJECT DeviceObject,
        IN PIRP           Irp
        )
    {
        Irp->IoStatus.Status      = STATUS_SUCCESS;
        IoCompleteRequest (Irp,
                           IO_NO_INCREMENT
                           );
        return Irp->IoStatus.Status;
    }VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
    {
        DbgPrint("ROOTKIT: OnUnload called\n");    _asm
        {
            CLI                    //dissable interrupt
            MOV    EAX, CR0        //move CR0 register into EAX
            AND EAX, NOT 10000H //disable WP bit 
            MOV    CR0, EAX        //write register back
        }    (NTCREATEPROCESSEX)(*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + 0x32))=OldNtCreateProcessEx;    _asm 
        {
            MOV    EAX, CR0        //move CR0 register into EAX
            OR    EAX, 10000H        //enable WP bit     
            MOV    CR0, EAX        //write register back        
            STI                    //enable interrupt
        }
    }NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
    {
        int i;    DbgPrint("My Driver Loaded!");
        GetProcessNameOffset();    // Register a dispatch function
        for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) 
        {
                theDriverObject->MajorFunction[i] = OnStubDispatch;
        }    theDriverObject->DriverUnload  = OnUnload;     // save old system call locations
        //OldNtCreateProcessEx=(NTCREATEPROCESSEX)(SYSTEMSERVICE(0x32));
        OldNtCreateProcessEx=(NTCREATEPROCESSEX)(*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + 0x32));
        _asm
        {
            CLI                    //dissable interrupt
            MOV    EAX, CR0        //move CR0 register into EAX
            AND EAX, NOT 10000H //disable WP bit 
            MOV    CR0, EAX        //write register back
        }    (NTCREATEPROCESSEX)(*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + 0x32))=  NewNtCreateProcessEx;    _asm 
        {
            MOV    EAX, CR0        //move CR0 register into EAX
            OR    EAX, 10000H        //enable WP bit     
            MOV    CR0, EAX        //write register back        
            STI                    //enable interrupt
        }
                        
        return STATUS_SUCCESS;
    }这样很不爽,每次都要这样看索引号,问了SOBEIT,可以通过从NTDLL中这样获取服务索引号:
    来自rookkit:
      

  2.   

    这篇是转贴,用 Hook ZwCreateProcess 的方法实现
    原文:http://www.xfocus.net/articles/200503/783.html
      

  3.   

    这种方式应该怎么实现:
    我在应用程序里面调用DeviceIOControl下发一个自定义的请求,
    当驱动收到这个请求以后,以当前用户身份创建运行一个进程。而且同时能在
    98、XP、NT2000、2003等系统中运行。
      

  4.   

    9x 和 NT 内核的处理要区别对待
    你可以参考 Undocumented Windows 2000 Secrets - The Programmers Cookbook