Hey folks,
I made this injector a long time ago and recently someone commented asking if I'd update it for Valofe S4L. Truth is, I don't really care about S4 anymore and haven't even tried this on the current client. I attempted to adapt it a few days ago but didn't test it at all. The logic in this was written years ago, so there's a decent chance it's detected.
Either way, I'm dropping the source here. Maybe someone finds it useful, wants to improve it.
⚠️ Use at your own risk. Detection is likely since this uses older techniques.
Features:
- Manual DLL injection via NtCreateThreadEx
- EAC Bypass was removed since it's useless
- Stealth techniques (basic debugger check, random console title [SO 2017 LOL])
- Console logging with colored output
- Auto-wait for target process (S4Client)[SHOULD BE CHANGED TO CLIENT_RELEASE.EXE IG]
- Basic cleanup and self-destruct mechanism[ SOO BASIC LOL]
Target Process: S4Client / S4Client.exe
DLL Name: anjaITC.dll (you can rename it in the source)
Source:
Code:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Security.Principal;
using System.Threading;
using System.IO;
using System.Text;
namespace SystemServiceHelper
{
class Program
{
[DllImport("ntdll.dll", EntryPoint = "NtCreateThreadEx")]
private static extern int NtCreateThreadEx(
out IntPtr hThread,
uint desiredAccess,
IntPtr objectAttributes,
IntPtr processHandle,
IntPtr startAddress,
IntPtr parameter,
bool createSuspended,
uint stackZeroBits,
uint sizeOfStack,
uint maximumStackSize,
IntPtr attributeList);
[DllImport("kernel32.dll", EntryPoint = "LoadLibraryW", CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibraryHidden(string lpFileName);
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_BASIC_INFORMATION
{
public IntPtr ExitStatus;
public IntPtr PebBaseAddress;
public IntPtr AffinityMask;
public IntPtr BasePriority;
public IntPtr UniqueProcessId;
public IntPtr InheritedFromUniqueProcessId;
}
[DllImport("ntdll.dll", EntryPoint = "NtQueryInformationProcess")]
private static extern int NtQueryInformationProcess(
IntPtr processHandle,
int processInformationClass,
ref PROCESS_BASIC_INFORMATION processInformation,
int processInformationLength,
out int returnLength);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
uint dwSize,
uint flAllocationType,
uint flProtect);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern IntPtr GetProcAddress(
IntPtr hModule,
string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr GetModuleHandle(
string lpModuleName);
private const uint PAGE_READWRITE = 0x04;
private const uint MEM_COMMIT = 0x00001000;
private const uint MEM_RESERVE = 0x00002000;
private const uint INFINITE = 0xFFFFFFFF;
private static readonly ConsoleColor DefaultColor = ConsoleColor.Gray;
private static readonly ConsoleColor SuccessColor = ConsoleColor.Green;
private static readonly ConsoleColor ErrorColor = ConsoleColor.Red;
private static readonly ConsoleColor WarningColor = ConsoleColor.Yellow;
static void Main(string[] args)
{
if (IsDebuggerPresent())
{
SelfDestruct();
return;
}
Console.Title = GenerateRandomTitle();
if (!IsElevated())
{
LogError("Administrator privileges required");
Thread.Sleep(2000);
Environment.Exit(1);
}
// Check for EAC
//if (IsEACRunning())
// {
// LogWarning("EAC detected - attempting bypass");
// BypassEAC();
// }
LogInfo("Waiting for game process...");
Process targetProcess = WaitForTargetProcess();
if (targetProcess == null)
{
LogError("Target process not found");
Thread.Sleep(3000);
return;
}
LogSuccess($"Found process: {targetProcess.ProcessName} [PID: {targetProcess.Id}]");
string dllPath = "anjaITC.dll"; // Change DLL Name
if (!File.Exists(dllPath))
{
LogError("Module not found");
Thread.Sleep(3000);
return;
}
if (ManualMap(targetProcess, dllPath))
{
LogSuccess("Injection completed successfully");
Cleanup();
}
else
{
LogError("Injection failed");
}
Thread.Sleep(2000);
}
#region Stealth Techniques
private static bool IsDebuggerPresent()
{
return Debugger.IsAttached;
}
private static void SelfDestruct()
{
try
{
File.Delete(Process.GetCurrentProcess().MainModule.FileName);
Environment.Exit(0);
}
catch { }
}
private static string GenerateRandomTitle()
{
string[] titles = {
"Windows Service Manager",
"System Configuration",
"Network Helper",
"Update Assistant"
};
return titles[new Random().Next(titles.Length)] + " v" +
new Random().Next(1, 5) + "." + new Random().Next(0, 9);
}
#endregion
[DllImport("kernel32.dll")]
private static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, int dwThreadId);
[DllImport("kernel32.dll")]
private static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(IntPtr hObject);
#endregion
#region Injection Methods
private static bool ManualMap(Process process, string dllPath)
{
IntPtr hProcess = IntPtr.Zero;
IntPtr pAllocatedMemory = IntPtr.Zero;
IntPtr hThread = IntPtr.Zero;
try
{
hProcess = OpenProcess(0x001F0FFF, false, process.Id);
if (hProcess == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
pAllocatedMemory = VirtualAllocEx(
hProcess,
IntPtr.Zero,
(uint)((dllPath.Length + 1) * 2),
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
if (pAllocatedMemory == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
byte[] bytes = Encoding.Unicode.GetBytes(dllPath);
UIntPtr bytesWritten;
if (!WriteProcessMemory(hProcess, pAllocatedMemory, bytes, (uint)bytes.Length, out bytesWritten))
throw new Win32Exception(Marshal.GetLastWin32Error());
IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
if (loadLibraryAddr == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
int status = NtCreateThreadEx(
out hThread,
0x1FFFFF,
IntPtr.Zero,
hProcess,
loadLibraryAddr,
pAllocatedMemory,
false,
0,
0,
0,
IntPtr.Zero);
if (hThread == IntPtr.Zero || status != 0)
throw new Exception($"NTSTATUS: 0x{status:X8}");
WaitForSingleObject(hThread, INFINITE);
return true;
}
catch (Exception ex)
{
LogError($"Injection error: {ex.Message}");
return false;
}
finally
{
if (hThread != IntPtr.Zero) CloseHandle(hThread);
if (pAllocatedMemory != IntPtr.Zero) VirtualFreeEx(hProcess, pAllocatedMemory, 0, 0x8000);
if (hProcess != IntPtr.Zero) CloseHandle(hProcess);
}
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint dwFreeType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
uint nSize,
out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
#endregion
#region Helper Methods
private static bool IsElevated()
{
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
}
private static Process WaitForTargetProcess()
{
string[] targetNames = { "S4Client", "S4Client.exe" };
int attempts = 0;
const int maxAttempts = 60;
while (attempts < maxAttempts)
{
foreach (string name in targetNames)
{
Process[] processes = Process.GetProcessesByName(name.Replace(".exe", ""));
if (processes.Length > 0)
return processes[0];
}
Thread.Sleep(1000);
attempts++;
}
return null;
}
private static void Cleanup()
{
try
{
Console.Clear();
}
catch { }
}
private static void LogInfo(string message)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] [INFO] {message}");
Console.ForegroundColor = DefaultColor;
}
private static void LogSuccess(string message)
{
Console.ForegroundColor = SuccessColor;
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] [SUCCESS] {message}");
Console.ForegroundColor = DefaultColor;
}
private static void LogWarning(string message)
{
Console.ForegroundColor = WarningColor;
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] [WARNING] {message}");
Console.ForegroundColor = DefaultColor;
}
private static void LogError(string message)
{
Console.ForegroundColor = ErrorColor;
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] [ERROR] {message}");
Console.ForegroundColor = DefaultColor;
}
#endregion
}
}
Feel free to fork, improve or do whatever with it. I’m not maintaining it anymore.
Peace.






