Katanaverse 1.0 : bi0sCTF 2024
tl;dr
- Utilises a VM to receive an input and modify the input by performing bit manipulation
- Quantum gates (quantum operations) are applied to the modified flag
- A quantum algorithm for the decisive match
Challenge points: 1000
No. of solves: 0
Challenge Description
Yes, that should work.
MD5 Hash:
katanaverse1.0: c86e0909a1f1d0296d58c059a02bbeed
1_dump.dmp: de7024faaf03edc69c2e52ee9aa95f9f
Author
- Sejal Koshta: k1n0r4 | k1n0r4
This challenge is a second part of Katanaverse 0.0
Two phases of Challenge:
- VM involving Bit Manipulation
- Quantum computation and algorithm
Overview
This challenge’s binary is broken and unexecutable beyond a particular point in the code since it starts involving quantum operations, which are provided in Python. On Quantum servers, these procedures may be carried out via the Python qiskit module.
The challenge’s primary goal was to comprehend how the binary operates and re-implement any sections that cannot be performed or do not exist. To understand the suggestion provided to re-implement the non-existent function, you might also need to refer to the earlier section of this challenge, “Katanaverse 0.0”. You may find the necessary technique/method by performing a simple Google search using the essential terms.
Visit this page to learn more about Katanaverse 0.0’s functionality. This comprises the challenge’s organizational notes.
Q. How will I know that it makes use of quantum concepts?
Indeed, you can observe the occurrence of alpha and beta in the shellcode itself, and the structure of the shellcode also suggests a quantum or Qiskit module.
VM
Control flow of the VM
- Prompt for Flag
- Takes the input
- Transforms the flag into its string encoded in base 64.
- Register S0 stores the updated flag’s length.
- Copying and storing flag bytes in “memory” and stack
- Binary representations of flag bytes are created and placed on the stack.
- As a result, each time a flag byte is converted, the byte is removed from memory.
- Memory is discovered to be empty following the conversion.
- A bit modification that is kept in memory is carried out using stored binary from the stack.
- VM exits
- It replicates its memory into a “classified” 2D array
- It stores the altered input length from register S0 in a new variable for use in future applications.
Here is more information on the VM used.
Quantum
Upon obtaining the bit-manipulated array, which I refer to as the “classified” array, the quantum operations commence.
Runtime Constant generation
Prior to that, a few significant constants are created at runtime using the flag’s known portion, that is, it’s flag format.
Seed for the srand function - 89
Aes key - [24, 6, 59, 77, 181, 112, 85, 180, 113, 194, 137, 37, 74, 136, 6, 25]
1 | uint8_t aes_key[16]; |

The seed generation also involves a user character input, which is ‘r’
By taking two bytes of the modified flag at a time and creating six bytes for each such pair, the classified array is created. Therefore, a pair of flag bytes corresponds to each of these sets of six bytes. The last byte of the preceding pair is overlapped and used as the first byte to obtain the next pair of bytes.
The classified array then has certain constraints applied to it, where the produced random numbers decide which row satisfies each requirement. Three such constraints are given here for each group in the classified array.

Five constraints were provided to each group in the preceding section of the challenge, “Katanaverse 0.0”, allowing any constraint solver to recover the flag (Ps. This was the unintended solution to the challenge).
Next in the line are 2 other constants, subtract_key and xor_key, which are again computed using the known part of the flag format
subtract_key = 24
xor_key = 181
Determining the operations performed
Each one group of the classififed array includes 12 nibbles which determine which 12 operations will be performed on the initial qubit.

The given loop first initialises the qubit as
Alpha = 1 + 0i
Beta = 0 + 0i
and then 12 operations are performed on the qubit(func_11) one after the other. These 12 states of qubits are saved and later converted into their coordinate form via func_13

These correspond to different operations performed on the qubit, one such function is Blaze.
There are in total 16 operations named as Blaze, Horizon, Nova, Quantum, Echo, Radiant, Zenith, Cipher, Nimbus, Pulse, Serene, Ember, Aurora, Lumina, Cascade and Kinetic.

Within func_10 under Blaze, we can see that it attempts at executing the shellcode given, but upon failure intends to displays “Well, I already said it’s broken.”

