More memory reading changes. We're getting there.

This commit is contained in:
raidmax@live.com 2015-07-06 12:13:42 -05:00
parent b8557fdb81
commit 6b381a214d
8 changed files with 395 additions and 263 deletions

View File

@ -799,7 +799,7 @@ namespace IW4MAdmin
public override void Execute(Event E) public override void Execute(Event E)
{ {
String[] Response = E.Owner.RCON.addRCON(E.Data.Trim()); 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!"); E.Origin.Tell("Successfuly sent RCON command!");
} }
} }

View File

@ -17,12 +17,29 @@ namespace IW4MAdmin
Directory.CreateDirectory(_Directory); Directory.CreateDirectory(_Directory);
if (!File.Exists(fileName)) if (!File.Exists(fileName))
{ {
FileStream penis = File.Create(fileName); try
penis.Close(); {
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) public file(String file, bool write)
@ -41,8 +58,11 @@ namespace IW4MAdmin
public void Write(String line) public void Write(String line)
{ {
writeHandle.WriteLine(line); if (writeHandle != null)
writeHandle.Flush(); {
writeHandle.WriteLine(line);
writeHandle.Flush();
}
} }
public String[] getParameters(int num) public String[] getParameters(int num)

View File

@ -11,6 +11,7 @@ namespace IW4MAdmin
static public double Version = 0.91; static public double Version = 0.91;
static public double latestVersion; static public double latestVersion;
static public bool usingMemory = true; static public bool usingMemory = true;
static private Manager serverManager;
static void Main(string[] args) static void Main(string[] args)
{ {
@ -36,13 +37,14 @@ namespace IW4MAdmin
monitorThread.Start(); monitorThread.Start();
} }
#endif #endif
IW4MAdmin.Manager IW4MAdmin = new IW4MAdmin.Manager(); IW4MAdmin.Manager serverManager = new IW4MAdmin.Manager();
IW4MAdmin.Init(); 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(); //IW4MAdmin_Web.WebFront frontEnd = new IW4MAdmin_Web.WebFront(serverManager.getServers());
frontEnd.Init(); //frontEnd.Init();
} }
#if DEBUG #if DEBUG
static void setupConfig() static void setupConfig()
@ -68,12 +70,17 @@ namespace IW4MAdmin
} }
#endif #endif
static String checkUpdate() static private String checkUpdate()
{ {
Connection Ver = new Connection("http://raidmax.org/IW4M/Admin/version.php"); Connection Ver = new Connection("http://raidmax.org/IW4M/Admin/version.php");
return Ver.Read(); return Ver.Read();
} }
static public List<Server> getServers()
{
return serverManager.getServers();
}
#if DEBUG #if DEBUG
static List<Server> checkConfig() static List<Server> checkConfig()
{ {

View File

@ -14,15 +14,27 @@ namespace IW4MAdmin
private List<Server> Servers; private List<Server> Servers;
private SortedDictionary<int, Thread> ThreadList; private SortedDictionary<int, Thread> ThreadList;
private List<int> activePIDs; private List<int> activePIDs;
private Log mainLog;
public Manager() public Manager()
{ {
ThreadList = new SortedDictionary<int, Thread>(); ThreadList = new SortedDictionary<int, Thread>();
file logFile = new file("IW4MAdmin_ApplicationLog.log");
mainLog = new Log(logFile, Log.Level.All, 0);
} }
public void Init() public void Init()
{ {
activePIDs = getCurrentIW4MProcesses(); 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(); Servers = loadServers();
foreach (Server S in Servers) foreach (Server S in Servers)
@ -31,12 +43,16 @@ namespace IW4MAdmin
Thread IW4MServerThread = new Thread(IW4MServer.Monitor); Thread IW4MServerThread = new Thread(IW4MServer.Monitor);
ThreadList.Add(IW4MServer.pID(), IW4MServerThread); ThreadList.Add(IW4MServer.pID(), IW4MServerThread);
IW4MServerThread.Start(); IW4MServerThread.Start();
//mainLog.Write("Now monitoring the server running on port " + IW4MServer.getPort(), Log.Level.All);
} }
while (true) while (true)
{ {
List<Server> defunctServers = new List<Server>();
lock (Servers) lock (Servers)
{ {
foreach (Server S in Servers) foreach (Server S in Servers)
{ {
if (S == null) if (S == null)
@ -50,22 +66,34 @@ namespace IW4MAdmin
Defunct.Abort(); Defunct.Abort();
ThreadList[S.pID()] = null; ThreadList[S.pID()] = null;
} }
mainLog.Write("Server with PID #" + S.pID() + " no longer appears to be running.", Log.Level.All);
activePIDs.Remove(S.pID()); activePIDs.Remove(S.pID());
defunctServers.Add(S);
} }
} }
} }
foreach (Server S in defunctServers)
Servers.Remove(S);
defunctServers = null;
scanForNewServers(); scanForNewServers();
Utilities.Wait(5); Utilities.Wait(5);
} }
} }
public List<Server> getServers()
{
return Servers;
}
private void scanForNewServers() private void scanForNewServers()
{ {
List<int> newProcesses = getCurrentIW4MProcesses(); List<int> newProcesses = getCurrentIW4MProcesses();
foreach (int pID in activePIDs) foreach (int pID in newProcesses)
{ {
bool newProcess = true; bool newProcess = true;
foreach (int I in newProcesses) foreach (int I in activePIDs)
{ {
if (I == pID) if (I == pID)
newProcess = false; newProcess = false;
@ -73,12 +101,16 @@ namespace IW4MAdmin
if (newProcess) 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) if (pID > 0)
{ {
Process P = Process.GetProcessById(pID); try
if (P.ProcessName.Length == 0) {
Process P = Process.GetProcessById(pID);
return true;
}
catch (System.ArgumentException)
{ {
return false; return false;
Console.WriteLine("Server with PID #" + pID + " doesn't seem to be running anymore");
} }
return true;
} }
return false; return false;
} }
@ -141,12 +178,24 @@ namespace IW4MAdmin
IntPtr Handle = OpenProcess(0x10, false, pID); IntPtr Handle = OpenProcess(0x10, false, pID);
if (Handle != null) 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_ip = Utilities.getDvar(0x64A1DF8, (int)Handle);
dvar net_port = Utilities.getDvar(0x64A3004, (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; return null;

View File

@ -18,9 +18,9 @@ namespace IW4MAdmin
public RCON(Server I) public RCON(Server I)
{ {
sv_connection = new UdpClient(); //sv_connection = new UdpClient();
sv_connection.Client.SendTimeout = 1000; // sv_connection.Client.SendTimeout = 1000;
sv_connection.Client.ReceiveTimeout = 1000; //sv_connection.Client.ReceiveTimeout = 1000;
Instance = I; Instance = I;
toSend = new Queue<RCON_Request>(); toSend = new Queue<RCON_Request>();
} }
@ -112,7 +112,8 @@ namespace IW4MAdmin
if (toSend.Count > 0) if (toSend.Count > 0)
{ {
RCON_Request Current = toSend.Peek(); RCON_Request Current = toSend.Peek();
Current.Response = responseSendRCON(Current.Request); //Current.Response = responseSendRCON(Current.Request);
Utilities.executeCommand(Instance.pID(), Current.Request);
toSend.Dequeue(); toSend.Dequeue();
Utilities.Wait(0.567); Utilities.Wait(0.567);
} }

View File

@ -19,7 +19,6 @@ namespace IW4MAdmin
Handle = H; Handle = H;
IP = address; IP = address;
Port = port; Port = port;
rcon_pass = password;
clientnum = 0; clientnum = 0;
RCON = new RCON(this); RCON = new RCON(this);
logFile = new file("admin_" + port + ".log", true); 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")] [DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
@ -562,6 +586,9 @@ namespace IW4MAdmin
Utilities.Wait(10); Utilities.Wait(10);
return; return;
} }
#if DEBUG #if DEBUG
//Thread to handle polling server for IP's //Thread to handle polling server for IP's
Thread statusUpdate = new Thread(new ThreadStart(pollServer)); Thread statusUpdate = new Thread(new ThreadStart(pollServer));
@ -784,197 +811,38 @@ namespace IW4MAdmin
} }
} }
#endif #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() private bool intializeBasics()
{ {
try try
{ {
String[] infoResponse = RCON.addRCON("getstatus"); // basic info dvars
hostname = Utilities.stripColors(getDvar("sv_hostname").current);
if (infoResponse == null || infoResponse.Length < 2) mapname = getDvar("mapname").current;
{ IW_Ver = getDvar("shortversion").current;
Log.Write("Could not get server status!", Log.Level.All); maxClients = Convert.ToInt32(getDvar("party_maxplayers").current);
hostname = "Offline"; // for the web front Gametype = getDvar("g_gametype").current;
return false;
}
infoResponse = infoResponse[1].Split('\\'); // important log variables
Dictionary<String, String> infoResponseDict = new Dictionary<string, string>(); 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 (Mod == String.Empty)
{ logPath = Basepath + '\\' + "m2demo" + '\\' + logPath;
if (i%2 == 0 || infoResponse[i] == String.Empty) else
continue; logPath = Basepath + '\\' + Mod + '\\' + logPath;
infoResponseDict.Add(infoResponse[i], infoResponse[i+1]);
}
mapname = infoResponseDict["mapname"]; if (!File.Exists(logPath))
try {
{ Log.Write("Gamelog does not exist!", Log.Level.All);
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);
return false; return false;
} }
lastPoll = DateTime.Now;
#if DEBUG logFile = new file(logPath);
/* System.Net.FtpWebRequest tmp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(""); Log.Write("Log file is " + logPath, Log.Level.Production);
tmp.Credentials = new System.Net.NetworkCredential("*", "*"); Log.Write("Now monitoring " + this.getName(), Log.Level.Production);
System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream(); return true;
String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/
//logPath = "games_old.log";
#endif
Log.Write("Now monitoring " + this.getName(), Log.Level.All);
return true;
} }
catch (Exception E) catch (Exception E)
{ {
@ -982,21 +850,10 @@ namespace IW4MAdmin
return false; return false;
} }
} }
#endif
//Process any server event //Process any server event
public bool processEvent(Event E) 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) if (E.Type == Event.GType.Connect)
{ {
return true; return true;
@ -1134,6 +991,8 @@ namespace IW4MAdmin
if (E.Type == Event.GType.MapChange) if (E.Type == Event.GType.MapChange)
{ {
Log.Write("New map loaded - " + clientnum + " active players", Log.Level.Debug); Log.Write("New map loaded - " + clientnum + " active players", Log.Level.Debug);
executeCommand("sv_mapRotation " + backupRotation);
executeCommand("scr_" + Gametype + "_timelimit " + backupTimeLimit);
Dictionary<String, String> infoResponseDict = new Dictionary<String, String>(); Dictionary<String, String> infoResponseDict = new Dictionary<String, String>();
String[] infoResponse = E.Data.Split('\\'); String[] infoResponse = E.Data.Split('\\');
@ -1215,14 +1074,7 @@ namespace IW4MAdmin
public void Tell(String Message, Player Target) public void Tell(String Message, Player Target)
{ {
if (Target.getClientNum() > -1) if (Target.getClientNum() > -1)
{
#if DEBUG
RCON.addRCON("tell " + Target.getClientNum() + " " + Message + "^7");
#else
RCON.addRCON("tellraw " + Target.getClientNum() + " " + Message + "^7"); // I fixed tellraw :> RCON.addRCON("tellraw " + Target.getClientNum() + " " + Message + "^7"); // I fixed tellraw :>
#endif
}
} }
public void Kick(String Message, Player Target) public void Kick(String Message, Player Target)
@ -1269,13 +1121,11 @@ namespace IW4MAdmin
{ {
clientDB.removeBan(Target.getID(), Target.getIP()); 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); Player P = clientDB.getPlayer(Target.getID(), -1);
P.setLevel(Player.Permission.User); P.setLevel(Player.Permission.User);
clientDB.updatePlayer(P); clientDB.updatePlayer(P);
Bans = clientDB.getBans();
return true; return true;
} }
} }
@ -1292,7 +1142,7 @@ namespace IW4MAdmin
public void mapRotate(int delay) public void mapRotate(int delay)
{ {
Utilities.Wait(delay); Utilities.Wait(delay);
RCON.addRCON("map_rotate"); executeCommand("map_rotate");
} }
public void tempBan(String Message, Player Target) public void tempBan(String Message, Player Target)
@ -1302,12 +1152,12 @@ namespace IW4MAdmin
public void mapRotate() 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() public String Wisdom()
@ -1531,6 +1381,8 @@ namespace IW4MAdmin
private DateTime lastWebChat; private DateTime lastWebChat;
private int Handle; private int Handle;
private int PID; private int PID;
private String backupRotation;
private int backupTimeLimit;
//Will probably move this later //Will probably move this later
public Dictionary<String, Player> statusPlayers; public Dictionary<String, Player> statusPlayers;

View File

@ -315,12 +315,72 @@ namespace IW4MAdmin
return "a very long time"; 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")] [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")] [DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); 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) public static dvar getDvar(int Location, int Handle)
{ {
int numberRead = 0; int numberRead = 0;
@ -363,6 +423,29 @@ namespace IW4MAdmin
return dvar_actual; 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<dvar_t>(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) public static String getStringFromPointer(int Location, int Handle)
{ {
int numberRead = 0; int numberRead = 0;
@ -391,6 +474,124 @@ namespace IW4MAdmin
return BitConverter.ToInt32(Buff, 0); 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) public static String timesConnected(int connection)
{ {
String Prefix = String.Empty; String Prefix = String.Empty;

View File

@ -8,7 +8,7 @@ using Kayak;
using Kayak.Http; using Kayak.Http;
using System.Net; using System.Net;
#if DEBUG
namespace IW4MAdmin_Web namespace IW4MAdmin_Web
{ {
class Client class Client
@ -32,6 +32,8 @@ namespace IW4MAdmin_Web
class WebFront class WebFront
{ {
private List<IW4MAdmin.Server> Servers;
public enum Page public enum Page
{ {
main, main,
@ -40,9 +42,9 @@ namespace IW4MAdmin_Web
player player
} }
public WebFront() public WebFront(List<IW4MAdmin.Server> curServers)
{ {
Servers = curServers;
} }
public void Init() public void Init()
@ -87,19 +89,18 @@ namespace IW4MAdmin_Web
switch (input) switch (input)
{ {
case "SERVERS": case "SERVERS":
var Servers = IW4MAdmin.Program.Servers;
int cycleFix = 0; int cycleFix = 0;
for (int i = 0; i < Servers.Count; i++) foreach (IW4MAdmin.Server S in IW4MAdmin.Program.getServers())
{ {
StringBuilder players = new StringBuilder(); StringBuilder players = new StringBuilder();
if (Servers[i].getClientNum() < 1) if (S.getClientNum() < 1)
players.Append("<h2>No Players</h2>"); players.Append("<h2>No Players</h2>");
else else
{ {
int count = 0; 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) if (P == null)
continue; continue;
@ -119,7 +120,7 @@ namespace IW4MAdmin_Web
} }
} }
players.AppendFormat("<td><a href='/{0}/{1}/userip/?player'>{2}</a></td>", i, P.getDBID(), IW4MAdmin.Utilities.nameHTMLFormatted(P)); players.AppendFormat("<td><a href='/{0}/{1}/userip/?player'>{2}</a></td>", S.pID(), P.getDBID(), IW4MAdmin.Utilities.nameHTMLFormatted(P));
if (count % 2 != 0) if (count % 2 != 0)
{ {
@ -144,10 +145,10 @@ namespace IW4MAdmin_Web
<table cellpadding='0' cellspacing='0' class='players'> <table cellpadding='0' cellspacing='0' class='players'>
{5} {5}
</table>", </table>",
Servers[i].getName(), Servers[i].getMap(), Servers[i].getClientNum() + "/" + Servers[i].getMaxClients(), IW4MAdmin.Utilities.gametypeLocalized(Servers[i].getGametype()), i, players.ToString()); S.getName(), S.getMap(), S.getClientNum() + "/" + S.getMaxClients(), IW4MAdmin.Utilities.gametypeLocalized(S.getGametype()), S.pID(), players.ToString());
buffer.AppendFormat("<div class='chatHistory' id='chatHistory_{0}'></div><script type='text/javascript'>$( document ).ready(function() {{ setInterval({1}loadChatMessages({0}, '#chatHistory_{0}'){1}, 2500); }});</script><div class='null' style='clear:both;'></div>", i, '\"'); buffer.AppendFormat("<div class='chatHistory' id='chatHistory_{0}'></div><script type='text/javascript'>$( document ).ready(function() {{ setInterval({1}loadChatMessages({0}, '#chatHistory_{0}'){1}, 2500); }});</script><div class='null' style='clear:both;'></div>", S.pID(), '\"');
if (Servers[i].getClientNum() > 0) if (S.getClientNum() > 0)
buffer.AppendFormat("<form class='chatOutFormat' action={1}javascript:chatRequest({0}, 'chatEntry_{0}'){1}><input class='chatFormat_text' type='text' placeholder='Enter a message...' id='chatEntry_{0}'/><input class='chatFormat_submit' type='submit'/></form>", i, '\"'); buffer.AppendFormat("<form class='chatOutFormat' action={1}javascript:chatRequest({0}, 'chatEntry_{0}'){1}><input class='chatFormat_text' type='text' placeholder='Enter a message...' id='chatEntry_{0}'/><input class='chatFormat_submit' type='submit'/></form>", server.pID(), '\"');
buffer.Append("<hr/>"); buffer.Append("<hr/>");
} }
return buffer.ToString(); return buffer.ToString();
@ -155,7 +156,7 @@ namespace IW4MAdmin_Web
return "IW4M Administration"; return "IW4M Administration";
case "BANS": case "BANS":
buffer.Append("<table cellspacing=0 class=bans>"); buffer.Append("<table cellspacing=0 class=bans>");
int totalBans = IW4MAdmin.Program.Servers[0].Bans.Count; int totalBans = IW4MAdmin.Program.getServers()[0].Bans.Count;
int range; int range;
int start = Pagination*30; int start = Pagination*30;
cycleFix = 0; cycleFix = 0;
@ -170,7 +171,7 @@ namespace IW4MAdmin_Web
List<IW4MAdmin.Ban> Bans = new List<IW4MAdmin.Ban>(); List<IW4MAdmin.Ban> Bans = new List<IW4MAdmin.Ban>();
if (totalBans > 0) 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 else
Bans.Add(new IW4MAdmin.Ban("No Bans", "0", "0", DateTime.Now, "")); Bans.Add(new IW4MAdmin.Ban("No Bans", "0", "0", DateTime.Now, ""));
@ -185,8 +186,8 @@ namespace IW4MAdmin_Web
if (Bans[i] == null) if (Bans[i] == null)
continue; continue;
IW4MAdmin.Player P = IW4MAdmin.Program.Servers[0].clientDB.getPlayer(Bans[i].getID(), -1); IW4MAdmin.Player P = IW4MAdmin.Program.getServers()[0].clientDB.getPlayer(Bans[i].getID(), -1);
IW4MAdmin.Player B = IW4MAdmin.Program.Servers[0].clientDB.getPlayer(Bans[i].getBanner(), -1); IW4MAdmin.Player B = IW4MAdmin.Program.getServers()[0].clientDB.getPlayer(Bans[i].getBanner(), -1);
if (P == null) if (P == null)
P = new IW4MAdmin.Player("Unknown", "n/a", 0, 0, 0, "Unknown", 0, ""); P = new IW4MAdmin.Player("Unknown", "n/a", 0, 0, 0, "Unknown", 0, "");
@ -212,8 +213,8 @@ namespace IW4MAdmin_Web
} }
} }
buffer.Append("</table><hr/>"); buffer.Append("</table><hr/>");
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(); return buffer.ToString();
case "PAGE": case "PAGE":
buffer.Append("<div id=pages>"); buffer.Append("<div id=pages>");
@ -662,3 +663,4 @@ namespace IW4MAdmin_Web
} }
} }
} }
#endif