BroncoCTF 2025

Beginner

Straight Up Circular

Category

Beginner

Tags

Flag

bronco{tr4n5p0sit1on_my_bel0v3d}

Someone’s been spreading weird messages around campus…

I keep seeing posters that have random characters on them, what could they mean?

Here’s one of them: dvlby_otspnr{cobrnot450i1nm_e03}


So there is a hint in the title that it is related to Circular. After looking around and I found the pattern is like this:

alt text

Forensics

Bucky's Impossible Obby

Category

Forensics

Tags

Flag

bronco{n0t_s0_1mp0551bl3_4ft3r_411_w0w!}

Bucky swears this obby (obstacle course) is IMPOSSIBLE. But he also says his obby has a flag for us in an alternate universe. What gives? https://www.roblox.com/games/131965012415321/BUCKYS-IMPOSSIBLE-OBBY

Note: Roblox Studio (and a Roblox account) is required for this challenge.

By yoshie878


Yeay a Robloks challenge! I love playing with someone until midnight :)). There is a game called BUCKY’S IMPOSSIBLE OBBY. Where you won’t be able to step on the finish checkpoint unless you use an exploit.

Because the note said Roblox Studio so I immediately went back to the game page and tried to see if there was an Edit in Studio option. Turns out there was!

alt text

After successfully opening Roblox Studio I tried to make the path easier by scaling the object so that there are no holes and can go straight to the finish. After succeeding I tried to play the game and managed to get to the finish.

alt text alt text

But when you get to the finish line, there’s only a placeholder that says {flag goes here}.

alt text

