Binary Search - General Skills
Last updated
Was this helpful?
Last updated
Was this helpful?
When I read the challenge's description above, two keywords stood out: the shell
and Binary Search
. From that information, I assumed this challenge was meant to introduce players to the idea of the Shell and the Binary Search algorithm. So, I downloaded the challenge files directly from the terminal:
I extracted the zip file, and there was only one shell script guessing_game.sh
inside the folder /home/ctf-player/drop-in/
:
I took a look at the script, read them, and realized it’s a simple 'Binary Search' guessing game:
This game asks the users to guess a number between 1 and 1000, and only get 10 tries to get it right. If the guess is too high, it tells to go lower. If it’s too low, it tells to go higher. Once I guess the correct number, it congratulates me and gives me the flag.
To solve this challenge, I needed to play the game by guessing the correct number using the Binary Search formula: mid_idx = (low_idx + high_idx) / 2
.
Since Binary Search works by cutting the range in half each time, I started by guessing the middle number between 1 and 1000, which is 500. Depending on whether the game told me to guess higher or lower, I adjusted my next guess and kept narrowing it down.
If you want to understand how the Binary Search algorithm works, you can watch this or read this. Now let's check the program's source code, and see how they actually work.
This shell script generates a random number between 1 and 1000 and gives the players chance to guess the correct number up to 10 guesses. If the players guess the number that is higher than the correct number, it will respond with a message: Lower! Try Again
, otherwise, it will respond: Higher! Try Again
, until the players guess the correct number and then it will give them the flag.
So, this is basically a simple challenge. I just need to play the game by guessing the correct numbers and get the flag. Here's one of my attempt to get the flag by playing the game:
Here’s the interesting part, though: while playing around with the script, I noticed a bug. Let’s break it down, and check the code again.
In the code above, we can see that it checks if the user’s input is a number (0 to 9). If it’s not, the script just asks for a valid number and moves on to the next try.
Next, the script compares the user's guess to the target number. If the guess is too low, it says, "Higher! Try again"
If it’s too high, it says, "Lower! Try again."
And if it's right, it prints the flag.
The logic works fine overall, but there’s a catch. If you enter a number with a leading zero followed by something greater than 7 (like 099
), the program crashes—and it still prints the flag to the console:
The issue arises from how the script handles input with leading zeros, such as 099
. In Bash, numbers starting with 0
are interpreted as octal (base 8) instead of decimal (base 10). Octal numbers only allow digits 0
through 7
, so entering something like 099
confuses Bash since 9
isn’t valid in octal. This causes the program to crash, but instead of handling the error properly, the script continues running and inadvertently prints the flag to the console.
This bug can be exploited to bypass the game entirely and retrieve the flag without playing. By simply entering an invalid octal number, the error is triggered, causing the program to behave unexpectedly.
Fixing this bug requires ensuring that user input is always treated as decimal and properly validated to prevent such edge cases. Simple changes, such as stripping leading zeros or enforcing base-10 interpretation, can safeguard against this issue. For example, using the following code:
If you want to know more about the bug, you can simply Google it using the keyword 'leading zeros in bash,' or just read this simple article.
You can see the solver (by playing the game) here.