Jump to content
Tuts 4 You

small, simple crackme


DefCon42

Recommended Posts

People who patch this instead of trying to find the key are boring :^)

 

Language : C++
Platform : Windows x64
OS Version : Windows 10
Packer / Protector : None

Description :

This is a simple crackme i made over the course of the last 30 minutes. Hopefully you get a little fun out of it.
 

Screenshot :

crackme_img_1.png.0a119e8c916d5408d0277d9e893ff243.png

crackme_img_2.png.805136964bff3a43a177ec98e382b264.png
 

crackme.exe

Link to post
VirtualPuppet

There are many working keys. One of them is "$^CQE!#(Mrfe%&&$":

image.png.8cae15324ba0e75c7d3d3b06f87f878e.png

 

The key was brute forced using a quickly written C++ executable:

image.png.1b2c158f408f5826ad121cdd59a52805.png

 

The code for the C++ executable is as follows:

Spoiler

 


#include <iostream>
#include <stdint.h>

#include <array>
#include <functional>

bool isallowed(char c)
{
	return (c != '"' && c != ' ');
}

bool check_keys(double additive_key, char k0, char k1, char k2, char k3)
{
	double product = additive_key +
		(static_cast<double>(k3) * 0.2254315957569856) +
		(static_cast<double>(k2) * -0.06225786672735933) +
		(static_cast<double>(k1) * 0.06576137583312501) +
		(static_cast<double>(k0) * -0.2174719016579794) +
		0.0;
	
	return (product > 0.00001 || product < -0.00001);
}

bool bruteforce(std::array<char, 16>& key, std::array<int, 4> indices, double additive_key)
{
	for (int a = 0; a < 256; a++) 
	{
		for (int b = 0; b < 256; b++) 
		{
			for (int c = 0; c < 256; c++) 
			{
				for (int d = 0; d < 256; d++)
				{
					if (isallowed(a) && isallowed(b) && isallowed(c) && isallowed(d))
					{
						if (!check_keys(additive_key, a, b, c, d) && isprint(a) && isprint(b) && isprint(c) && isprint(d))
						{
							std::cout << "Found partial key match!" << std::endl
								<< "a = " << a << "('" << static_cast<char>(a) << "')" << std::endl
								<< "b = " << b << "('" << static_cast<char>(b) << "')" << std::endl
								<< "c = " << c << "('" << static_cast<char>(c) << "')" << std::endl
								<< "d = " << d << "('" << static_cast<char>(d) << "')" << std::endl
								<< std::endl;

							key[indices[0]] = a;
							key[indices[1]] = b;
							key[indices[2]] = c;
							key[indices[3]] = d;
							return true;
						}
					}
				}
			}
		}
	}

	std::cout << "Could not bruteforce the selected keypart!" << std::endl;
	return false;
}

void printkey(std::array<char, 16> const& key)
{
	std::cout << "Current key:" << std::endl;

	for (char const& ch : key)
	{
		if (ch == 0)
			std::cout << "_";
		else
			std::cout << ch;
	}

	std::cout << std::endl;
	std::cout << std::endl;
}

int main(int argc, char* argv[])
{
	std::array<char, 16> key = { 0 };
	printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 0, 4, 8, 12 }}, -0.255666))
		printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 1, 5, 9, 13 }}, 16.80323))
		printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 2, 6, 10, 14 }}, 10.05288))
		printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 3, 7, 11, 15 }}, 13.157277))
		printkey(key);

	std::cout << "Finished bruteforce!" << std::endl;
	std::cin.ignore();
	std::cin.get();
	return 0;
}

 

Edited by VirtualPuppet (see edit history)
  • Like 1
Link to post
4 hours ago, VirtualPuppet said:

There are many working keys. One of them is "$^CQE!#(Mrfe%&&$":

image.png.8cae15324ba0e75c7d3d3b06f87f878e.png


 

The key was brute forced using a quickly written C++ executable:

image.png.1b2c158f408f5826ad121cdd59a52805.png


 

The code for the C++ executable is as follows:

  Hide contents


 



#include <iostream>
#include <stdint.h>

#include <array>
#include <functional>

bool isallowed(char c)
{
	return (c != '"' && c != ' ');
}

