Skip to content

Latest commit

 

History

History
executable file
·
109 lines (78 loc) · 3.36 KB

trickbot-persistence.org

File metadata and controls

executable file
·
109 lines (78 loc) · 3.36 KB

Trickbot persistence.

What is persistence ?

A system may be rebooted during regular intervals as part of its lifecycle when a new kernel is updated or if it enters an unknown state.

The author of the trickbot malware code has elected to use the cron task scheduling service to ensure it will continue to execute

Recovering an executable file.

The /proc filesystem will maintain a link to all files opened by an executing process even if the file has been removed from disk.

Each processes open files can be read from /proc/<numeric-pid>/exe

$ sudo ls -l /proc/975301/exe
lrwxrwxrwx. 1 root root 0 Nov  8 22:50 /proc/975301/exe -> /tmp/.malware/init

This is a regular file, and with root user permissions, the file can be copied for later inspection.

$ cat /proc/975301/exec >> ~/captured-executable

If the malware is a scripting language (Mirai is not), the actual executable script will be available in another location in the `/proc/<some-pid>/fd/

$ sudo ls -l /proc/975301/fd/
 total 0
 lr-x------. 1 root root 64 Nov 10 01:08 0 -> /dev/null
 lrwx------. 1 root root 64 Nov 10 01:08 1 -> 'socket:[38592]'
 l-wx------. 1 root root 64 Nov 10 01:08 10 -> /tmp/.malware/script.py

The sample code.

Mirai’s self deletion code is simple and unerror checked.

// Delete self
unlink(args[0]);

See it in action here.

The unlink function deletes a file by name from the file system. It has a number of possible error conditions, but it appears that the author did not care about any of them.

Porting to rust.

To implement the same functionality in rust we first need to get the current processes executable file path.

Much like all languages, it is the first arguement in the processes args array.

Once we have the program path, it ss a simple matter of using rusts std::fs remove_file function to delete the file.

The process will continue to run normally and the file will be removed from disk during execution, and the process will continue to run.

use std::fs;

 fn main() {
   //// Delete the executing file to remove incriminating evidence
   let argv0 = std::env::args().next().unwrap(); // this will always exist.
   let _result = delete_file(&argv0);
 }

 fn delete_file(filename: &str) -> std::result::Result<(), std::io::Error> {
  info!("Deleting binary!");
  fs::remove_file(filename)?;
  Ok(())
 }

Having the executable ‘missing’ would be one of the big alarm bells for an intrustion detection system.

Perhaps a better option to make this harder to detect would be to move a legit binary, rename the malware to the exeutable in place delete the malware then put the original executable back.

This would be much harder to detect, especially if it communicated using the same ports and had the same process name.

Resources: