How Hackers Delete Files and How to Recover Them Using Modified debugfs

During emergency response, it is common to encounter situations where hackers delete files. For example, a hacker might execute echo > /root/.bash_history to delete a file. If a host security agent for command auditing was not deployed in advance, this situation is generally unsolvable.

However, by modifying the source code of debugfs, this issue can be addressed.

Misconception: Does echo > $file really overwrite the file?

According to conventional understanding,

rm -f $file

Files deleted using the rm command can be recovered.

echo > $file

Using echo to append to a file “overwrites” the file’s content. This is why most hackers prefer using echo to “overwrite” files after an intrusion to prevent tracing.

Test Conclusion

 hackers delete files

But actual test results show that echo does not truly overwrite the file; it merely changes the file’s block pointer.

Simulating a Hacker’s File Deletion Scenario

Suppose a hacker deletes the ~/.bash_history file, but emergency response requires extracting the hacker’s command history.

 hackers delete files

At this point, the ~/.bash_history file is empty, and emergency personnel can only see the record of the last command executed.

Using Modified debugfs to Extract Disk Content

As analyzed earlier, echo overwriting a file only changes the file pointer, so the file content is still on the disk. Therefore, debugfs can be used to recover it. debugfs provides a command to find unused blocks called dump_unused.

I made extensive modifications to the debugfs source code to allow dump_unused to search for keywords within unused blocks while finding them.

For example, if I know I executed the command curl ip.sb in the history, the original .bash_history file would contain this command. Therefore, I can use it as a keyword to search within debugfs.

Principle Analysis

In the ext3/4 file system, when a file is deleted, the system overwrites the block pointer in the inode with 0 and marks the corresponding block as unused, but it does not overwrite the content within the block.

Unused blocks in the system are filled with zeros, but if a block is marked as unused yet contains data, it indicates that the block has been deleted.

Therefore, by using debugfs to search all blocks marked as unused but containing data and extracting blocks with the keyword, the content of files deleted by hackers can be quickly found.

The modified debugfs is very effective for tracing back deleted history, SSH logs, and other files with strong characteristics.

Divergent Thinking

This is unrelated to the main topic but worth noting. The previous file mentioned echo > $file to overwrite a file.

What is the difference between echo 0 > file.txt and echo 0> file.txt?

When you add a number before the redirection operator >, it changes the file descriptor being redirected. By default (without a number), the > operator redirects the standard output (file descriptor 1). echo > $file is equivalent to echo 1> $file. When you write 0>, you are actually redirecting the standard input (file descriptor 0) instead of the standard output.

echo 0 > file.txt and echo 0> file.txt functionally differ. The former writes “0” into file.txt, while the latter attempts to redirect the standard input of the echo command, which does not read from standard input, resulting in an empty file.txt.

What do 0, 1, 2, and 3 mean in Linux?

In Linux, each process has some predefined file descriptors. Here are the meanings of these predefined file descriptors:

  • 0: This file descriptor represents standard input (stdin). It is used when a program needs to get data from user input or file input.
  • 1: This file descriptor represents standard output (stdout). It is used when a program needs to print or output data.
  • 2: This file descriptor represents standard error output (stderr). It is used when a program needs to print error messages.
  • 3: File descriptor 3 and subsequent numbers are not predefined and can be used by processes to open and operate on any other necessary files. When a process opens a new file, the system provides the smallest unused file descriptor.

For example, to redirect both standard output and error output to the same file, use the following command:

command > file.txt 2>&1