Shellcode given unside the Blaze function looks like this
1 | OPENQASM 2.0; |
Division of points
The lines that are depicted between two spots are formed or determined by 41 pairs of numbers or integers. The distances between these locations multiplied by 10 (func_8) make up the weights of these points.
In this case, the two numbers point in the direction of two points that are connected by a line, as a result, a network made up of all 12 points is formed which are connected by those lines.
For each of the 41 pairings, the two points and their respective weights are kept in an array and sent to a function (func_7).

What is func_7 ?
This is revealed by the shellcode or encrypted bytes within the function.
1 | Oh no! Not only is this function flawed, it is nonexistent. Could you please solve this? |
Now let’s have a look at the shellcode given in Katanaverse 0.0 as well, because after all , this challenge is just an another part of 0.0
1 | Oh no! Not only is this function flawed, it is nonexistent. Could you please solve this? |
This clearly states few points -
- Quantum
- Division of points
- Optimization
- Weighted (Because of the distance calculated between 2 points)
- Brute
Using these terms in a Google search provides us with the necessary response.


These searches hint at using a popular Quantum optimization technique used in efficient division of enities, that is, QAOA (Quantum Approximate Optimization Algorithm)
In Katanaverse 1.0, we only need the brute version of this algorithm, which can be again found on blog posts or can be attempted to write on your own.
Since here, the weights of the points are also given, that again can be used to find the technique

Official qiskit page itself gives us an easy script to implement the given problem qiskit

Last step
After applying QAOA to every group in the classified array, 12 bits per group are obtained. These bits are then split in half to create two bytes. As a consequence, each group yields two final bytes, which are subsequently encrypted collectively using AES.


For comparison, the encrypted bytes of the right flag (after going through the full process) are provided.
Solution
So far we know what all is going on this challenge, therefore it’s time to consider how to get the flag back.
The constraints are given to make life easier.
We have the encrypted bytes of the result of the QAOA applied to the points. First, it is possible to decrypt the encrypted bytes and obtain all of the constants generated during runtime.
Since each group/set of classified array is constructed from overlapped pairs of modified flag, we can make use of the flag format to obtain the flag byte by byte.
The approach being, make use of the last known character of the flag format, that is, ‘{‘. The characters of the flag after this character are unknown, hence we find all the possibilities of the next byte by using the constraints given. Since the number of constraints for the classified array group of ‘{‘ and the next byte of the flag is 3, we have 32 possibilites (2^8[All possible 1 byte values] / 2^3[Branches narrowed down due to constraints given])
These 32 possibilites are passed through the entire process until the QAOA function and then the result is compared with the decrypted bytes from the binary.
Likewise, the discovered byte can be used to find the next byte in the order.
Authors note:
These might lead to more than one possible character for the given scenario, but the branches can be eliminated by acquiring the subsequent iteration. There is a single path that leads to the last character ‘{‘. You receive the right flag if you continue down that path.
Final Script
1 | import numpy as np |
1 |
|
Basically prune the branches which are not yielding any output in the next iteration and that narrows down the flag to
cV9jbXB0bmctaXNfZnVu
with a requirement of brute for few of the characters
Flag - bi0sctf{q_cmptng-is_fun}
Katanaverse 0.0
With the exception of the quantity of constraints and the technique for Dividing the points, this level is comparable to 1.0 in many ways. In contrast to the brute technique employed in 1.0, the appropriate quantum method is utilized in 0.0 to divide points more quickly. The same URL as previously has the code implementation for the same.
The platform that allows us to run our code on quantum computers, or the platform that supports the Qiskit module, is required to execute this. I think IBM’s Quantum laboratories is the best platform to conduct this on.
Flag - bi0sCTF{QuBitJugglr}
Closing Notes
It is undoubtedly difficult to use the notion of quantum in a challenge, but I did my best to do so and do it right.
We appreciate everyone who tried their hand at the CTF challenge.
- Title: Katanaverse 1.0 : bi0sCTF 2024
- Author: Sejal Koshta
- Created at : 2024-03-29 00:32:21
- Updated at : 2024-08-12 22:42:04
- Link: https://k1n0r4.github.io/2024/03/29/Katanaverse-1-0-bi0sCTF-2024/
- License: This work is licensed under CC BY-NC-SA 4.0.