Post

SpellBrewery

Challenge

  • CTF: Hack The Boo 2023 Official Writeup
  • Name: SpellBrewery
  • Category: Reversing
  • Difficulty: Easy
  • Points: 300
  • Description: I’ve been hard at work in my spell brewery for days, but I can’t crack the secret of the potion of eternal life. Can you uncover the recipe?
  • Objective: Decompiling a .NET application To Recover Flag Checker Logic

Files

Download: rev_spellbrewery.zip

Writeup

The challenge contains a Windows .NET DLL and Linux ELF executable file commonly named SpellBrewery after analyzing them using the file utility.

1
2
3
4
5
$ file *
SpellBrewery:                    ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8b106946c31c6346abd618ab5d2232845492e2d9, not stripped
SpellBrewery.deps.json:          JSON text data
SpellBrewery.dll:                PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows, 3 sections
SpellBrewery.runtimeconfig.json: JSON text data

Running SpellBrewery on Linux, appears to have a menu for adding ingredients to a spell. We can reverse this in Ghidra!

1
2
3
4
5
6
7
./SpellBrewery
1. List Ingredients
2. Display Current Recipe
3. Add Ingredient
4. Brew Spell
5. Clear Recipe
6. Quit

We could also reverse the Windows .NET DLL of SpellBrewery.dll in ILSpy.

In either case, we see 3 main classes Brewery, Ingredient, and Menu. We first can identify a function that would provide us with the flag called BrewSpell() that is found in the Brewery class as shown below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static void BrewSpell()
{
	if (recipe.Count < 1)
	{
		Console.WriteLine("You can't brew with an empty cauldron");
		return;
	}
	byte[] bytes = recipe.Select((Ingredient ing) => (byte)(Array.IndexOf(IngredientNames, ing.ToString()) + 32)).ToArray();
	if (recipe.SequenceEqual(correct.Select((string name) => new Ingredient(name))))
	{
		Console.WriteLine("The spell is complete - your flag is: " + Encoding.ASCII.GetString(bytes));
		Environment.Exit(0);
	}
	else
	{
		Console.WriteLine("The cauldron bubbles as your ingredients melt away. Try another recipe.");
	}
}

There are also 106 Ingredients and 36 correct sequences defined that contain a list of strings. It seems that if we provide the correct ingredient, it just adds 32 to a letter in the ingredient name (specific letter is based on where the ingredient is in the list). If we do this all 36 times, we obtain the flag.

