diff --git a/CRT/gen_wrapper.sh b/CRT/gen_wrapper.sh index d383d56..4e26162 100755 --- a/CRT/gen_wrapper.sh +++ b/CRT/gen_wrapper.sh @@ -57,11 +57,19 @@ while read -r line; do STATICS="${STATICS}\nstatic ${fnname}_t _${fnname} = NULL;" INITS=$(cat < +#ifdef __cplusplus +#define _KERNEL_MODE 1 +#include "obfuscate.hpp" + +extern "C" { +#endif EOF echo "${TYPEDEFS}" echo "${STATICS}" @@ -127,3 +141,10 @@ cat < +#ifdef __cplusplus +#define _KERNEL_MODE 1 +#include "obfuscate.hpp" + +extern "C" { +#endif typedef NTSTATUS NTAPI (*ObOpenObjectByPointer_t) (_In_ PVOID obj, _In_ ULONG HandleAttributes, _In_ PACCESS_STATE PassedAccessState, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_TYPE objType, _In_ KPROCESSOR_MODE AccessMode, _Out_ PHANDLE Handle); typedef NTSTATUS NTAPI (*MmCopyMemory_t) (_In_ PVOID TargetAddress, _In_ PVOID SourceAddress, _In_ SIZE_T NumberOfBytes, _In_ ULONG Flags, _Out_ PSIZE_T NumberOfBytesTransferred); @@ -27,67 +33,139 @@ int __cdecl ntdll_zw_functions (void) int retval = 0; UNICODE_STRING fnName; +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"ObOpenObjectByPointer")); +#else RtlInitUnicodeString(&fnName, L"ObOpenObjectByPointer"); - _ObOpenObjectByPointer = MmGetSystemRoutineAddress(&fnName); +#endif + _ObOpenObjectByPointer = (ObOpenObjectByPointer_t)MmGetSystemRoutineAddress(&fnName); if (_ObOpenObjectByPointer == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine ObOpenObjectByPointer not found.")); +#else DbgPrint("%s\n", "System routine ObOpenObjectByPointer not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"MmCopyMemory")); +#else RtlInitUnicodeString(&fnName, L"MmCopyMemory"); - _MmCopyMemory = MmGetSystemRoutineAddress(&fnName); +#endif + _MmCopyMemory = (MmCopyMemory_t)MmGetSystemRoutineAddress(&fnName); if (_MmCopyMemory == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine MmCopyMemory not found.")); +#else DbgPrint("%s\n", "System routine MmCopyMemory not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"MmCopyVirtualMemory")); +#else RtlInitUnicodeString(&fnName, L"MmCopyVirtualMemory"); - _MmCopyVirtualMemory = MmGetSystemRoutineAddress(&fnName); +#endif + _MmCopyVirtualMemory = (MmCopyVirtualMemory_t)MmGetSystemRoutineAddress(&fnName); if (_MmCopyVirtualMemory == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine MmCopyVirtualMemory not found.")); +#else DbgPrint("%s\n", "System routine MmCopyVirtualMemory not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"RtlLookupFunctionEntry")); +#else RtlInitUnicodeString(&fnName, L"RtlLookupFunctionEntry"); - _RtlLookupFunctionEntry = MmGetSystemRoutineAddress(&fnName); +#endif + _RtlLookupFunctionEntry = (RtlLookupFunctionEntry_t)MmGetSystemRoutineAddress(&fnName); if (_RtlLookupFunctionEntry == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine RtlLookupFunctionEntry not found.")); +#else DbgPrint("%s\n", "System routine RtlLookupFunctionEntry not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"ZwTraceControl")); +#else RtlInitUnicodeString(&fnName, L"ZwTraceControl"); - _ZwTraceControl = MmGetSystemRoutineAddress(&fnName); +#endif + _ZwTraceControl = (ZwTraceControl_t)MmGetSystemRoutineAddress(&fnName); if (_ZwTraceControl == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine ZwTraceControl not found.")); +#else DbgPrint("%s\n", "System routine ZwTraceControl not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"ZwTraceEvent")); +#else RtlInitUnicodeString(&fnName, L"ZwTraceEvent"); - _ZwTraceEvent = MmGetSystemRoutineAddress(&fnName); +#endif + _ZwTraceEvent = (ZwTraceEvent_t)MmGetSystemRoutineAddress(&fnName); if (_ZwTraceEvent == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine ZwTraceEvent not found.")); +#else DbgPrint("%s\n", "System routine ZwTraceEvent not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"ZwQueryVirtualMemory")); +#else RtlInitUnicodeString(&fnName, L"ZwQueryVirtualMemory"); - _ZwQueryVirtualMemory = MmGetSystemRoutineAddress(&fnName); +#endif + _ZwQueryVirtualMemory = (ZwQueryVirtualMemory_t)MmGetSystemRoutineAddress(&fnName); if (_ZwQueryVirtualMemory == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine ZwQueryVirtualMemory not found.")); +#else DbgPrint("%s\n", "System routine ZwQueryVirtualMemory not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"ZwProtectVirtualMemory")); +#else RtlInitUnicodeString(&fnName, L"ZwProtectVirtualMemory"); - _ZwProtectVirtualMemory = MmGetSystemRoutineAddress(&fnName); +#endif + _ZwProtectVirtualMemory = (ZwProtectVirtualMemory_t)MmGetSystemRoutineAddress(&fnName); if (_ZwProtectVirtualMemory == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine ZwProtectVirtualMemory not found.")); +#else DbgPrint("%s\n", "System routine ZwProtectVirtualMemory not found."); +#endif retval++; } +#ifdef __cplusplus + RtlInitUnicodeString(&fnName, skCrypt(L"ZwQuerySystemInformation")); +#else RtlInitUnicodeString(&fnName, L"ZwQuerySystemInformation"); - _ZwQuerySystemInformation = MmGetSystemRoutineAddress(&fnName); +#endif + _ZwQuerySystemInformation = (ZwQuerySystemInformation_t)MmGetSystemRoutineAddress(&fnName); if (_ZwQuerySystemInformation == NULL) { +#ifdef __cplusplus + DbgPrint(skCrypt("%s\n"), skCrypt("System routine ZwQuerySystemInformation not found.")); +#else DbgPrint("%s\n", "System routine ZwQuerySystemInformation not found."); +#endif retval++; } @@ -208,3 +286,7 @@ NTSTATUS NTAPI WrapperZwQuerySystemInformation (_In_ int SystemInformationClass, { return _ZwQuerySystemInformation (SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); } + +#ifdef __cplusplus +}; +#endif diff --git a/CRT/obfuscate.hpp b/CRT/obfuscate.hpp new file mode 100644 index 0000000..5522aad --- /dev/null +++ b/CRT/obfuscate.hpp @@ -0,0 +1,163 @@ +#pragma once + +/*____________________________________________________________________________________________________________ + +Original Author: skadro +Github: https://github.com/skadro-official +License: See end of file + +skCrypter + Compile-time, Usermode + Kernelmode, safe and lightweight string crypter library for C++11+ + + *Not removing this part is appreciated* +____________________________________________________________________________________________________________*/ + +#ifdef _KERNEL_MODE + namespace std + { + // STRUCT TEMPLATE remove_reference + template + struct remove_reference { + using type = _Ty; + }; + + template + struct remove_reference<_Ty&> { + using type = _Ty; + }; + + template + struct remove_reference<_Ty&&> { + using type = _Ty; + }; + + template + using remove_reference_t = typename remove_reference<_Ty>::type; + + // STRUCT TEMPLATE remove_const + template + struct remove_const { // remove top-level const qualifier + using type = _Ty; + }; + + template + struct remove_const { + using type = _Ty; + }; + + template + using remove_const_t = typename remove_const<_Ty>::type; + } +#else + #include +#endif + +namespace skc +{ + template + using clean_type = typename std::remove_const_t>; + + template + class skCrypter + { + public: + __forceinline constexpr skCrypter(T* data) + { + crypt(data); + } + + __forceinline T* get() + { + return _storage; + } + + __forceinline int size() // (w)char count + { + return _size; + } + + __forceinline char key() + { + return _key1; + } + + __forceinline T* encrypt() + { + if (!isEncrypted()) + crypt(_storage); + + return _storage; + } + + __forceinline T* decrypt() + { + if (isEncrypted()) + crypt(_storage); + + return _storage; + } + + __forceinline bool isEncrypted() + { + return _storage[_size - 1] != 0; + } + + __forceinline void clear() // set full storage to 0 + { + for (int i = 0; i < _size; i++) + { + _storage[i] = 0; + } + } + + __forceinline operator T* () + { + decrypt(); + + return _storage; + } + + private: + __forceinline constexpr void crypt(T* data) + { + for (int i = 0; i < _size; i++) + { + _storage[i] = data[i] ^ (_key1 + i % (1 + _key2)); + } + } + + T _storage[_size]{}; + }; +} + +#define skCrypt(str) skCrypt_key(str, __TIME__[4], __TIME__[7]) +#define skCrypt_key(str, key1, key2) []() { \ + constexpr static auto crypted = skc::skCrypter \ + >((skc::clean_type*)str); \ + return crypted; }() + +/*________________________________________________________________________________ + +MIT License + +Copyright (c) 2020 skadro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +________________________________________________________________________________*/ diff --git a/Makefile.deps b/Makefile.deps index 0bf6256..d8d93b3 100644 --- a/Makefile.deps +++ b/Makefile.deps @@ -38,6 +38,24 @@ else endif @echo 'AR $@' +$(LIBCNATIVE_STATIC_LIB): $(LIBCNATIVE_OBJECTS) + $(Q)test -d '$(LIBCRT_BUILD_DIR)' || mkdir -p '$(LIBCRT_BUILD_DIR)' +ifneq ($(Q),@) + $(Q)$(AR) -rsv '$@' $(LIBCNATIVE_OBJECTS) +else + $(Q)$(AR) -rs '$@' $(LIBCNATIVE_OBJECTS) 2>/dev/null >/dev/null +endif + @echo 'AR $@' + +$(LIBCXXNATIVE_STATIC_LIB): $(LIBCXXNATIVE_OBJECTS) + $(Q)test -d '$(LIBCRT_BUILD_DIR)' || mkdir -p '$(LIBCRT_BUILD_DIR)' +ifneq ($(Q),@) + $(Q)$(AR) -rsv '$@' $(LIBCXXNATIVE_OBJECTS) +else + $(Q)$(AR) -rs '$@' $(LIBCXXNATIVE_OBJECTS) 2>/dev/null >/dev/null +endif + @echo 'AR $@' + $(LIBUSERCRT_STATIC_LIB): $(LIBUSERCRT_OBJECTS) $(Q)test -d '$(LIBCRT_BUILD_DIR)' || mkdir -p '$(LIBCRT_BUILD_DIR)' ifneq ($(Q),@) @@ -57,6 +75,11 @@ $(LIBCRT_BUILD_DIR)/ntdll_zw_functions$(NAME_SUFFIX).o: $(CC) $(DPP_ROOT)/CRT/nt $(Q)$(CC) -std=gnu99 $(CFLAGS) -c CRT/ntdll_zw_functions.c -o $@ @echo 'CC $@' +$(LIBCRT_BUILD_DIR)/ntdll_zw_functions$(NAME_SUFFIX).opp: $(CXX) $(DPP_ROOT)/CRT/ntdll_zw_functions.c + $(Q)test -d '$(LIBCRT_BUILD_DIR)' || mkdir -p '$(LIBCRT_BUILD_DIR)' + $(Q)$(CXX) $(CFLAGS) $(CXXFLAGS) -c CRT/ntdll_zw_functions.c -o $@ + @echo 'CXX $@' + $(LIBCRT_BUILD_DIR)/eastl_compat$(NAME_SUFFIX).opp: $(CXX) $(DPP_ROOT)/CRT/eastl_compat.cpp $(Q)test -d '$(LIBCRT_BUILD_DIR)' || mkdir -p '$(LIBCRT_BUILD_DIR)' $(Q)$(CXX) $(CFLAGS) -Wno-format -Wno-format-extra-args $(CXXFLAGS) $(EASTL_CXXFLAGS) -c CRT/eastl_compat.cpp -o $@ @@ -141,6 +164,8 @@ deps-build: \ $(EASTL_STATIC_LIB) \ $(LIBCRT_STATIC_LIB) \ $(LIBCXXRT_STATIC_LIB) \ + $(LIBCNATIVE_STATIC_LIB) \ + $(LIBCXXNATIVE_STATIC_LIB) \ $(LIBUSERCRT_STATIC_LIB) \ $(SIGNTOOL_PREFIX) diff --git a/Makefile.inc b/Makefile.inc index f0959d8..15a4bbb 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -94,15 +94,21 @@ EASTL_STATIC_LIB := $(DPP_ROOT)/$(EASTL_BUILDDIR)/libEASTL.a LIBCRT_BUILD_DIR := $(DPP_ROOT)/CRT-build LIBCRT_OBJECTS := \ - $(LIBCRT_BUILD_DIR)/kcrt$(NAME_SUFFIX).o \ - $(LIBCRT_BUILD_DIR)/ntdll_zw_functions$(NAME_SUFFIX).o + $(LIBCRT_BUILD_DIR)/kcrt$(NAME_SUFFIX).o LIBCXXRT_OBJECTS := \ $(LIBCRT_BUILD_DIR)/eastl_compat$(NAME_SUFFIX).opp \ $(LIBCRT_BUILD_DIR)/kcrt$(NAME_SUFFIX).opp \ $(LIBCRT_BUILD_DIR)/DriverThread$(NAME_SUFFIX).opp +LIBCNATIVE_OBJECTS := \ + $(LIBCRT_BUILD_DIR)/ntdll_zw_functions$(NAME_SUFFIX).o +LIBCXXNATIVE_OBJECTS := \ + $(LIBCRT_BUILD_DIR)/ntdll_zw_functions$(NAME_SUFFIX).opp + LIBUSERCRT_OBJECTS := $(LIBCRT_BUILD_DIR)/ucrt$(NAME_SUFFIX).opp $(LIBCRT_BUILD_DIR)/eastl_compat$(NAME_SUFFIX).opp LIBCRT_STATIC_LIB := $(LIBCRT_BUILD_DIR)/libcrt.a LIBCXXRT_STATIC_LIB := $(LIBCRT_BUILD_DIR)/libcxxrt.a +LIBCNATIVE_STATIC_LIB := $(LIBCRT_BUILD_DIR)/libcnative.a +LIBCXXNATIVE_STATIC_LIB := $(LIBCRT_BUILD_DIR)/libcxxnative.a LIBUSERCRT_STATIC_LIB := $(LIBCRT_BUILD_DIR)/libusercrt.a is_set = \ @@ -122,6 +128,8 @@ define CHECK_REQUIRED_PATHS $(call is_set,$(EASTL_STATIC_LIB),Makefile argument EASTL_STATIC_LIB missing) $(call is_set,$(LIBCRT_STATIC_LIB),Makefile argument LIBCRT_STATIC_LIB missing) $(call is_set,$(LIBCXXRT_STATIC_LIB),Makefile argument LIBCXXRT_STATIC_LIB missing) + $(call is_set,$(LIBCNATIVE_STATIC_LIB),Makefile argument LIBCNATIVE_STATIC_LIB missing) + $(call is_set,$(LIBCXXNATIVE_STATIC_LIB),Makefile argument LIBCXXNATIVE_STATIC_LIB missing) $(call is_set,$(LIBUSERCRT_STATIC_LIB),Makefile argument LIBUSERCRT_STATIC_LIB missing) $(call path_exists,$(CC)) $(call path_exists,$(CXX)) @@ -131,6 +139,8 @@ define CHECK_REQUIRED_PATHS $(call path_exists,$(EASTL_STATIC_LIB)) $(call path_exists,$(LIBCRT_STATIC_LIB)) $(call path_exists,$(LIBCXXRT_STATIC_LIB)) + $(call path_exists,$(LIBCNATIVE_STATIC_LIB)) + $(call path_exists,$(LIBCXXNATIVE_STATIC_LIB)) $(call path_exists,$(LIBUSERCRT_STATIC_LIB)) endef @@ -161,6 +171,7 @@ define LINK_C_KERNEL_TARGET -o '$(2)' \ $(1) \ $(LIBCRT_STATIC_LIB) \ + $(LIBCNATIVE_STATIC_LIB) \ $(DRIVER_LIBS) \ $(LDFLAGS_$(2)) @echo 'LD $(2)' @@ -194,6 +205,7 @@ define LINK_CPP_KERNEL_TARGET $(1) \ $(EASTL_STATIC_LIB) \ $(LIBCRT_STATIC_LIB) \ + $(LIBCXXNATIVE_STATIC_LIB) \ $(LIBCXXRT_STATIC_LIB) \ $(DRIVER_LIBS) \ $(LDFLAGS_$(2)) diff --git a/examples/dpp-example-cplusplus-EASTL.cpp b/examples/dpp-example-cplusplus-EASTL.cpp index c28806e..5c4322f 100644 --- a/examples/dpp-example-cplusplus-EASTL.cpp +++ b/examples/dpp-example-cplusplus-EASTL.cpp @@ -31,6 +31,15 @@ typedef struct } UNICODE_STRING; typedef UNICODE_STRING * PUNICODE_STRING; typedef int NTSTATUS; +#else +extern "C" NTSTATUS NTAPI ZwQuerySystemInformation(_In_ int SystemInformationClass, + _Inout_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength); +extern "C" NTSTATUS NTAPI WrapperZwQuerySystemInformation(_In_ int SystemInformationClass, + _Inout_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength); #endif struct GeneratorUint32 @@ -131,6 +140,27 @@ void more_stl_test() DbgPrint("fill_me size: %zu\n", fill_me.size()); } +#ifndef BUILD_USERMODE +static void zw_test() +{ + NTSTATUS ret; + ULONG memoryNeeded = 0; + + ret = ZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded); + if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded) + { + DbgPrint("ZwQuerySystemInformation failed with 0x%lX (memory needed: %lu)\n", ret, memoryNeeded); + } + + memoryNeeded = 0; + ret = WrapperZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded); + if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded) + { + DbgPrint("ZwQuerySystemInformation failed 0x%lX (memory needed: %lu)\n", ret, memoryNeeded); + } +} +#endif + extern "C" { #ifndef BUILD_USERMODE @@ -144,6 +174,7 @@ extern "C" DbgPrint("%s\n", "Hello ring0!"); + zw_test(); stl_test(); more_stl_test(); diff --git a/examples/dpp-example.c b/examples/dpp-example.c index 625cbde..cc32009 100644 --- a/examples/dpp-example.c +++ b/examples/dpp-example.c @@ -10,6 +10,14 @@ extern NTSTATUS NTAPI ZwProtectVirtualMemory(_In_ HANDLE ProcessHandle, _In_ _Out_ PULONG NumberOfBytesToProtect, _In_ ULONG NewAccessProtection, _Out_ PULONG OldAccessProtection); +extern NTSTATUS NTAPI ZwQuerySystemInformation(_In_ int SystemInformationClass, + _Inout_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength); +extern NTSTATUS NTAPI WrapperZwQuerySystemInformation(_In_ int SystemInformationClass, + _Inout_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength); int example_exception_handler(_In_ EXCEPTION_POINTERS * lpEP) { @@ -32,6 +40,25 @@ static void another_seh_test() __dpptryend(anotherseh); } +static void zw_test() +{ + NTSTATUS ret; + ULONG memoryNeeded = 0; + + ret = ZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded); + if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded) + { + DbgPrint("ZwQuerySystemInformation failed with 0x%lX (memory needed: %lu)\n", ret, memoryNeeded); + } + + memoryNeeded = 0; + ret = WrapperZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded); + if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded) + { + DbgPrint("ZwQuerySystemInformation failed 0x%lX (memory needed: %lu)\n", ret, memoryNeeded); + } +} + NTSTATUS DriverEntry(struct _DRIVER_OBJECT * DriverObject, PUNICODE_STRING RegistryPath) { (void)DriverObject; @@ -52,6 +79,7 @@ NTSTATUS DriverEntry(struct _DRIVER_OBJECT * DriverObject, PUNICODE_STRING Regis __dpptryend(testseh); another_seh_test(); + zw_test(); DbgPrint("%s\n", "Disable/Enable Interrupts!"); _disable(); diff --git a/update_obfuscate.sh b/update_obfuscate.sh new file mode 100755 index 0000000..1968608 --- /dev/null +++ b/update_obfuscate.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +MYDIR="$(dirname ${0})" +cd "${MYDIR}" + +wget 'https://raw.githubusercontent.com/skadro-official/skCrypter/master/files/skCrypter.h' -O 'CRT/obfuscate.hpp'