• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            Driver to Hide Processes and Files

            Posted on 2009-10-24 20:50 S.l.e!ep.¢% 閱讀(1273) 評論(0)  編輯 收藏 引用 所屬分類: RootKit
            http://www.codeproject.com/KB/system/hide-driver.aspx



            Prize winner in Competition "Best C++/MFC article of January 2009"
            91 votes for this article.
            Popularity: 8.64 Rating: 4.41 out of 5
            8 votes, 8.8%
            1

            2
            1 vote, 1.1%
            3
            5 votes, 5.5%
            4
            77 votes, 84.6%
            5

            List of Contents

            1. Introduction
            2. Is this article dangerous?
            3. Legal reason to hide processes and files
            4. Projects used
            5. Project implementation
            6. Project structure
            7. NT function call scheme and hook
            8. Function index in SST
            9. Change the results returned by the original function
            10. Process hiding
            11. File hiding
            12. GUI application
            13. Communication with HideDriver
            14. Format of communication
            15. HideDriver IOCTLs
            16. How to build this solution
            17. Additional information about the build
            18. Supported Windows version and testing
            19. Bibliography
            20. Useful Links
            21. Documentation and additional info
            22. History

            Introduction

            We are glad to introduce our project - "The Hide Driver project".

            The main idea of this work is to create a driver for hiding of selected processes and files.

            The task: The processes selected by the user should be invisible for such applications as the Task Manager, Process Explorer, and others. In addition, they should not be available for such Windows API functions as EnumProcesses(), OpenProcess(), EnumProcessModules(), and other Process APIs. The files selected by the user should be invisible for such file managers as Windows Explorer, Far, Total Commander, etc. In addition, they should not be available for such Windows API functions as FindFile(), OpenFile() and other File API functions.

            This article is written as the result of one education project implemented during ApriorIT students courses.

            During the project implementation we add some features that were not mentioned in the initial task:

            • Correct work on the multiple-processor systems
            • Support of the wildcards in the names of files, processes, users
            • Filtering of the access by the name of the process that requested for access
            • Filtering of the access by the user name

            A lot of time was spent to create the Universal Subsystem of Interceptions where the implementation of the given interception is a kind of plug-in. Due to the limited terms we implemented only two such plug-ins with expanded functionality.

            More interesting features can be added using SST hooking but they were not implemented in this project frame:

            • Hiding of registry keys
            • Hiding of the list of services and drivers
            • Hiding of opened handles (file, process, etc.)
            • Storing of the parameters in the registry or *.xml file

            Is This Article Dangerous?

            It's up to you! One may think that the described technique is good for virus creation. But it surely was not the aim of our article. Here are some thoughts we follow:

            1. To install the driver you must have Administrator right.
            2. This is a popular technique of files and process hiding. So all antiviruses and security products know how to bypass it.
            3. When you try to install driver antivirus can block this or ask you to make a choice.
            4. All popular antiviruses use some techniques to see the hidden files. Techniques are different - for example it can be direct call to filesystem driver or using of the system internal structure.
            5. All popular antiviruses use some techniques to see hidden processes. For example hook of KiSwapContext function. KiSwapContext is called when the time quantum of the thread ends. Time quantum is in milliseconds and KiSwapContext is called very frequently so you can't hide anything from it.
            6. Antiviruses filter all calls to file system and if you try to load a virus, they will see it and it doesn't matter if this file is hidden or not. Usually antivirus uses filter drivers located under the filesystem. In this case, when you try to read something from the disk antivirus checks content using image signatures and if there is a virus block it calls and shows the warning.
            7. If you just try to search by following keywords: antirootkit, detecting hidden process, etc. you will find hundreds of pages with hundreds of various programs.

            Legal Reason to Hide Processes and Files

            The main and obvious application of such technology is enterprise security and management systems. You cannot rely fully on the permissions as some users (like most of you here - developers) should have more than usual access permissions on their PC. Many security systems take the approach of using such kind of techniques to make sure that only authorized person(s) can turn this system off. It helps to prevent IP theft and data leakage in many companies.

            Another application of the described technique is software licensing and copy protection frameworks.

            Project Implementation

            The task described in the Introduction was resolved by using one of the general ways - Hooking SSDT. A lot of information about this technology can be found in the articles mentioned in the Useful Links section.

            Projects Used

            I would like to thank the people who developed the following projects - they made the implementation of this project easier:

            Project Structure

            Directory Structure

            Collapse Copy Code
            						.\bin - folder with binary files
               .\lib - folder with library files
               .\obj - folder with object files
               .\src - folder with source files
                  ||-> .\Common        - Files that are shared between projects.
                  |-> .\STLPort       - Directory with STLPort 4.6 ported for 
            			 using in windows drivers.
                  |-> .\drvCppLib     - Kernel Library to develop driver in C++.
                  |-> .\drvCppLibTest - Kernel Driver to test drvCppLib.
                  |-> .\drvUtils      - Kernel Library with utils for kernel mode projects.
                  |-> .\HideDriver    - Kernel Driver installed by Gui App. Performs main work.
                  |-> .\HideDriverGui - Win32 Application used to run driver and communicate with it.
                  |-> .\Utils         - Win32 Library with utils for user mode projects.
                  |-> .\UtilsPortable - Directory with headers for user mode and kernel mode projects.
                  |-> .\UtilsPortableUnitTest - Win32 Application with unit test for UtilsPortable.

            Project Structure

            NT Function Call Scheme and Hook

            The scheme below describes the normal call cycle of functions FindFirstFile(), FindNextFile() used to enumerate files and folders.

            The next scheme describes the situation when HideDriver is installed.

            So let's make a conclusion after all of this.

            When hook is installed, you can:

            • Call original function or not
            • Change the results returned by the original function
            • Even if original function returned successful status, you can return an error

            Function Index in SST

            Let's look at the structures described in NT function call scheme.

            [Code from the file src\HideDriver\ServiceTableDef.h]

            Collapse Copy Code
            						typedef
            						struct _SYSTEM_SERVICE_TABLE
            {
                PNTPROC ServiceTable;
                PDWORD  CounterTable;
                ULONG   ServiceLimit;
                PBYTE   ArgumentTable;
            }
            SYSTEM_SERVICE_TABLE ,
                * PSYSTEM_SERVICE_TABLE ,
                * * PPSYSTEM_SERVICE_TABLE ;
            
            typedefstruct _SERVICE_DESCRIPTOR_TABLE {
                SYSTEM_SERVICE_TABLE ntoskrnl;  //SST for ntoskrnl.exe
                SYSTEM_SERVICE_TABLE win32k;    //SST for win32k.sys
                SYSTEM_SERVICE_TABLE unused1;
                SYSTEM_SERVICE_TABLE unused2;
            }
            SERVICE_DESCRIPTOR_TABLE ,
                * PSERVICE_DESCRIPTOR_TABLE,
                * * PPSERVICE_DESCRIPTOR_TABLE ;

            Where PNTPROC is defined as:

            Collapse Copy Code
            						typedef PVOID* PNTPROC;

            So ServiceTable is a simple array of pointers to NtXXX functions.

            Question is: how to find out what is the index of function NtQueryDirectoryFile in the ServiceTable array?

            First Approach (wrong)

            Driver stores many tables with all indexes of functions for all versions of Windows.

            If we use these tables, we have to:

            • store all indexes for all versions of Windows and service packs for each function
            • update index tables for each new?OS version or service pack

            For some similar tasks such as offset in EPROCESS structure, there is no other way of finding the index in the structure.

            But for SST, another way exists.

            Second Approach (right)

            To retrieve the index for all versions of Windows, we need to find some place in the system where it is always used.

            Lets disable function ZwQueryDirectoryFile in WinDBG by executing u command:

            As you can see, the?underlined number is the index of ZwQueryDirectoryFile function in the ServiceTable array.

            Disabling other ZwXXX functions, you can see that all of these functions look the same and start with: mov eax,SST_Index.

            The code below retrieves this index:

            [Code from file src\HideDriver\HookFactory.cpp]

            Collapse Copy Code
            SSTHook CreateSSTHook(IN const PVOID pNewFuncPtr,IN PUNICODE_STRING function_name)
            {
                ...
            
                PVOID pTrueFuncPtr_ZW=MmGetSystemRoutineAddress(function_name);
            
                if(pTrueFuncPtr_ZW == NULL)
                    throw std::exception(__FUNCTION__"Can't get function address");
            
                // Skip command byte, move to index byte
                ULONG mFuncID = *(PULONG)((PUCHAR) pTrueFuncPtr_ZW + 1);
            
                ...
            }

            Change the Results Returned by the Original Function

            After hook is installed and we receive NtQueryDirectorFile calls, we need to cut information about a file from the List to hide it.

            Let's look at NtQueryDirectoryFile and NtQuerySystemInformation function definitions:

            Collapse Copy Code
            NTSTATUS NtQuerySystemInformation(
                SYSTEM_INFORMATION_CLASS SystemInformationClass,
                PVOID SystemInformation,
                ULONG SystemInformationLength,
                PULONG ReturnLength
            );
            
            NTSTATUS NtQueryDirectoryFile(
                HANDLE  FileHandle,
                HANDLE  Event  OPTIONAL,
                PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,
                PVOID  ApcContext  OPTIONAL,
                PIO_STATUS_BLOCK  IoStatusBlock,
                PVOID  FileInformation,
                ULONG  Length,
                FILE_INFORMATION_CLASS  FileInformationClass,
                BOOLEAN  ReturnSingleEntry,
                PUNICODE_STRING  FileName  OPTIONAL,
                BOOLEAN  RestartScan
                );

            Here is one of the possible results returned by this function:

            Collapse Copy Code
            						typedef
            						struct _FILE_FULL_DIRECTORY_INFORMATION {
                ULONG NextEntryOffset;
                ULONG Unknown;
                LARGE_INTEGER CreationTime;
                LARGE_INTEGER LastAccessTime;
                LARGE_INTEGER LastWriteTime;
                LARGE_INTEGER ChangeTime;
                LARGE_INTEGER EndOfFile;
                LARGE_INTEGER AllocationSize;
                ULONG FileAttributes;
                ULONG FileNameLength;
                ULONG EaInformationLength;
                WCHAR FileName[1];
            } FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION;
            
            // SystemProcessesAndThreadsInformationtypedefstruct _SYSTEM_PROCESSES_INFORMATION {
                ULONG                       NextEntryDelta;
                ULONG                       ThreadCount;
                ULONG                       Reserved1[6];
                LARGE_INTEGER               CreateTime;
                LARGE_INTEGER               UserTime;
                LARGE_INTEGER               KernelTime;
                UNICODE_STRING              ProcessName;
                KPRIORITY                   BasePriority;
                ULONG                       ProcessId;
                ULONG                       InheritedFromProcessId;
                ULONG                       HandleCount;
                ULONG                       SessionId;
                ULONG                       Reserved2;
                VM_COUNTERS                 VmCounters;
            #if (VER_PRODUCTBUILD >= 2195)
                IO_COUNTERS                 IoCounters;
            #endif// (VER_PRODUCTBUILD >= 2195)
                SYSTEM_THREADS_INFORMATION  Threads[1];
            } SYSTEM_PROCESSES_INFORMATION, *PSYSTEM_PROCESSES_INFORMATION;

            These two functions returned information that look very similar.

            That's why we created several utility functions which operate with these two structures. This utility is showed in the code below:

            [Code from file src\UtilsPortable\ListUtils.h]

            Collapse Copy Code
            						#pragma once
            #include"boost/function.hpp"#include"boost/bind.hpp"namespace utils
            {
            
            struct NtList
            {
                size_t NextEntryOffset;
            };
            
            #define LastEntryOffset 0inlinebool IsEntryLast(NtList* pList)
            {
                return (pList->NextEntryOffset == LastEntryOffset);
            }
            
            ////////////////////////////////////// FOR EACH SECTION ///////////////////////////inline NtList*
            GetNextEntryPointer(NtList* list)
            {
                if(list->NextEntryOffset == 0)
                    throw std::exception("No more entries inside list");
            
                return (NtList*)((char*)list + list->NextEntryOffset);
            }
            
            template<class Visitor>inlinevoid
            ListForEach( NtList* list, Visitor visitor )
            {
                while( true )
                {
                    visitor(list);
            
                    if( IsEntryLast(list) )
                        break;
            
                    list = GetNextEntryPointer(list);
                }
            }
            ///////////////////////////////// ENTRY COUNT SECTION /////////////////////////////inlinevoid
            CountEntryVisitor(NtList* list,size_t* entryCount)
            {
                *entryCount += 1;
            }
            
            inline size_t
            GetEntryCount(NtList* list)
            {
                size_t count = 0;
                ListForEach(list,boost::bind(&CountEntryVisitor,_1,&count));
                return count;
            }
            
            ////////////////////////////////// LIST SIZE SECTION /////////////////////////////inlinevoid
            SizeEntryVisitor(NtList* list,size_t* size)
            {
                size += list->NextEntryOffset;
            }
            inline size_t
            GetListSize(NtList* list)
            {
                size_t size = 0;
                ListForEach(list,boost::bind(&SizeEntryVisitor,_1,&size));
                return size;
            }
            
            ///////////////////////////////// CUT SECTION ////////////////////////////////////inlinevoid
            CutNextEntryByFakeOffset( NtList* list )
            {
                NtList* pNextEntry = GetNextEntryPointer(list);
            
                if( IsEntryLast(pNextEntry) )
                    list->NextEntryOffset = LastEntryOffset;
                else
                    list->NextEntryOffset = list->NextEntryOffset + pNextEntry->NextEntryOffset;
            }
            
            template<class Checker>inlinevoid
            CutFromListByFakeOffset_IfImpl( NtList* list,
                                            Checker checker )
            {
                if( IsEntryLast(list) )
                    return; // Last entry already dispatchedwhile(true)
                {
                    NtList* pNextEntry = GetNextEntryPointer(list);
                    if( !checker(pNextEntry) )
                        break;
            
                    CutNextEntryByFakeOffset(list);
            
                    if( IsEntryLast(list) )
                        break;
                }
            }
            
            template<class Checker>inlinevoid
            CutFromListByFakeOffset_If( NtList* list
                                      , Checker checker )
            {
                ListForEach( list, boost::bind(&CutFromListByFakeOffset_IfImpl<Checker>,_1,
                                               boost::ref(checker) ) );
            }
            
            }//namespace utils

            Process Hiding

            To hide processes, we need to cut the information about them from the list returned by NtQuerySystemInformation().

            It's very easy using utils described above.

            [Code from file src\UtilsPortable\IProcessChecker.h]

            Collapse Copy Code
            						struct NtQuerySysInfoParams
            {
                SYSTEM_INFORMATION_CLASS SystemInformationClass;
                PVOID SystemInformation;
                ULONG SystemInformationLength;
                PULONG ReturnLength;
            };
            
            struct IProcessChecker
            {
                virtualbool
                CheckProcess( wchar_t* imageName
                            , size_t nameSize )=0;
            };

            [Code from file src\UtilsPortable\ProcessHideAlgorithm.h]

            Collapse Copy Code
            						inline
            						bool
            CheckProcEntry( utils::NtList* list,
                            const NtQuerySysInfoParams& params,
                            IProcessChecker* checker )
            {
                SYSTEM_PROCESSES_INFORMATION* info =
                    (SYSTEM_PROCESSES_INFORMATION*)list;
            
                return checker->CheckProcess(info->ProcessName.Buffer,
                                             info->ProcessName.Length/2);
            }
            
            inline NTSTATUS
            HideProcessImpl( const NtQuerySysInfoParams& params,
                             IProcessChecker* checker )
            {
                utils::NtList* pList =
                    (utils::NtList*)params.SystemInformation;
            
                // First entry always exist// because first entry is idle process
                utils::CutFromListByFakeOffset_If(pList,
                    boost::bind(&CheckProcEntry,_1,params,checker));
            
                return STATUS_SUCCESS;
            }

            File Hiding

            To hide a file, we need to cut the information about it from the list returned by NtQueryDirectoryFile().

            Hiding algorithm starts from NewNtQueryDirectoryFile() function which receives calls every time someone calls NtQueryDirectoryFile() function in the system.

            NewNtQueryDirectoryFile() calls original function and processes returned data by passing it to the HideFile() function from UtilsPortable\HideAlgorithm.h.

            [Code from file src\HookFile.cpp]

            Collapse Copy Code
            NTSTATUS NewNtQueryDirectoryFile(IN HANDLE FileHandle,
                                             IN HANDLE Event OPTIONAL,
                                             IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
                                             IN PVOID ApcContext OPTIONAL,
                                             OUT PIO_STATUS_BLOCK IoStatusBlock,
                                             OUT PVOID FileInformation,
                                             IN ULONG FileInformationLength,
                                             IN FILE_INFORMATION_CLASS FileInformationClass,
                                             IN BOOLEAN ReturnSingleEntry,
                                             IN PUNICODE_STRING FileName OPTIONAL,
                                             IN BOOLEAN RestartScan)
            {
                usingnamespace HideAlgorithm;
            
                NtQueryDirParams params = {FileHandle,Event,ApcRoutine,ApcContext,
                    IoStatusBlock,FileInformation,FileInformationLength,
                    FileInformationClass,ReturnSingleEntry,FileName,RestartScan};
            
                NTSTATUS status = OriginalHandlerWrapper(params);
                if( !NT_SUCCESS(status) )
                    return status;
            
                params.RestartScan = FALSE; // Search must be continued// Save original handler to request more data in future
                HideParams hideParams = {params,gFileChecker,&OriginalHandlerWrapper};
            
                switch(FileInformationClass)
                {
                case FileDirectoryInformation:
                    return HideFile<FILE_DIRECTORY_INFORMATION>(hideParams);
                case FileFullDirectoryInformation:
                    return HideFile<FILE_FULL_DIRECTORY_INFORMATION>(hideParams);
                case FileBothDirectoryInformation:
                    return HideFile<FILE_BOTH_DIRECTORY_INFORMATION>(hideParams);
                case FileNamesInformation:
                    return HideFile<FILE_NAMES_INFORMATION>(hideParams);
                case FileIdBothDirectoryInformation: // Used by Vista and later explorerreturn HideFile<FILE_ID_BOTH_DIR_INFORMATION>(hideParams);
                case FileIdFullDirectoryInformation: // Used by Vista and later explorerreturn HideFile<FILE_ID_FULL_DIR_INFORMATION>(hideParams);
                default:return status;
                }
            }

            When we know what type of information is requested, we can cut the process from the list using ListUtils from UtilsPortable.

            The first step is to establish correspondence between callers and algorithm.

            It is done by specifying virtual function and parameters in the code below.

            [Code from file src\UtilsPortable\IFileChecker.h]

            Collapse Copy Code
            						struct NtQueryDirParams
            {
                HANDLE FileHandle;
                HANDLE Event;
                PIO_APC_ROUTINE ApcRoutine;
                PVOID ApcContext;
                PIO_STATUS_BLOCK IoStatusBlock;
                PVOID FileInformation;
                ULONG FileInformationLength;
                FILE_INFORMATION_CLASS FileInformationClass;
                BOOLEAN ReturnSingleEntry;
                PUNICODE_STRING FileName;
                BOOLEAN RestartScan;
            };
            
            struct IFileChecker
            {
                virtualbool
                CheckFile( wchar_t* fileName
                         , size_t nameSize
                         , const NtQueryDirParams& params )=0;
            };

            Original handler needs to request more data if request is finished with the flag ReturnSingleEntry == TRUE.

            [Code from file src\UtilsPortable\FileHideAlgorithm.h]

            Collapse Copy Code
            						typedef NTSTATUS(*OriginalHandlerWrapperPtr)(const NtQueryDirParams& params);
            
            struct HideParams
            {
                const NtQueryDirParams& callParams;
                IFileChecker* checker;
                OriginalHandlerWrapperPtr wrapperPtr;
            };
            
            template<class InfoType>inlinebool
            CheckFileEntry( utils::NtList* list,
                            const HideParams& params )
            {
                InfoType* info = (InfoType*)list;
                return params.checker->CheckFile(info->FileName,
                                                 info->FileNameLength/2,
                                                 params.callParams);
            }

            The next step is to protect top level functions from exceptions that can arise during the hiding of processes.

            Unhandled exception will cause the system crash.

            Collapse Copy Code
            						template
            						<
            						class InfoType>inline NTSTATUS
            HideFile( const HideParams& params )
            {
                try
                {
                    return HideFileImpl<InfoType>(params);
                }
                catch(const std::exception& ex)
                {
            #ifdef KdPrint // For use in user mode environment
                    KdPrint( (__FUNCTION__" std::exception: %s\n",ex.what()) );
            #endif
                }
                return STATUS_SUCCESS;
            }

            After this, we need to process the first entry separately from the next entries.

            We should do it because we need to shift the buffer to hide the first entry but to hide the next entries, we need just to set fake offset.

            Collapse Copy Code
            						template
            						<
            						class InfoType>inline NTSTATUS
            HideFileImpl( const HideParams& params )
            {
                NTSTATUS status = FirstEntryProcessor<InfoType>(params);
                if( !NT_SUCCESS(status) )
                    return status;
            
                status = NextEntryProcessor<InfoType>(params);
                if( !NT_SUCCESS(status) )
                    return status;
            
                return STATUS_SUCCESS;
            }

            In the code below, you can see the algorithm of hiding of the first entry from the list returned by NtQueryDirectoryFile().

            Collapse Copy Code
            						template
            						<
            						class InfoType>inline NTSTATUS
            FirstEntryProcessor( const HideParams& params )
            {
                utils::NtList* pList =
                    (utils::NtList*)params.callParams.FileInformation;
            
                utils::NtList* pCurEntry = pList;
            
                while(true)
                {
                    if(!CheckFileEntry<InfoType>(pCurEntry,params))
                    {
                        if(pList == pCurEntry)
                            break; // Nothing to hide
            
                        ShiftBuffer(pList,pCurEntry);
                        break; // First entry hiding complete
                    }
            
                    // This entry needs to be hiddenif( utils::IsEntryLast(pCurEntry) == false )
                    {
                        // Move to next entry to check.// This is needed to shift buffer only once.
                        pCurEntry = utils::GetNextEntryPointer(pCurEntry);
                    }
                    else
                    {
                        // Reached last entry// This mean that all data needs to be hidden// Try to request more data
                        NTSTATUS status = params.wrapperPtr(params.callParams);
                        if( !NT_SUCCESS(status) )
                            return status;
            
                        // Move to begin and resume checking
                        pCurEntry = pList;
                    }
                }
                return STATUS_SUCCESS;
            }

            Algorithm of hiding the next entries is the same as the algorithm of process hiding.

            Collapse Copy Code
            						template
            						<
            						class InfoType>inline NTSTATUS
            NextEntryProcessor( const HideParams& params )
            {
                utils::NtList* pList =
                    (utils::NtList*)params.callParams.FileInformation;
            
                if( utils::IsEntryLast(pList) )
                    return STATUS_SUCCESS;
            
                utils::CutFromListByFakeOffset_If(pList,
                    boost::bind(&CheckFileEntry<InfoType>,_1,params));
            
                return STATUS_SUCCESS;
            }

            GUI Application

            The GUI application enables a user to choose processes or/and files for hiding in an easy way. You can find an example of such application in the attached file. It was developed using MFC. It should be also mentioned that you can create your own GUI application following the rules in the Format of communication section.

            Communication with HideDriver

            IOCTLs and the DeviceIoCotrol() routine should be used for communication between the user-mode application and driver.

            You can find additional information about such communication implementations in the article: "Driver Development Part 2: Introduction to Implementing IOCTLs".

            Wrapper class DriverWork was developed for communication with drivers. This class wraps DeviceIoControl() function and other service functions.

            Here is an example of using of DriverWorkclass to send IOCTL to HideDriver:

            [Code from file src\HideDriverGUI\FileForm.cpp]

            Collapse Copy Code
            						void FileForm::OnMenuAdd()
            {
            ...
                try
                {
                    utils::DriverWork::Exchange(
                        _T("\\\\.\\HideDriver"),
                        IOCTL_ADD_FILE_HIDE_RULE,
                        str,                     // Input string
                        size,                    // Size of input string
                        (PWCHAR)ret_data,        // Output stringsizeof(ret_data),        // Size of buffer for output string
                        &BytesReturned);
                }
                catch(const std::exception& ex)
                {
                    ::MessageBoxA(this->GetSafeHwnd(),ex.what(),"Error",MB_ICONERROR|MB_OK);
                    return;
                }
            ...
            }

            Below you can see the code of DriverWork::Exchange() function:

            [Code from file src\Utils\DriverWork.cpp]

            Collapse Copy Code
            						void DriverWork::Exchange(LPCTSTR driverName,
                                      unsignedlong ioctlCode,
                                      PWCHAR pInStr,
                                      DWORD inStr_size,
                                      PWCHAR pOutStr,
                                      DWORD outStr_size,
                                      PDWORD bytesReturned)
            {
                HANDLE hHandle =
                    CreateFile( driverName,
                                GENERIC_READ | GENERIC_WRITE,
                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL );
                if(hHandle == INVALID_HANDLE_VALUE)
                    throw std::runtime_error("Can't get handle to driver: " + GetLastErrorStr());
            
                HandleGuard guard1(hHandle);
            
                if( !DeviceIoControl(hHandle,
                                     ioctlCode,
                                     pInStr, inStr_size,  // Input
                                     pOutStr, outStr_size,// Output
                                     bytesReturned,
                                     NULL) )
                {
                    throw std::runtime_error("Driver communication error: " + GetLastErrorStr());
                }
            }

            Format of Communication

            All input strings (parameters) are UNICODE strings. If an error occurs, driver returns ASCII string with the error description.

            All HideDriver IOCTLs (except CLEAR IOCTLs) work with HIDE_RULE. HIDE_RULE supports the?following options:

            • Hide from the list of processes, it means that only selected processes should not see this process or file
            • Hide from the list of users, it means that only selected users should not see this process or file

            These options can be used together.

            Format of HIDE_RULE stringmust be: process(file)_name_to_hide;access_user_name;access_process_name.

            Where:

            • process(file)_name_to_hide - process name (file path) to hide
            • access_user_name - name of user, who should not see this process(file)
            • access_process_name - name of process, which should not see this process(file)

            To insert several processes or user names, separate them by ',' character.

            Example:

            Collapse Copy Code
            process_name_to_hide;user_name1,user_name2;process_name1,process_name2

            All names support wildcards:

            "*" - Matches all characters

            "?" - Matches any single character

            Some Examples

            *;*;* - Hide all processes from all users and processes. Just for fun.

            System;*;* - Hide process system from all users and processes.

            er*;*;* - Hide all processes whose name starts with "er" characters from everybody.

            System;*;Rob - Hide process "System" from User: Rob

            HideDriver IOCTLs

            All IOCTLs that can process HideDriver are located in file Ioctl.h.

            [Code from file src\Common\Ioctl.h]

            Collapse Copy Code
            /*-----------------------------------------------------------------------*//*                            Process hide IOCTLs                        */#define IOCTL_ADD_PROCESS_HIDE_RULE CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to add process hide rule to hide list.
            Input string must be HIDE_RULE.
            */#define IOCTL_DEL_PROCESS_HIDE_RULE CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to delete process hide rule from hide list.
            Input string must be HIDE_RULE.
            */#define IOCTL_CLEAR_PROCESS_HIDE_RULES CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to clear process hide list.
            Input string should be empty.
            */#define IOCTL_QUERY_PROCESS_HIDE_RULES CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to get process hide rule list.
            Input string should be empty.
            
            Format of output string:
            HIDE_RULEs separated by '\n' character
            and ends with '\0' character.
            
            Example:
                *;*;*\nSystem;*;*\0 - two hide rules (*;*;*) and (System;*;*)
            *//*-----------------------------------------------------------------------*//*-----------------------------------------------------------------------*//*                                File hide IOCTLs                       */#define IOCTL_ADD_FILE_HIDE_RULE CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to add file hide rule to hide list.
            Input string must be HIDE_RULE.
            */#define IOCTL_DEL_FILE_HIDE_RULE CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to delete file hide rule from hide list.
            Input string must be HIDE_RULE.
            */#define IOCTL_CLEAR_FILE_HIDE_RULES CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to clear file hide list.
            Input string should be empty.
            */#define IOCTL_QUERY_FILE_HIDE_RULES CTL_CODE( \
                FILE_DEVICE_UNKNOWN, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS)
            
            /*
            This IOCTL used to get file hide rule list.
            Input string should be empty.
            
            Format of output string same as in IOCTL_QUERY_PROCESS_HIDE_RULES.
            *//*-----------------------------------------------------------------------*/

            How to Build this Solution

            1. Install Windows Driver Developer Kit 2003
              http://www.microsoft.com/whdc/devtools/ddk/default.mspx
            2. Set global environment variable "BASEDIR" to path of installed DDK.
              Computer -> Properties -> Advanced -> Environment variables ->System Variables -> New
              Like this: BASEDIR -> c:\winddk\3790
              (You have to restart your computer after this.)
            3. Download and install boost (tested with 1.38 version)
              http://www.boost.org/users/download/
            4. Set global environment variable "BOOST" to path of installed boost.

            If you choose Visual Studio 2003, then you can simply open HideDriver_vs7.sln and build all.

            If you choose Visual Studio 2005 or 2008, you will need files from Visual Studio 2003 to do it. Copy files located here: C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\crt\src\intel\st_lib\ (But surely this path depends on the Visual Studio install path) to the project folder: HideDriver_source\src\drvCppLib\lib_copy\.

            After this, you can use the file "HideDriver_vs8.sln" in Visual Studio 2005 and file "HideDriver_vs9.sln" in Visual Studio 2008.

            Additional Information About the Build

            You will also need the file from $VCInstllPath\crt\src\intel\st_lib\ - Single Threaded C++ Run-Time is located in this directory. Any other version of run-time library can't be used for the driver building.

            This method was originally discovered by Gary Nebbett in the article: "Enabling C++ exceptions and RTTI in kernel-mode code". It's like nobody has invented something better since that time.

            Supported Windows Version and Testing

            All tests were performed with Driver Verifier Enabled with all options ON except low resource simulation.

            • Windows 2000, SP4
            • Windows XP, SP3
            • Windows 2003 Server, R2
            • Windows Vista, SP0,SP1
            • Windows 2008 Server
            • Windows 7 Beta, Build 7000

            All versions are x86; x64 windows version is not supported because of PatchGuard.

            Bibliography

            • Mark Russinovich, David Solomon. Microsoft Windows Internals ((Fourth Edition) ed.)
            • Greg Hoglund, Jamie Butler. Rootkits: Subverting the Windows Kernel
            • Gary Nebbett. Windows NT/2000 Native API Reference
            • Sven B. Schreiber. Undocumented Windows 2000 Secrets - A Programmer's Cookbook

            Useful Links

            We recommend the article "Driver Development" by Toby Opferman:

            It would also be useful to look through other articles (Part 2, Part 3, Part 4, Part 5, Part 6,Part 7).

            Also, a lot of knowledge that helped us to develop this project was obtained here:

            1. Hooking Windows NT System Services
            2. http://www.osronline.com/
            3. http://www.rootkit.com/
            4. http://msdn.microsoft.com/
            5. http://www.boost.org/

              For Russian speaking readers, we recommend these sources:

            6. http://wasm.ru/
            7. http://wasm.ru/article.php?article=apihook_3
            8. http://wasm.ru/article.php?article=hidingnt

            Additional Info

            Additional information can be found at the Apriorit Education page.

            History

            21/01/2009 (by Ivan Romanenko & Sergey Popenko)

            • Initial version of this article

            12/02/2009 (by Ivan Romanenko)

            • Added possibility to build solution in VS2003, VS2005, VS2008
            • Added the topic "How to build this solution"

            29/04/2009 (by Ivan Romanenko)

            • Project
              • Bugfix
                • Wrong hiding of the first file in the directory
                • Wrong synchronization that locks PC
                • Allocation memory on height IRQL
                • Bug with build using DDK2003
                • Bug in filtering by user
                • Removed using SingleMode and changed HookMng
              • New
                • Using Wildmat instead of own wild cards implementation
                • Unit tests
                • Using BOOST and STLPort
                • Changes in project structure, utils and tests are added
            • Article
              • Bugfix
                • Wrong language in Ioctl.h
                • Fixed spelling error at code comments
              • New
                • 11 new topics added

            13/08/2009 (by Ivan Romanenko)

            • Project?
              • Bugfix?
                • Fixed: synchronization bug in CReadWriteSection class?
                • Fixed: wrong name converting for network shares?
                • Added: heuristics for offset receiving. Absolute offsets are not used any more, except for case when DriverVerifier substitutes ntoskrnl code under Vista.

            License

            This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

            About the Authors

            SergeyPopenko


            Member
            Sergey Popenko.
            21 years old.
            The Driver Team`s junior developer.
            5th year student (master) of the Applied Math faculty, Dnipropetrovsk National University, Ukraine.
            Occupation: Software Developer (Junior)
            Company: ApriorIT
            Location: Ukraine Ukraine

            Apriorit Inc


            Member
            ApriorIT is a Software Research and Development company that works in advanced knowledge-intensive scopes.

            Company offers integrated research&development services for the software projects in such directions as Corporate Security, Remote Control, Mobile Development, Embedded Systems, Virtualization, Drivers and others.

            Official site http://www.apriorit.com
            Company: Apriorit Inc.
            Location: Ukraine Ukraine

            Ivan Romanenko


            Member

            Occupation: Software Developer (Junior)
            Company: Apriorit Inc
            Location: Ukraine Ukraine
            品成人欧美大片久久国产欧美...| 亚洲精品tv久久久久久久久| 99久久婷婷国产一区二区| 久久国产精品久久久| 久久久久久亚洲精品不卡| 亚洲国产成人精品女人久久久 | 亚洲精品美女久久久久99| 一本久道久久综合狠狠躁AV| 亚洲人成伊人成综合网久久久| 99热成人精品热久久669| 久久免费观看视频| 久久66热人妻偷产精品9| 无码国内精品久久人妻麻豆按摩 | 欧美亚洲国产精品久久| 久久久久久午夜成人影院| 大美女久久久久久j久久| 亚洲精品蜜桃久久久久久| 人妻无码久久精品| 久久精品国产亚洲网站| 久久99精品国产麻豆宅宅| 青青青青久久精品国产| 熟妇人妻久久中文字幕| 人人狠狠综合久久亚洲| 91精品国产91久久久久久蜜臀| 久久久久人妻一区二区三区 | 久久亚洲精品人成综合网| 欧美成人免费观看久久| 99久久精品国产一区二区蜜芽| 少妇人妻88久久中文字幕| 久久受www免费人成_看片中文| 一本大道加勒比久久综合| 性高湖久久久久久久久| 麻豆av久久av盛宴av| 中文字幕精品无码久久久久久3D日动漫 | 久久超碰97人人做人人爱| 99久久综合国产精品免费| 四虎久久影院| 久久久www免费人成精品| 狠狠色丁香久久婷婷综合| 少妇熟女久久综合网色欲| 久久久精品国产免大香伊|