Skip to main content

Temporary Folders

Temporary folder isolation is a crucial protection mechanism that prevents players from using modified game clients or extensions to bypass ACHCE Client. By running game files from temporary storage that is deleted after each session, the system ensures that only verified, unmodified game assets are used.
While the current codebase shows the infrastructure for session management, the temporary folder implementation represents the intended design pattern for preventing persistent game modifications.

The Problem: Modified Game Clients

Game modifications pose a significant threat to fair gameplay. Common modification methods include:

HAC2 Release

A popular modification tool that allows players to:
  • Connect to servers without proper authentication
  • Bypass anti-cheat detection mechanisms
  • Use unauthorized game features
  • Modify game behavior at the file level

Chimera

Another modification framework that provides:
  • Custom game scripts and plugins
  • Network protocol modifications
  • Client-side advantage features
  • Anti-cheat bypass capabilities
Both HAC2 and Chimera are specifically mentioned in the project documentation as threats that temporary folder isolation is designed to prevent.

How Temporary Folders Solve the Problem

The temporary folder approach creates an isolated, ephemeral environment for game files:

Key Benefits

  1. Immutability: Original game files remain untouched
  2. Fresh Start: Each session begins with clean, verified files
  3. Modification Prevention: Changes are not persisted between sessions
  4. Controlled Environment: All game operations occur in monitored location

Implementation Architecture

Temporary Folder Creation

When ACHCE Client launches, it should create a unique temporary directory:
using System.IO;

public class TemporaryGameEnvironment
{
    private string tempFolderPath;
    private string gameInstallPath;
    
    public TemporaryGameEnvironment(string originalGamePath)
    {
        gameInstallPath = originalGamePath;
        
        // Create unique temporary folder
        string tempRoot = Path.GetTempPath();
        string uniqueFolderName = $"ACHCE_{Guid.NewGuid().ToString("N")}";
        tempFolderPath = Path.Combine(tempRoot, uniqueFolderName);
        
        Directory.CreateDirectory(tempFolderPath);
    }
    
    public string GetTempPath()
    {
        return tempFolderPath;
    }
}
Using Guid.NewGuid() ensures each session has a unique folder name, preventing conflicts if multiple instances run or previous cleanup failed.

File Copying Process

Critical game files must be copied to the temporary location:
public void CopyGameFiles()
{
    try
    {
        // Copy all game files to temporary folder
        CopyDirectory(gameInstallPath, tempFolderPath, true);
    }
    catch (Exception ex)
    {
        throw new Exception($"Failed to copy game files: {ex.Message}");
    }
}

private void CopyDirectory(string sourceDir, string destDir, bool recursive)
{
    DirectoryInfo dir = new DirectoryInfo(sourceDir);
    
    if (!dir.Exists)
    {
        throw new DirectoryNotFoundException($"Source directory not found: {sourceDir}");
    }
    
    // Create destination directory
    Directory.CreateDirectory(destDir);
    
    // Copy files
    foreach (FileInfo file in dir.GetFiles())
    {
        string targetFilePath = Path.Combine(destDir, file.Name);
        file.CopyTo(targetFilePath, false);
    }
    
    // Recursively copy subdirectories
    if (recursive)
    {
        foreach (DirectoryInfo subDir in dir.GetDirectories())
        {
            string newDestDir = Path.Combine(destDir, subDir.Name);
            CopyDirectory(subDir.FullName, newDestDir, true);
        }
    }
}

Game Launch from Temporary Location

After copying, launch the game from the temporary folder:
using System.Diagnostics;

public Process LaunchGame(string gameExecutable)
{
    string tempGamePath = Path.Combine(tempFolderPath, gameExecutable);
    
    if (!File.Exists(tempGamePath))
    {
        throw new FileNotFoundException($"Game executable not found: {tempGamePath}");
    }
    
    ProcessStartInfo startInfo = new ProcessStartInfo
    {
        FileName = tempGamePath,
        WorkingDirectory = tempFolderPath,
        UseShellExecute = false
    };
    
    Process gameProcess = Process.Start(startInfo);
    return gameProcess;
}
Set WorkingDirectory to the temporary folder to ensure the game loads assets from the isolated environment rather than the original installation directory.

Automatic Cleanup

The temporary folder must be deleted when the game session ends:
public void Cleanup()
{
    try
    {
        if (Directory.Exists(tempFolderPath))
        {
            // Delete folder and all contents
            Directory.Delete(tempFolderPath, true);
        }
    }
    catch (Exception ex)
    {
        // Log cleanup failure but don't crash
        LogError($"Failed to delete temporary folder: {ex.Message}");
    }
}

Integration with Session Management

