Developing your own Anti-Exe (C - Device Driver Development)

Discussion in 'Develop Coding Skills - Tutorials' started by Wave, Oct 2, 2016.

  1. Zhou He

    Zhou He Level 1

    Mar 13, 2017
    29
    76
    China
    Windows 10
    ESET
  2. Opcode

    Opcode Level 18
    Content Creator

    Aug 17, 2017
    894
    6,332
    Caille
    Windows 10
    I am not the author of this thread but I hope you do not mind me stepping in and answering your question...

    The reason you require the INTEGRITYCHECK flag is because it will force verification of the digital signature for the binary (your device driver which follows the Portable Executable (PE) Format). It is an additional security feature and without applying this flag through the linker options, you'll get back STATUS_ACCESS_DENIED error-code when attempting to register a callback for PsSetCreateProcessNotifyRoutineEx (or any other callbacks for that matter).

    It may be worth mentioning that on Windows 10 there is a new version of PsSetCreateProcessNotifyRoutineEx, with the "2" prefix applied at the end of Ex: PsSetCreateProcessNotifyRoutineEx2. If you decide to use it in your software, remember to use the previous versions for earlier versions of Windows.
     
  3. venustus

    venustus Level 43
    Content Creator Trusted

    Dec 30, 2012
    3,226
    16,098
    Sydney
    Windows 10
    Kaspersky
    No, because he's a "guest" at the moment.
    But you can do a search "Wave" and you will find his posts:)
     
    harlan4096, XhenEd and Opcode like this.
  4. bromance

    bromance Level 1

    Nov 18, 2017
    3
    32
    Somewhere !
    Windows 10
    If you are interested in developing a security product such as an AV, performing cloud analysis on untrusted processes trying to run (and so on) then you need to auto-block execution and work with IOCTLs to send back to a user-mode process to perform the scan (and if clean then manually re-execute the program) since you cannot just hold up in kernel-mode and wait for scan responses since this would break the structure of kernel-mode (as it would result in hanging up the entire system!).

    Really informing post by the way, I am developing exactly such application, I was wondering how can I auto-block and re-execute the program? Any hint on this one is really appreciated !

    bromance
     
  5. Opcode

    Opcode Level 18
    Content Creator

    Aug 17, 2017
    894
    6,332
    Caille
    Windows 10
    @bromance The author of the post was incorrect. You don't have to block execution and then re-start it and doing this would cause problems anyway because programs trying to start other programs would be under the impression that the operation failed, as well as on-screen error messages from Windows notifying that execution of a program failed (potentially).

    You can change values for parameters in the callback routine to block the execution operation for the process spawn, and Kernel-Mode does not have support for spawning programs naturally. You can inject into a user-mode process via remote threads (if you can find the address for NtCreateThreadEx) or APC and have the injected code perform the process spawn.

    There are multiples of methods you can use for communication to and from both kernel-mode and user-mode. Kernel-mode communication can be a lot tougher at the start if you are not used to it. You can look into using Ports though, you can even add support for named pipes manually if you know how to (cautious you may be frowned at by others though who will disagree with doing something unsupported and undocumented by default like this, even if you manage to do it right).

    Another member recently asked about the function DeviceIoControl (KERNEL32) and I replied to them about communication a bit. You can find the thread here and my response is attached as a comment. Q&A - DeviceIoControl VS WriteFile and ReadFile

    On Windows 10 there is now a new kernel-mode callback called PsSetCreateProcessNotifyRoutineEx2. You could check the OS version to decide whether to use the Ex prefix version, or the Ex2 prefix version accordingly.
     
  6. bromance

    bromance Level 1

    Nov 18, 2017
    3
    32
    Somewhere !
    Windows 10
    @Opcode I read somewhere in docs Microsoft warns as follow:
    • Keep notify routines short and simple.
    • Do not make calls into a user mode service to validate the process, thread, or image.
    • Do not make registry calls.
    • Do not make blocking and/or Interprocess Communication (IPC) function calls.
    • Do not synchronize with other threads because it can lead to reentrancy deadlocks.
    • Use System Worker Threads to queue work especially work involving:
      • Slow API’s or API’s that call into other process.
      • Any blocking behavior which could interrupt threads in core services.
    • Be considerate of best practices for kernel mode stack usage. For examples, see How do I keep my driver from running out of kernel-mode stack? and Key Driver Concepts and Tips.
    do you have any thoughts by considering these limitations?
     
    XhenEd, Zhou He, harlan4096 and 2 others like this.
  7. Opcode

    Opcode Level 18
    Content Creator

    Aug 17, 2017
    894
    6,332
    Caille
    Windows 10
    @bromance If you implement the communication support properly then you won't have issues and it'll work fine, but you'll need to do extensive testing to ensure it really does work correctly. You could even use shared events and a log file -> user-mode program executes the callback routine for the event and replies back to the log based on the data read from it -> now another event is triggered from user-mode for kernel-mode and the driver stops waiting for the response and takes action accordingly depending on the new data within the log.

    There are endless possibilities. You have to decide which route is best for your project and most comfortable for you, and at the same time ensure the implementation is reliable and secure.

    You might want to look into ALPC (Native API) functions, might be interesting for you.
     
  8. bromance

    bromance Level 1

    Nov 18, 2017
    3
    32
    Somewhere !
    Windows 10
    I digged into documentation of Trend Micro Endpoint Application Control here and here. For user-level blocking they say:

    User-level blocking allows applications to start and then stops them at the task level. This may be unable to stop certain applications after they start and is less feature-rich than kernel-level blocking. User-level blocking is unable to block link libraries (DLLs) and is unable to support the Trusted Source feature.
    For kernel-level blocking the say:

    Kernel-level blocking prevents applications from starting by blocking file access. This provides greater security, but may unexpectedly block or momentarily delay access to certain files needed by allowed applications.
    After Endpoint Application Control blocks or delays an application start using the kernel-level method, related notifications for the event may be displayed to the end-user.
    I installed this software on my system, the have a driver named AcDriver.sys and AcDriverHelper.sys and also in .inf file for driver it has a this entry: DriverPackageType = FileSystemMinifilter, what does this mean?

    I have a few questions:
    1 - what do they mean at task level? How they have done it?
    2 - what do they mean by being less feature-rich?
    3 - in kernel-level blocking they say something about blocking file access file (what are we talking about here? :) )
    4 - block or delaying application by kernel-level methods, what are those?

    I have another question, how can I decipher a driver inner working? is it feasible or sane ?

    Any help idea is much appreciated.
     
    XhenEd and Zhou He like this.
  9. Opcode

    Opcode Level 18
    Content Creator

    Aug 17, 2017
    894
    6,332
    Caille
    Windows 10
    @bromance Please forgive me my friend, I have only just seen your response while browsing the forum list. I don't recall seeing the notification for the tag you used for me in your previous post, nor the reply at-all!

    Regarding your question about Trend Micro Endpoint Application Control, they must be using a file-system mini-filter driver for process start-up interception. Please do not get confused between what I mean when I refer to "process start-up interception" under this context - I'm not referring to intercepting when a process is starting up, but more triggering a scan and delaying events when a suspicion is raised that a program is about to execute. A file-system mini-filter device driver will provide Trend Micro the ability to intercept file-system events via a kernel-mode callback called FltRegisterFilter, and when a program is about to be executed it will trigger these file-system events. The Portable Executable must be accessed so its data can be mapped into memory by the Windows loader for example. They must be using filter checks within their callback routines and then depending on these checks, performing a scan of the PE file which is responsible for those callback routine event triggers.

    *.INF is data about the device driver, and also is configured for easier installation (e.g. right click -> Install -> now it copies to ..\\System32\\drivers and does other things which the Service Manager would have done, but it does a few extra things which the Service Manager does not do, which is why they are typically used for installation of file-system mini-filter drivers - you can still use the Service Manager to install those types of drivers but you'd have to do some manual things in addition for it to work).

    Anti-Virus vendors tend to rely on Ports for communication from kernel-mode to user-mode and back when dealing with file-system mini-filter device drivers. The reason for this, is because Ports is officially supported but also documented by Microsoft when working a file-system mini-filter driver. The official Microsoft sample for this framework of kernel-mode development even demonstrates a basic example for communication implementation, but you'll be required to make changes to get it working for what you would need to do.

    Heads up, if you decide to do checks from within a file-system mini-filter driver as opposed to relying on the standard kernel-mode driver framework for PsSetCreateProcessNotifyRoutine/Ex/Ex2, use wchar_t data-type when sending back the file-path down to user-mode. Stick to original data-types and you'll less likely run into problems. Also make sure that you don't blatantly pass pointers incorrectly (e.g. passing a pointer to a variable down to user-mode where the user-mode process accepting the request does not have access to the memory in-which the address of the pointer points-to will not work).

    There are many ways to intercept process start-up requests. You could even use PsSetLoadImageNotifyRoutine and wait until you detect the loading of NTDLL.DLL. All new processes load NTDLL.DLL as the very first module, and every single user-mode process will have it loaded.

    1. I believe they are referring to user-mode, but I cannot be certain. If they do happen to be referring to user-mode, they are likely byte-patching various Native API routines within the address space of other running programs (an hooking technique) such as: CreateProcessInternalW; NtCreateUserProcess; NtResumeThread; or NtMapViewOfSection.

    CreateProcessInternalW (KERNEL32) is an highly undocumented function, rarely anyone speaks of it nowadays although it has existed since Windows 2000 I believe (if not then Windows XP indefinitely). It is exported by kernel32.dll on Windows 7 and below, whereas for Windows 8 and above it is exported by both kernel32.dll and kernelbase.dll (always target kernelbase.dll for the function for Windows 8 and above otherwise you'll run into problems and I am saying this from experience). It is called internally by Windows for process start-up requests which pass through CreateProcessA/W. There's also an Ascii variant of the routine however the Ascii version will call the Unicode version anyway.

    NtCreateUserProcess (NTDLL) is another undocumented function. For Windows 2000 and Windows XP the function does not exist therefore you would target RtlCreateUserProcess. Starting on Windows Vista, which is the time the routine was introduced, RtlCreateUserProcess will internally call NtCreateUserProcess. This routine performs a system-call since the routine actually exists in kernel-mode (ntoskrnl.exe). Interception of this routine will allow you to control whether the affected processes can execute a new process or not, unless the interception is being bypassed (unlikely but possible). I've actually posted a tutorial here on intercepting this routine should you be interested:

    NtResumeThread (NTDLL) is a routine responsible for resuming a thread of a process. The reason this function can be intercepted to control process execution is because all new process start-ups in Windows will leave the new process in a suspended state until the Windows loader has finished initialisation. Once initialisation has completed, the Windows loader will resume the main thread of the new process which allows it to start executing its own code. The Windows loader executes under the process performing the start-up request - this means that when you call CreateProcessA/W to spawn a process, other routines related to memory mapping/memory access protection (NtMapViewOfSection, NtProtectVirtualMemory) as well as the actual process creation routine (NtCreateUserProcess) and the resuming of the main thread of the new process at the end (NtResumeThread) will be invoked from the process which made the call to CreateProcessA/W. Of course all these NTDLL routines exist in kernel-mode memory really, but NTDLL is a gate-way from user-mode to kernel-mode.

    NtMapViewOfSection can be intercepted to replicate a user-mode variant of the PsSetLoadImageNotifyRoutine kernel-mode callback. This can be achieved by performing conditional statements in the callback routine to determine the flags for the memory (e.g. SEC_IMAGE and PAGE_EXECUTE_READWRITE flags or others which indicate it is an image and also executable). This can not only be used to intercept process creation attempts at an extremely early stage, but also for DLLs being loaded within a process.

    2. By "less feature-rich" I would assume they are talking about one technique being more efficient/effective than another, and that based on the configuration, one technique will be used over the other for functionality.

    3. Earlier when I mentioned FltRegisterFilter, the callback responsible for intercepting file-system requests, within the callback routines for these events you can block the action should you deem to as long as you are within the Pre operation callbacks. Similar to blocking with PsSetCreateProcessNotifyRoutine by setting the NTSTATUS error code to STATUS_ACCESS_DENIED, or returning non-STATUS_SUCCESS with the CmRegisterCallbackEx callback routine.

    4. By "blocking" the action you would be denying the request at an early stage (Pre operation) so it cannot continue and be successfully carried out. By "delaying" I assume they are referring to holding up the request so the user can make a decision via an alert or similar.

    You can definitely do it however I highly recommend you don't reverse engineer technology belonging to other companies. Depending on your country laws it may be legal to reverse engineer other people's software for research purposes, but almost all the time, using this research to your own benefit by stealing their work is illegal. You also need to watch out for trademark infringement, which is when you use something another company has already done and trademarked which is in the scope of your location, without their consent.

    Generally speaking, you can reverse with Interactive Disassembler (IDA) and debugging tools such as WinDbg. You'll need experience with Assembly for disassembly, C for pseudo-code generation, and kernel-mode debugging with WinDbg since you're talking about reverse engineering kernel-mode software.
     
    Zhou He and harlan4096 like this.
Loading...