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 7b49705a0679e7217fd700770899a3d6f2771ad6
parent c33ad18c9557150e5d738feed4f6a13a522a31b9
Author: deurzen <m.deurzen@tum.de>
Date:   Sun, 24 Jan 2021 00:32:53 +0100

initial refactoring

Diffstat:
Mmem_forensics/memcheck-gdb.py | 46+++++++++++++++++++++++++++++++---------------
Mup.sh | 2+-
2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/mem_forensics/memcheck-gdb.py b/mem_forensics/memcheck-gdb.py @@ -624,43 +624,54 @@ class RkCheckFunctions(gdb.Command): print("populating dictionaries...", end='', flush=True) self.fill_code_dict() + print(self.code_dict) self.fill_altinstr_dict() + # print(self.altinstr_dict) self.fill_paravirt_dict() + # print(self.paravirt_dict) + self.compare_functions() print(" done!") def fill_code_dict(self): + sym_i = 0 for symbol in self.s.iter_symbols(): + if sym_i == 100: + break + if symbol.entry["st_info"]["type"] == "STT_FUNC": name = symbol.name size = symbol.entry["st_size"] else: continue - + if name is None or ".cold." in name or ".part." in name or ".constprop." in name: continue - + addr = self.get_v_addr(name) if addr is None: continue - objdump = subprocess.check_output(f"objdump -z --disassemble={name} {file_g}", shell=True).split(b"\n")[:-1] + objdump = subprocess.check_output(f"objdump -z --disassemble={name} {file_g}", shell=True) + objdump = objdump.split(b"\n")[:-1] start = None - for i, s in enumerate(objdump): - if name in s.decode(sys.stdout.encoding): - start = i - break - - objdump = objdump[start+1:] - end = None + for i, s in enumerate(objdump): - if b'' == s: - end = i + if start is not None: + if end is None and s == b'': + end = i + else: + if name in s.decode(sys.stdout.encoding): + start = i + 1 + + if start is not None and end is not None: break if end is not None: - objdump = objdump[:end] + objdump = objdump[start:end] + else: + objdump = objdump[start:] objdump = [line.split(b"\t") for line in objdump] @@ -668,6 +679,7 @@ class RkCheckFunctions(gdb.Command): elf_bytes = "".join(elf_bytes) self.code_dict[name] = (size, elf_bytes) + sym_i += 1 def fill_altinstr_dict(self): global file_g @@ -677,7 +689,7 @@ class RkCheckFunctions(gdb.Command): # .long offset <-- Adress to instructions we ignore: addr = (__alt_instructions + cur (offset into .altinstructions)) + offset + v_off_g # .long repl_offset # .word cpuid - # .byte instrlen + # .byte instrlen # .byte replacementlen <-- How many instructions we skip # .byte padlen @@ -685,7 +697,7 @@ class RkCheckFunctions(gdb.Command): data = sec.data() alt_instr_sz = 13 - replacementlen_off = 11 + replacementlen_off = 11 i = 0 while i < sec["sh_size"]: @@ -748,6 +760,10 @@ class RkCheckFunctions(gdb.Command): i = i + paravirt_patch_site_sz + def compare_functions(self): + for size, bytes in self.code_dict: + pass + def get_v_addr(self, symbol): try: return gdb.execute(f"x {symbol}", to_string=True).split(" ")[0] diff --git a/up.sh b/up.sh @@ -67,7 +67,7 @@ if ! test -z $BLOCKSET && test -z $GDBSET; then exit 1 fi -qemu-system-x86_64 $PARAMS -hda debian.img -m 4096 -enable-kvm -cpu host -device e1000,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 & +qemu-system-x86_64 -gdb tcp::1234 -hda debian.img -m 4096 -enable-kvm -cpu host -device e1000,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 & if ! test -z $GDBSET; then test -z $EXPECTSSH || st -e ./ssh.expect &