Reverse Engineering

Challenge
Topic

C#, Obfuscated, Harmony

C0d3_Fu5 (499 pts)

Description

-

Solution

Given C# executable that hardly obfuscated.

Through running the executable, we can see that there is a form created.

We can see that there is a button, but it is disabled. Since it is a crackme challenge, let's try to enable it. First, search variable with Button data type in decompiler, i use dnSpyEx.

If we take a look on Button constructor, we can see that it use setStyle from Control class. Through debugging createParams i found a way to enable the Button which is by forcing the properties enabled to True. So the easiest way i think to modify it is by setting breakpoint on Enabled setter and change the value to True.

Now, TEST is clickable, but when i clicked it it doesnt show flag.

Back to the class where Button lied, we found that there is TextBox, let's try to set breakpoint on getter of Text for TextBox Class.

Continue the process and right before showing Wrong Flag, the breakpoint on Text getter will be hitted. Doing step in we will see that the text value is empty "".

If we continue to step in, the debugger will crash. By looking at the stack trace we know that probably it crashes because the caller function is a native function.

But now, at least we've a nudge from a stack trace regarding what is the function actually did

  • FUCKED_BY_AD3M_XTN\u1160\u1160\u1160\u1160\u1160FUCKED_BY_AD3M_XTNNBFUCKED_BY_AD3M_XTN\u1160\u1160\u1160\u1160\u1160FUCKED_BY_AD3M_XTNNBFUCKED_BY_AD3M_XTN\u1160\u1160\u1160\u1160\u1160FUCKED_BY_AD3M_XTN.e\u0015\u0015;|(A_0);

    • TextBox.Text()

The next step we need to do is deobfuscating the initialization of function. Let's try with function that we found earlier, analyze function e\u0015\u0015;| and take a look on assigned by.

Take a look at function FUCKED_BY_AD3M_XTN\u1160\u1160\u1160\u1160\u1160FUCKED_BY_AD3M_XTNIcFUCKED_BY_AD3M_XTN\u1160\u1160\u1160\u1160\u1160FUCKED_BY_AD3M_XTNIcFUCKED_BY_AD3M_XTN\u1160\u1160\u1160\u1160\u1160FUCKED_BY_AD3M_XTN and we can see that the function is creating a dynamic function.

Setting up breakpoint on that function then we can get a brief idea about the function obfuscation things.

We can print IL from that code by using dncil .

In this context, through array4 construction, we can see that callvirt is calling get_Text() and castclass is System.Windows.Forms.Control. So we can conclude that the function is resolving function, argument, and type then creating a dynamic method for it. But If we take a look on another function, we can see also that that there is a function that doesn't need to create a dynamic method but just doing a delegation by calling following code fieldFromHandle.SetValue(null, Delegate.CreateDelegate(fieldType, (MethodInfo)methodBase));. Until this step, we can get several functions that we can use to dump the actual behavior of the program, such as following

  • System.Reflection.Module.ResolveMethod

    • returned data is a function that probably a function that will be delegated to obfuscated function

  • System.Reflection.FieldInfo.GetFieldFromHandle

    • argument can be used to derive fieldInfo which is useful to trace modified function

  • System.Reflection.FieldInfo.SetValue

    • last step of reflection, setting field's value

  • System.Reflection.Emit.DynamicILInfo.SetCode

    • the first argument is the bytecode of the newly created dynamic method

With this information, now we can create automation to dump information needed to understand the actual flow. Previously i've been facing an issue with automation in C# reverse engineering because of dnSpy limitation, so i choose to use Harmonyarrow-up-right to do the automation part.

Next, debug the program with dnSpy then do the same action (change enabled to True). After that detach the program then run the injector.

Click TEST then we'll get following dump in log.txt.

Now, we've several option to continue the analysis, we can setup breakpoint on imported functions or we can setup breakpoint on the known obfuscated function. But since setting up breakpoint using dnSpy on obfuscated function make it failed to detect the local variables so i decided to setup breakpoint on imported functions. Filter the imported functions and we can see list of functions such as following

Set up breakpoint on several imported function above

When the breakpoint hits, looking at the call stack, we can see several native functions that will make dnSpy crash if we double click on it (or trying to decompile it using dnSpy). So let's dump those native function and decompile it using IDA.

The decompiled result will looks bad, but we still can understand the big picture of it. The idea is by tracing through call stack when breakpoint on imported function hit.

Example in image above we can see that address 0x0B0334A8+0x5E6 is return from Split function call in native function so we can create comment on it (would be nice if we can create struct but too lazy at the moment).

Next, just reconstruct the algorithm in python. To get the modulus, we can do the same approach because the program convert it from Double using internal windows function.

If we take a look on existing values, we can see that cmp2 length has different length with unk length so probably unk is our input since variable res or key will not affect the length. With this assumption so let's try to create the decryption.

Flag: Securinets{N1c3_C#_Sk1llz_But_C4n_Y0u_H4ndl3_Th1s_0n3}

Last updated