ICS: Programming Homework: Rootkits

Go up to the ICS HW page (md) | view tabbed version

Overview

In this assignment, you will investigate both types of rootkits: application and kernel. There are four tasks to be completed for submission. You will want to review the rootkit slides.

In this assignment, you will create both types of rootkits: a kernel-level one and an application-level one.

YOU MUST RUN THIS ON THE VIRGINIA CYBER RANGE!!!, described below. You are going to negatively affect the machine you develop this on. Do not think that you can or should do this on your computer and still have your computer work.

We are not responsible if you render your computer inoperable because you did not follow this warning! This is why we provided the Cyber Defense Range account!

Changelog

Any changes to this page will be put here for easy reference. Typo fixes and minor clarifications are not listed here.

Platform

We will be using the Virginia Cyber Range at https://www.virginiacyberrange.org/. This site basically allows you to run a remote virtual environment; we are using Ubunmtu 22.04.

Go to https://www.virginiacyberrange.org/. Click on “sign up”, then “join as a student”. Use the invitation code on the canvas landing page, then sign in (presumably with your Google UVA account). You will need to accept the agreement to continue.

If you already have an account, there is (presumably) a way to add this course via the invitation code…

Once you log in, click on the course. There will then be a list of exercise environments at the bottom of the page – there should be only one, called “Rootkits HW Environment”. Click on it, then click on the power button on the page that appears (it’s in the lower left of the page). It will take a minute or so to start (boot). Once it does, hit the play button (the right-arrow that replaced the power button) to attach to a screen in the virtual environment.

You can load up a terminal via one of the icons on the bottom of the screen. You will then have to install a bit of the software. To do so, enter the following two commands:

sudo apt update
sudo apt install -y make g++ emacs

You are welcome to install any other software that you would like to use. gedit is already installed, as is python3.

When you are done, you should close that window, and you can stop the virtual machine (the stop button, which is next to the play button that started this whole party).

WARNING: This site is free to use for class purposes for all students in the course. Using it for non-class purposes is an honor violation, and will be dealt with as such. Anything outside the reasonable bounds of an assignment in this course is considered a non-class purpose.

This is a great resource, but it is a finite resource. If you decide to wait to the last minute to start the assignment, and the rest of your class-mates do so as well, it’s going to be slooooooow. You cannot get an extension because you waited until the last minute along with everybody else, and the system was slow as a result.

Working as root

Some of these commands will require to to execute them as the root user. You can do this by prepending sudo in front of the command. For example, to insert a module called root.ko, you would call sudo insmod root.ko – this executes the insmod root.ko command as root.

Task 1: Kernel-level rootkit

Kernel level rootkit: Recall that a Linux kernel level rootkit installs a loadable kernel module (LKM) that gives the attacker more privileges on the compromised machine. We are going to build such a module here. There are two tasks to be done for the kernel level rootkit aspect of this assignment.

Follow this tutorial at 0x00SEC. It is not necessary to read the two sub-tutorials (1 and 2), if you do not want to. This rootkit will allow you to gain root access on the machine from a non-root user. Note: the sub-tutorials (if you want to read them) should be used to understand what is happening on the main tutorial at 0x00SEC page; they do not all compile at this point.

A few notes from those tutorials:

The first task for this assignment is to create this rootkit as specified in the tutorial.

Note that to complete this part, you can just copy the code that is listed there – that’s the code that you have to submit, after all. However, you have to explain to us how the code works. We are looking for a half-page, and it needs to be specific enough that we see that you really understand what is going on in that code. This should go into a kernel-rootkits.pdf file (more content will go into that file for the next task).

For submission of your code, you should put your code in a root.c file (the same name as in the tutorial), and put the appropriate compilation lines in the Makefile. The module name MUST be root.ko, otherwise we won’t be able to load it ourselves.

Task 2: What else?

What else can rootkits do?

This was a fairly simple rootkit, as far as complexity goes, although it’s a lot to learn all at once. All this does is allow one to gain root access – useful, to be sure, but there is much more that rootkits can do.

