You can change the date on a file to whatever you want. And not only the access time, but also the last modified and creation time. For example, we could change a file to be 3000 years old, which may seem impossible, but it will say that.

I wrote this because lots of customers at work kept saying, “This file says it’s really old. It was on there before my account was ever made! Were your systems hacked?!”

Me: “Nope, that’s called malware that either was in a zip/tar file and extracted it’s timestamp with itself, or changed it’s timestamp to try to hide.”

After I showed them how to make a really old file, they said “Dude! This is crazy!” I simply laughed.

Make the file

First, let’s create our file that says it’s 3000 years old.

[root]# touch -d "today - 3000 years" file.txt
[root]# ls -lh file.txt 
-rw-r--r-- 1 root root 0 Nov 17  -984 file.txt

There you have it. A file that’s 3000 years old from 984 BC. No joke.

Breakdown

The command uses the touch command to make the file, which can specify the date using the -d argument. This can also be done with just about any programming language.

By default, the touch command will update the access and modified times. Using -a or -m we can update only one or the other.

Get the real date

You can still find the real date of the file creation. This will require root/admin access, and assume that no file system level changes have been done. (Those can still be detected using special means and methods, but are beyond the scope of this article.)

The date is the evening of Nov 17, 2016.

We need to get the inode of the file:

[root]# ls -i file.txt
393454 file.txt

So the inode for the file is 393454. Let’s make sure we know which partition we are on:

[root]# df -h file.txt
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        20G  8.0G   11G  44% /

Ok, so drive /dev/vda1.

Now all we need to do is use debugfs to, using the inode and the drive, to get the creation, last access, and modification times:

[root]# debugfs -R 'stat <393454>' /dev/vda1
debugfs 1.42.9 (28-Dec-2013)
Inode: 393454   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 3258162841    Version: 0x00000000:00000001
User:     0   Group:     0   Size: 0
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 0
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x582e02bb:1c549188 -- Thu Nov 17 20:19:23 2016
 atime: 0x4d5abab7:1c86b6e2 -- Tue Feb 15 18:41:11 2011
 mtime: 0x4d5abab7:1c86b6e2 -- Tue Feb 15 18:41:11 2011
crtime: 0x582e02bb:1c549188 -- Thu Nov 17 20:19:23 2016
Size of extra inode fields: 28
EXTENTS:

As you can see, the crtime is the actual one, not the fake 3000 years old. Using stat we get even odder values:

[root]# stat file.txt 
  File: ‘file.txt’
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: fd01h/64769d    Inode: 393454      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-11-17 21:15:03.775938026 -0700
Modify: 2283-05-01 08:37:43.119647672 -0600
Change: 2016-11-17 20:19:23.118826082 -0700
 Birth: -

But you can see that the Change time says the actual time it was created.

Of course, there are ways the change even those… but that’s for another day.

The idea of using debugfs to read get the real date originally came from this Stackoverflow post.