The temporary folder lifecycle aligns with the database session tracking shown in Form1.cs:
// Form1.cs - Session start
private void PlayAcON()
{
    Player ply = new Player()
    {
        IP = IpPlayer,
    };
    
    // Register session in database
    var setter = client.Set("PlayerIpList/" + randomName, ply);
    
    // Initialize temporary folder environment
    var tempEnv = new TemporaryGameEnvironment(gameInstallPath);
    tempEnv.CopyGameFiles();
    tempEnv.LaunchGame("game.exe");
}

// Form1.cs - Session end
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    // Remove from database
    var result = client.Delete("PlayerIpList/" + randomName);
    
    // Clean up temporary files
    tempEnv.Cleanup();
}
The database cleanup code exists in the current implementation (Form1.cs:100-104), and temporary folder cleanup would follow the same pattern.

Security Considerations

File Verification

Before copying to the temporary folder, verify file integrity:
using System.Security.Cryptography;

public bool VerifyGameFile(string filePath, string expectedHash)
{
    using (var sha256 = SHA256.Create())
    {
        using (var stream = File.OpenRead(filePath))
        {
            byte[] hash = sha256.ComputeHash(stream);
            string fileHash = BitConverter.ToString(hash).Replace("-", "");
            return fileHash.Equals(expectedHash, StringComparison.OrdinalIgnoreCase);
        }
    }
}

Read-Only Files

Make copied files read-only to prevent runtime modifications:
private void SetFilesReadOnly(string directory)
{
    DirectoryInfo dirInfo = new DirectoryInfo(directory);
    
    foreach (FileInfo file in dirInfo.GetFiles("*", SearchOption.AllDirectories))
    {
        // Set read-only attribute
        file.Attributes |= FileAttributes.ReadOnly;
    }
}
While read-only attributes prevent simple modifications, determined attackers can still override permissions. This should be combined with runtime memory integrity checks.

Cleanup Guarantee

Ensure cleanup occurs even if the application crashes:
static class Program
{
    private static TemporaryGameEnvironment tempEnv;
    
    [STAThread]
    static void Main()
    {
        // Register cleanup on unexpected exit
        AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
        AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
        
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new ACHCE());
    }
    
    private static void OnProcessExit(object sender, EventArgs e)
    {
        tempEnv?.Cleanup();
    }
    
    private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        tempEnv?.Cleanup();
    }
}

Performance Optimization

Selective File Copying

Not all game files need to be copied. Optimize by copying only essentials:
private readonly string[] essentialFiles = new[]
{
    "game.exe",
    "config.ini",
    "*.dll",
    "maps/*.map",
    "saved/*.sav"
};

public void CopyEssentialFiles()
{
    foreach (string pattern in essentialFiles)
    {
        CopyFilesByPattern(gameInstallPath, tempFolderPath, pattern);
    }
}

Parallel Copying

For large game installations, use parallel copying:
using System.Threading.Tasks;

public async Task CopyGameFilesAsync()
{
    DirectoryInfo dir = new DirectoryInfo(gameInstallPath);
    FileInfo[] files = dir.GetFiles("*", SearchOption.AllDirectories);
    
    await Task.Run(() =>
    {
        Parallel.ForEach(files, file =>
        {
            string relativePath = file.FullName.Substring(gameInstallPath.Length + 1);
            string destPath = Path.Combine(tempFolderPath, relativePath);
            
            Directory.CreateDirectory(Path.GetDirectoryName(destPath));
            file.CopyTo(destPath, false);
        });
    });
}
For very large games, consider using symbolic links instead of copying:
using System.Runtime.InteropServices;

[DllImport("kernel32.dll")]
static extern bool CreateSymbolicLink(string lpSymlinkFileName, 
                                       string lpTargetFileName, 
                                       int dwFlags);

public void CreateSymbolicLinks()
{
    // Create symbolic links for large, static files
    // Copy only small, frequently modified files
}
Symbolic links reduce copy time but require administrator privileges and careful management to prevent modification of original files.

User Experience Considerations

Loading Indicators

Show progress while copying files:
public void CopyWithProgress(IProgress<int> progress)
{
    DirectoryInfo dir = new DirectoryInfo(gameInstallPath);
    FileInfo[] files = dir.GetFiles("*", SearchOption.AllDirectories);
    
    int totalFiles = files.Length;
    int copiedFiles = 0;
    
    foreach (FileInfo file in files)
    {
        // Copy file...
        copiedFiles++;
        
        int percentComplete = (copiedFiles * 100) / totalFiles;
        progress.Report(percentComplete);
    }
}
Integration with Form1’s loading animation:
// Form1.cs - Timer2_Tick shows loading animation
private void Timer2_Tick(object sender, EventArgs e)
{
    string texto = "/";
    int indice = 0;
    
    if (indice < texto.Length)
    {
        TextoCarga.Text += texto[indice];
        indice++;
    }
}
Replace the simple text animation with a progress bar that reflects actual file copying progress for better user feedback.

