kao Posted April 8, 2015 Posted April 8, 2015 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.0Obfuscation: 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 3
n0th!ng Posted April 8, 2015 Posted April 8, 2015 (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 handlerexception_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!ngpassword : +Zv+c9HB3mE= Edited April 8, 2015 by n0th!ng 3
atom0s Posted April 8, 2015 Posted April 8, 2015 (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: atom0sPass: 9t/ldsDcuQ== Attached is a basic keygen. Edit - Updated keygen to use x86 so it will run on any machine.keygen.7z Edited April 8, 2015 by atom0s 4
kao Posted April 8, 2015 Author Posted April 8, 2015 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"); } } 1
n0th!ng Posted April 8, 2015 Posted April 8, 2015 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.
atom0s Posted April 8, 2015 Posted April 8, 2015 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. 1
yck1509 Posted April 9, 2015 Posted April 9, 2015 Just for you https://github.com/yck1509/ICSharpCode.Decompiler/commit/20c40b08a2e89995798fa3a6d323f171ff677fd6 2
kao Posted April 9, 2015 Author Posted April 9, 2015 @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.
yck1509 Posted April 9, 2015 Posted April 9, 2015 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 7
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now