bool check_keys(double additive_key, char k0, char k1, char k2, char k3)
{
	double product = additive_key +
		(static_cast<double>(k3) * 0.2254315957569856) +
		(static_cast<double>(k2) * -0.06225786672735933) +
		(static_cast<double>(k1) * 0.06576137583312501) +
		(static_cast<double>(k0) * -0.2174719016579794) +
		0.0;
	
	return (product > 0.00001 || product < -0.00001);
}

bool bruteforce(std::array<char, 16>& key, std::array<int, 4> indices, double additive_key)
{
	for (int a = 0; a < 256; a++) 
	{
		for (int b = 0; b < 256; b++) 
		{
			for (int c = 0; c < 256; c++) 
			{
				for (int d = 0; d < 256; d++)
				{
					if (isallowed(a) && isallowed(b) && isallowed(c) && isallowed(d))
					{
						if (!check_keys(additive_key, a, b, c, d) && isprint(a) && isprint(b) && isprint(c) && isprint(d))
						{
							std::cout << "Found partial key match!" << std::endl
								<< "a = " << a << "('" << static_cast<char>(a) << "')" << std::endl
								<< "b = " << b << "('" << static_cast<char>(b) << "')" << std::endl
								<< "c = " << c << "('" << static_cast<char>(c) << "')" << std::endl
								<< "d = " << d << "('" << static_cast<char>(d) << "')" << std::endl
								<< std::endl;

							key[indices[0]] = a;
							key[indices[1]] = b;
							key[indices[2]] = c;
							key[indices[3]] = d;
							return true;
						}
					}
				}
			}
		}
	}

	std::cout << "Could not bruteforce the selected keypart!" << std::endl;
	return false;
}

void printkey(std::array<char, 16> const& key)
{
	std::cout << "Current key:" << std::endl;

	for (char const& ch : key)
	{
		if (ch == 0)
			std::cout << "_";
		else
			std::cout << ch;
	}

	std::cout << std::endl;
	std::cout << std::endl;
}

int main(int argc, char* argv[])
{
	std::array<char, 16> key = { 0 };
	printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 0, 4, 8, 12 }}, -0.255666))
		printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 1, 5, 9, 13 }}, 16.80323))
		printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 2, 6, 10, 14 }}, 10.05288))
		printkey(key);
	
	if (bruteforce(key, std::array<int, 4> {{ 3, 7, 11, 15 }}, 13.157277))
		printkey(key);

	std::cout << "Finished bruteforce!" << std::endl;
	std::cin.ignore();
	std::cin.get();
	return 0;
}

can't complain about a bruteforce, though i could probably have made it impractical with a longer key length
 

Link to post
VirtualPuppet
9 hours ago, DefCon42 said:

can't complain about a bruteforce, though i could probably have made it impractical with a longer key length
 

Well, mathematically, it’s just a question of finding 4 variables that, when multiplied with their factor and summed together yields a value within the allowed limit.

one could either brute force it or calculate it by hand. Even if you increase keylength, the key will be easy to recover as long as you calculate the key parts separately.

Link to post
1 hour ago, VirtualPuppet said:

Well, mathematically, it’s just a question of finding 4 variables that, when multiplied with their factor and summed together yields a value within the allowed limit.

one could either brute force it or calculate it by hand. Even if you increase keylength, the key will be easy to recover as long as you calculate the key parts separately.

that's true if you only have 4 variables to work with, but that might not always be the case (even four wasn't instant on my machine); it's relatively easy to make it large enough that a bruteforce becomes ineffective

Link to post
  • 2 weeks later...
On 8/28/2019 at 6:39 PM, Hookahice said:

DefCon42, can you remake the Crackme with more than 4 variables so we can put it to the test?

Thanks,
-HooK

Sure! See attached.

crackme2.exe

Edited by DefCon42
clarification (see edit history)
  • Like 1
Link to post
  • 1 year later...
DrayNeur

Hi i just look to it and than decompile it so it give me all the source code so i could recompile it myself and decrypt the control flow :D. Great share m8!

Info: I use IDA Pro last version to get the Pseudo code that i retranslated in Windows c++

main.cpp

Link to post

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