Jump to content
Tuts 4 You

Analysis of changes in .Net Reactor 6


Recommended Posts

Kingmaker_oo7
Posted (edited)

Necrobit

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)

Spoiler

We are looking for a problematic instruction

spacer.png

Go to IL

spacer.png

Nop call and change brfalse to br.s

spacer.png

As you can see, the cocoa is gone))

spacer.png

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;

                                        arithmeticSolved++;
                                    }
                                    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

Spoiler


  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))

Spoiler

We see that the system methods are hidden

spacer.png

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

spacer.png

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

spacer.png

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);
    }
    binary.Close();

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))

spacer.png

 

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
Posted

Nice post VEL007, good information! 💯

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...