Code:
namespace D3Starter
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
internal class Program
{
private static IntPtr dwSharePatch = IntPtr.Zero;
private static IntPtr launcherPatch = IntPtr.Zero;
[DllImport("advapi32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TOKEN_PRIVILEGES newst, int len, IntPtr prev, IntPtr relen);
[SuppressUnmanagedCodeSecurity, DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool CloseHandle(IntPtr hHandle);
[DllImport("kernel32.dll")]
private static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
private static IntPtr FindPatchAddress(byte[] pattern, IntPtr hProc, IntPtr baseAddress)
{
try
{
byte[] lpBuffer = new byte[0x200000];
try
{
int num;
if (!ReadProcessMemory(hProc, baseAddress, lpBuffer, lpBuffer.Length, out num))
{
throw new Win32Exception();
}
}
catch (Win32Exception exception)
{
Console.WriteLine(exception.ToString());
return IntPtr.Zero;
}
for (int i = 0; i < lpBuffer.Length; i++)
{
for (int j = 0; j < pattern.Length; j++)
{
if (lpBuffer[i + j] != pattern[j])
{
continue;
}
}
return (baseAddress + i);
}
}
catch
{
}
return IntPtr.Zero;
}
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
private static void Main(string[] args)
{
int num2;
Console.Title = "D3 Starter";
Process.EnterDebugMode();
int result = 0;
string path = null;
string str2 = " -launch";
if ((args == null) || (args.Length == 0))
{
Console.WriteLine("Please enter the path to your D3 executable");
path = Console.ReadLine();
while (true)
{
Console.WriteLine("How many instances would you like to start? (Please enter a numerical value)");
if (int.TryParse(Console.ReadLine(), out result))
{
goto Label_00BA;
}
Console.WriteLine("Invalid input value!");
}
}
if (args.Length >= 1)
{
path = args[0];
result = 1;
}
if ((args.Length >= 2) && !int.TryParse(args[1], out result))
{
Console.WriteLine("Invalid input value for number of processes!");
Console.ReadLine();
return;
}
Label_00BA:
num2 = 0;
while (num2 < result)
{
Console.WriteLine("Launching a proccess now with the -launch argument");
StartGame(path, str2);
Thread.Sleep(0x5dc);
num2++;
}
Console.WriteLine(result + " game instances started! All done!");
Console.ReadLine();
}
[DllImport("kernel32.dll")]
internal static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);
private static void PatchProcess(IntPtr hProc, IntPtr baseAddress)
{
int num;
byte[] pattern = new byte[] {
0x8b, 0x5d, 0x10, 0x89, 0x85, 0xe4, 0xfb, 0xff, 0xff, 0x8b, 0x45, 0x20, 0x89, 0x8d, 0xe0, 0xfb,
0xff, 0xff, 0x56, 0x8d, 0x8d, 0x90
};
byte[] lpBuffer = new byte[] { 0x6a, 3, 0x5b };
if (dwSharePatch == IntPtr.Zero)
{
dwSharePatch = FindPatchAddress(pattern, hProc, baseAddress);
}
if (dwSharePatch != IntPtr.Zero)
{
Console.WriteLine("Patching file access at address: " + dwSharePatch.ToString("X"));
WriteProcessMemory(hProc, dwSharePatch, lpBuffer, lpBuffer.Length, out num);
}
byte[] buffer3 = new byte[] { 0xf6, 0x40, 5, 0x10, 0x75, 0x17 };
if (launcherPatch == IntPtr.Zero)
{
launcherPatch = FindPatchAddress(buffer3, hProc, baseAddress);
}
if (launcherPatch != IntPtr.Zero)
{
Console.WriteLine("Patching launcher startup at address: " + dwSharePatch.ToString("X"));
WriteProcessMemory(hProc, launcherPatch + 4, new byte[] { 0xeb }, 1, out num);
}
}
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);
private static void ResumeProcess(IntPtr thread, IntPtr proc)
{
if (thread != IntPtr.Zero)
{
ResumeThread(thread);
}
CloseHandle(thread);
CloseHandle(proc);
}
[DllImport("kernel32.dll")]
private static extern uint ResumeThread(IntPtr hThread);
private static void SetSeDebugPrivs(IntPtr procHandle)
{
IntPtr ptr;
LUID luid;
if (!OpenProcessToken(procHandle, 40, out ptr))
{
throw new Exception("OpenProcessToken");
}
if (!LookupPrivilegeValue(null, "SeDebugPrivilege", out luid))
{
throw new Exception("LookupPrivilegeValue");
}
TOKEN_PRIVILEGES newst = new TOKEN_PRIVILEGES
{
PrivilegeCount = 1,
Luid = luid,
Attributes = 2
};
Console.WriteLine("Val: " + AdjustTokenPrivileges(ptr, false, ref newst, 0, IntPtr.Zero, IntPtr.Zero));
}
public static void StartGame(string path, string args)
{
IntPtr ptr;
IntPtr ptr2;
if (!File.Exists(path))
{
Console.WriteLine("File does not exist: " + path);
}
Process process = StartProcess(path, args, out ptr, out ptr2);
if (process != null)
{
Console.WriteLine("Process ID " + process.Id + " started.");
Console.WriteLine("Patching process " + process.Id);
PatchProcess(ptr2, (IntPtr)0x81C29D);
Console.WriteLine("Resuming process " + process.Id);
ResumeProcess(ptr, ptr2);
}
else
{
Console.WriteLine("Could not create process for " + path);
}
}
private static Process StartProcess(string path, string arguments, out IntPtr hThread, out IntPtr hProc)
{
Process processById = null;
hThread = IntPtr.Zero;
hProc = IntPtr.Zero;
STARTUPINFO lpStartupInfo = new STARTUPINFO();
PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION();
if (CreateProcess(path, arguments, IntPtr.Zero, IntPtr.Zero, false, 4, IntPtr.Zero, null, ref lpStartupInfo, out lpProcessInformation))
{
hThread = lpProcessInformation.hThread;
processById = Process.GetProcessById((int)lpProcessInformation.dwProcessId);
hProc = OpenProcess(ProcessAccessFlags.SYNCHRONIZE | ProcessAccessFlags.PROCESS_QUERY_INFORMATION | ProcessAccessFlags.PROCESS_SET_INFORMATION | ProcessAccessFlags.PROCESS_VM_WRITE | ProcessAccessFlags.PROCESS_VM_READ | ProcessAccessFlags.PROCESS_VM_OPERATION | ProcessAccessFlags.PROCESS_CREATE_THREAD | ProcessAccessFlags.PROCESS_TERMINATE, false, processById.Id);
SetSeDebugPrivs(GetCurrentProcess());
SetSeDebugPrivs(hProc);
}
return processById;
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out int lpNumberOfBytesWritten);
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[Flags]
public enum ProcessAccessFlags
{
DELETE = 0x10000,
PROCESS_ALL_ACCESS = 0x1f0fff,
PROCESS_CREATE_PROCESS = 0x80,
PROCESS_CREATE_THREAD = 2,
PROCESS_DUP_HANDLE = 0x40,
PROCESS_QUERY_INFORMATION = 0x400,
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000,
PROCESS_SET_INFORMATION = 0x200,
PROCESS_SET_QUOTA = 0x100,
PROCESS_SUSPEND_RESUME = 0x800,
PROCESS_TERMINATE = 1,
PROCESS_VM_OPERATION = 8,
PROCESS_VM_READ = 0x10,
PROCESS_VM_WRITE = 0x20,
READ_CONTROL = 0x20000,
SYNCHRONIZE = 0x100000,
WRITE_DAC = 0x40000,
WRITE_OWNER = 0x80000
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public uint cb;
public short cbReserved2;
public uint dwFillAttribute;
public uint dwFlags;
public uint dwX;
public uint dwXCountChars;
public uint dwXSize;
public uint dwY;
public uint dwYCountChars;
public uint dwYSize;
public IntPtr hStdError;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public string lpDesktop;
public string lpReserved;
public IntPtr lpReserved2;
public string lpTitle;
public short wShowWindow;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
public uint PrivilegeCount;
public Program.LUID Luid;
public uint Attributes;
}
}
}