zoukankan      html  css  js  c++  java
  • 【转】[内核/驱动]驱动中获取进程全路径和注册表全路径

    转载地址: http://blog.sina.com.cn/s/blog_60a1a51d0100e78g.html

    2008.07.05 
        经过这几天的努力,注册表保护驱动已经基本稳定。很多人都在网上问如何获取访问注册表的进程全路径和被访问的注册表的全路径,下面就将部分代码贴出来。
    
    
    //驱动中获取被访问注册表的全路径
    BOOLEAN GetRegFullPath(HANDLE KeyHandle,
           PUNICODE_STRING pRegFullPath)
    {
        POBJECT pKey = NULL;
        BOOLEAN bSucc = TRUE;
    
    
        //由句柄得到对象指针
        pKey = GetPointer(KeyHandle);
        if (NULL == pKey)
        {
            bSucc = FALSE;
            goto BeforeLeave;
        }
    
    
        //减少引用计数
        ReleasePointer(pKey);
    
    
        ULONG uActualLen = 0;
        __try
        {
            //查询注册表项(注意这里是项)全路径
            if(!NT_SUCCESS(ObQueryNameString(pKey,
                (OBJECT_NAME_INFORMATION*)pRegFullPath, 
                MAXPATHLEN,
                &uActualLen)))
            {
                bSucc = FALSE;
                goto BeforeLeave;
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            KdPrint(("GetRegFullPath ObQueryNameString Exception!"));
            bSucc = FALSE;
            goto BeforeLeave;
        }
    
    
        BeforeLeave:
            return bSucc;
    }
    
    
    //由句柄得到对象指针
    POBJECT GetPointer(HANDLE KeyOrHandle)
    {
        POBJECT pKey = NULL;
    
    
        if(!KeyOrHandle)
        {
            return NULL;
        }
    
    
        // Make sure that we're not going to access
        // the kernel handle table from a non-system process
        //
        if((LONG)(ULONG_PTR) KeyOrHandle < 0 &&
            ExGetPreviousMode() != KernelMode) 
        {
            return NULL;
        }
    
    
        if(!NT_SUCCESS(ObReferenceObjectByHandle(KeyOrHandle, 
            0, 
            NULL, 
            KernelMode,
            &pKey, 
            NULL))) 
        {
            KdPrint(("Error %x getting key pointer
    "));
            pKey = NULL;
        } 
    
    
        return pKey;
    }
    
    
    //减少引用计数
    VOID ReleasePointer(POBJECT object)
    {
        if(object) ObDereferenceObject(object);
    }
     
    //使用方法
    ……
    PUNICODE_STRING pRegFullPath = (PUNICODE_STRING)ExAllocatePoolWithTag(NonPagedPool,
        MAXPATHLEN * sizeof(WCHAR) + 2 * sizeof(ULONG),
        'abcd');
    GetRegFullPath(pRegFullPath );
    KdPrint(("%wZ", pRegFullPath ));
    ExFreePoolWithTag(pRegFullPath, 'abcd');
    ……
    //至于为什么要这样申请内存,下面这个链接给出了解释:
    http://hi.baidu.com/1ian9yu/blog/item/a41cbadd73576adf8c102931.html
     
    
     
    //驱动中获取访问注册表的进程全路径
    有好几种方法:有一篇博文写的很清楚,下面是链接:http://hi.baidu.com/30571/blog/item/a718e52252e2304cac34de7d.html
    下面给出我试过的两种方法:
    第一种:EPROCESS->PEB->ProcessParameters->ImagePathName
    要想很好地理解下面的代码,建议在WinDbg下使用命令 dt _EPROCESS(更详细的命令请查help)等查看相关结构,自己算一下面代码中的偏移量。这段代码在Windows 2000 / Windows XP 下都可以使用,缺点在上面那个链接里面写的很清楚。
    PWCHAR GetProcessFullPath()
    {
        if(KeGetCurrentIrql() != PASSIVE_LEVEL)
        {
            return NULL;
        }
    
    
        //返回的是PEPROCESS类型
        //dwAddress是EPROCESS的地址
        DWORD dwAddress = (DWORD)PsGetCurrentProcess();
        if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)
        {
            return NULL;
        }
        //dwAddress是EPROCESS中PEB*成员的地址
        dwAddress += 0x1B0;
        //dwAddress是PEB*
        if((dwAddress = *(DWORD*)dwAddress) == 0)
        {
            return 0;
        }
        //dwAddress是PEB中的ProcessParameters(PRTL_USER_PROCESS_PARAMETERS类型)的地址
        dwAddress += 0x10;
        //dwAddress是ProcessParameters(PRTL_USER_PROCESS_PARAMETERS类型)
        if((dwAddress = *(DWORD*)dwAddress) == 0)
        {
            return 0;
        }
        //dwAddress是ImagePathName(UNICODE_STRING)的地址
        dwAddress += 0x3C;
        //dwAddress是ImagePathName(UNICODE_STRING)
        if((dwAddress = *(DWORD*)dwAddress) == 0) 
        {
            return 0;
        }
    
    
        return (PWCHAR)dwAddress; 
    }
    
    
    第二种:
    自己写了一段测试代码,比较乱哈,但这种方法确实是可行的,不过貌似只能在Windows XP上使用。
    DWORD GetCurrentProcessFullPath(WCHAR *pImageName)
    {
        KIRQL CurIRQL;
        NTSTATUS QueryStatus;
        ULONG returnedLength;
        PVOID buffer = NULL;
        UNICODE_STRING ImageName;
        DWORD dwRet = 0;
        NTSTATUS CreateStatus;
        HANDLE FileHandle = NULL;
        OBJECT_ATTRIBUTES ObjAttrib;
        IO_STATUS_BLOCK IoStatusBlock;
        PFILE_OBJECT pFileObj;
        NTSTATUS ReferenceStatus;
        NTSTATUS DeviceToDosStatus;
        WCHAR wcVolume;
        WCHAR wszDeviceNameTemp[10] = L"\??\X:";
        WCHAR wszDeviceName[10] = {0};
        UNICODE_STRING DeviceName;
        OBJECT_ATTRIBUTES ob;
        HANDLE LinkHandle;
        ULONG rt;
        UNICODE_STRING VolumeName;
        WCHAR BufferVolume[32] = L"";
        UNICODE_STRING FullPath;
        WCHAR BufferPath[MAXPATHLEN] = L"";
    
    
        PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process
    
    
        CurIRQL = KeGetCurrentIrql();
            if (PASSIVE_LEVEL != CurIRQL)
        {   
            dwRet = 1;
            goto BeforeLeave;
        }
    
    
        __try
        {
            if (!MmIsAddressValid(pImageName))
            {
                dwRet = 1;
                goto BeforeLeave;
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            dwRet = 1;
            goto BeforeLeave;
        }
    
        if (NULL == ZwQueryInformationProcess) 
        {
            //获取ZwQueryInformationProcess函数的地址
            UNICODE_STRING routineName;
            RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess");
            ZwQueryInformationProcess = (ZWQUERYINFORMATIONPROCESS)MmGetSystemRoutineAddress(&routineName);
            if (NULL == ZwQueryInformationProcess)
            {
                dwRet = 1;
                goto BeforeLeave;
            }
        }
    
    
        //获取保存进程路径需要的buffer长度
        QueryStatus = ZwQueryInformationProcess(NtCurrentProcess(),
            ProcessImageFileName,
            NULL,
            0,
            &returnedLength);
    
    
        if (STATUS_INFO_LENGTH_MISMATCH != QueryStatus)
        {
            dwRet = 1;
            goto BeforeLeave;
        }
    
    
        buffer = ExAllocatePoolWithTag(NonPagedPool,
            returnedLength,
            'ipgD');
    
    
        if (NULL == buffer)
        {
            dwRet = 1;
            goto BeforeLeave;
        }
    
    
        __try
        {
            QueryStatus = ZwQueryInformationProcess(NtCurrentProcess(),
                ProcessImageFileName,
                buffer,
                returnedLength,
                &returnedLength);
    
    
            if (!NT_SUCCESS(QueryStatus))
            {
                dwRet = 1;
                goto BeforeLeave;
            }
    
    
            InitializeObjectAttributes(&ObjAttrib,
                (PUNICODE_STRING)buffer,
                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                NULL,
                NULL);
    
    
            CreateStatus = ZwCreateFile(&FileHandle,
                GENERIC_READ,
                &ObjAttrib,
                &IoStatusBlock,
                NULL,
                FILE_ATTRIBUTE_NORMAL,
                0,
                FILE_OPEN,
                FILE_SYNCHRONOUS_IO_NONALERT,
                NULL,
                0);
    
    
            if (!NT_SUCCESS(CreateStatus) || !FileHandle)
            {
                dwRet = 1;
                goto BeforeLeave;
            }
    
    
            ReferenceStatus = ObReferenceObjectByHandle(FileHandle,
                FILE_READ_DATA,
                NULL,
                KernelMode,
                &pFileObj,
                NULL);
    
    
            if (!NT_SUCCESS(ReferenceStatus))
            {
                dwRet = 1;
                goto BeforeLeave;
            }
    
    
            ObDereferenceObject(pFileObj);
            for (wcVolume = L'A'; wcVolume <= L'Z'; wcVolume++)
            {
                wszDeviceNameTemp[4] = wcVolume;
                DeviceName.Buffer = wszDeviceNameTemp;
                DeviceName.Length = (USHORT)(wcslen(wszDeviceNameTemp) * sizeof(WCHAR));
                DeviceName.MaximumLength = (USHORT)sizeof(wszDeviceNameTemp);
                //KdPrint(("Symbolelic Name %wZ", &DeviceName));
                InitializeObjectAttributes(&ob,
                    &DeviceName,
                    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                    NULL,
                    NULL);
    
    
                VolumeName.Buffer = BufferVolume;
                VolumeName.Length = 0;
                VolumeName.MaximumLength = MAXPATHLEN;
                ZwOpenSymbolicLinkObject(&LinkHandle, GENERIC_READ, &ob);
                ZwQuerySymbolicLinkObject(LinkHandle, &VolumeName, &rt);
    
    
                //KdPrint(("Volume Name %wZ", &VolumeName));
    
    
                if (LinkHandle)
                {
                    ZwClose(LinkHandle);
                }
    
    
                memset(BufferPath, 0, sizeof(BufferPath));
                RtlInitEmptyUnicodeString(&FullPath, BufferPath, MAXPATHLEN);
                RtlCopyUnicodeString(&FullPath, &VolumeName);
                RtlAppendUnicodeStringToString(&FullPath, &(pFileObj->FileName));
                //KdPrint(("%wZ", &FullPath));
                if (0 == RtlCompareUnicodeString(&FullPath, (PUNICODE_STRING)buffer, TRUE))
                {
                    pImageName[0] = wcVolume;
                    pImageName[1] = L':';
                    pImageName[2] = L'';
                    wcsncat(pImageName, pFileObj->FileName.Buffer, pFileObj->FileName.Length);
                    break;
                }
            }
    
    
            //不知道什么原因,IoVolumeDeviceToDosName这个函数可能导致系统死锁
            //所以没有使用这个函数
            dwRet = 0;
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            //KdPrint(("Symbolelic EXCEPTION %wZ"));
            dwRet = 1;
        }
    BeforeLeave:
        if (buffer)
        {
            ExFreePoolWithTag(buffer,  'ipgD');
        }
    
    
        if (FileHandle)
        {
            ZwClose(FileHandle);
        }
    
    
        return dwRet;
     
    }
  • 相关阅读:
    Linux下c开发 之 线程通信(转)
    mount -t nfs 的使用
    window共享linux下的文件 samba
    C/C++ 的使用
    php获取格式时间和时间戳
    php压缩文件夹
    php递归删除文件夹
    php生成文件夹(递归生成)
    QQ音乐API分析记录
    $(this)与this的区别
  • 原文地址:https://www.cnblogs.com/Lthis/p/4491442.html
Copyright © 2011-2022 走看看