From 6b381a214dd7bbb21a4eda0eba0c7250487ea15e Mon Sep 17 00:00:00 2001 From: "raidmax@live.com" Date: Mon, 6 Jul 2015 12:13:42 -0500 Subject: [PATCH] More memory reading changes. We're getting there. --- Admin/Command.cs | 2 +- Admin/File.cs | 34 ++++-- Admin/Main.cs | 19 +++- Admin/Manager.cs | 77 ++++++++++--- Admin/RCON.cs | 9 +- Admin/Server.cs | 274 +++++++++++---------------------------------- Admin/Utilities.cs | 203 ++++++++++++++++++++++++++++++++- Admin/WebFront.cs | 40 +++---- 8 files changed, 395 insertions(+), 263 deletions(-) diff --git a/Admin/Command.cs b/Admin/Command.cs index c4c559d1c..e8548348b 100644 --- a/Admin/Command.cs +++ b/Admin/Command.cs @@ -799,7 +799,7 @@ namespace IW4MAdmin public override void Execute(Event E) { String[] Response = E.Owner.RCON.addRCON(E.Data.Trim()); - if (Response.Length > 0) + if (Response != null && Response.Length > 0) E.Origin.Tell("Successfuly sent RCON command!"); } } diff --git a/Admin/File.cs b/Admin/File.cs index d6c96c445..43e04d031 100644 --- a/Admin/File.cs +++ b/Admin/File.cs @@ -17,12 +17,29 @@ namespace IW4MAdmin Directory.CreateDirectory(_Directory); if (!File.Exists(fileName)) - { - FileStream penis = File.Create(fileName); - penis.Close(); + { + try + { + FileStream penis = File.Create(fileName); + penis.Close(); + } + + catch + { + //Console.WriteLine("Unable to open log file for writing!"); + } + } + + try + { + Handle = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); + sze = Handle.BaseStream.Length; + } + + catch + { + //Console.WriteLine("Unable to open log file for writing!"); } - Handle = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); - sze = Handle.BaseStream.Length; } public file(String file, bool write) @@ -41,8 +58,11 @@ namespace IW4MAdmin public void Write(String line) { - writeHandle.WriteLine(line); - writeHandle.Flush(); + if (writeHandle != null) + { + writeHandle.WriteLine(line); + writeHandle.Flush(); + } } public String[] getParameters(int num) diff --git a/Admin/Main.cs b/Admin/Main.cs index 830352953..37f100f3c 100644 --- a/Admin/Main.cs +++ b/Admin/Main.cs @@ -11,6 +11,7 @@ namespace IW4MAdmin static public double Version = 0.91; static public double latestVersion; static public bool usingMemory = true; + static private Manager serverManager; static void Main(string[] args) { @@ -36,13 +37,14 @@ namespace IW4MAdmin monitorThread.Start(); } #endif - IW4MAdmin.Manager IW4MAdmin = new IW4MAdmin.Manager(); - IW4MAdmin.Init(); + IW4MAdmin.Manager serverManager = new IW4MAdmin.Manager(); + serverManager.Init(); - Console.WriteLine("IW4M Now Initialized! Visit http://127.0.0.1:1624 for server overview."); + if (serverManager.getServers() != null) + Console.WriteLine("IW4M Now Initialized! Visit http://127.0.0.1:1624 for server overview."); - IW4MAdmin_Web.WebFront frontEnd = new IW4MAdmin_Web.WebFront(); - frontEnd.Init(); + //IW4MAdmin_Web.WebFront frontEnd = new IW4MAdmin_Web.WebFront(serverManager.getServers()); + //frontEnd.Init(); } #if DEBUG static void setupConfig() @@ -68,12 +70,17 @@ namespace IW4MAdmin } #endif - static String checkUpdate() + static private String checkUpdate() { Connection Ver = new Connection("http://raidmax.org/IW4M/Admin/version.php"); return Ver.Read(); } + static public List getServers() + { + return serverManager.getServers(); + } + #if DEBUG static List checkConfig() { diff --git a/Admin/Manager.cs b/Admin/Manager.cs index b1d280819..136d6e460 100644 --- a/Admin/Manager.cs +++ b/Admin/Manager.cs @@ -14,15 +14,27 @@ namespace IW4MAdmin private List Servers; private SortedDictionary ThreadList; private List activePIDs; + private Log mainLog; public Manager() { ThreadList = new SortedDictionary(); + file logFile = new file("IW4MAdmin_ApplicationLog.log"); + mainLog = new Log(logFile, Log.Level.All, 0); } public void Init() { activePIDs = getCurrentIW4MProcesses(); + + if (activePIDs.Count == 0) + { + mainLog.Write("No viable IW4M instances detected.", Log.Level.All); + mainLog.Write("Shutting Down...", Log.Level.All); + Utilities.Wait(5); + return; + } + Servers = loadServers(); foreach (Server S in Servers) @@ -31,12 +43,16 @@ namespace IW4MAdmin Thread IW4MServerThread = new Thread(IW4MServer.Monitor); ThreadList.Add(IW4MServer.pID(), IW4MServerThread); IW4MServerThread.Start(); + + //mainLog.Write("Now monitoring the server running on port " + IW4MServer.getPort(), Log.Level.All); } while (true) { + List defunctServers = new List(); lock (Servers) { + foreach (Server S in Servers) { if (S == null) @@ -50,22 +66,34 @@ namespace IW4MAdmin Defunct.Abort(); ThreadList[S.pID()] = null; } + mainLog.Write("Server with PID #" + S.pID() + " no longer appears to be running.", Log.Level.All); activePIDs.Remove(S.pID()); + defunctServers.Add(S); } } } + + foreach (Server S in defunctServers) + Servers.Remove(S); + defunctServers = null; + scanForNewServers(); Utilities.Wait(5); } } + public List getServers() + { + return Servers; + } + private void scanForNewServers() { List newProcesses = getCurrentIW4MProcesses(); - foreach (int pID in activePIDs) + foreach (int pID in newProcesses) { bool newProcess = true; - foreach (int I in newProcesses) + foreach (int I in activePIDs) { if (I == pID) newProcess = false; @@ -73,12 +101,16 @@ namespace IW4MAdmin if (newProcess) { - Server S = loadIndividualServer(pID); - Servers.Add(S); - Thread IW4MServerThread = new Thread(S.Monitor); - ThreadList.Add(pID, IW4MServerThread); - IW4MServerThread.Start(); + if (!ThreadList.ContainsKey(pID)) + { + Server S = loadIndividualServer(pID); + Servers.Add(S); + Thread IW4MServerThread = new Thread(S.Monitor); + ThreadList.Add(pID, IW4MServerThread); + mainLog.Write("New server dectected on port " + S.getPort(), Log.Level.All); + IW4MServerThread.Start(); + } } } @@ -88,14 +120,19 @@ namespace IW4MAdmin { if (pID > 0) { - Process P = Process.GetProcessById(pID); - if (P.ProcessName.Length == 0) + try + { + Process P = Process.GetProcessById(pID); + return true; + } + + catch (System.ArgumentException) { return false; - Console.WriteLine("Server with PID #" + pID + " doesn't seem to be running anymore"); } - return true; + } + return false; } @@ -141,12 +178,24 @@ namespace IW4MAdmin IntPtr Handle = OpenProcess(0x10, false, pID); if (Handle != null) { + int timeWaiting = 0; + bool sv_running = false; + int sv_runningPtr = Utilities.getIntFromPointer(0x1AD7934, (int)Handle) + 0x10; // where the dvar_t struct is stored + the offset for current value + + while(!sv_running) // server is still booting up + { + sv_running = Utilities.getBoolFromPointer(sv_runningPtr, (int)Handle); + Utilities.Wait(1); + timeWaiting++; + + if (timeWaiting > 60) // don't want to get stuck waiting forever if the server is frozen + return null; + } + dvar net_ip = Utilities.getDvar(0x64A1DF8, (int)Handle); dvar net_port = Utilities.getDvar(0x64A3004, (int)Handle); - // unfortunately this needs to be updated for every iw4m build :/ - dvar rcon_password = Utilities.getDvar(0x1120CC3C, (int)Handle); - return new Server(Dns.GetHostAddresses(net_ip.current)[1].ToString(), Convert.ToInt32(net_port.current), rcon_password.current, (int)Handle, pID); + return new Server(net_ip.current, Convert.ToInt32(net_port.current), "", (int)Handle, pID); } return null; diff --git a/Admin/RCON.cs b/Admin/RCON.cs index 528a59a7d..b0acd754d 100644 --- a/Admin/RCON.cs +++ b/Admin/RCON.cs @@ -18,9 +18,9 @@ namespace IW4MAdmin public RCON(Server I) { - sv_connection = new UdpClient(); - sv_connection.Client.SendTimeout = 1000; - sv_connection.Client.ReceiveTimeout = 1000; + //sv_connection = new UdpClient(); + // sv_connection.Client.SendTimeout = 1000; + //sv_connection.Client.ReceiveTimeout = 1000; Instance = I; toSend = new Queue(); } @@ -112,7 +112,8 @@ namespace IW4MAdmin if (toSend.Count > 0) { RCON_Request Current = toSend.Peek(); - Current.Response = responseSendRCON(Current.Request); + //Current.Response = responseSendRCON(Current.Request); + Utilities.executeCommand(Instance.pID(), Current.Request); toSend.Dequeue(); Utilities.Wait(0.567); } diff --git a/Admin/Server.cs b/Admin/Server.cs index d14cf329a..a2c82ad5e 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -19,7 +19,6 @@ namespace IW4MAdmin Handle = H; IP = address; Port = port; - rcon_pass = password; clientnum = 0; RCON = new RCON(this); logFile = new file("admin_" + port + ".log", true); @@ -528,6 +527,31 @@ namespace IW4MAdmin } } + public void executeCommand(String CMD) + { + if (CMD.ToLower() == "map_restart" || CMD.ToLower() == "map_rotate") + return; + + else if (CMD.ToLower().Substring(0, 4) == "map ") + { + backupRotation = getDvar("sv_mapRotation").current; + backupTimeLimit = Convert.ToInt32(getDvar("scr_" + Gametype + "_timelimit").current); + Utilities.executeCommand(PID, "sv_maprotation map " + CMD.ToLower().Substring(4, CMD.Length-4)); + Utilities.executeCommand(PID, "scr_" + Gametype + "_timelimit 0.001"); + Utilities.Wait(1); + Utilities.executeCommand(PID, "scr_" + Gametype + "_timelimit " + backupTimeLimit); + } + + else + Utilities.executeCommand(PID, CMD); + + } + + private dvar getDvar(String DvarName) + { + return Utilities.getDvarValue(PID, DvarName); + } + [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); @@ -562,6 +586,9 @@ namespace IW4MAdmin Utilities.Wait(10); return; } + + + #if DEBUG //Thread to handle polling server for IP's Thread statusUpdate = new Thread(new ThreadStart(pollServer)); @@ -784,197 +811,38 @@ namespace IW4MAdmin } } #endif - - //Vital RCON commands to establish log file and server name. May need to cleanup in the future -#if USINGMEMORY - private bool initializeBasics() - { - dvar map = Utilities.getDvar(0x2098DDC, Handle); - - String mapOut; - - mapname = map.current; - - dvar sv_hostname = Utilities.getDvar(0x2098D98, Handle); - hostname = sv_hostname.current; - - dvar shortversion = Utilities.getDvar(0x1AD79D0, Handle); - IW_Ver = shortversion.current; - - dvar party_maxplayers = Utilities.getDvar(0x1080998, Handle); - maxClients = Convert.ToInt32(party_maxplayers.current); - - dvar g_gametype = Utilities.getDvar(0x1AD7934, Handle); - Gametype = g_gametype.current; - - // skipping website b/c dynamically allocated ( we will pick it up on maprotate ) - } -#else private bool intializeBasics() { try - { - String[] infoResponse = RCON.addRCON("getstatus"); - - if (infoResponse == null || infoResponse.Length < 2) - { - Log.Write("Could not get server status!", Log.Level.All); - hostname = "Offline"; // for the web front - return false; - } + { + // basic info dvars + hostname = Utilities.stripColors(getDvar("sv_hostname").current); + mapname = getDvar("mapname").current; + IW_Ver = getDvar("shortversion").current; + maxClients = Convert.ToInt32(getDvar("party_maxplayers").current); + Gametype = getDvar("g_gametype").current; - infoResponse = infoResponse[1].Split('\\'); - Dictionary infoResponseDict = new Dictionary(); + // important log variables + Basepath = getDvar("fs_basepath").current; + Mod = getDvar("fs_game").current; + logPath = getDvar("g_log").current; + //int logSync = Convert.ToInt32(getDvar("g_logSync").current); - for (int i = 0; i < infoResponse.Length; i++) - { - if (i%2 == 0 || infoResponse[i] == String.Empty) - continue; - infoResponseDict.Add(infoResponse[i], infoResponse[i+1]); - } + if (Mod == String.Empty) + logPath = Basepath + '\\' + "m2demo" + '\\' + logPath; + else + logPath = Basepath + '\\' + Mod + '\\' + logPath; - mapname = infoResponseDict["mapname"]; - try - { - mapname = maps.Find(m => m.Name.Equals(mapname)).Alias; - } - - catch(Exception) - { - Log.Write(mapname + " doesn't appear to be in the maps.cfg", Log.Level.Debug); - } - - hostname = Utilities.stripColors(infoResponseDict["sv_hostname"]); - IW_Ver = infoResponseDict["shortversion"]; - maxClients = Convert.ToInt32(infoResponseDict["sv_maxclients"]); - Gametype = infoResponseDict["g_gametype"]; - - try - { - Website = infoResponseDict["_website"]; - } - - catch (Exception) - { - Website = "this server's website"; - Log.Write("Seems not to have website specified", Log.Level.Debug); - } - - String[] p = RCON.addRCON("fs_basepath"); - - if (p == null) - { - Log.Write("Could not obtain basepath!", Log.Level.All); - return false; - } - - p = p[1].Split('"'); - Basepath = p[3].Substring(0, p[3].Length - 2).Trim(); - p = null; - //END - - //get fs_game - p = RCON.addRCON("fs_game"); - - if (p == null) - { - Log.Write("Could not obtain mod path!", Log.Level.All); - return false; - } - - p = p[1].Split('"'); - Mod = p[3].Substring(0, p[3].Length - 2).Trim().Replace('/', '\\'); - p = null; - - //END - - //get g_log - p = RCON.addRCON("g_log"); - - if (p == null) - { - Log.Write("Could not obtain log path!", Log.Level.All); - return false; - } - - if (p.Length < 4) - { - Thread.Sleep(FLOOD_TIMEOUT); - Log.Write("Server does not appear to have map loaded. Please map_rotate", Log.Level.All); - return false; - } - - p = p[1].Split('"'); - string log = p[3].Substring(0, p[3].Length - 2).Trim(); - p = null; - - //END - - //get g_logsync - p = RCON.addRCON("g_logsync"); - - if (p == null) - { - Log.Write("Could not obtain log sync status!", Log.Level.All); - return false; - } - - - p = p[1].Split('"'); - int logsync = Convert.ToInt32(p[3].Substring(0, p[3].Length - 2).Trim()); - p = null; - - if (logsync != 1) - RCON.addRCON("g_logsync 1"); - //END - - //get iw4m_onelog - p = RCON.addRCON("iw4m_onelog"); - - if (p[0] == String.Empty || p[1].Length < 15) - { - Log.Write("Could not obtain iw4m_onelog value!", Log.Level.All); - return false; - } - - p = p[1].Split('"'); - string onelog = p[3].Substring(0, p[3].Length - 2).Trim(); - p = null; - //END - - if (Mod == String.Empty || onelog == "1") - logPath = Basepath + '\\' + "m2demo" + '\\' + log; - else - logPath = Basepath + '\\' + Mod + '\\' + log; - - if (!File.Exists(logPath)) - { - Log.Write("Gamelog does not exist!", Log.Level.All); - return false; - } - - logFile = new file(logPath); - Log.Write("Log file is " + logPath, Log.Level.Debug); - - //get players ip's - p = RCON.addRCON("status"); - if (p == null) - { - Log.Write("Unable to get initial player list!", Log.Level.Debug); + if (!File.Exists(logPath)) + { + Log.Write("Gamelog does not exist!", Log.Level.All); return false; - } - - lastPoll = DateTime.Now; + } -#if DEBUG - /* System.Net.FtpWebRequest tmp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(""); - tmp.Credentials = new System.Net.NetworkCredential("*", "*"); - System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream(); - String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/ - //logPath = "games_old.log"; -#endif - Log.Write("Now monitoring " + this.getName(), Log.Level.All); - return true; + logFile = new file(logPath); + Log.Write("Log file is " + logPath, Log.Level.Production); + Log.Write("Now monitoring " + this.getName(), Log.Level.Production); + return true; } catch (Exception E) { @@ -982,21 +850,10 @@ namespace IW4MAdmin return false; } } -#endif + //Process any server event public bool processEvent(Event E) { - -#if DEBUG - /*if (E.Type == Event.GType.Connect) // this is anow handled by memory :) - { - if (E.Origin == null) - Log.Write("Connect event triggered, but no client is detected!", Log.Level.Debug); - addPlayer(E.Origin); - return true; - }*/ -#endif - if (E.Type == Event.GType.Connect) { return true; @@ -1134,6 +991,8 @@ namespace IW4MAdmin if (E.Type == Event.GType.MapChange) { Log.Write("New map loaded - " + clientnum + " active players", Log.Level.Debug); + executeCommand("sv_mapRotation " + backupRotation); + executeCommand("scr_" + Gametype + "_timelimit " + backupTimeLimit); Dictionary infoResponseDict = new Dictionary(); String[] infoResponse = E.Data.Split('\\'); @@ -1215,14 +1074,7 @@ namespace IW4MAdmin public void Tell(String Message, Player Target) { if (Target.getClientNum() > -1) - { -#if DEBUG - RCON.addRCON("tell " + Target.getClientNum() + " " + Message + "^7"); - -#else RCON.addRCON("tellraw " + Target.getClientNum() + " " + Message + "^7"); // I fixed tellraw :> -#endif - } } public void Kick(String Message, Player Target) @@ -1269,13 +1121,11 @@ namespace IW4MAdmin { clientDB.removeBan(Target.getID(), Target.getIP()); - - for (int i = 0; i < IW4MAdmin.Program.Servers.Count; i++) - IW4MAdmin.Program.Servers[i].Bans = IW4MAdmin.Program.Servers[i].clientDB.getBans(); - Player P = clientDB.getPlayer(Target.getID(), -1); P.setLevel(Player.Permission.User); clientDB.updatePlayer(P); + + Bans = clientDB.getBans(); return true; } } @@ -1292,7 +1142,7 @@ namespace IW4MAdmin public void mapRotate(int delay) { Utilities.Wait(delay); - RCON.addRCON("map_rotate"); + executeCommand("map_rotate"); } public void tempBan(String Message, Player Target) @@ -1302,12 +1152,12 @@ namespace IW4MAdmin public void mapRotate() { - RCON.addRCON("map_rotate"); + mapRotate(0); } - public void Map(String map) + public void Map(String mapName) { - RCON.addRCON("map " + map); + executeCommand("map " + mapName); } public String Wisdom() @@ -1531,6 +1381,8 @@ namespace IW4MAdmin private DateTime lastWebChat; private int Handle; private int PID; + private String backupRotation; + private int backupTimeLimit; //Will probably move this later public Dictionary statusPlayers; diff --git a/Admin/Utilities.cs b/Admin/Utilities.cs index a5c929aa1..968662065 100644 --- a/Admin/Utilities.cs +++ b/Admin/Utilities.cs @@ -315,12 +315,72 @@ namespace IW4MAdmin return "a very long time"; } + [Flags] + public enum ProcessAccessFlags : uint + { + Terminate = 0x00000001, + CreateThread = 0x00000002, + VMOperation = 0x00000008, + VMRead = 0x00000010, + VMWrite = 0x00000020, + DupHandle = 0x00000040, + SetInformation = 0x00000200, + QueryInformation = 0x00000400, + Synchronize = 0x00100000, + All = 0x001F0FFF + } + + [Flags] + public enum AllocationType + { + Commit = 0x00001000, + Reserve = 0x00002000, + Decommit = 0x00004000, + Release = 0x00008000, + Reset = 0x00080000, + TopDown = 0x00100000, + WriteWatch = 0x00200000, + Physical = 0x00400000, + LargePages = 0x20000000 + } + + [Flags] + public enum MemoryProtection + { + NoAccess = 0x0001, + ReadOnly = 0x0002, + ReadWrite = 0x0004, + WriteCopy = 0x0008, + Execute = 0x0010, + ExecuteRead = 0x0020, + ExecuteReadWrite = 0x0040, + ExecuteWriteCopy = 0x0080, + GuardModifierflag = 0x0100, + NoCacheModifierflag = 0x0200, + WriteCombineModifierflag = 0x0400 + } + [DllImport("kernel32.dll")] - public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); + public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll")] public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); + [DllImport("kernel32.dll")] + public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); + + [DllImport("kernel32.dll")] + static extern bool TerminateThread(IntPtr hThread, uint dwExitCode); + + [DllImport("kernel32.dll")] + public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect); + + [DllImport("kernel32.dll")] + public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId); + + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize, AllocationType type); + public static dvar getDvar(int Location, int Handle) { int numberRead = 0; @@ -363,6 +423,29 @@ namespace IW4MAdmin return dvar_actual; } + public static int getDvarCurrentAddress(int Location, int Handle) + { + int numberRead = 0; + Byte[] Buff = new Byte[72]; + Byte[] Ptr = new Byte[4]; + + ReadProcessMemory(Handle, Location, Ptr, Ptr.Length, ref numberRead); // get location of dvar + + ReadProcessMemory(Handle, (int)BitConverter.ToUInt32(Ptr, 0), Buff, Buff.Length, ref numberRead); // read dvar memory + + dvar_t dvar_raw = Helpers.ReadStruct(Buff); // get the dvar struct + + int current = (int)dvar_raw.current; + + return current; + } + + public static void setDvar(int Location, int Handle, String Value) + { + UIntPtr bytesWritten = UIntPtr.Zero; + WriteProcessMemory((IntPtr)Handle, (IntPtr)Location, Encoding.ASCII.GetBytes(Value), (uint)Value.Length, out bytesWritten); + } + public static String getStringFromPointer(int Location, int Handle) { int numberRead = 0; @@ -391,6 +474,124 @@ namespace IW4MAdmin return BitConverter.ToInt32(Buff, 0); } + public static Boolean getBoolFromPointer(int Location, int Handle) + { + int numberRead = 0; + Byte[] Buff = new Byte[1]; + + ReadProcessMemory(Handle, Location, Buff, Buff.Length, ref numberRead); + + return BitConverter.ToBoolean(Buff, 0); + } + + public static void executeCommand(int pID, String Command) + { + IntPtr ProcessHandle = OpenProcess(ProcessAccessFlags.All, false, pID); + IntPtr memoryForCMDName = allocateAndWrite(Encoding.ASCII.GetBytes(Command + "\0"), ProcessHandle); + uint threadID; + + if (memoryForCMDName == IntPtr.Zero) + return; + + // set the dvar's current value pointer to our desired command + setDvarCurrentPtr((IntPtr)0x2098D9C, memoryForCMDName, ProcessHandle); + + // assembly instruction to execute the command we want stored in `surogate` dvar + byte[] executeCMD = { + 0x55, 0x8B, 0xEC, 0x51, 0xC7, 0x45, 0xFC, // --------------------------------------------- + 0x9C, 0x8D, 0x09, 0x02, 0x8B, 0x45, 0xFC, // dvar_t** dvarWithCMD = (dvar_t**)(0x2098D9C); + 0x8B, 0x08, 0x8B, 0x51, 0x10, 0x52, 0x6A, + 0x00, 0x6A, 0x00, 0xFF, 0x15, 0x1C, 0x53, // Cmd_ExecuteSingleCommand(0, 0, (*dvarWithCMD)->current.string ); + 0x11, 0x10, 0x83, 0xC4, 0x0C, 0x8B, 0xE5, // --------------------------------------------- + 0x5D, 0xC3 + }; + + // allocate the memory for the assembly command and write it + IntPtr codeAllocation = allocateAndWrite(executeCMD, ProcessHandle); + if (codeAllocation == IntPtr.Zero) + return; + + // create our thread that executes command :) + Console.WriteLine(codeAllocation.ToString("X8")); + IntPtr ThreadHandle = CreateRemoteThread(ProcessHandle, IntPtr.Zero, 0, codeAllocation, IntPtr.Zero, 0, out threadID); + + // cleanup + if (!VirtualFree(codeAllocation, (UIntPtr)executeCMD.Length, AllocationType.Decommit)) + Thread.Sleep(1); + if (!VirtualFree(memoryForCMDName, (UIntPtr)Command.Length + 1, AllocationType.Decommit)) + Thread.Sleep(1); + } + + public static IntPtr allocateAndWrite(Byte[] Data, IntPtr ProcessHandle) + { + UIntPtr bytesWritten; + IntPtr AllocatedMemory = VirtualAllocEx(ProcessHandle, IntPtr.Zero, (uint)Data.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite); + if (!WriteProcessMemory(ProcessHandle, AllocatedMemory, Data, (uint)Data.Length, out bytesWritten)) + { + Console.WriteLine("UNABLE TO WRITE PROCESS MEMORY!"); + return IntPtr.Zero; + } + + if ((int)bytesWritten != Data.Length) + return IntPtr.Zero; + else + return AllocatedMemory; + } + + public static bool setDvarCurrentPtr(IntPtr DvarAddress, IntPtr ValueAddress, IntPtr ProcessHandle) + { + int locationOfCurrentPtr = getIntFromPointer((int)DvarAddress, (int)ProcessHandle) + 0x10; + Byte[] newTextPtr = BitConverter.GetBytes((int)ValueAddress); + UIntPtr bytesWritten; + if (!WriteProcessMemory(ProcessHandle, (IntPtr)locationOfCurrentPtr, newTextPtr, (uint)newTextPtr.Length, out bytesWritten)) + return false; + if (newTextPtr.Length != (int)bytesWritten) + return false; + return true; + } + + public static dvar getDvarValue(int pID, String DVAR) + { + uint threadID = 0; + + IntPtr ProcessHandle = OpenProcess(ProcessAccessFlags.All, false, pID); + + IntPtr memoryForDvarName = allocateAndWrite(Encoding.ASCII.GetBytes(DVAR + "\0"), ProcessHandle); + if (memoryForDvarName == IntPtr.Zero) + Console.WriteLine("UNABLE TO ALLOCATE MEMORY FOR DVAR NAME"); + + setDvarCurrentPtr((IntPtr)0x2098D9C, memoryForDvarName, ProcessHandle); + + byte[] copyDvarValue = { + 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x08, // ----------------------------------------------- + 0xC7, 0x45, 0xFC, 0x9C, 0x8D, 0x09, // dvar_t** surogateDvar = (dvar_t**)(0x2098D9C); + 0x02, 0x8B, 0x45, 0xFC, 0x8B, 0x08, // + 0x8B, 0x51, 0x10, 0x52, 0xFF, 0x15, // dvar_t *newDvar = Dvar_FindVar((*surogateDvar)->current.string); + 0x6C, 0x53, 0x11, 0x10, 0x83, 0xC4, // + 0x04, 0x89, 0x45, 0xF8, 0x83, 0x7D, // if (newDvar) + 0xF8, 0x00, 0x74, 0x0B, 0x8B, 0x45, // + 0xFC, 0x8B, 0x08, 0x8B, 0x55, 0xF8, // (*surogateDvar)->current.integer = (int)newDvar; + 0x89, 0x51, 0x10, 0x8B, 0xE5, 0x5D, // ----------------------------------------------- + 0xC3 + }; + + IntPtr codeAllocation = allocateAndWrite(copyDvarValue, ProcessHandle); + + if (codeAllocation == IntPtr.Zero) + Console.WriteLine("UNABLE TO ALLOCATE MEMORY FOR CODE"); + + IntPtr ThreadHandle = CreateRemoteThread(ProcessHandle, IntPtr.Zero, 0, codeAllocation, IntPtr.Zero, 0, out threadID); + + if (!VirtualFree(codeAllocation, UIntPtr.Zero, AllocationType.Release)) + Thread.Sleep(1); + if (!VirtualFree(memoryForDvarName, UIntPtr.Zero, AllocationType.Release)) + Thread.Sleep(1); + + int dvarLoc = getIntFromPointer(0x2098D9C, (int)ProcessHandle); + //int ptrToOurDvar = getIntFromPointer(dvarLoc +, (int)ProcessHandle); + return getDvar(dvarLoc + 0x10, (int)ProcessHandle); + } + public static String timesConnected(int connection) { String Prefix = String.Empty; diff --git a/Admin/WebFront.cs b/Admin/WebFront.cs index 990856f44..9d468f2b5 100644 --- a/Admin/WebFront.cs +++ b/Admin/WebFront.cs @@ -8,7 +8,7 @@ using Kayak; using Kayak.Http; using System.Net; - +#if DEBUG namespace IW4MAdmin_Web { class Client @@ -32,6 +32,8 @@ namespace IW4MAdmin_Web class WebFront { + private List Servers; + public enum Page { main, @@ -40,9 +42,9 @@ namespace IW4MAdmin_Web player } - public WebFront() + public WebFront(List curServers) { - + Servers = curServers; } public void Init() @@ -87,19 +89,18 @@ namespace IW4MAdmin_Web switch (input) { case "SERVERS": - var Servers = IW4MAdmin.Program.Servers; int cycleFix = 0; - for (int i = 0; i < Servers.Count; i++) + foreach (IW4MAdmin.Server S in IW4MAdmin.Program.getServers()) { StringBuilder players = new StringBuilder(); - if (Servers[i].getClientNum() < 1) + if (S.getClientNum() < 1) players.Append("

