Skip to content

Anti Detection

blank edited this page Dec 12, 2016 · 6 revisions

libdl hooks

  • A somewhat more reliable and in-depth method of detecting LD_PRELOAD malware is by using the libdl functions to check and compare symbols and their addresses.
  • By comparing symbol addresses, we're able to tell if a symbol has been hooked by malware or not.
  • detect_preload.c uses dlsym to resolve symbol addresses, and then compares the current symbol address to the address of the same symbol in libc.
  • If the addresses do not match, then something is causing another new(er) symbol to be called.
  • vlany hides from this kind of detection however by hooking the libdl symbols responsible for detecting LD_PRELOAD malware.

Tools

To hide from any possible detection, vlany temporarily uninstalls itself from the system until said process is finished. Since this won't work for normal users, as they can't remove any root-owned files, sensitive applications are broken for non-root users - as you'll see below.

By checking for execution of specific binaries, we can hide from just about any application that we deem necessary.
This also applies to any rootkit detection tools - rkhunter, chkrootkit, etc.

ldd

ldd outputs any shared libraries being loaded for a specific binary in userland. This is usually a quick way to catch any LD_PRELOAD malware on a box, but vlany makes it less easy.

Expected (regular) output of libraries being loaded for /bin/echo

root@debian:~# ldd /bin/echo
        linux-vdso.so.1 (0x00007ffe66ed8000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3705998000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3705d48000)
root@debian:~#

This is the libraries that are expected to be loaded. /bin/echo is a very small binary, so only the minimal, default libraries are required.

Result when running ldd from a normal (non-root) user after vlany installation

tmp@debian:~$ ldd /bin/echo
-bash: /usr/bin/ldd: /bin/bash: bad interpreter: Input/output error
tmp@debian:~$

Since normal users cannot remove any root-owned files, we need to conditionally and carefully prevent execution of some commands - until of course they're run by root. If any user could run these tools, the current process wouldn't have the correct permissions on the system to remove the preload file and rewrite it when done.

Result when running ldd from root user after vlany installation

root@debian:~# ldd /bin/echo
        linux-vdso.so.1 (0x00007ffcf2f80000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd4a2658000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fd4a2a08000)
root@debian:~#

As you can see, the output that ldd provides is the exact same to the expected output. That's because execve was being called as root, and we can open, write, read and remove any files we need to. Once the process is finished, the preload file is rewritten and it's like nothing even happened. vlany just isn't installed for this very short period of time.

It's not all positive though. A background process could exploit this feature of vlany, so that it's never really installed. Something as simple as while true; do ldd /bin/echo; done in bash will temporarily break vlany until all the ldd processes are killed.

Dynamic linker modification

  • By modifying the dynamic linker libraries, we can make it more of a challenge for whoever's looking for us.
  • Usually, LD_PRELOAD malware relies on /etc/ld.so.preload to globally load their library into userland.
  • vlany's patch_ld.py patches any "/etc/ld.so.preload" strings in the libraries and changes them to a new, random file location string.
  • Essentially, we change the location of the global library preload file.
root@debian:~# cat /etc/ld.so.preload
cat: /etc/ld.so.preload: No such file or directory
root@debian:~# echo "/some/lib/path.so" > /etc/ld.so.preload
root@debian:~# cat /etc/ld.so.preload
/some/lib/path.so
root@debian:~# rm /etc/ld.so.preload
root@debian:~#
  • As you can see, we can open, read, write, and remove the regular /etc/ld.so.preload file, and it has zero functionality after installing vlany.
  • In the case of this installation, the 'actual' preload file is now pointing to '/sbin/.Zappyn7R', and the contents read "/lib/libc.so.mempodippy.85/KsPBjB6zibXU.so.$PLATFORM" - as that is indeed the location of the rootkit libraries.
  • Of course, I only know this because I searched for it from the PAM backdoor owner shell.
root@debian:~# cat /sbin/.
./  ../
root@debian:~# cat /sbin/.Zappyn7R
cat: /sbin/.Zappyn7R: No such file or directory
root@debian:~# rm /sbin/.Zappyn7R
rm: cannot remove ‘/sbin/.Zappyn7R’: No such file or directory
root@debian:~#
  • Back on a regular root account, we can see that the new preload file is also hidden from userland. Only those with access to an owner shell can access this file.
  • However, reading the strings of the dynamic linker libraries can reveal the location of the new file.
tmp@debian:~$ strings /lib/ld-linux.so.2
uTi7J
|F:m
_rtld_global
_dl_find_dso_for_object
_dl_make_stack_executable
__libc_stack_end
__libc_memalign
malloc
_dl_deallocate_tls
__libc_enable_secure
_dl_get_tls_static_info
calloc
_dl_debug_state
_dl_argv
_dl_allocate_tls_init
_rtld_global_ro
realloc
_dl_tls_setup
_dl_rtld_di_serinfo
_dl_mcount
_dl_allocate_tls
___tls_get_addr
_r_debug
free
ld-linux.so.2
...
/sbin/.Zappyn7R 
dl_main
elf_machine_rel_relative
elf_dynamic_do_Rel
cannot allocate name record
dl-load.c
lastp != ((void *)0)
cannot read file data
ELF file ABI version invalid
invalid ELF header
internal error
nonzero padding in e_ident
...
tmp@debian:~$
  • Just as a normal user, we can see the location of the new preload file, "/sbin/.Zappyn7R", in place of where "/etc/ld.so.preload" would be.