And there are dev notes which say: (dev note #878: still deciding on the flag, testing some options before i ship it to this place) if you look closely there are the words test and place in bold. So let’s just look for test place in the inventory of the game maker.

alt text

It turns out there is and it can be edited with Roblox Studio.

alt text alt text

And another troll from the game maker. We can see the lua code used to create the game. It turns out that the flag that appears after finish is invoked from the server using InvokeServer.

alt text alt text

We get that after the server receives the invoke from the client, it will return a flag that comes from a module. We can find that module by using the url https://create.roblox.com/store/asset/<id>.

alt text

After adding the module to our inventory we can see the lua code used to create the flag.

local buckysSuperAmazingFlagModule = {}
function buckysSuperAmazingFlagModule.flaggyflagflags() 

	-- hey you!
	-- yeah you!
	-- stop snooping around!
	-- there's nothing to see here! 

	-- ( - v - ) . z Z


	-- ( o - o )

	-- i'm his assistant!
	-- let's take a tour of this amazing module
	-- while he's asleep.

	-- important data!
	local data = {
		var_0107 = "_is_one_",
		var_0113 = "percent_",
		var_0103 = "his_flag",
		var_0011 = "11_w0w!}",
		var_0127 = "wrong_sr",
		var_0109 = "hundred_",
		var_0005 = "p0551bl3",
		var_0003 = "0t_s0_1m",
		var_0101 = "Boncoo{T",
		var_0002 = "bronco{n",
		var_0007 = "_4ft3r_4",
		var_0131 = "ry_mate}",
	}	

	-- helper function
	local function ip(n)
		if n <= 1 then
			return false
		end
		for i = 2, math.sqrt(n) do
			if n % i == 0 then
				return false
			end
		end
		return true
	end
	-- helper function
	local ps = {}
	local n = 100
	local lim = 7
	while #ps < lim do
		if ip(n) then
			table.insert(ps, n)
		end
		n = n + 1
	end
	-- where the flag magic happens
	local flag = ""
	for i, p in pairs(ps) do
		flag = flag .. data["var_" .. string.format("%04d", tostring(p))]
	end

	-- and there you go!
	return flag
end
return buckysSuperAmazingFlagModule

By removing the variable used to troll us, we get the actual flag.

local data = {
    var_0011 = "11_w0w!}",
    var_0005 = "p0551bl3",
    var_0003 = "0t_s0_1m",
    var_0002 = "bronco{n",
    var_0007 = "_4ft3r_4",
}

We reorder the variables and get the actual flags.

local data = {
    var_0002 = "bronco{n",
    var_0003 = "0t_s0_1m",
    var_0005 = "p0551bl3",
    var_0007 = "_4ft3r_4",
    var_0011 = "11_w0w!}",
}

Logged

Category

Forensics

Tags

Flag

bronco{l0gg1ng_ftw}

We managed to get a keylogger on a notorious hacker’s computer.

Our best analysts are pretty sure they type their password into a text file during this log segment, but we can’t figure it out.

Can you get us the flag from this?

By shwhale


We are given a log file keys.log that contains keypresses and releases. The log file contains lines like the following:

KeyRelease event, serial 18, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36801639, (1314,474), root:(1322,554), state 0x0, keycode 50 (keysym 0xffe1), same_screen YES
KeyPress event, serial 18, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36801639, (1314,474), root:(1322,554), state 0x0, keycode 50 (keysym 0xffe1), same_screen YES
KeyRelease event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36801841, (1314,474), root:(1322,554), state 0x1, keycode 52 (keysym 0x3a), same_screen YES
KeyPress event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36801841, (1314,474), root:(1322,554), state 0x1, keycode 52 (keysym 0x3a), same_screen YES
KeyRelease event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36801908, (1314,474), root:(1322,554), state 0x1, keycode 50 (keysym 0xffe1), same_screen YES
KeyRelease event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36801918, (1314,474), root:(1322,554), state 0x0, keycode 52 (keysym 0x3b), same_screen YES
KeyRelease event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36802249, (1314,474), root:(1322,554), state 0x0, keycode 40 (keysym 0x65), same_screen YES
KeyPress event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36802249, (1314,474), root:(1322,554), state 0x0, keycode 40 (keysym 0x65), same_screen YES
KeyRelease event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36802332, (1314,474), root:(1322,554), state 0x0, keycode 40 (keysym 0x65), same_screen YES
KeyRelease event, serial 21, synthetic NO, window 0x180000e, root 0x6c0, subw 0x0, time 36802446, (1314,474), root:(1322,554), state 0x0, keycode 65 (keysym 0x20), same_screen YES

The log file contains keypresses and releases for various keys. The keysym value is the keysym value of the key that was pressed or released. We can extract the keysym value from the log file and convert it to a character to get the plaintext.

import re

plaintext = []
shift_pressed = False

# Regex to extract keysym from the log line
keysym_regex = re.compile(r'keysym 0x([0-9a-fA-F]+)')

with open('keys.log', 'r') as file:
	for line in file:
		if 'KeyPress' in line or 'KeyRelease' in line:
			keysym_match = keysym_regex.search(line)
			if keysym_match:
				keysym = int(keysym_match.group(1), 16)

				if keysym == 0xffe1:
					if 'KeyPress' in line:
						shift_pressed = True
					elif 'KeyRelease' in line:
						shift_pressed = False
				elif keysym == 0xff0d:
					if 'KeyPress' in line:
						plaintext.append('\n')
				elif keysym == 0xff08:
					if 'KeyPress' in line:
						if plaintext:
							plaintext.pop()
				elif keysym == 0xff1b:
					if 'KeyPress' in line:
						plaintext.append('<Esc>')
				else:
					if 'KeyPress' in line:
						# Convert keysym to character
						try:
							char = chr(keysym)
							if shift_pressed:
								if char.isalpha():
									char = char.upper()
								else:
									plaintext.append('<Shift>')
							plaintext.append(char)
						except ValueError:
							pass

print(f'Plaintext: {"".join(plaintext)}')

Running the script on the provided keys.log file gives us the following plaintext:

Plaintext: <Shift>:e flag.txt
iI cannot wait to write the flag in plaintext.
But first, let me take some steps in case ¬I am being keylogged...<Esc>oasonethubkxxmloreucigqxlrcgmxlrcgmsneth xiexsuinthexsuebntixkxq ;aojeubs m<Esc>Te;aro<Esc>lvhhhx0Pldtclrollla<Shift>{<Esc>wwa<Shift>}<Esc><Shift>%hxhxhs<Esc>llllr0hxlllrglR1n<Esc>lxllRft<Esc>lllllrwhvTexllD<Shift>:s/m//g
3fga<Shift>_<Esc>twx¬:wq

The hacker tried to write flags in flag.txt but he tried to avoid keylogger by writing flags in a different way. Notice that some of the commands executed are :e flag.txt which means open the flag.txt file and :s/m//g which means delete all m characters from the file. So most likely this biggest hacker is using vim to write the flags. We can read the flags back in the same way as the hacker did.

alt text

Miscllaneous

Mined Solving This?

Category

Miscllaneous

Tags

Flag

bronco{m1n3d}

I used to think Minecraft was just a silly game. I woold play it for hours and accomplish nothing. Making this challenge gave me perspective though!

Note: You do not need a copy of Minecraft for this challenge

By shwhale


So this challenge is a Minecraft map. Downloaded the map and opened it in Minecraft. Open the map in Minecraft and we will be spawned in a far place.

At the beginning we will be at coordinates 1000 ~ 1000, so we can teleporte to coordinates 0 ~ 0 with the command /tp 0 0 0. After that looked around and found a structure. Because there were no more clues, I tried to open the inventory and see if there were any clues there. And it turned out there were clues there.

alt text

After asking the problem setter, and he couldn’t answer it was certain that wool was a clue. And it turned out to be true after explored the structure, it turned out that there were several colored wool blocks after standing on the wool and looking around, something would happen! namely the diamond block will show a letter pattern. And after we collect all the letter patterns, we will get a flag.

alt text alt text alt text alt text alt text alt text alt text alt text alt text alt text alt text alt text alt text alt text

By matching the pattern with the wool order in the inventory, we will get the flag.

OSINT

April 25

Category

OSINT

Tags

Flag

bronco{I_w@s_pr3p@r1ng_4_ctfs}

Do you really want to know where BroncoSec (full of security enthusiasts and influencers) was April 25?

By tiffany_ttn


There is Instagram account scubroncosec that has a post on April 25.

alt text

Elite Stacker

Category

OSINT

Tags

Flag

bronco{The Laboratory 1,015.8m}

YOOOO check out this new personal best in sprint that my bestie yoshie just got! He truly is the elitest elite stacker of all time! (p.s. not really. he needs waaaay more T-Spins.)

Ok honestly though, that mode is boooooring. Where’s all the garbage at? No challenge at all.

Tell me, what is the highest floor and altitude in the Zenith Tower that yoshie has climbed up to?

Flag Format: bronco{<Floor Name> <Altitude>}, where:

  • Floor Name is the name (NOT number) of the floor. Include space(s).

  • Altitude is a number to one decimal place, commas optional, with m at the end for meters.

  • There is a space between the entries.

By yoshie878


So they give a file named imthegoatatstacking_7e41cb366aa7.ttr which is a replay file for the game tetr.io. I downloaded the file and opened it in the game. The game is a tetris game and the replay file is a recording of a game played by the user. The user in this case is yoshie878.

alt text

The user mentions that he is the “elitest elite stacker of all time” and that he needs “waaaay more T-Spins”. This is a hint that the user is good at the game and that he is not satisfied with his current performance.

The user also mentions that the mode is boring and that there is no challenge at all. This is a hint that the user is playing in a mode that is not challenging enough for him.

The user asks for the highest floor and altitude in the Zenith Tower that he has climbed up to. This is a hint that the user has played in the Zenith Tower mode and has reached a high floor and altitude.

alt text

By viewing the player’s profile, we can see that the user has played in the Zenith Tower mode and has reached a high floor and altitude. The highest altitude that the user has reached is 1,015.8m.

alt text

Because the replay file is expired, we cannot view the replay of the game. However, we can search the floor name in Google and find the altitude of the floor. Which is The Laboratory floor.

Misclellaneous

World's Hardester Flag

Category

Misclellaneous

Tags

Flag

bronco{n0th1ng_1s_2oo_h4rd_4_m3!}

Hey. It’s me, Mr. Dehnemy. Remember me from last year?

I have a new challenge for you. I present to you, the WORLD’S HARDEST(ER) FLAG!!

Your tactics from last year will not work. YOU WILL NOT GET MY FLAG!!!!!!!!!!!!!

https://www.roblox.com/games/97958089823595/Worlds-Hardester-Flag

Note 1: Roblox Player (and a Roblox account) is required for this challenge.

Note 2: If you load the game and get stuck on a blank colored screen, reset your character. Keep resetting your character if the screen keeps on being blank

By yoshie878


The game is a Roblox game. The objective is to get the flag. There are two paths to get the flag. The first path is to go through old levels and the second path is to go through new levels. The flag is located at the end of the old or new levels.

alt text

Left is the new levels and right is the old levels. The flag is located at the end of the either new or old levels.

After looking around in the game, I found that we can execute lua scripts in the game.

I am familiar with Lua and Roblox scripting because I once made a script for a game for someone who often invited me to play roblox from morning to midnight WKKWKWK. So I tried to execute the lua script to get the flag.

Idea 1

My first idea was to search for all the descendants of the game and look for an object that has the name Flag. It turns out that there is an object that has the name Flag after seeing the parent of the object is a GUI so there is likely to be a constant text on the object. Sure enough, it turns out that the object is a TextLabel containing the flag.

Because there are some banned words like Name, Position then we need to bypass them by using array and string concation.

for _, v in pairs(game:GetDescendants()) do
    if v["N" .. "ame"] == "Flag" then
        print(v.Text)
    end
end

Here we call print then the result will appear in the roblox console. We can see the roblox console by pressing F9 or CTRL + F9.

alt text

Idea 2

Because I’m bored, I tried to be a hacker 😎, so I thought about being able to penetrate the blue object or obstacle by setting CanCollide to false or by clearing all children of an object by using the ClearAllChildren function.

Because in this game we are given the ability to debug objects in the game, we can use that information to remove obstacles in the game.

-- There is OG1, OG2, OG3, OG4 (final level)
Workspace.Levels.OG1.Hazards:ClearAllChildren()

After removing the obstacles in the game, we can easily pass all the levels in the game.

Idea 3

Directly teleport to the last checkpoint and get the flag. There are two checkpoints we can teleport to, namely WinPad at the OG4 level and OldWinPad at the Demo level.

-- Workspace.Levels.OG4.Checkpoints.WinPad
-- Workspace.Levels.Demo.Checkpoints.OldWinPad

local localPlayer = game.Players.LocalPlayer
local character = localPlayer.Character or localPlayer.CharacterAdded:Wait()
-- local manusia = character:WaitForChild("H" .. "umanoid")

character:PivotTo(CFrame.new(Workspace.Levels.OG4.Checkpoints.WinPad["P" .. "osition"]) + Vector3.new(0, 5, 0))

alt text

Reverse Engineering

Actual Reversing

Category

Reverse Engineering

Tags

Flag

bronco{r3v3r5ed_3n0ugh?}

Here is something reversible. :)

