Created
December 7, 2018 11:08
-
-
Save BigETI/d587b50d6935bc1238e919f15ac3b4f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using AngasalPI; | |
using Newtonsoft.Json; | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Net; | |
using System.Reflection; | |
using System.Text; | |
using System.Threading; | |
/// <summary> | |
/// Angasal SA:MP namespace | |
/// </summary> | |
namespace AngasalSAMP | |
{ | |
public class Plugin : IPlugin | |
{ | |
/// <summary> | |
/// Servers | |
/// </summary> | |
private List<SAMPServerData> servers; | |
/// <summary> | |
/// Webserver | |
/// </summary> | |
private IWebserver webserver; | |
/// <summary> | |
/// Name | |
/// </summary> | |
public string Name => "SA:MP browser"; | |
/// <summary> | |
/// Author | |
/// </summary> | |
public string Author => "Ethem Kurt"; | |
/// <summary> | |
/// Version | |
/// </summary> | |
public string Version | |
{ | |
get | |
{ | |
string ret = null; | |
try | |
{ | |
Assembly assembly = Assembly.GetExecutingAssembly(); | |
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); | |
ret = fvi.FileVersion; | |
} | |
catch (Exception e) | |
{ | |
((webserver == null) ? Console.Error : webserver.ErrorOutput).WriteLine(e); | |
} | |
if (ret == null) | |
{ | |
ret = "Unknown"; | |
} | |
return ret; | |
} | |
} | |
/// <summary> | |
/// Commands | |
/// </summary> | |
public ICommand[] Commands => null; | |
/// <summary> | |
/// Inject plugin | |
/// </summary> | |
/// <param name="pluginPath">Plugin path</param> | |
/// <param name="processHandle">Process handle</param> | |
/// <param name="loadLibraryW">LoadLibraryW function pointer</param> | |
private static void InjectPlugin(string pluginPath, IntPtr processHandle, IntPtr loadLibraryW) | |
{ | |
if (File.Exists(pluginPath)) | |
{ | |
IntPtr ptr = Kernel32.VirtualAllocEx(processHandle, IntPtr.Zero, (uint)(pluginPath.Length + 1) * 2U, Kernel32.AllocationType.Reserve | Kernel32.AllocationType.Commit, Kernel32.MemoryProtection.ReadWrite); | |
if (ptr != IntPtr.Zero) | |
{ | |
int nobw = 0; | |
byte[] p = Encoding.Unicode.GetBytes(pluginPath); | |
byte[] nt = Encoding.Unicode.GetBytes("\0"); | |
if (Kernel32.WriteProcessMemory(processHandle, ptr, p, (uint)(p.Length), out nobw) && Kernel32.WriteProcessMemory(processHandle, new IntPtr(ptr.ToInt64() + p.LongLength), nt, (uint)(nt.Length), out nobw)) | |
{ | |
uint tid = 0U; | |
IntPtr rt = Kernel32.CreateRemoteThread(processHandle, IntPtr.Zero, 0U, loadLibraryW, ptr, /* CREATE_SUSPENDED */ 0x4, out tid); | |
if (rt != IntPtr.Zero) | |
{ | |
Kernel32.ResumeThread(rt); | |
unchecked | |
{ | |
Kernel32.WaitForSingleObject(rt, (uint)(Timeout.Infinite)); | |
} | |
} | |
} | |
Kernel32.VirtualFreeEx(processHandle, ptr, 0, Kernel32.AllocationType.Release); | |
} | |
} | |
} | |
/// <summary> | |
/// Launch SA:MP | |
/// </summary> | |
/// <param name="ip">IP</param> | |
/// <param name="port">Port</param> | |
/// <param name="username">Username</param> | |
/// <param name="serverPassword">Server password</param> | |
/// <param name="rconPassword">RCON password</param> | |
/// <param name="debug">Debug mode</param> | |
public static void LaunchSAMP(string ip, string port, string username, string serverPassword, string rconPassword, bool debug) | |
{ | |
if ((ip != null) || debug) | |
{ | |
IntPtr mh = Kernel32.GetModuleHandle("kernel32.dll"); | |
if (mh != IntPtr.Zero) | |
{ | |
IntPtr load_library_w = Kernel32.GetProcAddress(mh, "LoadLibraryW"); | |
if (load_library_w != IntPtr.Zero) | |
{ | |
Kernel32.PROCESS_INFORMATION process_info; | |
Kernel32.STARTUPINFO startup_info = new Kernel32.STARTUPINFO(); | |
string modified_username = ((username == null) ? "" : username.Trim().Replace(' ', '_')); | |
if (Kernel32.CreateProcess("Z:\\Rockstar Games\\GTA San Andreas\\gta_sa.exe", debug ? "-d" : "-c " + ((rconPassword == null) ? "" : rconPassword) + " -h " + ip + " -p " + port + " -n " + modified_username + ((serverPassword == null) ? "" : (" -z " + serverPassword)), IntPtr.Zero, IntPtr.Zero, false, /* DETACHED_PROCESS */ 0x8 | /* CREATE_SUSPENDED */ 0x4, IntPtr.Zero, "Z:\\Rockstar Games\\GTA San Andreas\\", ref startup_info, out process_info)) | |
{ | |
InjectPlugin("Z:\\Rockstar Games\\GTA San Andreas\\samp.dll", process_info.hProcess, load_library_w); | |
Kernel32.ResumeThread(process_info.hThread); | |
Kernel32.CloseHandle(process_info.hProcess); | |
} | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// On load | |
/// </summary> | |
/// <param name="webserver"></param> | |
public void OnLoad(IWebserver webserver) | |
{ | |
this.webserver = webserver; | |
webserver.StandardOutput.WriteLine(""); | |
webserver.StandardOutput.WriteLine("\t========================="); | |
webserver.StandardOutput.WriteLine("\t= Angasal SA:MP loaded! ="); | |
webserver.StandardOutput.WriteLine("\t========================="); | |
webserver.StandardOutput.WriteLine(""); | |
} | |
/// <summary> | |
/// On request | |
/// </summary> | |
/// <param name="context">Command context</param> | |
public void OnRequest(ListenerContext context) | |
{ | |
if (context.HTTPListenerContext.Request.Url.LocalPath.StartsWith("/launch/")) | |
{ | |
string input = context.HTTPListenerContext.Request.Url.LocalPath.Substring("/launch/".Length); | |
string[] ip = input.Split(':'); | |
if (ip != null) | |
{ | |
if (ip.Length == 2) | |
{ | |
LaunchSAMP(ip[0], ip[1], "BigETI", null, null, false); | |
context.Response = "<h1>Launching " + input + "...</h1>"; | |
} | |
else | |
{ | |
context.Response = "<h1>Failed to launch " + input + "</h1>"; | |
} | |
} | |
else | |
{ | |
context.Response = "<h1>Failed to launch " + input + "</h1>"; | |
} | |
} | |
else | |
{ | |
try | |
{ | |
if (servers == null) | |
{ | |
using (WebClientEx web_client = new WebClientEx(5000)) | |
{ | |
web_client.Headers.Set(HttpRequestHeader.Accept, "application/json"); | |
web_client.Headers.Set(HttpRequestHeader.UserAgent, "Test plugin"); | |
string json = Encoding.UTF8.GetString(web_client.DownloadData("https://api.samp-servers.net/v2/servers")); | |
if (json != null) | |
{ | |
servers = JsonConvert.DeserializeObject<List<SAMPServerData>>(json); | |
} | |
} | |
} | |
} | |
catch (Exception e) | |
{ | |
context.ErrorOutput.WriteLine(e); | |
} | |
if (servers != null) | |
{ | |
StringBuilder sb = new StringBuilder(); | |
foreach (SAMPServerData server in servers) | |
{ | |
if (server != null) | |
{ | |
sb.Append("<p style=\"font-size:21px;\"><a href=\"./launch/"); | |
sb.Append(server.IP); | |
sb.Append("\">"); | |
sb.Append(System.Security.SecurityElement.Escape(server.Hostname)); | |
sb.Append("</a></p><br />"); | |
} | |
} | |
context.Response = sb.ToString(); | |
} | |
} | |
} | |
/// <summary> | |
/// On unload | |
/// </summary> | |
/// <param name="webserver">Webserver</param> | |
public void OnUnload(IWebserver webserver) | |
{ | |
webserver.StandardOutput.WriteLine(""); | |
webserver.StandardOutput.WriteLine("\t==========================="); | |
webserver.StandardOutput.WriteLine("\t= Angasal SA:MP unloaded! ="); | |
webserver.StandardOutput.WriteLine("\t==========================="); | |
webserver.StandardOutput.WriteLine(""); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment