You may have heard about Jynx and Jynx2 rootkits. These are the so-called userland rootkits; they use the LD_PRELOAD variable feature, which allows you to load any libraries before the program is launched. They are already relatively old, but still work well.
2 days ago, Github-user Chokepoint posted a rootkit Azazel. It is based on the Jynx source code and has many new features:
Anti-debugging mechanisms
Hiding from unhide, lsof, ps, ldd
Hiding files and directories
Hiding remote connections
Hiding processes
Hiding logins
Hiding from local traffic sniffing via PCAP
2 backdoors with full shell (with PTY):
- Crypthook accept () - backdoor
- Normal accept () - backdoor
PAM backdoor for authentication by any user
Clearing utmp / wtmp logs for PTY
Obfuscating compiled library lines with xor.
LD_PRELOAD
. The question is, is it possible to somehow control it?execve
function (or rather sys_execve ), scans the parameters of the list of environment variables (known as envp
) for the presence of a specific string in them, namely the very LD_PRELOAD
. DECLARE_KHOOK(sys_execve); long khook_sys_execve( const char __user * file, const char __user * const __user * argv, const char __user * const __user * envp ) { long result; KHOOK_USAGE_INC(sys_execve); scan_env_for((void *)file, (void *)envp, env_token); result = KHOOK_ORIGIN(sys_execve, file, argv, envp); KHOOK_USAGE_DEC(sys_execve); return result; }
sys_execve
, a search is made for matching environmental variables with the specified string env_token
. This makes the simple scan_env_for function: void scan_env_for(char * file, char * envp[], const char * token) { int i; char * string; char * string_ptr; if (!envp || !token) return; string = kmalloc(MAX_ARG_STRLEN + 1, GFP_KERNEL); if (!string) { debug("Can't get memory for the environ string\n"); return; } for (i = 0; i < MAX_ARG_STRINGS; i++) { if (get_user(string_ptr, envp + i)) { debug("Can't get user pointer value\n"); goto out_kfree; } if (string_ptr == NULL) goto out_kfree; if (strncpy_from_user(string, string_ptr, MAX_ARG_STRLEN) == -EFAULT) { debug("Can't get user string\n"); goto out_kfree; } string[MAX_ARG_STRLEN] = 0; if (strncmp(string, token, strlen(token)) == 0) { char * filename; filename = kmalloc(PATH_MAX + 1, GFP_KERNEL); if (filename) { strncpy_from_user(filename, file, PATH_MAX + 1); filename[PATH_MAX] = 0; } debug("Attention, task \"%s\" trying to execute \"%s\" with \"%s\"\n", \ current->comm, filename ? filename : "(unknown)", string); kfree(filename); goto out_kfree; } } out_kfree: kfree(string); }
$ sudo insmod envscan.ko env_token=\"LD_PRELOAD=\" $ dmesg | grep envscan [37713.809903] [envscan] Symbol "module_free" found @ ffffffff810bdcd0 [37713.810190] [envscan] Symbol "module_alloc" found @ ffffffff810407e0 [37713.810523] [envscan] Symbol "sort_extable" found @ ffffffff81048a90 [37713.810524] [envscan] Hunting for "LD_PRELOAD=" [37713.811798] [envscan] Symbol "sys_execve" found @ ffffffff8119ba30 $ LD_PRELOAD=/lib/ld-linux.so.2 ls [37743.786499] [envscan] Attention, task "bash" trying to execute "/bin/ls" with "LD_PRELOAD=/lib/ld-linux.so.2"
LD_PRELOAD
.Source: https://habr.com/ru/post/212825/
All Articles