By shwhale


ok!! Actual Reversing.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char i; // [rsp+7h] [rbp-59h]
  int v5; // [rsp+8h] [rbp-58h]
  int v6; // [rsp+Ch] [rbp-54h]
  char s[72]; // [rsp+10h] [rbp-50h] BYREF
  unsigned __int64 v8; // [rsp+58h] [rbp-8h]

  v8 = __readfsqword(0x28u);
  puts("Welcome to the transformer! We take what you have, and make it into what you have always wanted!");
  printf("What do you have to offer?\n> ");
  fgets(s, 64, _bss_start);
  s[strcspn(s, "\n")] = 0;
  v5 = 0;
  v6 = 0;
  while ( s[v5] )
  {
    for ( i = s[v5]; i; i >>= 1 )
      v6 += i & 1;
    ++v5;
  }
  if ( v6 == 108 )
  {
    puts("Here's my perscription:");
    perscribe(s);
    printf("%s", TRUTH);
  }
  else
  {
    puts("That'll NEVER turn into what you want!");
  }
  return 0;
}

The binary reads a string from the user, and then calculates the number of bits set in the string. If the number of bits set is 108, it calls a function perscribe with the string. The perscribe function then does some bit manipulation and prints out a message.

unsigned __int64 __fastcall perscribe(char *a1)
{
  void *v1; // rsp
  __int64 v3; // [rsp+0h] [rbp-60h] BYREF
  char *s; // [rsp+8h] [rbp-58h]
  int i; // [rsp+18h] [rbp-48h]
  int j; // [rsp+1Ch] [rbp-44h]
  int k; // [rsp+20h] [rbp-40h]
  int v8; // [rsp+24h] [rbp-3Ch]
  int v9; // [rsp+28h] [rbp-38h]
  int v10; // [rsp+2Ch] [rbp-34h]
  int v11; // [rsp+30h] [rbp-30h]
  int v12; // [rsp+34h] [rbp-2Ch]
  __int64 v13; // [rsp+38h] [rbp-28h]
  __int64 *v14; // [rsp+40h] [rbp-20h]
  unsigned __int64 v15; // [rsp+48h] [rbp-18h]

  s = a1;
  v15 = __readfsqword(0x28u);
  v8 = strlen(TRUTH);
  v9 = 8 * v8;
  v13 = 8 * v8 - 1LL;
  v1 = alloca(16 * ((8 * v8 + 15LL) / 0x10uLL));
  v14 = &v3;
  for ( i = 0; i < 8 * v8; ++i )
    *((_BYTE *)v14 + i) = 0;
  v10 = strlen(s);
  for ( i = 0; i < v10; ++i )
  {
    for ( j = 0; j <= 7; ++j )
    {
      v11 = 1 << j;
      if ( ((1 << j) & s[i]) != 0 )
      {
        v12 = 8 * i + j;
        for ( k = 0; ((TRUTH[k >> 3] >> (k & 7)) & 1) == 0 || *((_BYTE *)v14 + k); ++k )
          ;
        printf("Take %d of these, then\n", (unsigned int)(k - v12));
        *((_BYTE *)v14 + k) = 1;
      }
    }
  }
  puts("You're done!");
  return v15 - __readfsqword(0x28u);
}