No Players

"); else { int count = 0; - double currentPlayers = Servers[i].statusPlayers.Count; + double currentPlayers = S.statusPlayers.Count; - foreach (IW4MAdmin.Player P in Servers[i].getPlayers()) + foreach (IW4MAdmin.Player P in S.getPlayers()) { if (P == null) continue; @@ -119,7 +120,7 @@ namespace IW4MAdmin_Web } } - players.AppendFormat("{2}", i, P.getDBID(), IW4MAdmin.Utilities.nameHTMLFormatted(P)); + players.AppendFormat("{2}", S.pID(), P.getDBID(), IW4MAdmin.Utilities.nameHTMLFormatted(P)); if (count % 2 != 0) { @@ -144,10 +145,10 @@ namespace IW4MAdmin_Web {5}
", - Servers[i].getName(), Servers[i].getMap(), Servers[i].getClientNum() + "/" + Servers[i].getMaxClients(), IW4MAdmin.Utilities.gametypeLocalized(Servers[i].getGametype()), i, players.ToString()); - buffer.AppendFormat("
", i, '\"'); - if (Servers[i].getClientNum() > 0) - buffer.AppendFormat("
", i, '\"'); + S.getName(), S.getMap(), S.getClientNum() + "/" + S.getMaxClients(), IW4MAdmin.Utilities.gametypeLocalized(S.getGametype()), S.pID(), players.ToString()); + buffer.AppendFormat("
", S.pID(), '\"'); + if (S.getClientNum() > 0) + buffer.AppendFormat("
", server.pID(), '\"'); buffer.Append("
"); } return buffer.ToString(); @@ -155,7 +156,7 @@ namespace IW4MAdmin_Web return "IW4M Administration"; case "BANS": buffer.Append(""); - int totalBans = IW4MAdmin.Program.Servers[0].Bans.Count; + int totalBans = IW4MAdmin.Program.getServers()[0].Bans.Count; int range; int start = Pagination*30; cycleFix = 0; @@ -170,7 +171,7 @@ namespace IW4MAdmin_Web List Bans = new List(); if (totalBans > 0) - Bans = IW4MAdmin.Program.Servers[0].Bans.GetRange(start, range).OrderByDescending(x => x.getTime()).ToList(); + Bans = IW4MAdmin.Program.getServers()[0].Bans.GetRange(start, range).OrderByDescending(x => x.getTime()).ToList(); else Bans.Add(new IW4MAdmin.Ban("No Bans", "0", "0", DateTime.Now, "")); @@ -185,8 +186,8 @@ namespace IW4MAdmin_Web if (Bans[i] == null) continue; - IW4MAdmin.Player P = IW4MAdmin.Program.Servers[0].clientDB.getPlayer(Bans[i].getID(), -1); - IW4MAdmin.Player B = IW4MAdmin.Program.Servers[0].clientDB.getPlayer(Bans[i].getBanner(), -1); + IW4MAdmin.Player P = IW4MAdmin.Program.getServers()[0].clientDB.getPlayer(Bans[i].getID(), -1); + IW4MAdmin.Player B = IW4MAdmin.Program.getServers()[0].clientDB.getPlayer(Bans[i].getBanner(), -1); if (P == null) P = new IW4MAdmin.Player("Unknown", "n/a", 0, 0, 0, "Unknown", 0, ""); @@ -212,8 +213,8 @@ namespace IW4MAdmin_Web } } buffer.Append("

"); - - buffer.Append(parsePagination(server, IW4MAdmin.Program.Servers[0].Bans.Count, 30, Pagination, "bans")); + + buffer.Append(parsePagination(server, IW4MAdmin.Program.getServers()[0].Bans.Count, 30, Pagination, "bans")); return buffer.ToString(); case "PAGE": buffer.Append("
"); @@ -662,3 +663,4 @@ namespace IW4MAdmin_Web } } } +#endif \ No newline at end of file