Archive for February, 2017


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.

 


Open ReadMe file:

Reversing.Kr

Find The Password

By ezbeat

Use DIE to scan target:

hateintel_die

Result: Type: MACH, and compiler is GCC, so I guess that the author use MacOS to code and compile this challenge. I’ve never reversing target like this challenge before, … shame on me!! adore

I don’t know how to use the other tools to reverse this challenge, so i open it in IDA and let’s IDA analyze it. Go to main function at 0x00002224, I see the ARM instructions. Use Hex-Rays Decompiler plugin to gets pseudo code:

int __cdecl main(int argc, const char **argv, const char **envp)
{
char InputKey[80]; // [sp+4h] [bp-5Ch]@1
int Value_4; // [sp+54h] [bp-Ch]@1
signed __int32 Len_InputKey; // [sp+58h] [bp-8h]@1
signed __int32 i; // [sp+5Ch] [bp-4h]@1
char vars0; // [sp+60h] [bp+0h]@2

Value_4 = 4;
printf("Input key : ", argv, envp);
scanf("%s", InputKey);
Len_InputKey = strlen(InputKey);
Calculate((signed __int32)InputKey, Value_4);
for ( i = 0; i < Len_InputKey; ++i )
{
if ( (unsigned __int8)*(&vars0 + i - 0x5C) != validate_value[i] )
{
puts("Wrong Key! ");
return 0;
}
}
puts("Correct Key! ");
return 0;
}

Notice sub_232C, i renamed it to Calculate. The Calculate’s pseudo code:

signed __int32 __fastcall Calculate(signed __int32 Input_Len, int Value_4)
{
  int Loop_Size; // [sp+0h] [bp-14h]@1
  char *InputKey; // [sp+4h] [bp-10h]@1
  int i; // [sp+8h] [bp-Ch]@1
  signed __int32 j; // [sp+Ch] [bp-8h]@2

  InputKey = (char *)Input_Len;
  Loop_Size = Value_4;                          // Loop_Size=4
  for ( i = 0; i < Loop_Size; ++i )
  {
    for ( j = 0; ; ++j )
    {
      Input_Len = strlen(InputKey);
      if ( Input_Len <= j )
        break;
      InputKey[j] = ProcessChar(InputKey[j], 1);
    }
  }
  return Input_Len;
}

Calculate function calls other function is sub_2494, i renamed it to ProcessChar. The Calculate function performs with the iteration loop is 4 times, each time it performs calculation loop on each character of input Key.

ProcessChar’s pseudo code is so simple:

int __fastcall ProcessChar(unsigned __int8 Input, int Value_1)
{
  int Input_Char; // [sp+8h] [bp-8h]@1
  int i; // [sp+Ch] [bp-4h]@1

  Input_Char = Input;
  for ( i = 0; i < Value_1; ++i )
  {
    Input_Char *= 2;
    if ( Input_Char & 0x100 )
      Input_Char |= 1u;
  }
  return (unsigned __int8)Input_Char;
}

Then the result of each character in InputKey is compared to each value of default table (i renamed to validate_value). In IDA, i found the values of validate_value[]:

hateintel_validate_value

validate_value = [0x44, 0xF6, 0xF5, 0x57, 0xF5, 0xC6, 0x96, 0xB6, 0x56, 0xF5, 0x14, 0x25, 0xD4, 0xF5, 0x96, 0xE6, 0x37, 0x47, 0x27, 0x57, 0x36, 0x47, 0x96, 0x03, 0xE6, 0xF3, 0xA3, 0x92]

Okay, i have all info to find the key!! 36

So here is the simple code to find the correct Key:

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

int main()
{
    int defArray[29] = {0x44, 0xF6, 0xF5, 0x57, 0xF5, 0xC6, 0x96, 0xB6, 0x56, 0xF5, 0x14, 0x25, 0xD4, 0xF5, 0x96, 0xE6, 0x37, 0x47, 0x27, 0x57, 0x36, 0x47, 0x96, 0x03, 0xE6, 0xF3, 0xA3, 0x92};
    int i, j, k, ch, result, temp;
    char Flag[29]={0};

    result = 0;
    for (k=0; k<29;k++)
{
    for (i=32; i<128; i++)
    {
        ch = i;
        for (j=0; j<4; j++)
        {
            temp = ch*2;
            if (temp & 0x100)
                temp |= 1;
            ch = temp & 0xFF;
        }
        if (ch == defArray[result])
        {
            Flag[result] = i;
            result++;
        }
    }
}

    printf("Found Flag: \n %s", Flag);
    return 0;
}

Final Result:

hateintel_findkey

End.