The perscribe function initializes an array of bytes v14 with zeros. It then iterates over each byte in the input string s, and for each bit set in the byte, it finds the first bit set in the TRUTH string that has not already been used. It then prints out "Take X of these, then", where X is the difference between the bit position in the TRUTH string and the bit position in the input string. It then marks that bit as used.

alt text

Matching with TRUTH

  • The function scans through the bits of TRUTH (for (k = 0; ... ; ++k)) looking for:
    • The first bit that is set (((TRUTH[k >> 3] >> (k & 7)) & 1) != 0).
    • The first bit that has not already been used (!*((_BYTE *)v14 + k)).
  • Once it finds such a bit, it prints "Take X of these, then", where X = k - v12 (the offset between input and TRUTH).
  • It marks that bit position as used (*((_BYTE *)v14 + k) = 1).

They give perscription for the correct input string. We can use this perscription to recover the flag.

Here's my perscription:
Take -1 of these, then
Take -4 of these, then
Take 0 of these, then
Take -1 of these, then
Take 1 of these, then
Take 1 of these, then
Take 3 of these, then
Take 2 of these, then
Take 2 of these, then
Take 3 of these, then
Take 3 of these, then
Take 8 of these, then
Take 11 of these, then
Take 12 of these, then
Take 12 of these, then
Take 13 of these, then
Take 14 of these, then
Take 15 of these, then
Take 14 of these, then
Take 16 of these, then
Take 15 of these, then
Take 15 of these, then
Take 14 of these, then
Take 17 of these, then
Take 19 of these, then
Take 19 of these, then
Take 19 of these, then
Take 19 of these, then
Take 20 of these, then
Take 20 of these, then
Take 19 of these, then
Take 25 of these, then
Take 27 of these, then
Take 28 of these, then
Take 28 of these, then
Take 26 of these, then
Take 28 of these, then
Take 28 of these, then
Take 28 of these, then
Take 28 of these, then
Take 26 of these, then
Take 27 of these, then
Take 25 of these, then
Take 27 of these, then
Take 26 of these, then
Take 28 of these, then
Take 28 of these, then
Take 27 of these, then
Take 28 of these, then
Take 26 of these, then
Take 32 of these, then
Take 31 of these, then
Take 30 of these, then
Take 31 of these, then
Take 31 of these, then
Take 30 of these, then
Take 31 of these, then
Take 30 of these, then
Take 30 of these, then
Take 29 of these, then
Take 28 of these, then
Take 29 of these, then
Take 31 of these, then
Take 28 of these, then
Take 27 of these, then
Take 28 of these, then
Take 29 of these, then
Take 29 of these, then
Take 31 of these, then
Take 33 of these, then
Take 33 of these, then
Take 32 of these, then
Take 32 of these, then
Take 32 of these, then
Take 32 of these, then
Take 32 of these, then
Take 29 of these, then
Take 32 of these, then
Take 33 of these, then
Take 32 of these, then
Take 32 of these, then
Take 28 of these, then
Take 32 of these, then
Take 30 of these, then
Take 31 of these, then
Take 30 of these, then
Take 30 of these, then
Take 31 of these, then
Take 30 of these, then
Take 33 of these, then
Take 35 of these, then
Take 33 of these, then
Take 39 of these, then
Take 37 of these, then
Take 37 of these, then
Take 37 of these, then
Take 37 of these, then
Take 37 of these, then
Take 38 of these, then
Take 39 of these, then
Take 41 of these, then
Take 41 of these, then
Take 40 of these, then
Take 39 of these, then
Take 39 of these, then
Take 39 of these, then
Take 39 of these, then
Take 39 of these, then
You're done!
Can birds even understand me?

