Jump to content
Tuts 4 You

Analysis of changes in .Net Reactor 6


Recommended Posts



To mess up the old de4dot implementation, the .Net reactor changed the P / Invoke methods, but for the unpack, you can use the SMD from Code Cracker, which will do an excellent job of this.

Control Flow

To break de4dot.blocks, ezriz added a number of instructions to the flow cases, which de4dot cannot process, it's easy to fix it, just repeat after me)


We are looking for a problematic instruction


Go to IL


Nop call and change brfalse to br.s


As you can see, the cocoa is gone))


The whole thing can be automated with my favorite dnlib

  for (int i = 0; i < method.Body.Instructions.Count; i++)
                                    bool flag = method.Body.Instructions[i].OpCode == OpCodes.Brfalse && method.Body.Instructions[i + 1].OpCode == OpCodes.Pop && method.Body.Instructions[i - 1].OpCode == OpCodes.Call;
                                    if (flag)
                                        method.Body.Instructions[i - 1].OpCode = OpCodes.Nop;
                                        method.Body.Instructions[i ].OpCode = OpCodes.Br_S;

                                    bool flag6 = method.Body.Instructions[i].OpCode == OpCodes.Brtrue && method.Body.Instructions[i + 1].OpCode == OpCodes.Pop && method.Body.Instructions[i - 1].OpCode == OpCodes.Call;
                                    if (flag6)
                                        method.Body.Instructions[i - 1].OpCode = OpCodes.Nop;
                                        method.Body.Instructions[i].OpCode = OpCodes.Br_S;


After that, we just banish it with our favorite de4dot, and the flow was gone)



String Encrypt

Ezriz changed the resource encryption algorithm for strings, which messed up the old decryptor implementation.

This problem is solved by dynamic emulation of the method, with obtaining LDC.I4 values for initializing the decrypt method, I will show an example of getting MethodDef by the Call dnlib operand


  private static MethodInfo GetStringMethod(int MethodToken, Assembly asm)
            MethodInfo info = (MethodInfo)asm.ManifestModule.ResolveMethod(MethodToken);
            if (info.IsGenericMethodDefinition || info.IsGenericMethod)
                return info.MakeGenericMethod(new Type[] { typeof(string) });
            return info;

How to get MD token

GetStringMethod((int)((MethodSpec)method.Body.Instructions[i].Operand).Method.MDToken.Raw, second_module);

How to invoke a method

   int intergerevalue1 = (int)method.Body.Instructions[i - 0x1].GetLdcI4Value();
   string returnedstring = methodx.Invoke(null, new object[] { intergerevalue1 });

Replace the result

  if (returnedstring != null)
                                    method.Body.Instructions[i - 1].OpCode = OpCodes.Nop;
                                    method.Body.Instructions[i].OpCode = OpCodes.Ldstr;
                                    method.Body.Instructions[i].Operand = (string)returnedstring;

As you can see, nothing complicated))


Hide Methods Calls NEW!

New reactor protection, taken half from open source fuser.

The bottom line is that system methods are initialized from delegates.

It sounds scary, let's try to figure it out))


We see that the system methods are hidden


As arguments, a parameter for the system method and field are passed
Let's move on to the method initialization method)


The first step is the resource decrypt for delegates, I'm too lazy to write the implementation of the decryptor, so I'll just take the byte array at runtime We put a breakpoint


Click start and go to the local variables window

spacer.pngDump array, resources have been decrypted, hurray)
Dachshund, now let's put everything together and write the damn decryptor))
We initialize the required dictionary, remember that byte array that we stole?)))


  byte[] array = File.ReadAllBytes("The path to the file that you dumped");
  Dictionary<int, int> keys = new Dictionary<int, int>();
  int num23 = array.Length / 8;
  BinaryReader binary = new BinaryReader(new MemoryStream(array));
  for (int l = 0; l < num23; l++)
    int key = binary.ReadInt32();
    int value = binary.ReadInt32();
    dictionary.Add(key, value);

First, we get Fied, with which we will initialize our future call

  int fieldDef = (int)((FieldDef)method.Body.Instructions[i - 1].Operand).MDToken.Raw;

Then we just get MethodDef

 int num24 = keys[fieldDef];
          bool flag2 = (num24 & 1073741824) > 0;
           num24 &= 1073741823;
           MethodInfo methodInfo = (MethodInfo)assembly.ManifestModule.ResolveMethod(num24);

Decryptuli, hurray)
Replace our call

MethodBase methodBase = assembly.ManifestModule.ResolveMethod(num24);
method.Body.Instructions[i - 1].OpCode = OpCodes.Nop;
method.Body.Instructions[i] = new Instruction(OpCodes.Call, module.Import(methodBase));

We drive away, and a miracle)
Calls are normal again))



Well, we won the new reactor, I hope you enjoyed this article, thanks for reading))



                                                                                         All The  Credit Goes to   Eshelon Mayskih

Edited by VEL007
  • Like 9
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...