Phan Mem Key Auth
Phan Mem Key Auth
using System.Security.Cryptography;
using System.Collections.Specialized;
using System.Text;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Diagnostics;
using System.Security.Principal;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Threading;
using Cryptographic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using System.Windows;
namespace KeyAuth
{
public class api
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool TerminateProcess(IntPtr hProcess, uint
uExitCode);
this.name = name;
this.ownerid = ownerid;
this.version = version;
this.path = path;
}
#region structures
[DataContract]
private class response_structure
{
[DataMember]
public bool success { get; set; }
[DataMember]
public bool newSession { get; set; }
[DataMember]
public string sessionid { get; set; }
[DataMember]
public string contents { get; set; }
[DataMember]
public string response { get; set; }
[DataMember]
public string message { get; set; }
[DataMember]
public string ownerid { get; set; }
[DataMember]
public string download { get; set; }
[DataMember]
public List<msg> messages { get; set; }
[DataMember]
public List<users> users { get; set; }
[DataContract]
private class user_data_structure
{
[DataMember]
public string username { get; set; }
[DataMember]
public string ip { get; set; }
[DataMember]
public string hwid { get; set; }
[DataMember]
public string createdate { get; set; }
[DataMember]
public string lastlogin { get; set; }
[DataMember]
public List<Data> subscriptions { get; set; } // array of subscriptions
(basically multiple user ranks for user with individual expiry dates
}
[DataContract]
private class app_data_structure
{
[DataMember]
public string numUsers { get; set; }
[DataMember]
public string numOnlineUsers { get; set; }
[DataMember]
public string numKeys { get; set; }
[DataMember]
public string version { get; set; }
[DataMember]
public string customerPanelLink { get; set; }
[DataMember]
public string downloadLink { get; set; }
}
#endregion
private static string sessionid, enckey;
bool initialized;
/// <summary>
/// Initializes the connection with keyauth in order to use any of the
functions
/// </summary>
public async Task init()
{
Random random = new Random();
// Generate a random length for the string (let's assume between 5 and
50 characters)
int length = random.Next(5, 51); // Min length: 5, Max length: 50
seed = sb.ToString();
checkAtom();
if (!string.IsNullOrEmpty(path))
{
values_to_upload.Add("token", File.ReadAllText(path));
values_to_upload.Add("thash", TokenHash(path));
}
if (response == "KeyAuth_Invalid")
{
error("Application not found");
TerminateProcess(GetCurrentProcess(), 1);
}
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
if (json.success)
{
sessionid = json.sessionid;
initialized = true;
}
else if (json.message == "invalidver")
{
app_data.downloadLink = json.download;
}
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
#pragma warning disable IDE0052
private System.Threading.Timer atomTimer;
#pragma warning restore IDE0052
void checkAtom()
{
atomTimer = new System.Threading.Timer(_ =>
{
ushort foundAtom = GlobalFindAtom(seed);
if (foundAtom == 0)
{
TerminateProcess(GetCurrentProcess(), 1);
}
}, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}
/// <summary>
/// Registers the user using a license and gives the user a subscription
that matches their license level
/// </summary>
/// <param name="username">Username</param>
/// <param name="pass">Password</param>
/// <param name="key">License key</param>
public async Task register(string username, string pass, string key, string
email = "")
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
GlobalAddAtom(seed);
GlobalAddAtom(ownerid);
load_response_struct(json);
if (json.success)
load_user_data(json.info);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
/// <summary>
/// Allow users to enter their account information and recieve an email to
reset their password.
/// </summary>
/// <param name="username">Username</param>
/// <param name="email">Email address</param>
public async Task forgot(string username, string email)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
}
/// <summary>
/// Authenticates the user using their username and password
/// </summary>
/// <param name="username">Username</param>
/// <param name="pass">Password</param>
public async Task login(string username, string pass, string code = null)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
GlobalAddAtom(seed);
GlobalAddAtom(ownerid);
load_response_struct(json);
if (json.success)
load_user_data(json.info);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
start:
outputten = "handshake";
outputten = "http://localhost:1337/" + outputten + "/";
listener.Prefixes.Add(outputten);
listener.Start();
if (request.HttpMethod == "OPTIONS")
{
responsepp.StatusCode = (int)HttpStatusCode.OK;
Thread.Sleep(1); // without this, the response doesn't return to
the website, and the web buttons can't be shown
listener.Stop();
goto start;
}
listener.AuthenticationSchemes = AuthenticationSchemes.Negotiate;
listener.UnsafeConnectionNtlmAuthentication = true;
listener.IgnoreWriteExceptions = true;
datastore = datastore2;
var json =
response_decoder.string_to_generic<response_structure>(response);
bool success = true;
if (json.ownerid == ownerid)
{
GlobalAddAtom(seed);
GlobalAddAtom(ownerid);
load_response_struct(json);
if (json.success)
{
load_user_data(json.info);
responsepp.StatusCode = 420;
responsepp.StatusDescription = "SHEESH";
}
else
{
Console.WriteLine(json.message);
responsepp.StatusCode = (int)HttpStatusCode.OK;
responsepp.StatusDescription = json.message;
success = false;
}
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
responsepp.ContentLength64 = buffer.Length;
Stream output = responsepp.OutputStream;
output.Write(buffer, 0, buffer.Length);
Thread.Sleep(1); // without this, the response doesn't return to the
website, and the web buttons can't be shown
listener.Stop();
if (!success)
TerminateProcess(GetCurrentProcess(), 1);
/// <summary>
/// Use Buttons from KeyAuth Customer Panel
/// </summary>
/// <param name="button">Button Name</param>
string output;
output = button;
output = "http://localhost:1337/" + output + "/";
listener.Prefixes.Add(output);
listener.Start();
responsepp.StatusCode = 420;
responsepp.StatusDescription = "SHEESH";
listener.AuthenticationSchemes = AuthenticationSchemes.Negotiate;
listener.UnsafeConnectionNtlmAuthentication = true;
listener.IgnoreWriteExceptions = true;
listener.Stop();
}
/// <summary>
/// Gives the user a subscription that has the same level as the key
/// </summary>
/// <param name="username">Username of the user thats going to get
upgraded</param>
/// <param name="key">License with the same level as the subscription you
want to give the user</param>
public async Task upgrade(string username, string key)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
json.success = false;
load_response_struct(json);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
/// <summary>
/// Authenticate without using usernames and passwords
/// </summary>
/// <param name="key">Licence used to login with</param>
public async Task license(string key, string code = null)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
GlobalAddAtom(seed);
GlobalAddAtom(ownerid);
load_response_struct(json);
if (json.success)
load_user_data(json.info);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
/// <summary>
/// Checks if the current session is validated or not
/// </summary>
public async Task check()
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
/// <summary>
/// Disable two factor authentication (2fa)
/// </summary>
public async Task disable2fa(string code)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
}
/// <summary>
/// Enable two factor authentication (2fa)
/// </summary>
public async Task enable2fa(string code = null)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
if (json.success)
{
if (code == null) // First time enabling 2FA, no code provided
{
// Display the secret code to the user
Clipboard.SetText(json.twoFactor.SecretCode);
System.Windows.MessageBox.Show($"Your 2FA Secret Code has been
copied to your clipboard! \n\n: {json.twoFactor.SecretCode}", "2FA Secret");
}
else // Code provided by the user
{
System.Windows.MessageBox.Show("2FA has been successfully
enabled!", "2FA Setup");
}
}
else
{
Thread.Sleep(3000);
TerminateProcess(GetCurrentProcess(), 1);
}
}
/// <summary>
/// Change the data of an existing user variable, *User must be logged in*
/// </summary>
/// <param name="var">User variable name</param>
/// <param name="data">The content of the variable</param>
public async Task setvar(string var, string data)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
/// <summary>
/// Gets the an existing user variable
/// </summary>
/// <param name="var">User Variable Name</param>
/// <returns>The content of the user variable</returns>
public async Task<string> getvar(string var)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
if (json.success)
return json.response;
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
return null;
}
/// <summary>
/// Bans the current logged in user
/// </summary>
public async Task ban(string reason = null)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
}
/// <summary>
/// Gets an existing global variable
/// </summary>
/// <param name="varid">Variable ID</param>
/// <returns>The content of the variable</returns>
public async Task<string> var(string varid)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
if (json.success)
return json.message;
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
return null;
}
/// <summary>
/// Fetch usernames of online users
/// </summary>
/// <returns>ArrayList of usernames</returns>
public async Task<List<users>> fetchOnline()
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
if (json.success)
return json.users;
return null;
}
/// <summary>
/// Fetch app statistic counts
/// </summary>
public async Task fetchStats()
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
if (json.success)
load_app_data(json.appinfo);
}
/// <summary>
/// Gets the last 50 sent messages of that channel
/// </summary>
/// <param name="channelname">The channel name</param>
/// <returns>the last 50 sent messages of that channel</returns>
public async Task<List<msg>> chatget(string channelname)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
if (json.success)
{
return json.messages;
}
return null;
}
/// <summary>
/// Sends a message to the given channel name
/// </summary>
/// <param name="msg">Message</param>
/// <param name="channelname">Channel Name</param>
/// <returns>If the message was sent successfully, it returns true if not
false</returns>
public async Task<bool> chatsend(string msg, string channelname)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
if (json.success)
return true;
return false;
}
/// <summary>
/// Checks if the current ip address/hwid is blacklisted
/// </summary>
/// <returns>If found blacklisted returns true if not false</returns>
public async Task<bool> checkblack()
{
CheckInit();
string hwid = WindowsIdentity.GetCurrent().User.Value;
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
if (json.success)
return true;
else
return false;
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
return true; // return yes blacklisted if the OwnerID is spoofed
}
/// <summary>
/// Sends a request to a webhook that you've added in the dashboard in a
safe way without it being showed for example a http debugger
/// </summary>
/// <param name="webid">Webhook ID</param>
/// <param name="param">Parameters</param>
/// <param name="body">Body of the request, empty by default</param>
/// <param name="conttype">Content type, empty by default</param>
/// <returns>the webhook's response</returns>
public async Task<string> webhook(string webid, string param, string body =
"", string conttype = "")
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
if (json.ownerid == ownerid)
{
load_response_struct(json);
if (json.success)
return json.response;
}
else
{
TerminateProcess(GetCurrentProcess(), 1);
}
return null;
}
/// <summary>
/// KeyAuth acts as proxy and downlods the file in a secure way
/// </summary>
/// <param name="fileid">File ID</param>
/// <returns>The bytes of the download file</returns>
public async Task<byte[]> download(string fileid)
{
CheckInit();
["type"] = "file",
["fileid"] = fileid,
["sessionid"] = sessionid,
["name"] = name,
["ownerid"] = ownerid
};
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
if (json.success)
return encryption.str_to_byte_arr(json.contents);
return null;
}
/// <summary>
/// Logs the IP address,PC Name with a message, if a discord webhook is set
up in the app settings, the log will get sent there and the dashboard if not set up
it will only be in the dashboard
/// </summary>
/// <param name="message">Message</param>
public async Task log(string message)
{
CheckInit();
await req(values_to_upload);
}
/// <summary>
/// Change the username of a user, *User must be logged in*
/// </summary>
/// <param username="username">New username.</param>
public async Task changeUsername(string username)
{
CheckInit();
var json =
response_decoder.string_to_generic<response_structure>(response);
load_response_struct(json);
}
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
if (!File.Exists(file))
{
using (FileStream stream = File.Create(file))
{
File.AppendAllText(file, DateTime.Now + " > This is the start
of your error logs file");
}
}
if (!response.IsSuccessStatusCode)
{
switch (response.StatusCode)
{
case (HttpStatusCode)429: // Rate Limited
error("You're connecting too faster to loader, slow
down");
Logger.LogEvent("You're connecting too faster to
loader, slow down");
TerminateProcess(GetCurrentProcess(), 1);
break;
default:
error("Connection failure. Please try again, or
contact us for help.");
Logger.LogEvent("Connection failure. Please try
again, or contact us for help.");
TerminateProcess(GetCurrentProcess(), 1);
break;
}
return "";
}
if (response.Headers.TryGetValues("x-signature-timestamp", out
IEnumerable<string> timeStampValues))
headers["x-signature-timestamp"] =
timeStampValues.FirstOrDefault();
Logger.LogEvent(raw_response + "\n");
return raw_response;
}
}
catch (Exception ex)
{
error("Connection failure. Please try again, or contact us for
help. Exception: " + ex.Message);
Logger.LogEvent("Connection failure. Please try again, or contact
us for help. Exception: " + ex.Message);
TerminateProcess(GetCurrentProcess(), 1);
return "";
}
}
}
}
try
{
string signature = headers["x-signature-ed25519"];
string timestamp = headers["x-signature-timestamp"];
#region app_data
public app_data_class app_data = new app_data_class();
public class app_data_class
{
public string numUsers { get; set; }
public string numOnlineUsers { get; set; }
public string numKeys { get; set; }
public string version { get; set; }
public string customerPanelLink { get; set; }
public string downloadLink { get; set; }
}
#region user_data
public user_data_class user_data = new user_data_class();
[DataContract]
private class TwoFactorData
{
[DataMember(Name = "secret_code")]
public string SecretCode { get; set; }
[DataMember(Name = "QRCode")]
public string QRCode { get; set; }
}
#region response_struct
public response_class response = new response_class();
string exeName =
Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Loca
tion);
string logDirectory =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationD
ata), "KeyAuth", "debug", exeName);
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
try
{
// Redact sensitive fields - Add more if you would like.
content = RedactField(content, "sessionid");
content = RedactField(content, "ownerid");
content = RedactField(content, "app");
content = RedactField(content, "version");
content = RedactField(content, "fileid");
content = RedactField(content, "webhooks");
content = RedactField(content, "nonce");
if (!is_serializable(object_type))
throw new Exception($"the object {current_object} isn't a
serializable");
}