The second task for this assignment is to investigate other things that rootkits can perform. We are looking for specific things that can be done, not high-level mumbo-jumbo. For each thing, a sentence describing it would be sufficient. For example, the access that the rootkit that you just implemented might be phrased such as:

How many to find? That’s up to you. If you have a bunch, and you are not finding anymore, then you are done. You can use Google searches, look at rootkit code online – take a look here to start. That source code lists 12 different functionalities (one of which being giving root access to non-root users). Thus, we would expect a list of 20 or more.

This part should be put into a PDF called kernel-rootkits.pdf; note that there will also be content in that file from the first task.

Task 3: Wrapper files

Application level rootkit: Recall that an application level rootkit will replace specific utilities with compromised versions. There are two tasks to be done for the application level rootkit aspect of this assignment.

You are going to create a “wrapper” program that will perform the “malicious” task, and then call the original program. For this one, we will attack the sha224sum program, which is located at /usr/bin/sha224sum. We chose this file because it’s not all that critical, and if it gets messed up, you can still use the operating system.

The sha224sum program has a number of command-line parameters that it accepts. See here for a list of these. Note that different versions of sha224sum, as well as different OSes, will have different options. In particular, you cannot assume any particular set of options.

First, BACK UP THE PROGRAM. For example: sudo cp /usr/bin/sha224sum /usr/bin/sha224sum.bak. This way if you mess up, you can easily restore it.

Next, copy the sha224sum program to another name – we will use /usr/bin/sha224sum.original for this task. When we test your program, we are going to rename our /usr/bin/sha224sum to /usr/bin/sha224sum.original, so if you use a different name, your submission will not work.

You are going to write a wrapper program that you will name sha224sum, and put it in /usr/bin/ – thus, when you normally call sha224sum, it will call your wrapper file. Your wrapper file will then call the renamed (and original) sha224sum.original.

Example usage:

$ sha224sum Makefile
09142d9d6dc3f122f931dd9c5dc733f78250063fb03e30997daea6c2  Makefile
$ sha224sum --tag Makefile
SHA224 (Makefile) = 09142d9d6dc3f122f931dd9c5dc733f78250063fb03e30997daea6c2
$ sha224sum --be-evil Makefile
09142d9d6dc3f122f931dd9c5dc733f78250063fb03e30997daea6c2  Makefile
The sky above the port was the color of television, tuned to a dead channel.
$ sha224sum --tag --be-evil Makefile
SHA224 (Makefile) = 09142d9d6dc3f122f931dd9c5dc733f78250063fb03e30997daea6c2
The sky above the port was the color of television, tuned to a dead channel.
$ 

Obviously, your hash is expected to be different.

You can do this in any language that you want:

For this assignment, you should name your source code file sha224sum-fake.? where the “?” is the appropriate filename extension (use ‘sh’ for a shell script).

Your Makefile MUST create a sha224sum executable file. If your code requires compilation, then compile it to the sha224sum file name. If you are using a scripting language (Python or bash), then copy the file over WITHOUT a .py or .sh extension. If you are using C, C++, or Go, then compile it to that file name. We are going to run make, then assume that the sha224sum file is present.

NOTE: In your Makefile, you should NOT copy the resulting sha224sum file to /usr/bin – our grading scripts will do that for you. You will need to do that manually when testing it, but let our grading scripts handle that upon submission.

Task 4: Modify source code

For this task, we will attack the sha384sum binary, for similar reasons as the previous task – it’s not likely to be critical to your OS booting.

First, BACK UP THE PROGRAM. For example: sudo cp /usr/bin/sha384sum /usr/bin/sha384sum.bak. This way if you mess up, you can easily restore it.

