2

Context

I'm investigating a compromised Linux box where I found files with malicious code. The file system is too big to just make a copy of the whole block device and so far I'm only interested in the files of a not so big sub-directory.

While the last-modified timestamp (also called "mtime") of one example file is older, the so called ctime (inode change time) is rather new. So I want to also capture the ctime as it might be relevant.

JFTR: I know that neither timestamp needs to show time the file was created because a chmod or chown command will also change the ctime and the last-modified date might be set by the downloading tool used to download the file, e.g. wget, because—in contrary to the ctime—Linux allows the mtime of a file to be set to arbitrary times.

Question

How do I capture the ctime properly when making forensic copies of such files?

I'm not aware of any archive format (e.g. tar, zip, rar) which captures the (potentially file-system-specific) ctime in addition to the mtime.

So far I came up with these of workarounds:

  • Do ls -l --time=ctime $file for each captured file and save the out in a text file together with the files. (Did that for now.)
  • Save the files onto a medium which also contains a file system which stores ctimes, e.g. an ext4 formatted USB stick, and set the system time to the ctime of the to be copied file immediately before copying so that the ctime of the copy is within seconds of the original ctime. (Should theoretically work, but likely has other side-effects on the OS; never actually tried it.)

Both workarounds are highly unsatisfying and I wonder if there are better methods to capture the ctime when making forensic copies of files (with Linux and preferably with open source software), e.g. a tool which can modify the ctime of a file or an archive format which can store more than one timestamp per file, etc.

9
  • I suggest asking this on U&L, because it's specific to just one OS, but useful for many purposes besides forensics,
    – Ben Voigt
    Sep 14 '18 at 21:41
  • 2
    You're going to need a lot more than just mtime and ctime if you want to do a proper forensic analysis. The inode numbers are highly valuable when looking for replaced executables, for example. The same applies to "hidden" timestamps such as crtime on ext4 and dtime on deleted inodes. Anyway, there are a few forensic tools (whose names escape me) which take extremely detailed information about files' metadata.
    – forest
    Sep 15 '18 at 1:36
  • 2
    @BenVoigt Forensics is unique to information security. Other sites may not give answers that are forensically viable.
    – forest
    Sep 15 '18 at 1:37
  • 1
    @AxelBeckert For ext4 at least, crtime is the creation time (also called btime on some filesystems). It is hidden though, and stat() is not able to query the crtime for a given file. Only low-level utilities like debugfs (the program, not the virtual filesystem) are capable of accessing it.
    – forest
    Sep 26 '18 at 13:55
  • 1
    Update for future readers: GNU/Linux coreutils stat(1) now uses the Linux statx(2) syscall which does include birth time. Birth is empty on ext4 Dec 9 '20 at 16:01
2

File archive formats don't capture the ctime because it would be pointless since it's impossible to restore it¹.

For forensics purposes, you need to keep things simple, because you need to be able to prove that the data you captured is genuine. There's no escaping doing a low-level copy of the block device that contains the filesystem. For analysis purposes, where you sift through the data to figure out what is interesting, you can use complex data extraction methods, and verify your findings against the real data afterwards.

Using ls may be tricky if the files have names containing special characters such as spaces, newlines or unprintable characters. Also ls prints an approximation of the time which is timezone-dependent and annoying to parse. If you must use ls, use the --full-time option of GNU ls to get an unambiguous time display, and make sure that you're using a set of options that print the file name unambiguously and that you later parse the name correctly. Recent versions of GNU ls print the file name unambiguously by default, but the format is relatively complex.

Linux provides a stat command which prints more metadata including all the timestamps and the inode number. *BSD systems including macOS have a stat command with a similar purpose but completely syntax. Beware that they print the file name literally, which can make the output ambiguous if some file names contain newlines.

Of course, do all of this from a view of the filesystem that's as read-only as you can get. For forensic purposes, it's best if the first thing you do is to make a copy of the disk through a hardware dongle that ensures that it doesn't modify the source, that way there won't be any doubt that you corrupted the evidence. If the legal risk is low, you may dispense with the special-purpose hardware, but at least make sure that you've made the block device read-only. Doing a read-only mount of the filesystem (mount -r) is not enough: it guarantees that you won't update timestamps, but it will replay the journal, so you can't claim that your capture didn't modify the evidence.

¹ If you're root, you can change the system time, but that impacts the whole system so it would be extremely disruptive.

1
  • Thanks. Yes, this is meant for analysis, not for forensic evidence. And yes, I use a live CD which makes all block devices read-only by default. So changing the system time of a running live CD seems my best bet. I don't care about its implications on the running OS if it's coming from a live CD and a throw away instance anyways. And yes, ISO time format is the only sane one. Oh, and thanks for the reminder on the stat command. That's indeed potentially more useful than ls. Sep 26 '18 at 13:52
1

star with exustar format (tar with POSIX.1-2001 extended headers) stores all 3 timestamps:

$ stat 3times
  File: '3times'
  Size: 7               Blocks: 8          IO Block: 4096   regular file
Device: 13h/19d Inode: 20209028    Links: 1
Access: (0400/-r--------)  Uid: ( 1000/   gotar)   Gid: ( 1000/   users)
Access: 2021-07-15 12:31:53.085946972 +0200
Modify: 2021-07-15 12:32:10.049040551 +0200
Change: 2021-07-15 12:32:16.435616907 +0200
 Birth: -

$ star artype=exustar 3times -c > 3times.star
star: 1 blocks + 0 bytes (total of 10240 bytes = 10.00k).

$ grep -a time= 3times.star | strings
[...]
30 atime=1626345113.085946972
30 ctime=1626345136.435616907
30 mtime=1626345130.049040551
[...]

$ perl -E 'say scalar localtime 1626345113; say scalar localtime 1626345136; say scalar localtime 1626345130'
Thu Jul 15 12:31:53 2021
Thu Jul 15 12:32:16 2021
Thu Jul 15 12:32:10 2021

and under certain conditions they can be restored. Or more or less roughly extracted (like above).

-3

I think the command cp have an option for preserve some information of the original file

--preserve=mode,ownership,timestamps

Not sure if this will fix your problem.

2
  • 1
    Doesn't -a do all this, and more?
    – forest
    Sep 15 '18 at 1:37
  • 3
    cp cannot preserve the ctime. That's not a defect of cp: no file copying tool can preserve the ctime. The ctime of the target is always the time at which the target's inode was last changed. Sep 15 '18 at 6:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.