#1 — Cracking A Simple Crackme

This blog is going to be a saga of my journey into reverse engineering. Before we proceed, I want to set some ground rules:

  1. I am absolutely not a malicious code author and never will be one. However, I will be learning a lot about how malicious code works during the course of my journey so that I can help fight it as much as possible. As the saying goes, sometimes you have to fight fire with fire.
  2. I’ve discovered my true passion in life/tech (as if they’re the same, lol) is reverse-engineering software, and more specifically, I’m going to be getting into reverse engineering, analyzing, and researching malware. In order to do it effectively, one must first learn to reverse engineer in general, x86–84 assembly, and operating system programming, all of which I have learned some of already and will be continuing my education indefinitely.
  3. I will be posting this disclaimer on every post: This post is intended for educational purposes only. I am not responsible for any damages (personal or property) incurred by software mentioned in this post or advice followed from this post. Read, click, run executables, and follow along at your own risk!
  4. Let’s get to it and have some fun!

Link: https://tuts4you.com/download.php?view.2064

  1. I downloaded this Crackme and immediately ran it through FileAlyzer, went to the “PE Imports” tab and immediately noticed that the only important was _CorExeMain . FileAlyzer has a nice feature where if you right-click it, you can do a 1-click check on MSDN but this import is what launches the .NET CLR — BINGO! This is not a native executable, it’s a CLR assembly.
  2. I ran strings on the crackme as well and discovered several obvious clues that this was written in VB.NET such as the following strings:
mscorlib
Microsoft.VisualBasic
WindowsFormsApplicationBase
Dispose__Instance__
GetInstance
Dispose
disposing
System.ComponentModel
IContainer
components
InitializeComponent
Button

Blah blah blah, anyone who has programmed in .NET would recognize that this is a .NET file.

3. I opened the file in ILSpy — a .NET assembly decompiler that takes .NET Common Intermediate Language (CIL, formerly MSIL) code and tries to turn it back into C# or VB.NET Code.

4. I examined the project’s structure using the left navigation pane and quickly found that there wasn’t much of any substance other than the Form1 file, which from prior experience, I knew is where the code is placed (by default) for the “Windows Form” application, what .NET calls a traditional Windows-style application. The file is quite large for a blog post but I’ll go ahead and post it up here so you can see what I was looking at:

namespace My_Crackme
{
[DesignerGenerated]
public class Form1 : Form
{
private IContainer components;

[AccessedThroughProperty("Button1")]
private Button _Button1;

[AccessedThroughProperty("Button2")]
private Button _Button2;

[AccessedThroughProperty("TextBox1")]
private TextBox _TextBox1;

[AccessedThroughProperty("Label1")]
private Label _Label1;

[AccessedThroughProperty("Label2")]
private Label _Label2;

[AccessedThroughProperty("TextBox2")]
private TextBox _TextBox2;

[AccessedThroughProperty("Button3")]
private Button _Button3;

internal virtual Button Button1
{
[DebuggerNonUserCode]
get
{
return this._Button1;
}
[DebuggerNonUserCode]
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
if (this._Button1 != null)
{
this._Button1.Click -= new EventHandler(this.Button1_Click);
}
this._Button1 = value;
if (this._Button1 != null)
{
this._Button1.Click += new EventHandler(this.Button1_Click);
}
}
}

internal virtual Button Button2
{
[DebuggerNonUserCode]
get
{
return this._Button2;
}
[DebuggerNonUserCode]
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
if (this._Button2 != null)
{
this._Button2.Click -= new EventHandler(this.Button2_Click);
}
this._Button2 = value;
if (this._Button2 != null)
{
this._Button2.Click += new EventHandler(this.Button2_Click);
}
}
}

internal virtual TextBox TextBox1
{
[DebuggerNonUserCode]
get
{
return this._TextBox1;
}
[DebuggerNonUserCode]
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
this._TextBox1 = value;
}
}

internal virtual Label Label1
{
[DebuggerNonUserCode]
get
{
return this._Label1;
}
[DebuggerNonUserCode]
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
if (this._Label1 != null)
{
this._Label1.Click -= new EventHandler(this.Label1_Click);
}
this._Label1 = value;
if (this._Label1 != null)
{
this._Label1.Click += new EventHandler(this.Label1_Click);
}
}
}

internal virtual Label Label2
{
[DebuggerNonUserCode]
get
{
return this._Label2;
}
[DebuggerNonUserCode]
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
this._Label2 = value;
}
}

internal virtual TextBox TextBox2
{
[DebuggerNonUserCode]
get
{
return this._TextBox2;
}
[DebuggerNonUserCode]
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
this._TextBox2 = value;
}
}

internal virtual Button Button3
{
[DebuggerNonUserCode]
get
{
return this._Button3;
}
[DebuggerNonUserCode]
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
if (this._Button3 != null)
{
this._Button3.Click -= new EventHandler(this.Button3_Click);
}
this._Button3 = value;
if (this._Button3 != null)
{
this._Button3.Click += new EventHandler(this.Button3_Click);
}
}
}

[DebuggerNonUserCode]
public Form1()
{
this.InitializeComponent();
}

[DebuggerNonUserCode]
protected override void Dispose(bool disposing)
{
if (disposing && this.components != null)
{
this.components.Dispose();
}
base.Dispose(disposing);
}

