Archive for the ‘Chal15. CSharp’ Category


Download the challenge and use DIE to check it:

csharp_die

Huh .NET, I hate it! 107 Looking for strings, i found some interesting:

csharp_tobase64

csharp_strings

Run the challenge, input key and press check button:

csharp_wrong

Open this challenge in .NET Reflector and go to entry point:

private static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

Click on Form1() to open it:

public Form1()
{
    bb = base.GetType().GetMethod("MetMett", BindingFlags.NonPublic | BindingFlags.Static).GetMethodBody().GetILAsByteArray();
    byte num = 0;
    for (int i = 0; i < bb.Length; i++)
    {
        bb[i] = (byte) (bb[i] + 1);
        num = (byte) (num + bb[i]);
    }
    bb[0x12] = (byte) (num - 0x26);
    bb[0x23] = (byte) (num - 3);
    bb[0x34] = (byte) (num ^ 0x27);
    bb[0x45] = (byte) (num - 0x15);
    bb[0x57] = (byte) (0x47 - num);
    bb[0x7c] = (byte) (num ^ 0x72);
    bb[0x8d] = (byte) (num ^ 80);
    bb[0x9f] = (byte) (0xeb - num);
    bb[0xb3] = (byte) (0x6a + num);
    bb[200] = (byte) (0x24 - num);
    bb[220] = (byte) (num - 3);
    this.InitializeComponent();

In above code, i see that this code will be executed before calls InitializeComponent() – a method that shows the challenge GUI. I dont know what it does but i guess that it gets the body of MetMett method in byte array, save into bb and later use bb to calculate something.

Follow the InitializeComponent() method, then click on btnCheck_Click:

private void btnCheck_Click(object sender, EventArgs e)
{
    try
    {
        MetMetMet(this.txtAnswer.Text);
    }
    catch (Exception exception)
    {
        if (exception.InnerException == null)
        {
            MessageBox.Show(exception.Message, "Error");
        }
        else
        {
            MessageBox.Show(exception.InnerException.Message, "Error");
        }
    }
}

Follow MetMetMet method:

private static void MetMetMet(string sss)
{
    string str;
    byte[] bytes = Encoding.ASCII.GetBytes(Convert.ToBase64String(Encoding.ASCII.GetBytes(sss)));
    AssemblyName name = new AssemblyName("DynamicAssembly");
    TypeBuilder builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave).DefineDynamicModule(name.Name, name.Name + ".exe").DefineType("RevKrT1", TypeAttributes.Public);
    MethodBuilder builder2 = builder.DefineMethod("MetMet", MethodAttributes.Static | MethodAttributes.Private, CallingConventions.Standard, null, null);
    TypeBuilder builder3 = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave).DefineDynamicModule(name.Name, name.Name + ".exe").DefineType("RevKrT2", TypeAttributes.Public);
    builder3.DefineMethod("MetM", MethodAttributes.Static | MethodAttributes.Private, CallingConventions.Standard, null, new Type[] { typeof(byte[]), typeof(byte[]) }).CreateMethodBody(bb, bb.Length);
    Type type = builder3.CreateType();
    MethodInfo method = type.GetMethod("MetM", BindingFlags.NonPublic | BindingFlags.Static);
    object obj2 = Activator.CreateInstance(type);
    byte[] buffer2 = new byte[] { 1, 2 };
    method.Invoke(obj2, new object[] { buffer2, bytes });
    if (buffer2[0] == 1)
    {
        str = "Wrong";
    }
    else
    {
        str = "Correct!!";
    }
    ILGenerator iLGenerator = builder2.GetILGenerator();
    iLGenerator.Emit(OpCodes.Ldstr, str);
    iLGenerator.EmitCall(OpCodes.Call, typeof(MessageBox).GetMethod("Show", new Type[] { typeof(string) }), null);
    iLGenerator.Emit(OpCodes.Pop);
    iLGenerator.Emit(OpCodes.Ret);
    Type type2 = builder.CreateType();
    MethodInfo info2 = type2.GetMethod("MetMet", BindingFlags.NonPublic | BindingFlags.Static);
    object obj3 = Activator.CreateInstance(type2);
    info2.Invoke(obj3, null);
}

I see that, the btnCheck_Click pass input string to sss variable of MetMetMet, sss string is converted to Base64 String and saved into bytes. Then i see the comparison to show “Wrong” or “Correct!!” Nag.

Ok, next click to MetMett method, i get error:

csharp_error

Wtf, i dont know why!!after_boom Back to the Form1() method, i can confirm that the original bytes of MetMett method will be replaced at runtime to decode the method body. So we need to use dnSpy to debug this challenge to find the bb values at original and after calculate.

Open dnSpy, load challenge, set breakpoints same as the picture bellow:

csharp_dnspy

Press F5 to start, stop at the 1st bp, press F10 to step over. Go to locals window and find the value of bb (these values is the original bytes of MetMett method):

csharp_bbarray

Show bb array in the Memory Window:

csharp_bbinmem

Copy and Save all these bytes. Then, press F5 to continue and stop at the 2nd bp. The bb’s array values are replaced after calculate:

csharp_bbreplaced

Copy and Save all new values. Close dnSpy to stop debugging. Next, duplicate the challenge and use HxD (hex editor) to replace the original bytes of MetMett method by the calculated bytes like picture bellow:

csharp_hxd

Save file and close HxD. Re-open dnSpy and load new file, then click on MetMett method to decompile it:

private static void MetMett(byte[] chk, byte[] bt)
{
	if (bt.Length == 12)
	{
		chk[0] = 2;
		if ((bt[0] ^ 16) != 74)
		{
			chk[0] = 1;
		}
		if ((bt[3] ^ 51) != 70)
		{
			chk[0] = 1;
		}
		if ((bt[1] ^ 17) != 87)
		{
			chk[0] = 1;
		}
		if ((bt[2] ^ 33) != 77)
		{
			chk[0] = 1;
		}
		if ((bt[11] ^ 17) != 44)
		{
			chk[0] = 1;
		}
		if ((bt[8] ^ 144) != 241)
		{
			chk[0] = 1;
		}
		if ((bt[4] ^ 68) != 29)
		{
			chk[0] = 1;
		}
		if ((bt[5] ^ 102) != 49)
		{
			chk[0] = 1;
		}
		if ((bt[9] ^ 181) != 226)
		{
			chk[0] = 1;
		}
		if ((bt[7] ^ 160) != 238)
		{
			chk[0] = 1;
		}
		if ((bt[10] ^ 238) != 163)
		{
			chk[0] = 1;
		}
		if ((bt[6] ^ 51) != 117)
		{
			chk[0] = 1;
		}
	}
}

Wow doubt, i see the the simple xor calculation to check the value of bt[] array. So, to find the bt’s value, i also use xor loop like this:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int byte1[] = {16, 17, 33, 51, 68, 102, 51, 160, 144, 181, 238, 17};
    int byte2[] = {74, 87, 77, 70, 29, 49, 117, 238, 241, 226, 163, 44};
    char result[]={0};
    int i;

    for (i=0; i<(sizeof(byte1)/sizeof(int)); i++)
    {
        result[i] = byte1[i] ^ byte2[i];
    }

    printf("The result is: %s \n", result);
    return 0;
}

Compile and run this code, i get the Base64 string: ZFluYWFNaWM=. Use Base64 to decode this string, i get the flag: dYnaaMic.

Check the flag 36:

csharp_checkflag

End.