Disk Space Verification

Check available disk space before copying:
public bool HasSufficientDiskSpace()
{
    long requiredSpace = CalculateDirectorySize(gameInstallPath);
    
    DriveInfo tempDrive = new DriveInfo(Path.GetPathRoot(Path.GetTempPath()));
    long availableSpace = tempDrive.AvailableFreeSpace;
    
    // Require 10% extra space for safety margin
    return availableSpace > (requiredSpace * 1.1);
}

private long CalculateDirectorySize(string path)
{
    DirectoryInfo dir = new DirectoryInfo(path);
    return dir.GetFiles("*", SearchOption.AllDirectories)
              .Sum(file => file.Length);
}

Testing Temporary Folder Implementation

Unit Tests

[TestClass]
public class TemporaryFolderTests
{
    [TestMethod]
    public void TestFolderCreation()
    {
        var tempEnv = new TemporaryGameEnvironment(@"C:\GamePath");
        string tempPath = tempEnv.GetTempPath();
        
        Assert.IsTrue(Directory.Exists(tempPath), 
            "Temporary folder should be created");
        
        tempEnv.Cleanup();
        Assert.IsFalse(Directory.Exists(tempPath), 
            "Temporary folder should be deleted after cleanup");
    }
    
    [TestMethod]
    public void TestFileIsolation()
    {
        var tempEnv = new TemporaryGameEnvironment(@"C:\GamePath");
        tempEnv.CopyGameFiles();
        
        string tempFile = Path.Combine(tempEnv.GetTempPath(), "test.txt");
        File.WriteAllText(tempFile, "modified");
        
        string originalFile = @"C:\GamePath\test.txt";
        Assert.AreNotEqual(File.ReadAllText(tempFile), 
                          File.ReadAllText(originalFile),
                          "Modifications should not affect original files");
        
        tempEnv.Cleanup();
    }
}

Comparison with Other Approaches

File Monitoring: Watches for changes to game files in the original location.
  • Pros: No copying required, faster startup
  • Cons: Reactive rather than preventive, can be bypassed
Temporary Folders: Copies files to isolated location.
  • Pros: Proactive prevention, guarantees clean state
  • Cons: Slower startup, requires disk space
Virtual File System: Uses kernel driver to intercept file operations.
  • Pros: No copying, complete control over file access
  • Cons: Complex implementation, kernel-level risks
Temporary Folders: User-space file copying.
  • Pros: Simple, safe, no kernel drivers needed
  • Cons: Can be bypassed by modifying temp files
Containerization: Runs game in isolated container (Docker, Sandboxie).
  • Pros: Complete isolation, works for any application
  • Cons: High overhead, complex setup
Temporary Folders: Simple file copying approach.
  • Pros: Lightweight, easy to implement
  • Cons: Only isolates files, not entire process

Relationship to Other Protections

Temporary folders work synergistically with other ACHCE mechanisms:
  • TopMost Protection: Prevents opening tools to modify temp files during gameplay
  • Hardware ID: Ensures bans persist even if modified clients are eventually used
  • Database Tracking: Monitors which sessions might have encountered tampering attempts

Known Limitations

Temporary folder isolation has several limitations that should be understood:
  1. Memory Modifications: Does not prevent runtime memory injection
  2. Network Interception: Does not stop network protocol modifications
  3. Process Hooking: Does not prevent function hooking in game process
  4. Cleanup Failures: Orphaned folders may remain if cleanup fails

Mitigation Strategies

  • Combine with memory integrity checks
  • Implement network packet validation
  • Add periodic cleanup of old temporary folders
  • Use process monitoring to detect hooking attempts

Best Practices

1

Verify Before Copying

Always validate original game files before copying to temporary location
2

Use Unique Folder Names

Generate unique temporary folder names for each session to prevent conflicts
3

Implement Robust Cleanup

Ensure cleanup occurs even during crashes or unexpected termination
4

Monitor Disk Space

Check available disk space before creating temporary folders
5

Optimize Copy Performance

Use selective copying or parallel operations for large game installations

Summary

Temporary folder isolation is a powerful technique that:
  • Prevents persistent game modifications
  • Blocks modified client bypasses (HAC2, Chimera)
  • Ensures each session starts with verified files
  • Complements other anti-cheat mechanisms
The approach is particularly effective against:
  • File-based game modifications
  • Configuration tampering
  • Asset replacements
  • Persistent cheat installations
For maximum security, combine temporary folder isolation with runtime memory protection, network validation, and hardware-based player identification.

Build docs developers (and LLMs) love