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 715f54206041178485c2a42f7c4a8417dd7426f2
parent 55c4588254f7cf09ef6ee9b8867c667c0ba25ce3
Author: Tizian Leonhardt <tizianleonhardt@web.de>
Date:   Fri,  5 Feb 2021 19:08:40 +0100

Handle pointers and 'direct' structs [WIP]

Diffstat:
Mproject/extract_sizeret.py | 65++++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 50 insertions(+), 15 deletions(-)

diff --git a/project/extract_sizeret.py b/project/extract_sizeret.py @@ -88,35 +88,68 @@ class RKPrintData(gdb.Command): if not "struct" in type: print(f"Printing hexdump of base type '{type}'") - gdb.execute(f"x/{size}b {addr}") + gdb.execute(f"x/{size}x {addr}") else: - self.data_lookup(type, addr, size) + self.data_lookup(type, addr, 0) - def data_lookup(self, type, addr, size): + def data_lookup(self, type, addr, reclevel): + # Only recurse 3 levels + if reclevel > 3: + return None + + try: contents = gdb.execute(f"ptype {type}", to_string=True).splitlines() + except: + print("Could not infer type!") + return None + + # Print type declarator - "type = ", get rid of last curly bracket + print(reclevel * '\t', contents.pop(0)[len("type = "):]) + contents = contents[:-1] - # Print type declarator, get rid of last curly bracket - print(contents.pop(0)) - contents = contents[:-1] + basetype = ["struct", '*'] - basetype = ["struct", "*"] + for line in contents: + sz = 0 - for line in contents: - # Case basetype - if not any(b in line for b in basetype) and not self.is_struct(line): - self.basetype(line, addr) + # Case basetype + if not any(b in line for b in basetype) and not self.is_struct(line): + sz = self.basetype(line, addr, reclevel) + + #Case pointer + elif '*' in line: + sz = self.pointer(line, addr, reclevel) + + #Case struct + else: + t = self.type_from_line(line) + self.data_lookup(t, addr, reclevel + 1) - print("}") + addr += sz - def basetype(self, line, addr): + print(reclevel * '\t', "}") + + def basetype(self, line, addr, reclevel): # We only need type information, no name needed t = self.type_from_line(line) # Retrieve size and read memory accordingly sz = int(gdb.parse_and_eval(f"sizeof({t})")) dt = gdb.selected_inferior().read_memory(addr, sz) + self.print_line(line, dt, reclevel) + + return sz - print(f"{line.replace(';', '')} => 0x{bytes(dt).hex()}") + def pointer(self, line, addr, reclevel): + # 8 byte addresses + POINTER_SZ = 8 + + t = self.type_from_line(line) + + dt = gdb.selected_inferior().read_memory(addr, 8) + self.print_line(line, dt, reclevel) + + return POINTER_SZ def type_from_line(self, line): t = line.split(" ")[:-1] @@ -126,7 +159,9 @@ class RKPrintData(gdb.Command): def is_struct(self, line): t = self.type_from_line(line) return "struct" in gdb.execute(f"ptype {t}", to_string=True) - + + def print_line(self, line, data, reclevel): + print(reclevel * '\t', f"{line.replace(';', '')} => 0x{bytes(data).hex()}") RKPrintData()