For string obfuscation:
namespace RemObjects.Elements.Obfuscation;
uses
RemObjects.Elements.Cirrus.*;
type
[MethodAspectAttribute(typeOf(RemObjects.Elements.Obfuscation.__Global), true, 'ObfuscateString', 0, [typeOf(String)])]
StringObfuscationAspect = public class(IMethodCallDecorator, IAspectFinishCallback)
private
class var fRandom: Random := new Random();
class var fObfuscatedString: IFieldDefinition;
class var fDemangleString: IMethodDefinition;
class var fCtor: IMethodDefinition;
class var fValue: String;
class method MangleString(s: String; aKey: Integer): String;
begin
var c := new Char[s.Length + 2];
var lLen := s.Length xor aKey;
c[0] := Char(lLen);
c[1] := Char(lLen shr 16);
aKey := ((aKey shl 3) or (aKey shr 29)) + s.Length;
for i: Integer := 0 to s.Length -1 do begin
c[i + 2] := Char(Word(s[i]) xor aKey);
aKey := ((aKey shl 3) or (aKey shr 29)) + ord(s[i]);
end;
exit new String(c);
end;
public
method Finish(services: IServices);
begin
if fObfuscatedString <> nil then
fCtor.ReplaceMethodBody(new BeginStatement(
new PlaceHolderStatement,
new AssignmentStatement(new FieldValue(new TypeValue(fObfuscatedString.Owner), fObfuscatedString), fValue)));
fObfuscatedString := nil;
end;
method ProcessMethodCall(aContext: IContext; aMethod: IMethod; aValue: ParameterizedValue): Value;
begin
if aValue.Parameters.Count <> 1 then begin
aContext.Services.EmitError('Single string parameter expected!');
exit
end;
var lVal := aValue.Parameters[0];
if lVal.Kind <> ValueKind.Data then begin
aContext.Services.EmitError('Single string parameter expected!');
exit
end;
var lStringValue := String(lVal);
if fObfuscatedString = nil then begin
var lTD := coalesce(
ITypeDefinition(aContext.Services.FindType('<PrivateImplementationDetails>')),
aContext.Services.CreateTypeDefinition('', '<PrivateImplementationDetails>', TypeDefKind.Class));
fCtor := coalesce(lTD.GetClassConstructor as IMethodDefinition, lTD.AddConstructor(true));
fObfuscatedString := lTD.AddField('data', aContext.Services.GetBaseType(13), true);
// TODO: Java, Toffee implementation.
fDemangleString := lTD.AddMethod('a', aContext.Services.GetBaseType(13), true);
//fDemangleString.AddParameter('a', ParameterModifier.In, aContext.Services.GetBaseType(13));
fDemangleString.AddParameter('b', ParameterModifier.In, aContext.Services.GetBaseType(7));
fDemangleString.AddParameter('d', ParameterModifier.In, aContext.Services.GetBaseType(7));
var parameter := new FieldValue(new TypeValue(fObfuscatedString.Owner), fObfuscatedString);
var parameter2 := fDemangleString.GetParameter('b');
var parameter3 := fDemangleString.GetParameter('d');
/*
class method DemangleString(aIn: String; aOffset, aKey: Integer): String;
begin
var lLen := Word(aIn[aOffset + 0]) or (Integer(aIn[aOffset + 1]) shl 16);
lLen := lLen xor aKey;
aKey := ((aKey shl 3) or (aKey shr 29)) + lLen;
var c := new Char[lLen];
for i: Integer := 0 to lLen -1 do begin
c[i] := Char(Word(aIn[i + aOffset + 2]) xor aKey);
aKey := ((aKey shl 3) or (aKey shr 29)) + ord(c[i]);
end;
exit new String(c);
end;
*/
fDemangleString.ReplaceMethodBody(new BeginStatement([
new LocalVariable("lLen", fDemangleString.GetContextType("System.Int32")),
new LocalVariable("c", fDemangleString.GetContextType("array of System.Char"))
],
new AssignmentStatement(new NamedLocalValue("lLen"), new BinaryValue(new UnaryValue(new ProcValue(parameter, "get_Chars", new IType[0], false, new BinaryValue(parameter2, new DataValue(fDemangleString.GetContextType("System.Int32"), 0), BinaryOperator.Add, fDemangleString.GetContextType("System.Int32"))), UnaryOperator.ImpCast, fDemangleString.GetContextType("System.UInt16")), new BinaryValue(new UnaryValue(new ProcValue(parameter, "get_Chars", new IType[0], false, new BinaryValue(parameter2, new DataValue(fDemangleString.GetContextType("System.Int32"), 1), BinaryOperator.Add, fDemangleString.GetContextType("System.Int32"))), UnaryOperator.ImpCast, fDemangleString.GetContextType("System.Int32")), new DataValue(fDemangleString.GetContextType("System.Int32"), 16), BinaryOperator.Shl, fDemangleString.GetContextType("System.Int32")), BinaryOperator.Or, fDemangleString.GetContextType("System.Int32"))),
new AssignmentStatement(new IdentifierValue("lLen"), new BinaryValue(new IdentifierValue("lLen"), parameter3, BinaryOperator.Xor, fDemangleString.GetContextType("System.Int32"))),
new AssignmentStatement(parameter3, new BinaryValue(new BinaryValue(new BinaryValue(parameter3, new DataValue(fDemangleString.GetContextType("System.Int32"), 3), BinaryOperator.Shl, fDemangleString.GetContextType("System.Int32")), new BinaryValue(parameter3, new DataValue(fDemangleString.GetContextType("System.Int32"), 29), BinaryOperator.Shr, fDemangleString.GetContextType("System.Int32")), BinaryOperator.Or, fDemangleString.GetContextType("System.Int32")), new IdentifierValue("lLen"), BinaryOperator.Add, fDemangleString.GetContextType("System.Int32"))),
new AssignmentStatement(new NamedLocalValue("c"), new ArrayCtorCallValue(IArrayType(fDemangleString.GetContextType("array of System.Char")), new IdentifierValue("lLen"))),
new ForStatement("i", fDemangleString.GetContextType("System.Int32"), new DataValue(fDemangleString.GetContextType("System.Int32"), 0), new BinaryValue(new IdentifierValue("lLen"), new DataValue(fDemangleString.GetContextType("System.Int32"), 1), BinaryOperator.Sub, fDemangleString.GetContextType("System.Int32")), nil, new BeginStatement(new AssignmentStatement(new SubArrayValue(new IdentifierValue("c"), new IdentifierValue("i")), new UnaryValue(new BinaryValue(new UnaryValue(new ProcValue(parameter, "get_Chars", new IType[0], false, new BinaryValue(new BinaryValue(new IdentifierValue("i"), parameter2, BinaryOperator.Add, fDemangleString.GetContextType("System.Int32")), new DataValue(fDemangleString.GetContextType("System.Int32"), 2), BinaryOperator.Add, fDemangleString.GetContextType("System.Int32"))), UnaryOperator.ImpCast, fDemangleString.GetContextType("System.UInt16")), parameter3, BinaryOperator.Xor, fDemangleString.GetContextType("System.Int32")), UnaryOperator.ImpCast, fDemangleString.GetContextType("System.Char"))), new AssignmentStatement(parameter3, new BinaryValue(new BinaryValue(new BinaryValue(parameter3, new DataValue(fDemangleString.GetContextType("System.Int32"), 3), BinaryOperator.Shl, fDemangleString.GetContextType("System.Int32")), new BinaryValue(parameter3, new DataValue(fDemangleString.GetContextType("System.Int32"), 29), BinaryOperator.Shr, fDemangleString.GetContextType("System.Int32")), BinaryOperator.Or, fDemangleString.GetContextType("System.Int32")), new UnaryValue(new SubArrayValue(new IdentifierValue("c"), new IdentifierValue("i")), UnaryOperator.ImpCast, fDemangleString.GetContextType("System.UInt16")), BinaryOperator.Add, fDemangleString.GetContextType("System.Int32")))), false, false),
new ExitStatement(new NewValue(fDemangleString.GetContextType("System.String"), [new IdentifierValue("c")], new System.Collections.Generic.KeyValuePair<String, Value>[0]))));
end;
var lOffset: Integer;
var lKey := fRandom.Next;
if fValue = nil then begin
fValue := MangleString(lStringValue, lKey);
lOffset := 0;
end else begin
var lOld := fValue;
lOffset := lOld.Length;
fValue := lOld + MangleString(lStringValue, lKey);
end;
exit new ProcValue(new TypeValue(fDemangleString.Owner), fDemangleString, [lOffset, lKey]);
end;
end;
method ObfuscateString(s: String): String;
begin
exit s;
end;
end.
(.NET only at the moment, but that’s just a question of porting the code)
Usage: put it in a dll, use it like:
type
Program = class
public
class method Main(args: array of String): Int32;
begin
writeLn(ObfuscateString('HAHA'));
writeLn(ObfuscateString('HIHI'));
// add your own code here
writeLn('The magic happens here.');
end;
end;
end result looks like:
public static int Main(string[] args)
{
Console.Out.WriteLine(<PrivateImplementationDetails>.a(0, 1325031605));
Console.Out.WriteLine(<PrivateImplementationDetails>.a(6, 1888006488));
Console.Out.WriteLine("The magic happens here.");
int result = default(int);
return result;
}
a single string is stored as "悱仺צⷺvɹ녜炈誏\rȡᏙ"
this needs todays build to compile