Created
April 24, 2024 22:33
-
-
Save Donaldduck8/21e296a8d96b350339cb818f8e554915 to your computer and use it in GitHub Desktop.
Automatic decryptor for packed Tyrone assemblies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Mono.Cecil; | |
using Mono.Cecil.Cil; | |
void Main() | |
{ | |
var assembly = Assembly.LoadFile(@"C:\Users\Donald\Desktop\bf8d6a6c87df124721dc95f7420c67d15668a14865d5719505737e8d78bb335c.exe_Dumps\3.bin"); | |
var assemblyDef = AssemblyDefinition.ReadAssembly(@"C:\Users\Donald\Desktop\bf8d6a6c87df124721dc95f7420c67d15668a14865d5719505737e8d78bb335c.exe_Dumps\3.bin"); | |
string[] resourceNames = assemblyDef.MainModule.Resources.Select(resource => resource.Name.Split(".").FirstOrDefault()).ToArray(); | |
uint[] tokens = new uint[]{ | |
0x06000004, | |
0x06000005, | |
0x06000006, | |
0x06000007, | |
0x06000008 | |
}; | |
Dictionary<uint, MethodInfo> decryptionFunctions = new Dictionary<uint, System.Reflection.MethodInfo>(); | |
foreach (uint token in tokens) | |
{ | |
decryptionFunctions.Add(new MetadataToken(token).RID, GetStringDecryptionMethod(assembly, (int)token)); | |
} | |
(var resourceNameField, var resourceName) = GetResourceNameField(assemblyDef, decryptionFunctions, resourceNames); | |
var xorKeyField = GetXORKeyField(assemblyDef, resourceNameField); | |
var xorKey = GetXORKey(assemblyDef, decryptionFunctions, xorKeyField); | |
var resourceIndex = assemblyDef.MainModule.Resources.Select(resource => resource.Name).ToList().IndexOf(resourceName + ".resources"); | |
var resource = (EmbeddedResource) assemblyDef.MainModule.Resources.ElementAt(resourceIndex); | |
var resourceStream = resource.GetResourceStream(); | |
var reader = new ResourceReader(resourceStream); | |
reader.GetResourceData(resourceName, out var _, out byte[] resourceData); | |
// The first 4 bytes are just the length | |
resourceData = resourceData.Skip(4).ToArray(); | |
byte[] decryptedResource = xor(resourceData, xorKey); | |
Console.WriteLine(decryptedResource); | |
} | |
public static byte[] xor(byte[] ct, string key) | |
{ | |
byte[] array = Encoding.ASCII.GetBytes(key); | |
for (int i = 0; i <= ct.Length; i++) { | |
ct[i % ct.Length] = Convert.ToByte((Convert.ToInt32((int)(ct[i % ct.Length] ^ array[i % array.Length])) - Convert.ToInt32(ct[(i + 1) % ct.Length]) +256) % 256); | |
} | |
Array.Resize<byte>(ref ct, ct.Length - 1); | |
return ct; | |
} | |
String GetXORKey(AssemblyDefinition assemblyDef, Dictionary<uint, MethodInfo> decryptionFunctions, FieldDefinition xorKeyField) | |
{ | |
foreach (var instruction in GetAllInstructions(assemblyDef)) | |
{ | |
if (instruction.OpCode == OpCodes.Stsfld && instruction.Operand is FieldDefinition) | |
{ | |
var operand = (FieldDefinition)instruction.Operand; | |
if (operand.MetadataToken.RID == xorKeyField.MetadataToken.RID) | |
{ | |
var call = instruction.Previous; | |
Debug.Assert(OpCodes.Call == call.OpCode); | |
Debug.Assert(call.Operand is MethodReference); | |
var ldc = call.Previous; | |
Debug.Assert(OpCodes.Ldc_I4 == ldc.OpCode); | |
return decryptWrapper(decryptionFunctions, ldc, call); | |
} | |
} | |
} | |
return null; | |
} | |
FieldDefinition GetXORKeyField(AssemblyDefinition assemblyDef, FieldDefinition resourceNameField) | |
{ | |
foreach (var instruction in GetAllInstructions(assemblyDef)) | |
{ | |
if (instruction.OpCode == OpCodes.Ldsfld && instruction.Operand is FieldDefinition) | |
{ | |
var operand = (FieldDefinition)instruction.Operand; | |
if (operand.MetadataToken.RID == resourceNameField.MetadataToken.RID) | |
{ | |
var next_ldsfld_instruction = instruction.Next.Next; | |
Debug.Assert(next_ldsfld_instruction.OpCode == OpCodes.Ldsfld); | |
Debug.Assert(next_ldsfld_instruction.Operand is FieldDefinition); | |
var other_field = (FieldDefinition)next_ldsfld_instruction.Operand; | |
return other_field; | |
} | |
} | |
} | |
return null; | |
} | |
(FieldDefinition, String) GetResourceNameField(AssemblyDefinition assemblyDef, Dictionary<uint, MethodInfo> decryptionFunctions, string[] resourceNames) | |
{ | |
foreach (var instruction in GetAllInstructions(assemblyDef)) { | |
if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference) | |
{ | |
var methodRef = (MethodReference)instruction.Operand; | |
if (methodRef is GenericInstanceMethod) | |
{ | |
methodRef = methodRef.GetElementMethod(); | |
} | |
if (decryptionFunctions.ContainsKey(methodRef.MetadataToken.RID)) | |
{ | |
var ldc = instruction.Previous; | |
Debug.Assert(OpCodes.Ldc_I4 == ldc.OpCode); | |
var decrypted_string = decryptWrapper(decryptionFunctions, ldc, instruction); | |
if (resourceNames.Contains(decrypted_string)) | |
{ | |
var stsfld = instruction.Next; | |
Debug.Assert(OpCodes.Stsfld == stsfld.OpCode); | |
var resource_name_field = stsfld.Operand; | |
return ((FieldDefinition) resource_name_field, decrypted_string); | |
} | |
} | |
} | |
} | |
return (null, null); | |
} | |
String decryptWrapper(Dictionary<uint, MethodInfo> decryptionFunctions, Instruction ldc, Instruction call) | |
{ | |
var methodRef = (MethodReference)call.Operand; | |
if (methodRef is GenericInstanceMethod) | |
{ | |
methodRef = methodRef.GetElementMethod(); | |
} | |
var argument = ldc.Operand; | |
var uint_arg = (uint)(int)argument; | |
if (!decryptionFunctions.TryGetValue(methodRef.MetadataToken.RID, out var decryptionFunction)) | |
{ | |
throw new Exception(); | |
} | |
try | |
{ | |
return Decrypt(decryptionFunction, uint_arg); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine($"Method: {methodRef.MetadataToken.RID + 0x06000000:X}, Value: {uint_arg}"); | |
throw(e); | |
} | |
} | |
IEnumerable<Instruction> GetAllInstructions(AssemblyDefinition assemblyDef, bool nonEmpty = true) | |
{ | |
foreach (var type in assemblyDef.MainModule.Types) | |
{ | |
foreach (var method in type.Methods) | |
{ | |
if (nonEmpty && !method.HasBody) | |
{ | |
continue; | |
} | |
foreach (var instruction in method.Body.Instructions) | |
{ | |
yield return instruction; | |
} | |
} | |
} | |
} | |
MethodInfo GetStringDecryptionMethod(Assembly assembly, int token) | |
{ | |
var MethodProto = assembly.Modules.First().ResolveMethod(token); | |
var MethodInfo = (MethodInfo)MethodProto; | |
var Method = MethodInfo.MakeGenericMethod(new Type[] { typeof(string) }); | |
return Method; | |
} | |
string Decrypt(MethodInfo method, UInt32 parameter) | |
{ | |
return (string) method.Invoke(null, new object[] { parameter }); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment