Oxfuscator

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

2 Likes