Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Direct syscalls implementation (2) #16

Merged
merged 2 commits into from Jan 12, 2024

Conversation

cdelafuente-r7
Copy link

This PR brings direct syscalls capability to the original Reflective DLL Injection library. This is a new implementation based on this first PR. This includes the logic to retrieve the syscall numbers using a technique similar to the one used in this evasion module. This is based on the assumption that the syscall numbers are sequential and can be deduced from the position of the related native API function in memory. The technique consists in selecting the system call function starting with Zw… from NTDLL exports and sorting them in ascending order of their memory addresses. The syscall number of one given native API function is simply its index in this array.

Also, this implementation uses a "trampoline" logic similar to what is used by RecycledGate to ensure that all the system calls go through ntdll.dll.

Only the following native API functions have been implemented with these techniques so far:

  • NtAllocateVirtualMemory
  • NtProtectVirtualMemory
  • NtFlushInstructionCache
  • NtLockVirtualMemory

These functions now replace the functions used by the original Reflective DLL Injection implementation.

This also supports x86, x64 and Wow64 architectures. Note that ARM is not supported.

So far, this has been tested successfully on the following systems:

  • Windows 11 x64
  • Windows 10 x64
  • Windows 7 x64 and x86
  • Windows Server 2019 x64
  • Windows Server 2016 x64
  • Windows Server 2012 x64
  • Windows Server 2008 R2 x64
  • Windows XP
  • Windows Vista SP2

Testing

You will need to open the solution with Visual Studio, select the Release configuration (Debug doesn't work for some reasons I haven't investigated yet) and select the platform x64 or Win32, according to your target OS. Note that Wow64 binaries are supported, so you can still run a x86 binary on a x64 architecture.

The build will generate an executable and a dll.
For a x86 build:

  • Release\inject.Win32.exe
  • Release\reflective_dll.Win32.dll

For a x64 build:

  • x64\Release\inject.x64.exe
  • x64\Release\reflective_dll.x64.dll

Note that both the executable and the dll need to be located in the same folder.

Executing the inject binary should inject the dll and pop up a Messagebox:

Screenshot 2023-10-04 at 22 06 00

TODO

Add a custom implementation of the following functions from kernel32.dll:

  • LoadLibraryA
  • GetProcAddress

These functions are used by the reflective loader. Getting rid of calls through kernel32.dll would certainly reduce the footprint.

} Syscall;

// TODO: Have a custom implementation of these function to avoid using Kernel32 and reduce the dependency issue.
#define UTILITY_FUNC_NB 2

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look like it's referenced anywhere. Can it be removed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, these are left over from the previous implementation I forgot to remove. Thanks!

dll/src/ReflectiveDll.c Outdated Show resolved Hide resolved
dll/src/ReflectiveLoader.c Outdated Show resolved Hide resolved
@smcintyre-r7
Copy link

Tested this out using the included PoC and validated the results using API Monitor. The results were as expected, the Direct Syscall implementation eliminated API invocations. The code also compiled without any issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
2 participants