For this task we are going to modify the source code to insert our compromise into the program itself. Linux is open source, and all of the core utilities are GNU, so their source code is freely available. You can download the latest (highest-numbered) version from https://ftp.gnu.org/gnu/coreutils/ – although there are likely later verions, we are going to version 8.31. The specific file to download is here. The coreutils are the basic utilities used by all Linux systems – ls, cp, mv, etc. Once you’ve downloaded it, uncompress it (tar xfa coreutils-8.31.tar.xz). Once in that directory, run ./configure then make. This will work on the Virginia Cyber Range – you are on your own if you are using your own computer’s OS.

The source code for the various files in coreutils is all inter-dependent on each other, and it’s not worth our time for this assignment to figure out the details or try to separate it. So you are going to edit the appropriate files in the coreutils archive and compile it with the Makefile that the archive provides. The main() function for the sha384sum binary is in src/md5sum.c (SHA-1 was originally added as an “extension” of MD5, and it stayed that way as successive SHA versions were created). Once you modify that file, you can run make src/sha384sum.

To ensure that you can get it to work, put a printf() statement in the top of the main() method in md5sum.c, then run make src/sha384sum. When you run the command (src/sha384sum <file>), it should print your output from the printf() line, then the 384-bit SHA hash. Then remove that printf() statement.

The challenge for this task is that you have to find out some information about the host system and then send that over a network connection. This all has to happen when sha384sum is run.

One can find out a lot of information about the system. For this part, though, we aren’t as focused on what you can find out, but instead how you send that information back. The information we want is the output of lsb_release -a. On the Virginia Cyber Range, it would print out:

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.2 LTS
Release:        18.04
Codename:       bionic

Note that the first line will vary, as that is reporting on the hardware on your machine (mine said “LSB Version: core-9.20170808ubuntu1-noarch:security-9.20170808ubuntu1-noarch”). Also note that this is multiple lines – how you send it back is up to you. It can be multiple calls (one per line) – or, more easily, just one call. It’s fine if you just remove spaces and newlines so that the text sent back is:

NoLSBmodulesareavailable.DistributorID:UbuntuDescription:Ubuntu18.04.2LTSRelease:18.04Codename:bionic

You can even replace all spaces with underscores, if you wish. We are less focused on text formatting and more on the obtaining and transmission of the information. And if your system does not print the first line (“No LSB modules are available.”), that’s fine as well.

From the C code, you will need to execute a command-line program and capture the output. There are a few ways to do this:

You will then need to transmit this over the network. To simplify it, you just call a URL, which is shwown on the Canvas landing page. In that URL, mst3k is your userid and the ... is the data you are sending. You can do this via a wget call (executing a command-line program from the C/C++ program via system(): wget <URL>. This puts the information into the apache web server log. There are more efficient ways to do this, but putting it into the apache log is fine for this assignment. Note that you should supress the output from the wget call – you can do this with the -q flag.

You may also want to familiarize yourself with the system() function.

NOTE: Your program should NOT display any output from the wget command. You can redirect it to a file (use /dev/null: wget ... > /dev/null) or use the -q (quiet) option, or both.

To see what information has been sent, go directly to the rootkit data viewer URL, which is on the Canvas landing page. Once you log in with Netbadge, you will be able to see all the data sent in under that userid.

Note that the logs that are displayed only keep the information sent in the last few hours – we will look at the entire log history when we grade the assignment, but the information that you see will be only the most recent. So don’t worry if the entries that you saw on a previous day are no longer present. As long as they were there at some point, we’ll see them when we grade the assignment.

The only file you should submit from this is the modified md5sum.c file. We will unpack and configure the entire coreutils archive, put the md5sum.c file in there, and then recompile the sha384sum program. Thus, you do NOT need anything in your Makefile for this task.

Hints

We’ve collected a few of these here…

Submission

Sanity checks

A few things to check before you submit…

Submission

The following files will need to be submitted:

The primary Makefile target must:

Below is the Makefile that we used (recall that the indentation in the Makefile must be tabs, not spaces), however your mileage may vary.

obj-m+=root.o

all:
    make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
    /bin/cp -a sha224sum-fake.py sha224sum

clean:
    make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean

Recall that the sha224sum compilation (or copy) line will vary based on the language used.