[DebuggerStepThrough]
private void InitializeComponent()
{
this.Button1 = new Button();
this.Button2 = new Button();
this.TextBox1 = new TextBox();
this.Label1 = new Label();
this.Label2 = new Label();
this.TextBox2 = new TextBox();
this.Button3 = new Button();
this.SuspendLayout();
Control arg_68_0 = this.Button1;
Point location = new Point(67, 187);
arg_68_0.Location = location;
this.Button1.Name = "Button1";
Control arg_8F_0 = this.Button1;
Size size = new Size(75, 23);
arg_8F_0.Size = size;
this.Button1.TabIndex = 0;
this.Button1.Text = "Register?";
this.Button1.UseVisualStyleBackColor = true;
Control arg_D4_0 = this.Button2;
location = new Point(159, 187);
arg_D4_0.Location = location;
this.Button2.Name = "Button2";
Control arg_FB_0 = this.Button2;
size = new Size(75, 23);
arg_FB_0.Size = size;
this.Button2.TabIndex = 1;
this.Button2.Text = "Exit";
this.Button2.UseVisualStyleBackColor = true;
Control arg_13A_0 = this.TextBox1;
location = new Point(67, 102);
arg_13A_0.Location = location;
this.TextBox1.Name = "TextBox1";
Control arg_164_0 = this.TextBox1;
size = new Size(167, 20);
arg_164_0.Size = size;
this.TextBox1.TabIndex = 2;
this.Label1.AutoSize = true;
Control arg_193_0 = this.Label1;
location = new Point(64, 86);
arg_193_0.Location = location;
this.Label1.Name = "Label1";
Control arg_1BA_0 = this.Label1;
size = new Size(87, 13);
arg_1BA_0.Size = size;
this.Label1.TabIndex = 3;
this.Label1.Text = "Registration Key:";
this.Label2.AutoSize = true;
Control arg_1FC_0 = this.Label2;
location = new Point(12, 243);
arg_1FC_0.Location = location;
this.Label2.Name = "Label2";
Control arg_226_0 = this.Label2;
size = new Size(195, 13);
arg_226_0.Size = size;
this.Label2.TabIndex = 4;
this.Label2.Text = "Super easy CrackMe By Cameron Ward";
Control arg_259_0 = this.TextBox2;
location = new Point(98, 50);
arg_259_0.Location = location;
this.TextBox2.Name = "TextBox2";
this.TextBox2.ReadOnly = true;
Control arg_28C_0 = this.TextBox2;
size = new Size(95, 20);
arg_28C_0.Size = size;
this.TextBox2.TabIndex = 5;
this.TextBox2.Text = "UNREGISTERED!";
Control arg_2C2_0 = this.Button3;
location = new Point(87, 158);
arg_2C2_0.Location = location;
this.Button3.Name = "Button3";
Control arg_2EC_0 = this.Button3;
size = new Size(136, 23);
arg_2EC_0.Size = size;
this.Button3.TabIndex = 6;
this.Button3.Text = "Yay you are Registered!";
this.Button3.UseVisualStyleBackColor = true;
this.Button3.Visible = false;
SizeF autoScaleDimensions = new SizeF(6f, 13f);
this.AutoScaleDimensions = autoScaleDimensions;
this.AutoScaleMode = AutoScaleMode.Font;
size = new Size(284, 265);
this.ClientSize = size;
this.Controls.Add(this.Button3);
this.Controls.Add(this.TextBox2);
this.Controls.Add(this.Label2);
this.Controls.Add(this.Label1);
this.Controls.Add(this.TextBox1);
this.Controls.Add(this.Button2);
this.Controls.Add(this.Button1);
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.Name = "Form1";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "Cameron's super easy Crackme";
this.ResumeLayout(false);
this.PerformLayout();
}

private void Label1_Click(object sender, EventArgs e)
{
}

private void Button1_Click(object sender, EventArgs e)
{
if (Operators.CompareString(this.TextBox1.Text, "408994", false) == 0)
{
MessageBox.Show("Congratulations you Registered!", "Nice Work!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
this.TextBox2.Text = "REGISTERED!";
this.Button1.Enabled = false;
this.Button3.Visible = true;
}
else
{
MessageBox.Show("Sorry incorrect Registry key, Try again : )", "Bad Luck", MessageBoxButtons.OK, MessageBoxIcon.Hand);
this.TextBox2.Text = "UNREGISTERED!";
}
}

private void Button2_Click(object sender, EventArgs e)
{
this.Close();
}

private void Button3_Click(object sender, EventArgs e)
{
}
}
}

If you skimmed through, you can pretty much figure out the rest… This is probably why it was called a super easy crackme. At this point, I looked for an event handler for a button and found the solution —

private void Button1_Click(object sender, EventArgs e)
{
if (Operators.CompareString(this.TextBox1.Text, "408994", false) == 0)

Clearly, we see that the text placed in TextBox1 will be compared with 408994 and if the comparison comes up as “not false” (making it equal zero), then we’re in. It’s important to note here that this is not likely how the code was written by Cameron, which is why it reads funny (“not false”) rather than just checking for a true statement, but decompilers still often get the job done.

The final step was running the program and trying the number, which succeeded! BINGO:

I want to note that I’ve worked through this crackme in the exact way described. I’m going to always write my steps exactly how I perform them so that I illustrate how I think and approach these problems rather than give a summary of the best case in the blog post. E.G. I actually did not run the crackme until after I discovered the registration key! Last but not least, some interesting info can also be extracted from all of the variable assignments that are smashed together in the Form1 file. Go read through it and see what you can come up with! Until next time!