Jump to content
Tuts 4 You

[keygenme] Catch-When


Recommended Posts

Posted

This is a simple keygenme designed to show a new feature in C# 6.0 (VS2015): catch-when exception filters. It's a part of my blog post.


 


.NET Framework version: 2.0


Obfuscation: none, written in pure C#


Difficulty: 2/10, should not take more than 30 minutes for a skilled reverser;


 


Rules:


#1 - It's a keygenme, so valid solution is a keygen (or valid username/pass, if you're really lazy).


#2 - Please, please spend few minutes describing how you solved it. It will help everyone else to learn.


#3 - Don't waste your time patching few bytes - you will not learn anything that way.


#4 - Have fun!


 


Cheers,


kao.


CatchMeWhen.zip

  • Like 3
Posted (edited)

1 - searched in google about "endfilter" instruction , and found this 


 



Value (which must be of type int32 and is one of a specific set of values) is returned from the filter clause. It should be one of:


 



  • exception_continue_search (value = 0) to continue searching for an exception handler


  • exception_execute_handler (value = 1) to start the second phase of exception handling where finally blocks are run until the handler associated with this filter clause is located. Upon discovery, the handler is executed.

 



 


so all the return value mus be "false" for all condition to push 0 to stack.


to write encryption function i identified the fixed piece of code (initializing arrays) and reverse the other,


,my english isn't so rich and good so this is what i can write it 


encryption function 



private static string Encrypt(string name)
{
byte[] array = Encoding.UTF8.GetBytes(name+Convert.ToChar(0));
byte[] array2 = new byte[]
{
1,
2,
3,
4,
5,
6,
7,
8
};
byte[] array3 = new byte[256];
byte[] array4 = new byte[256];
int i;
for (i = 0; i < 256; i++)
{
array3[i] = (byte)i;
array4[i] = array2[i % array2.GetLength(0)];
}
int num = 0;
for (i = 0; i < 256; i++)
{
num = (num + (int)array3[i] + (int)array4[i]) % 256;
byte b = array3[i];
array3[i] = array3[num];
array3[num] = b;
}
num = (i = 0);
for (int j = 0; j < array.GetLength(0); j++)
{ i = (i + 1) % 256;
num = (num + (int)array3[i]) % 256;
byte b = array3[i];
byte[] expr_FB_cp_0 = array;
int expr_FB_cp_1 = j;
int num2 = (int)(array3[i] + array3[num]) % 256;
expr_FB_cp_0[expr_FB_cp_1] ^= array3[num2];
array3[i] = array3[num];
array3[num] = b; }
return Convert.ToBase64String(array);
}

username : n0th!ng


password : +Zv+c9HB3mE=


Edited by n0th!ng
  • Like 3
Posted (edited)

Here is my analysis / keygen..


 


The catch-when flow is setup like this:



Exception Handler Chain
-----------------------------------------------------------------------------------------------------------------------------------------------------
    preshorten -> Adds our entered data into the exceptions data directory. (Name = converted to UTF8 bytes, Pass = converted from base64 string)
    snitchier  -> Ensures that the user has entered text.
    nonego     -> RC4 decrypts the given password.
    lariat     -> Takes the username and password data and compares byte by byte to ensure data matches. (Last byte must be 0!)
    emogene    -> Ensures that we have data set to 'Beat' data object.
    carya      -> Checks if the 'Beat' data is set to greater then 0. (We want it to be 0.)
    <normal>   -> Normal catch handler; if this is hit, we are good.

So for me working key is:


User: atom0s


Pass: 9t/ldsDcuQ==


 


Attached is a basic keygen.


 


Edit - Updated keygen to use x86 so it will run on any machine.


keygen.7z

Edited by atom0s
  • Like 4
Posted

Very nicely done, both of you! Great explanations as well. :) 


Just out of curiosity - what tools (decompiler) did you use?


 


This is how original code looked like:



private void button1_Click(object sender, EventArgs e)
{
    try
    {
        int a = 0;
        int b = 1;
        int c = b / a;
    }
    catch (Exception ex) when (preshorten(ex)) { }
    catch (Exception ex) when (snitchier(ex)) { }
    catch (Exception ex) when (nonego(ex)) { }
    catch (Exception ex) when (lariat(ex)) { }
    catch (Exception ex) when (emogene(ex)) { }
    catch (Exception ex) when (carya(ex)) { }
    catch
    {
        MessageBox.Show("good boy");
    }
}

  • Like 1
Posted

Very nicely done, both of you! Great explanations as well. :)

Just out of curiosity - what tools (decompiler) did you use?

 

This is how original code looked like:

private void button1_Click(object sender, EventArgs e)

{

    try

    {

        int a = 0;

        int b = 1;

        int c = b / a;

    }

    catch (Exception ex) when (preshorten(ex)) { }

    catch (Exception ex) when (snitchier(ex)) { }

    catch (Exception ex) when (nonego(ex)) { }

    catch (Exception ex) when (lariat(ex)) { }

    catch (Exception ex) when (emogene(ex)) { }

    catch (Exception ex) when (carya(ex)) { }

    catch

    {

        MessageBox.Show("good boy");

    }

}


I used ILSpy 2.0.0.1564, this version allows you to debug assembly.

Posted

For me I used Reflector 8.5.0.179. It will show the catch/when setup but without the actual calls/code. So I changed to IL view and just following the code flow to determine what function was called when. Does not seem like catch-when is fully implemented yet. But Reflector seems to do the best job showing part of it so far. 


  • Like 1
Posted

@yck: thanks, looks nice, but I can't manage to compile it properly. ;) Submodules in your repo are at different revisions, so if I just compile DNSpy and then replace ICSharpCode.Decompiler.DLL (or all DLLs from ICSharpCode.Decompiler project), DNSpy won't start at all.

Posted

You might just do a diff on the last 2 commits, and apply it on your version of ILSpy. Anyways, I'll upload my binaries for you. :)


dnExplorer.zip

  • Like 7

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