linux-rootkit

Feature-rich interactive rootkit that targets Linux kernel 4.19, accompanied by a dynamic kernel memory analysis GDB plugin for in vivo introspection (e.g. using QEMU)
git clone git://git.deurzen.net/linux-rootkit
Log | Files | Refs

commit 620ba833a65e837eb8dc2c88b74db0fe0b3934ee
parent efc0e72c5de4465d7a2b3d2fcffebc3f9e8ee76e
Author: deurzen <m.deurzen@tum.de>
Date:   Sat, 16 Jan 2021 02:34:34 +0100

reorganizes files; adds memory forensics gdb plugin

Diffstat:
Amem_forensics/memcheck-gdb.py | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arootkit/.gitignore | 17+++++++++++++++++
RMakefile -> rootkit/Makefile | 0
Rcheckers/check_filehiding -> rootkit/checkers/check_filehiding | 0
Rcheckers/check_pingpong.py -> rootkit/checkers/check_pingpong.py | 0
Rsrc/backdoor.c -> rootkit/src/backdoor.c | 0
Rsrc/backdoor.h -> rootkit/src/backdoor.h | 0
Rsrc/channel.c -> rootkit/src/channel.c | 0
Rsrc/channel.h -> rootkit/src/channel.h | 0
Rsrc/common.h -> rootkit/src/common.h | 0
Rsrc/creds.c -> rootkit/src/creds.c | 0
Rsrc/creds.h -> rootkit/src/creds.h | 0
Rsrc/filehide.c -> rootkit/src/filehide.c | 0
Rsrc/filehide.h -> rootkit/src/filehide.h | 0
Rsrc/filehide_lstar.c -> rootkit/src/filehide_lstar.c | 0
Rsrc/filehide_lstar.h -> rootkit/src/filehide_lstar.h | 0
Rsrc/g7.c -> rootkit/src/g7.c | 0
Rsrc/hook.c -> rootkit/src/hook.c | 0
Rsrc/hook.h -> rootkit/src/hook.h | 0
Rsrc/inputlog.c -> rootkit/src/inputlog.c | 0
Rsrc/inputlog.h -> rootkit/src/inputlog.h | 0
Rsrc/ioctl.h -> rootkit/src/ioctl.h | 0
Rsrc/modhide.c -> rootkit/src/modhide.c | 0
Rsrc/modhide.h -> rootkit/src/modhide.h | 0
Rsrc/openhide.c -> rootkit/src/openhide.c | 0
Rsrc/openhide.h -> rootkit/src/openhide.h | 0
Rsrc/packhide.c -> rootkit/src/packhide.c | 0
Rsrc/packhide.h -> rootkit/src/packhide.h | 0
Rsrc/pidhide.c -> rootkit/src/pidhide.c | 0
Rsrc/pidhide.h -> rootkit/src/pidhide.h | 0
Rsrc/porthide.c -> rootkit/src/porthide.c | 0
Rsrc/porthide.h -> rootkit/src/porthide.h | 0
Rsrc/read.c -> rootkit/src/read.c | 0
Rsrc/read.h -> rootkit/src/read.h | 0
Rsrc/rkctl/rkctl.c -> rootkit/src/rkctl/rkctl.c | 0
Rsrc/rkctl/rkctl.h -> rootkit/src/rkctl/rkctl.h | 0
Rsrc/rootkit.h -> rootkit/src/rootkit.h | 0
Rsrc/sockhide.c -> rootkit/src/sockhide.c | 0
Rsrc/sockhide.h -> rootkit/src/sockhide.h | 0
39 files changed, 165 insertions(+), 0 deletions(-)