The perscription tells us how to construct the flag from the input string. We can write a script to do this.

import math

TRUTH = "Can birds even understand me?"

T = []
for k in range(8 * len(TRUTH)):
    if (ord(TRUTH[k // 8]) >> (k % 8)) & 1:
        T.append(k)

log_d = [
    -1, -4, 0, -1, 1, 1, 3, 2, 2, 3, 3, 8, 11, 12, 12, 13, 14, 15, 14, 16,
    15, 15, 14, 17, 19, 19, 19, 19, 20, 20, 19, 25, 27, 28, 28, 26, 28, 28,
    28, 28, 26, 27, 25, 27, 26, 28, 28, 27, 28, 26, 32, 31, 30, 31, 31, 30,
    31, 30, 30, 29, 28, 29, 31, 28, 27, 28, 29, 29, 31, 33, 33, 32, 32, 32,
    32, 32, 29, 32, 33, 32, 32, 28, 32, 30, 31, 30, 30, 31, 30, 33, 35, 33,
    39, 37, 37, 37, 37, 37, 38, 39, 41, 41, 40, 39, 39, 39, 39, 39
]

b_positions = []
for j, d in enumerate(log_d):
    b_j = T[j] - d
    b_positions.append(b_j)

max_bit = max(b_positions)
num_bytes = math.ceil((max_bit + 1) / 8)

input_bytes = [0] * num_bytes

for pos in b_positions:
    byte_index = pos // 8
    bit_index = pos % 8
    input_bytes[byte_index] |= (1 << bit_index)

print(f'Flag: {"".join(chr(b) for b in input_bytes)}')

Reversing for Ophidiophiles

Category

Reverse Engineering

Tags

Flag

bronco{charge_away}

Do you love python? Or at least tolerate it? Then this is the challenge for you!

When run with the correct flag, the given file prints: 23a326c27bee9b40885df97007aa4dbe410e93.

What is the flag?

By shwhale


The challenge provides a python script that encrypts the flag and prints the ciphertext. The script is as follows:

flag = input()
carry = 0
key = "Awesome!"
output = []
for i,c in enumerate(flag):
    val = ord(c)
    val += carry
    val %= 256
    val ^= ord(key[i % len(key)])
    output.append(val)
    carry += ord(c)
    carry %= 256

print(bytes(output).hex())

So here the flag is added to the carry where at the beginning the carry is 0 after that there will be a check if the flag is outside the ascii then the modulus is 256 after adding the carry then it will be continued with the XOR operation with the Awesome key! after that it will be added to the output array variable after that the variable will be added with the ascii of the current character if the carry is outside the ascii range then it will be modulated by 256.

To decrypt the flag, we can reverse the encryption process. We can start by converting the ciphertext to bytes, and then decrypting each character in reverse order. The decryption process is as follows:

ciphertext = "23a326c27bee9b40885df97007aa4dbe410e93"
ciphertext = bytes.fromhex(ciphertext)
key = "Awesome!"
carry = 0

flag = []
for i, c in enumerate(ciphertext):
    c ^= ord(key[i % len(key)])
    c -= carry
    c %= 256
    flag.append(c)
    carry += c
    carry %= 256

print(f'Flag: {bytes(flag).decode()}')

sus

Category

Reverse Engineering

Tags

Flag

bronco{br4inr0t}

So, my friend just hit me up with this lit file, right? But like, they totally forgot to define their keywords\u2014straight up left me hanging. It\u2019s like I\u2019m playing a game of “guess the meaning” with no map. I gotta reverse the code and figure out what\u2019s actually poppin\u2019 in there. There\u2019s a flag hidden somewhere, but it\u2019s got mad twists and turns. If you\u2019re down to decode it too, try flipping the meaning of the words and see if you can catch the vibe. Let’s see who can crack it first!

By serilical


The challenge provides a sus.cpp file with the following contents we need to figure out the meaning of the keywords:

#define skibidi ?

using namespace skibidi;

#define hawk ?
#define pressed ?
#define crash_out ?
#define ate ?
#define twin ?
#define periodt ?
#define vibe ?
#define blud ?
#define delulu ?
#define uhh ?
#define slay ?
#define dap ?
#define yap ?
#define diff ?
#define lit ?
#define free ?
#define stan ?
#define savage ?
#define hop_off ?
#define take_a_seat ?
#define amped ?
#define tuah ?
#define gucci ?
#define finna ?
#define rent ?
#define tea ?
#define flex ?
#define mid ?
#define cancelled ?

AFTER SOME MANUAL WORK, we can figure out the following mapping:

#define skibidi std

using namespace skibidi;

#define hawk if
#define pressed -
#define crash_out }
#define ate +
#define twin ==
#define periodt ;
#define vibe while
#define blud char
#define delulu %
#define uhh ,
#define slay return
#define dap {
#define yap cout
#define diff <
#define lit int
#define free ]
#define stan =
#define savage NULL
#define hop_off )
#define take_a_seat endl
#define amped *
#define tuah else
#define gucci string
#define finna (
#define rent [
#define tea <<
#define flex >
#define mid /
#define cancelled break

theflagishere!

Category

Reverse Engineering

Tags

Flag

bronco{i_am_a_flag}

So, my friend sent me this program that\u2019s supposed to determine the flag for this challenge, right? But, somehow, they forgot to actually say what the flag is. Classic move. \ud83d\ude02 Now, it\u2019s on you to figure out what the true flag is. If you can crack it and figure out what my friend was trying to send, that flag is all yours! Ready to flex those decoding skills? Let\u2019s get it!

Format: bronco{flag}

By serilical


Given a file named theflagishere.pyc and a hint that it is a python compiled file, we can use a decompiler to get the source code. I used pylingual.io to decompile the file.

https://pylingual.io/view_chimera?identifier=1f1468a7d8ca8cbfa686caa36e17a1a373bb9fb326870e9a78e2655dc7a8fce6

# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: theflagishere.py
# Bytecode version: 3.9.0beta5 (3425)
# Source timestamp: 2025-02-13 23:36:18 UTC (1739489778)

def what_do_i_do(whoKnows):
    a_st = {}
    for a in whoKnows:
        if a_st.get(a) == None:
            a_st[a] = 1
        else:
            a_st[a] += 1
    variable_name = 0
    not_a_variable_name = 'None'
    for a in a_st:
        if a_st[a] > variable_name:
            not_a_variable_name = a
            variable_name = a_st[a]
    return (not_a_variable_name, variable_name)

def char_3():
    return 'm'

def i_definitely_return_the_flag():

    def notReal():

        def actually_real():
            return 'actuallyaflag'
        return actually_real

    def realFlag():
        return 'xXx___this__is_the__flag___xXx'
    return (realFlag, notReal)

def i_am_a_function_maybe(param):
    variableName = (param + 102) * 47
    for i in range(0, 100):
        variableName *= i + 1
        variableName /= i + 1
        newVariable = variableName * i
        newVariable += 100
    return chr(ord(chr(int(variableName) + 1)))

def i_do_not_know():
    realFlagHere = 'br0nc0s3c_fl4g5_4r3_345y'
    return 'long_live_long_flags'

def unrelated_statement():
    return 'eggs_go_great_with_eggs'

def i_am_a_function(param):
    variableName = (param + 102) * 47
    for i in range(0, 100):
        variableName *= i + 1
        newVariable = variableName * i
        newVariable += 100
        variableName /= i + 1
    return chr(ord(chr(int(variableName))))

def i_return_a_helpful_function():

    def i_do_something(char):
        var = []
        for i in range(54, 2000):
            var.append(ord(char) / 47 - 102)
        var.reverse()
        return var.pop()
    return i_do_something

def i_return_the_flag():
    return 'thisisdefinitelytheflag!'

def i():
    return 'free_flag_f'

def char_0():
    return i_am_a_function_maybe(i_return_a_helpful_function()(what_do_i_do(i_return_the_flag())[0]))

def char_1_4_6():
    return i_am_a_function_maybe(i_return_a_helpful_function()(what_do_i_do(i_definitely_return_the_flag()[0]())[0]))

def char_2_5_9():
    return i_am_a_function_maybe(i_return_a_helpful_function()(what_do_i_do(i_definitely_return_the_flag()[1]()())[0]))

def char_7():
    return i_am_a_function_maybe(i_return_a_helpful_function()(what_do_i_do(interesting()()()())[0]))

def char_8():
    return i_am_a_function_maybe(i_return_a_helpful_function()(what_do_i_do(i_do_not_know())[0]))

def char_10():
    return i_am_a_function_maybe(i_return_a_helpful_function()(what_do_i_do(unrelated_statement())[0]))

def interesting():

    def notinteresting():

        def veryuninteresting():

            def interesting_call():
                return i
            return interesting_call
        return veryuninteresting
    return notinteresting

There are a lot of functions that are not used in the main function. We can ignore them. The main function is char_0, char_1_4_6, char_2_5_9, char_7, char_8, and char_10. We can run these functions to get the flag.

print(f'bronco{{{char_0() + char_1_4_6() + char_2_5_9() + char_3() + char_1_4_6() + char_2_5_9() + char_6() + char_1_4_6() + char_2_5_9() + char_9() + "?" + char_8() + char_10()}}}')

Because char_7 had an error, ***<module>.char_7: Failure: Different bytecode we need to guess the character for char_7 which is f.