# Oxfuscator

**URL:** https://talk.remobjects.com/t/oxfuscator/16474
**Category:** Oxfuscator
**Created:** [May 23, 2018, 3:17pm UTC](https://talk.remobjects.com/t/oxfuscator/16474 "2018-05-23T15:17:15Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 11:09am UTC](https://talk.remobjects.com/t/oxfuscator/16474/21 "2018-07-06T11:09:23Z")

</div>

You are right. The decompiler itself tries to make some readable names for the local variables, based on the variable type.  
So local vars are OK too.

Then the only thing missing is the string encryption - nu push, but it would make me very happy.

Thanks for the fast implementation!

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 11:21am UTC](https://talk.remobjects.com/t/oxfuscator/16474/22 "2018-07-06T11:21:53Z")

</div>

And one more thing: can you generate a mappings file, so I can map the original names to the obfuscated names? This is needed to investigate a crash of an obfuscated assembly.

b.e.:  
class a = orgClassName  
method a.a = OrgClassName.OrgMethodName  
property a.a = OrgClassName.OrgPropertyName

---

<div class="post-metadata">

### Author: ![ck](https://talk.remobjects.com/user_avatar/talk.remobjects.com/ck/32/8740_2.png) [@ck](https://talk.remobjects.com/u/ck)
#### Post date: [July 6, 2018, 11:22am UTC](https://talk.remobjects.com/t/oxfuscator/16474/23 "2018-07-06T11:22:40Z")

</div>

Do you have any ideas for how to best do string encryption?

---

<div class="post-metadata">

### Author: ![RemObjectsSoftware](https://talk.remobjects.com/user_avatar/talk.remobjects.com/remobjectssoftware/32/15947_2.png) [@RemObjectsSoftware](https://talk.remobjects.com/u/RemObjectsSoftware)
#### Post date: [July 6, 2018, 11:27am UTC](https://talk.remobjects.com/t/oxfuscator/16474/24 "2018-07-06T11:27:36Z")

</div>

Thanks, logged as bugs://80509 (For map files)

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 11:28am UTC](https://talk.remobjects.com/t/oxfuscator/16474/25 "2018-07-06T11:28:10Z")

</div>

Store a key somewhere in the assembly info.  
Encrypt all strings to bytearrays (AES with that key).  
Generate a method somewhere in the assembly that uses AES decryption to convert the bytearrays to the original strings.

A string then becomes a call: q() that returns a string.

Absolutely not fail-safe against professionals, but good enough against hobbyist, as the strings are not visible anymore in the decompiled code.

---

<div class="post-metadata">

### Author: ![ck](https://talk.remobjects.com/user_avatar/talk.remobjects.com/ck/32/8740_2.png) [@ck](https://talk.remobjects.com/u/ck)
#### Post date: [July 6, 2018, 11:28am UTC](https://talk.remobjects.com/t/oxfuscator/16474/26 "2018-07-06T11:28:53Z")

</div>

True yeah. I was hoping there was a better way, this of course has quite a bit of overhead.

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 11:30am UTC](https://talk.remobjects.com/t/oxfuscator/16474/27 "2018-07-06T11:30:24Z")

</div>

You can make it a assembly property:

[Assembly:EncryptStrings]

So if the overhead is a problem, you can choose to use it or not.

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 11:32am UTC](https://talk.remobjects.com/t/oxfuscator/16474/28 "2018-07-06T11:32:08Z")

</div>

Or introduce the @:

var a := “unencrypted string”;  
var b := @“encrypted string”

This give the possibility to encrypt only sensitive strings.

---

<div class="post-metadata">

### Author: ![RemObjectsSoftware](https://talk.remobjects.com/user_avatar/talk.remobjects.com/remobjectssoftware/32/15947_2.png) [@RemObjectsSoftware](https://talk.remobjects.com/u/RemObjectsSoftware)
#### Post date: [July 6, 2018, 11:33am UTC](https://talk.remobjects.com/t/oxfuscator/16474/29 "2018-07-06T11:33:35Z")

</div>

Thanks, logged as bugs://80510 (string obfuscation)

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 11:50am UTC](https://talk.remobjects.com/t/oxfuscator/16474/30 "2018-07-06T11:50:37Z")

</div>

I would suggest both of the above:  
[Assembly:EncryptStrings] to encrypt all strings (marked for encryption or not)  
[EncryptStrings] to do this on class or method level  
@ to encrypt one specific string

and one more, only method level: [DoNotEncrypt]  
for methods that have heavy fixed string manipulation.

---

<div class="post-metadata">

### Author: ![mh](https://talk.remobjects.com/user_avatar/talk.remobjects.com/mh/32/18050_2.png) [@mh](https://talk.remobjects.com/u/mh)
#### Post date: [July 6, 2018, 12:18pm UTC](https://talk.remobjects.com/t/oxfuscator/16474/31 "2018-07-06T12:18:36Z")

</div>

EncryptStrings would probably best be a property of the `Obfuscate` attribute.

I’m not sure I like `@`. For one, it already has a meaning in Pascal (address of), for another, we cant use it in C# because there `@` already is a valid string prefix to disable escape chars (plus, it would be confusing for the same prefix to have different meanings in Pascal vs C#, for those of us who use both ;). But if we can diff a different prefix char, I’m all for the general syntax.

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 12:21pm UTC](https://talk.remobjects.com/t/oxfuscator/16474/32 "2018-07-06T12:21:01Z")

</div>

You are correct.  
@ was just an idea - any prefix (or whatever to encrypt one string) will do.  
We could also use the ` character (instead of ") for an encrypted string.

---

<div class="post-metadata">

### Author: ![mh](https://talk.remobjects.com/user_avatar/talk.remobjects.com/mh/32/18050_2.png) [@mh](https://talk.remobjects.com/u/mh)
#### Post date: [July 6, 2018, 12:25pm UTC](https://talk.remobjects.com/t/oxfuscator/16474/33 "2018-07-06T12:25:53Z")

</div>

Or even an attribute ON the string const

```auto
writeLn([Obfuscate]"secret string");

```

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 6, 2018, 12:26pm UTC](https://talk.remobjects.com/t/oxfuscator/16474/34 "2018-07-06T12:26:33Z")

</div>

Very nice!

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 7, 2018, 6:19am UTC](https://talk.remobjects.com/t/oxfuscator/16474/35 "2018-07-07T06:19:50Z")

</div>

Carlo, I was thinking that encryption is indeed too much overhead.  
But the goal is to make it unreadable - we could use a byte array for this.

1. Generate a method that converts a bytearray to a string using UTF32 encoding
2. Convert all strings to a byte array using UTF32 encoding

So in the code a string will get the form of:  
var myString := obfuscatedfunction([77, 0, 0, 0, 121, 0, 0, 0, 83, 0, 0, 0, 116, 0, 0, 0, 114, 0, 0, 0, 105, 0, 0, 0, 110, 0, 0, 0, 103, 0, 0, 0]);  
instead of  
var myString := “MyString”;

This will make it 100% unreadable.

Edit: Timing on this call: only 2 ms (on an 8 year old 2 Ghz AMD Opteron machine with 1333 Mhz DDR3 memory)

---

<div class="post-metadata">

### Author: ![ck](https://talk.remobjects.com/user_avatar/talk.remobjects.com/ck/32/8740_2.png) [@ck](https://talk.remobjects.com/u/ck)
#### Post date: [July 10, 2018, 8:11am UTC](https://talk.remobjects.com/t/oxfuscator/16474/36 "2018-07-10T08:11:09Z")

</div>

Yeah. something like that.

---

<div class="post-metadata">

### Author: ![Theo69](https://talk.remobjects.com/letter_avatar_proxy/v4/letter/t/35a633/32.png) [@Theo69](https://talk.remobjects.com/u/Theo69)
#### Post date: [July 10, 2018, 9:52am UTC](https://talk.remobjects.com/t/oxfuscator/16474/37 "2018-07-10T09:52:47Z")

</div>

> [@ck](#):
>
> Consider parameter names to be obfuscated (in todays build)

Just tested: it works.

---

<div class="post-metadata">

### Author: ![RemObjectsSoftware](https://talk.remobjects.com/user_avatar/talk.remobjects.com/remobjectssoftware/32/15947_2.png) [@RemObjectsSoftware](https://talk.remobjects.com/u/RemObjectsSoftware)
#### Post date: [July 20, 2018, 12:22pm UTC](https://talk.remobjects.com/t/oxfuscator/16474/38 "2018-07-20T12:22:09Z")

</div>

bugs://80509 got closed with status fixed.

---

<div class="post-metadata">

### Author: ![ck](https://talk.remobjects.com/user_avatar/talk.remobjects.com/ck/32/8740_2.png) [@ck](https://talk.remobjects.com/u/ck)
#### Post date: [August 3, 2018, 12:32pm UTC](https://talk.remobjects.com/t/oxfuscator/16474/39 "2018-08-03T12:32:53Z")

</div>

For string obfuscation:

```auto
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:

```auto

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:

```auto
        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

---

<div class="post-metadata">

### Author: ![ck](https://talk.remobjects.com/user_avatar/talk.remobjects.com/ck/32/8740_2.png) [@ck](https://talk.remobjects.com/u/ck)
#### Post date: [August 9, 2018, 8:31am UTC](https://talk.remobjects.com/t/oxfuscator/16474/40 "2018-08-09T08:31:47Z")

</div>

This works on all 4 platforms now, and is integrated in cirrus.

[Previous page](https://talk.remobjects.com/t/oxfuscator/16474.md?page=1)

[Next page](https://talk.remobjects.com/t/oxfuscator/16474.md?page=3)