diff --git a/mem_forensics/memcheck-gdb.py b/mem_forensics/memcheck-gdb.py @@ -0,0 +1,148 @@ +import os + +file = None + +class RkLoadSymbols (gdb.Command): + """Determine the KASLR-Offset and map the symbols.""" + + v_off = 0 + symbol = "native_safe_halt" + + def __init__ (self): + super (RkLoadSymbols, self).__init__ ("rk-load-symbols", gdb.COMMAND_USER, gdb.COMMAND_DATA) + + + def invoke (self, arg, from_tty): + self.get_v_off(arg) + self.load_sym(arg) + + def load_sym (self, arg): + v_off = hex(self.v_off) + + print(f"attempting to load symbols from \"{arg}\" with offset {v_off}") + try: + gdb.execute(f"add-symbol-file {arg} -o {self.v_off}") + except: + print("error loading symbol file, does it exist?") + return None + + def get_v_off (self, arg): + global file + + sym_addr = get_symbol_address(arg, self.symbol) + + if sym_addr is None: + return None + + file = arg + + #minimal assumption: user is at login prompt + try: + real = gdb.execute("where", to_string=True).split(" ")[2] + except: + print("error executing where, is the VM running?") + return None + + real_addr = int(real, 16) + self.v_off = ((real_addr - sym_addr) & (~0xf)) + +RkLoadSymbols () + + + + +class RkKaslrOffset (gdb.Command): + """Output the calculated physical and virtual KASLR offset.""" + + symbol = "native_safe_halt" + obj_addr = None + + def __init__ (self): + super (RkKaslrOffset, self).__init__ ("rk-kaslr-offset", gdb.COMMAND_USER, gdb.COMMAND_DATA) + + # assuming rk-load-symbols has already been run + def invoke (self, arg, from_tty): + global file + + if file is None: + print("no object file has been read in to calculate offsets, please run `rk-load-symbols` first.") + return None + + self.obj_addr = get_symbol_address(file, self.symbol) + obj_addr = hex(self.obj_addr) + + print(f"address for symbol `{self.symbol}` inside object file \"{file}\" is {obj_addr}") + + v_addr = self.get_v_addr() + p_addr = self.get_p_addr(v_addr) + + print(f"looking up addresses for symbol `{self.symbol}`") + print(f"found virtual address {v_addr} with associated physical address {p_addr}") + + v_off = self.get_off(v_addr) + p_off = self.get_off(p_addr) + + print(f"virtual KASLR offset: {v_off}") + print(f"physical KASLR offset: {p_off}") + + + def get_v_addr(self): + try: + return gdb.execute(f"p {self.symbol}", to_string=True).split(" ")[-2] + except: + print("error executing `where`, is the VM running?") + return None + + + def get_p_addr(self, v_addr): + try: + return gdb.execute(f"monitor gva2gpa {v_addr}", to_string=True).split(" ")[-1] + except: + print("error interacting with monitor, is the VM running?") + return None + + + def get_off (self, addr): + global file + + if self.obj_addr is None: + return None + + real_addr = int(addr, 16) + + return hex((real_addr - self.obj_addr) & (~0xf)) + + +RkKaslrOffset () + + + + +class RkSyscallCheck (gdb.Command): + """Check the integrity of the syscall table. Run rk-load-symbols first.""" + + def __init__ (self): + super (RkSyscallCheck, self).__init__ ("rk-syscall-check", gdb.COMMAND_USER, gdb.COMMAND_DATA) + + + def invoke (self, arg, from_tty): + print("Soose!") + +RkSyscallCheck () + + + + +# return address of symbol from file through nm +def get_symbol_address(file, symbol): + stream = os.popen(f"nm {file} | grep -w \"\\b{symbol}\\b$\" | awk \'{{print $1}}\'") + sym = stream.read() + stream.close() + + # symbol address _before_ randomization + try: + sym_addr = int(sym, 16) + return sym_addr + except: + print(f"error retrieving address from '{arg}', did you specify a file?") + return None diff --git a/rootkit/.gitignore b/rootkit/.gitignore @@ -0,0 +1,17 @@ +/.*.ko.cmd +/*.img +/.*.mod.cmd +/.*.mod.o.cmd +/.*.o.cmd +/Module.symvers +/*.ko +/*.mod +/*.mod.c +/*.mod.o +/*.o +/modules.order +/src/.*.o.cmd +/src/*.o +/rkctl +/tags +/*.o.d diff --git a/Makefile b/rootkit/Makefile diff --git a/checkers/check_filehiding b/rootkit/checkers/check_filehiding Binary files differ. diff --git a/checkers/check_pingpong.py b/rootkit/checkers/check_pingpong.py diff --git a/src/backdoor.c b/rootkit/src/backdoor.c diff --git a/src/backdoor.h b/rootkit/src/backdoor.h diff --git a/src/channel.c b/rootkit/src/channel.c diff --git a/src/channel.h b/rootkit/src/channel.h diff --git a/src/common.h b/rootkit/src/common.h diff --git a/src/creds.c b/rootkit/src/creds.c diff --git a/src/creds.h b/rootkit/src/creds.h diff --git a/src/filehide.c b/rootkit/src/filehide.c diff --git a/src/filehide.h b/rootkit/src/filehide.h diff --git a/src/filehide_lstar.c b/rootkit/src/filehide_lstar.c diff --git a/src/filehide_lstar.h b/rootkit/src/filehide_lstar.h diff --git a/src/g7.c b/rootkit/src/g7.c diff --git a/src/hook.c b/rootkit/src/hook.c diff --git a/src/hook.h b/rootkit/src/hook.h diff --git a/src/inputlog.c b/rootkit/src/inputlog.c diff --git a/src/inputlog.h b/rootkit/src/inputlog.h diff --git a/src/ioctl.h b/rootkit/src/ioctl.h diff --git a/src/modhide.c b/rootkit/src/modhide.c diff --git a/src/modhide.h b/rootkit/src/modhide.h diff --git a/src/openhide.c b/rootkit/src/openhide.c diff --git a/src/openhide.h b/rootkit/src/openhide.h diff --git a/src/packhide.c b/rootkit/src/packhide.c diff --git a/src/packhide.h b/rootkit/src/packhide.h diff --git a/src/pidhide.c b/rootkit/src/pidhide.c diff --git a/src/pidhide.h b/rootkit/src/pidhide.h diff --git a/src/porthide.c b/rootkit/src/porthide.c diff --git a/src/porthide.h b/rootkit/src/porthide.h diff --git a/src/read.c b/rootkit/src/read.c diff --git a/src/read.h b/rootkit/src/read.h diff --git a/src/rkctl/rkctl.c b/rootkit/src/rkctl/rkctl.c diff --git a/src/rkctl/rkctl.h b/rootkit/src/rkctl/rkctl.h diff --git a/src/rootkit.h b/rootkit/src/rootkit.h diff --git a/src/sockhide.c b/rootkit/src/sockhide.c diff --git a/src/sockhide.h b/rootkit/src/sockhide.h