[CrackMyApp] ๐Ÿคฎ Toxic CTF - Find the password! ํ’€์ด

_2ยท2025๋…„ 1์›” 9์ผ

Crackme

๋ชฉ๋ก ๋ณด๊ธฐ
3/12

CrackMe

1. ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ถ„์„

.NET CrackMe ์ด๋‹ค.

dnspy์— ๋„ฃ์—ˆ์„ ๋•Œ ์•ˆ๋‚˜์˜ค๊ธธ๋ž˜ self-contained ์˜ต์…˜์œผ๋กœ .NET ๋ฐ”์ด๋„ˆ๋ฆฌ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ ํ™•์ธํ•ด ๋ดค๋‹ค.

section , binary ๊ตฌ์กฐ ๋ชจ๋‘ ์ผ์น˜ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— dnspy์—์„œ ์ง€์›์„ ์•ˆํ•˜๋Š” ๊ฑธ๋กœ ์ƒ๊ฐํ•˜๊ณ  ๋‹ค๋ฅธ ๋””์ปดํŒŒ์ผ๋Ÿฌ ๋„๊ตฌ์˜ ์ตœ์‹  ๋ฒ„์ „์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

2. ์ฝ”๋“œ ๋ถ„์„

{
		TUI.Initialize();
		Console.CancelKeyPress += delegate
		{
			Environment.Exit(0);
		};
		while (true)
		{
			if (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape)
			{
				Environment.Exit(0);
			}
			TUI.DrawBox(5, 2, Console.WindowWidth - 10, Console.WindowHeight - 4, ConsoleColor.Cyan);
			TUI.WriteCenter("Welcome to the Toxic Crackme", 4, ConsoleColor.Yellow);
			TUI.WriteCenter("Enter the password to win:", 6);
			string text = TUI.ReadInput(Console.WindowWidth / 2 - 10, 9);
			if (text.Length > 0 && text[0] == '\u001b')
			{
				Environment.Exit(0);
			}
			TUI.Clear();
			TUI.DrawBox(5, 2, Console.WindowWidth - 10, Console.WindowHeight - 4, ConsoleColor.Cyan);
			if (cr4ck.VK(text))
			{
				break;
			}
			TUI.WriteCenter("Sorry, that's not the correct password.", 6, ConsoleColor.Red);
			TUI.WriteCenter("Press any key to try again...", 8, ConsoleColor.DarkGray);
			if (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape)
			{
				Environment.Exit(0);
			}
			Console.ReadKey();
			TUI.Clear();
		}
		TUI.WriteCenter("\ud83c\udf89 Congratulations! You found the correct password! \ud83c\udf89", 6, ConsoleColor.Green);
		TUI.WriteCenter("Press any key to exit...", 8, ConsoleColor.DarkGray);
		if (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape)
		{
			Environment.Exit(0);
		}
		Console.ReadKey();
if (cr4ck.VK(text))
			{
				break;
			}

cr4ck.VK์—์„œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค.

private static string BTS(byte[] P_0)
{
	if (P_0 == null || P_0.Length == 0)
	{
		return string.Empty;
	}
	char[] array = new char[P_0.Length];
	int num = 0;
	for (int i = 0; i < P_0.Length; i++)
	{
		if (P_0[i] <= 127)
		{
			array[num++] = (char)P_0[i];
			continue;
		}
		int num2;
		uint num3;
		if ((P_0[i] & 0xE0) == 192)
		{
			if (i + 1 >= P_0.Length)
			{
				break;
			}
			num2 = 2;
			num3 = (uint)(((P_0[i] & 0x1F) << 6) | (P_0[i + 1] & 0x3F));
		}
		else if ((P_0[i] & 0xF0) == 224)
		{
			if (i + 2 >= P_0.Length)
			{
				break;
			}
			num2 = 3;
			num3 = (uint)(((P_0[i] & 0xF) << 12) | ((P_0[i + 1] & 0x3F) << 6) | (P_0[i + 2] & 0x3F));
		}
		else
		{
			if ((P_0[i] & 0xF8) != 240)
			{
				continue;
			}
			if (i + 3 >= P_0.Length)
			{
				break;
			}
			num2 = 4;
			num3 = (uint)(((P_0[i] & 7) << 18) | ((P_0[i + 1] & 0x3F) << 12) | ((P_0[i + 2] & 0x3F) << 6) | (P_0[i + 3] & 0x3F));
		}
		if (num3 <= 65535)
		{
			array[num++] = (char)num3;
		}
		else
		{
			num3 -= 65536;
			array[num++] = (char)((num3 >> 10) + 55296);
			array[num++] = (char)((num3 & 0x3FF) + 56320);
		}
		i += num2 - 1;
	}
	return new string(array, 0, num);
}

public static bool VK(string P_0)
{
	try
	{
		byte[] array = Convert.FromBase64String(BTS(_secretBytes));
		string text = BTS(array);
		if (_resBytes.SequenceEqual(array))
		{
			return false;
		}
		return string.Equals(P_0, text, StringComparison.Ordinal);
	}
	catch
	{
		return false;
	}
}

VK ํ•จ์ˆ˜์—์„  secretBytes๋กœ๋ถ€ํ„ฐ ๋ฌธ์ž์—ด์„ ๋งŒ๋“  ๋’ค ์ž…๋ ฅ๊ณผ ๋น„๊ตํ•œ๋‹ค.

secretBytes๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

private static readonly byte[] _secretBytes = new byte[20]
{
	84, 106, 66, 48, 88, 51, 77, 119, 88, 51,
	81, 119, 101, 68, 70, 106, 73, 81, 61, 61
};

BTS ํ•จ์ˆ˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
(BytesToString)

for (int i = 0; i < P_0.Length; i++)
	{
		if (P_0[i] <= 127)
		{
			array[num++] = (char)P_0[i];
			continue;
		}

๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ›„ base64 decode ํ•ด์ฃผ๋ฉด password๊ฐ€ ๋‚˜์˜จ๋‹ค.

local t = {	84, 106, 66, 48, 88, 51, 77, 119, 88, 51,
	81, 119, 101, 68, 70, 106, 73, 81, 61, 61}

return byteTableToString(t)
>>> TjB0X3MwX3QweDFjIQ==

์ถ”๊ฐ€๋กœ Vkํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ณ„ ์˜๋ฏธ ์—†๊ฒŒ resBytes๋ผ๋Š” ๊ฒƒ๋„ ์“ฐ์ด๋Š”๋ฐ

	private static readonly byte[] _resBytes = new byte[16]
	{
		68, 101, 118, 105, 111, 117, 115, 32, 68, 101,
		99, 111, 121, 32, 58, 41
	};

ํ™•์ธํ•ด๋ณด๋ฉด ์ด๋Ÿฐ ๋‚ด์šฉ์ด ์žˆ๋‹ค.

local t = {	68, 101, 118, 105, 111, 117, 115, 32, 68, 101,
		99, 111, 121, 32, 58, 41}
return byteTableToString(t)
>>> Devious Decoy :)

๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋๋‚œ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€