The following proof-of-concept python code was used to solve this challenge.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# internal class Brewery
# private static readonly string[] IngredientNames = new string[106]
IngredientNames = [
    "Witch's Eye",
    "Bat Wing",
    "Ghostly Essence",
    "Toadstool Extract",
    "Vampire Blood",
    "Mandrake Root",
    "Zombie Brain",
    "Ghoul's Breath",
    "Spider Venom",
    "Black Cat's Whisker",
    "Werewolf Fur",
    "Banshee's Wail",
    "Spectral Ash",
    "Pumpkin Spice",
    "Goblin's Earwax",
    "Haunted Mist",
    "Wraith's Tear",
    "Serpent Scale",
    "Moonlit Fern",
    "Cursed Skull",
    "Raven Feather",
    "Wolfsbane",
    "Frankenstein's Bolt",
    "Wicked Ivy",
    "Screaming Banshee Berry",
    "Mummy's Wrappings",
    "Dragon's Breath",
    "Bubbling Cauldron Brew",
    "Gorehound's Howl",
    "Wraithroot",
    "Haunted Grave Moss",
    "Ectoplasmic Slime",
    "Voodoo Doll's Stitch",
    "Bramble Thorn",
    "Hocus Pocus Powder",
    "Cursed Clove",
    "Wicked Witch's Hair",
    "Halloween Moon Dust",
    "Bog Goblin Slime",
    "Ghost Pepper",
    "Phantom Firefly Wing",
    "Gargoyle Stone",
    "Zombie Toenail",
    "Poltergeist Polyp",
    "Spectral Goo",
    "Salamander Scale",
    "Cursed Candelabra Wax",
    "Witch Hazel",
    "Banshee's Bane",
    "Grim Reaper's Scythe",
    "Black Widow Venom",
    "Moonlit Nightshade",
    "Ghastly Gourd",
    "Siren's Song Seashell",
    "Goblin Gold Dust",
    "Spider Web Silk",
    "Haunted Spirit Vine",
    "Frog's Tongue",
    "Mystic Mandrake",
    "Widow's Peak Essence",
    "Wicked Warlock's Beard",
    "Crypt Keeper's Cryptonite",
    "Bewitched Broomstick Bristle",
    "Dragon's Scale Shimmer",
    "Vampire Bat Blood",
    "Graveyard Grass",
    "Halloween Harvest Pumpkin",
    "Cursed Cobweb Cotton",
    "Phantom Howler Fur",
    "Wraithbone",
    "Goblin's Green Slime",
    "Witch's Brew Brew",
    "Voodoo Doll Pin",
    "Bramble Berry",
    "Spooky Spellbook Page",
    "Halloween Cauldron Steam",
    "Spectral Spectacles",
    "Salamander's Tail",
    "Cursed Crypt Key",
    "Pumpkin Patch Spice",
    "Haunted Hay Bale",
    "Banshee's Bellflower",
    "Ghoulish Goblet",
    "Frankenstein's Lab Liquid",
    "Zombie Zest Zest",
    "Werewolf Whisker",
    "Gargoyle Gaze",
    "Black Cat's Meow",
    "Wolfsbane Extract",
    "Goblin's Gold",
    "Phantom Firefly Fizz",
    "Spider Sling Silk",
    "Widow's Weave",
    "Wraith Whisper",
    "Siren's Serenade",
    "Moonlit Mirage",
    "Spectral Spark",
    "Dragon's Roar",
    "Banshee's Banshee",
    "Witch's Whisper",
    "Ghoul's Groan",
    "Toadstool Tango",
    "Vampire's Kiss",
    "Bubbling Broth",
    "Mystic Elixir",
    "Cursed Charm",
]
# internal class Brewery
# private static readonly string[] correct = new string[36]
correct = [
    "Phantom Firefly Wing",
    "Ghastly Gourd",
    "Hocus Pocus Powder",
    "Spider Sling Silk",
    "Goblin's Gold",
    "Wraith's Tear",
    "Werewolf Whisker",
    "Ghoulish Goblet",
    "Cursed Skull",
    "Dragon's Scale Shimmer",
    "Raven Feather",
    "Dragon's Scale Shimmer",
    "Zombie Zest Zest",
    "Ghoulish Goblet",
    "Werewolf Whisker",
    "Cursed Skull",
    "Dragon's Scale Shimmer",
    "Haunted Hay Bale",
    "Wraith's Tear",
    "Zombie Zest Zest",
    "Serpent Scale",
    "Wraith's Tear",
    "Cursed Crypt Key",
    "Dragon's Scale Shimmer",
    "Salamander's Tail",
    "Raven Feather",
    "Wolfsbane",
    "Frankenstein's Lab Liquid",
    "Zombie Zest Zest",
    "Cursed Skull",
    "Ghoulish Goblet",
    "Dragon's Scale Shimmer",
    "Cursed Crypt Key",
    "Wraith's Tear",
    "Black Cat's Meow",
    "Wraith Whisper",
]
print("".join(chr(IngredientNames.index(f) + 32) for f in correct))
1
2
python3 get_flag.py
HTB{y0ur3_4_tru3_p0t10n_m45st3r_n0w}

Flag: HTB{y0ur3_4_tru3_p0t10n_m45st3r_n0w}

This post is licensed under CC BY 4.0 by the author.