Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions Confuser.Protections/Compress/Compressor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ void PackModules(ConfuserContext context, CompressorContext compCtx, ModuleDef s
for (int i = 0; i < name.Length; i++)
name[i] *= key[i + 4];

uint state = 0x6fff61;
uint state = compCtx.LcgInit;
foreach (byte chr in name)
state = state * 0x5e3f1f + chr;
state = state * compCtx.LcgMultiplier + chr;
byte[] encrypted = compCtx.Encrypt(comp, entry.Value, state, progress => {
progress = (progress + moduleIndex) / modules.Count;
context.ProgressReporter.Progress((int)(progress * 10000), 10000);
Expand Down Expand Up @@ -242,6 +242,17 @@ void InjectStub(ConfuserContext context, CompressorContext compCtx, ProtectionPa
new MemberRefUser(stubModule, ".ctor", ctorSig, attrType)));
}

// Randomize the encryption feedback constant (baked-in 0x3ddb2819 fingerprints the
// stub). Any value works since it is purely additive; the same value is injected into
// the runtime Decrypt method below so encrypt/decrypt stay in sync.
compCtx.Feedback = random.NextUInt32();

// Randomize the rolling-hash used to derive each library's seed from its name
// (baked-in 0x6fff61 / 0x5e3f1f). The multiplier is kept odd for good distribution.
// The same values are injected into the runtime Resolve method below.
compCtx.LcgInit = random.NextUInt32();
compCtx.LcgMultiplier = random.NextUInt32() | 1;

uint seed = random.NextUInt32();
compCtx.OriginModule = context.OutputModules[compCtx.ModuleIndex];

Expand All @@ -263,7 +274,11 @@ void InjectStub(ConfuserContext context, CompressorContext compCtx, ProtectionPa
List<Instruction> instrs = decrypter.Body.Instructions.ToList();
for (int i = 0; i < instrs.Count; i++) {
Instruction instr = instrs[i];
if (instr.OpCode == OpCodes.Call) {
if (instr.OpCode == OpCodes.Ldc_I4 && (int)instr.Operand == 0x3ddb2819) {
// Sync the runtime feedback constant with the value used during encryption.
instr.Operand = (int)compCtx.Feedback;
}
else if (instr.OpCode == OpCodes.Call) {
var method = (IMethod)instr.Operand;
if (method.DeclaringType.Name == "Mutation" &&
method.Name == "Crypt") {
Expand All @@ -286,6 +301,18 @@ void InjectStub(ConfuserContext context, CompressorContext compCtx, ProtectionPa
foreach (Instruction instr in instrs)
decrypter.Body.Instructions.Add(instr);

// Resolve — sync the runtime rolling-hash constants with the values used when
// deriving each library's seed from its name (see PackModules).
MethodDef resolver = defs.OfType<MethodDef>().Single(method => method.Name == "Resolve");
foreach (Instruction instr in resolver.Body.Instructions) {
if (instr.OpCode != OpCodes.Ldc_I4)
continue;
if ((int)instr.Operand == 0x6fff61)
instr.Operand = (int)compCtx.LcgInit;
else if ((int)instr.Operand == 0x5e3f1f)
instr.Operand = (int)compCtx.LcgMultiplier;
}

// Pack modules
PackModules(context, compCtx, stubModule, comp, random);
}
Expand Down
5 changes: 4 additions & 1 deletion Confuser.Protections/Compress/CompressorContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ internal class CompressorContext {
public byte[] OriginModule;
public ModuleDef OriginModuleDef;
public bool CompatMode;
public uint Feedback;
public uint LcgInit;
public uint LcgMultiplier;

public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed, Action<double> progressFunc) {
data = (byte[])data.Clone();
Expand Down Expand Up @@ -46,7 +49,7 @@ public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed, Acti
for (int i = 0; i < data.Length; i += 4) {
var datum = (uint)(data[i + 0] | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24));
uint encrypted = datum ^ key[keyIndex & 0xf];
key[keyIndex & 0xf] = (key[keyIndex & 0xf] ^ datum) + 0x3ddb2819;
key[keyIndex & 0xf] = (key[keyIndex & 0xf] ^ datum) + Feedback;
encryptedData[i + 0] = (byte)(encrypted >> 0);
encryptedData[i + 1] = (byte)(encrypted >> 8);
encryptedData[i + 2] = (byte)(encrypted >> 16);
Expand Down