Skip to content

Instantly share code, notes, and snippets.

@BigETI
Created December 7, 2018 11:08
Show Gist options
  • Save BigETI/d587b50d6935bc1238e919f15ac3b4f9 to your computer and use it in GitHub Desktop.
Save BigETI/d587b50d6935bc1238e919f15ac3b4f9 to your computer and use it in GitHub Desktop.
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