Challenge 3: Ciphered Writes ============================ Suppose you want to enforce automatic data transformation at the kernel level whenever applications write data to files. Instead of trusting each application to handle encryption correctly, you decide to implement a mechanism that transparently modifies data inside the kernel before it reaches the filesystem. In this challenge, you will develop an eBPF program that intercepts write operations and applies a **simple** encryption scheme to the data being written. Description ----------- Processes normally write plain text data to files using system calls such as ``write()``. Your objective is to intercept these write operations and automatically transform the data before it is committed to disk. Specifically, the eBPF program must apply a Caesar cipher to the data being written. A Caesar cipher shifts each alphabetical character in the text by a fixed number of positions in the alphabet. For example, with a shift of 3, the letter 'A' would be transformed to 'D', 'B' to 'E', and so on. The cipher should wrap around the alphabet, so 'Z' would become 'C'. Both uppercase and lowercase letters should be transformed accordingly. Non-alphabetical characters (such as digits, punctuation, and whitespace) should be left unchanged. Your program should transparently modify the data buffer passed to the ``write()`` system call so that the file ultimately contains the ciphered version of the original text. Setup ----- Download this challenge's template using: .. code-block:: bash $ wget --no-check-certificate https://people.montefiore.uliege.be/~gain/courses/info0940/asset/ciphered.tar.gz $ tar -xzvf ciphered.tar.gz The program that will be used for testing is located in ``echo_test``. This will simply write the string "Hello123" to a file named ``output.txt``. You can compile it using the Makefile provided (simply run ``make`` within the ``echo_test`` directory). Then you can run it using: .. code-block:: bash $ ./echo_test After running the ``echo_test`` program, the content of ``output.txt`` should be "Hello123" if your eBPF program is not loaded. Inside ``ciphered/src``, you will find the same template as in tutorial 3. Use it to implement the eBPF program that applies the Caesar cipher to the data being written to files. What you need to do ------------------- Your task is to develop an eBPF program that applies a Caesar cipher to data written via the ``write()`` system call. However, the cipher should only be active when two conditions are met: the process issuing the write is named "echo_test", and it is writing to a file rather than the standard output or standard error. .. important:: Not filtering the process that you want to target ("echo_test") could lead to unintended consequences on the system. You must only consider alphabetic characters: both uppercase (``A-Z``) and lowercase (``a-z``). Other characters (such as digits, punctuation, etc.) should be left unchanged. The shift value for the Caesar cipher should be configurable when loading the eBPF program. The argument is the following: - ``--shift``: The number of positions to shift each letter in the alphabet. Default should be 3. The shift value should be modulo 26, meaning that a shift of 29 would be equivalent to a shift of 3. This is what it will look like when you run the "echo_test" program with your eBPF program loaded: .. code-block:: bash # By default the shift value is 3, so the output should be: $ ./echo_test echo_test successfully wrote to output.txt $ cat output.txt Khoor123 # If the shift value of 10 was used when loading the eBPF program, the output should be: $ ./echo_test echo_test successfully wrote to output.txt $ cat output.txt Rovvy123 .. tip:: - To add an argument ``--shift`` to the user-space program, you will have to modify the user-space code. You can use ``getopt_long`` to parse user-space arguments. You will also have to use new eBPF notions in this tutorial, which you learned in tutorial 4. - You won't be able to read from and write to user-space memory from your eBPF program without using helper functions [1]_. However, in the arguments passed to the ``write()``, there is a pointer to the user-space buffer that contains the data to be written ("Hello123" in this example). - When writing a loop, remember that a verification engine will check your eBPF program before it is loaded. (See tutorial 3) .. [1] These helpers are used to read from or write to kernel or userspace memory: `Memory helpers `_