Category: Security
Author/Contact Info PixelRat
Description: Wiper is a program to overwrite free space on your hdd. Updated the code on 29 Oct 2002, so the comments might refer to the previous version(s).
#!/usr/bin/perl -w

# 
# Wiper 0.3 by Thomas Sjogren (thomas@northernsecurity.net).
# Utility to overwrite the free space on a hdd.
# Released under GPL version 2 (http://www.gnu.org/licenses/gpl.txt).
# 
# October 2002
#
# Additional information:
# Peter Gutmann, Secure Deletion of Data from Magnetic and Solid-State
# Memory, http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html
#
# DoD 5220.22-M (NISPOM), chapter 8, "Clearing and Sanitization 
# Matrix", http://www.dss.mil/isec/nispom.htm
#

use Getopt::Std;

 srand (time ^ $$ ^ unpack "%32L*", `ps wwaxl | gzip`);

 @letters = ('A' .. 'Z', 'a' .. 'z', '0' .. '9', '.');
 $file = "." . $letters[rand@letters] . $letters[rand@letters] .  
            $letters[rand@letters] . $letters[rand@letters];

my $version=0.3;
my %opts;
getopts("vhm:rsdg", \%opts);

    if ($opts{v}){
        version();
        }

    if ($opts{h} || !$opts{m}){
        help();
        }

    if ($opts{m}){
        $bits=($opts{m} * 1048576) || die "No size specified $!";
        }

    if ($opts{r}){
        random();
        }

    if ($opts{s}){
        six();
        }

    if ($opts{d}){
        dod();
        }

    if ($opts{g}){
        gutmann();
        }

sub version {
    print "Wiper version $version\n";
    exit(1);
    }

sub help {
    print "\nWiper $version\n";
    print "Usage: wiper.pl [type] -m [megabytes]\n";
    print "Types:\n";
    print "\t-r One random layer overwrite\n";
    print "\t One random character\n";
    print "\t-s Six layers\n";
    print "\t 0x92,0x49,0x24,0x6D,0xB6,0xDB\n";
    print "\t-d Seven layers\n";
    print "\t 0x00,0xFF,three random,0xFF,0x00\n";
    print "\t-g 35 layers\n";
    print "\t Gutmann method\n\n";
    print "Misc:\n";
    print "\t-v Version\n";
    print "\t-h This help message\n\n";
    print "Example:\n";
    print "\t./wiper.pl -g -m 300\n\n";
    exit(1);
    }

sub random {
    print STDOUT "One random layer overwrite : $opts{m}M\n";

    open TMP, "> $file" || die "Error: $!";

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    close TMP;
    unlink("$file");

    print STDOUT "Done.\n";
    }

sub six {
    print STDOUT "Six layer overwrite : $opts{m}M\n"; 

    open TMP, "> $file" || die "Error: $!";

    print TMP (chr(0x92),chr(0x49),chr(0x24)) x ($bits / 3); 
    seek(TMP,0,0);

    print TMP (chr(0x49),chr(0x24),chr(0x92)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0x24),chr(0x92),chr(0x49)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0x6D),chr(0xB6),chr(0xDB)) x ($bits / 3); 
    seek(TMP,0,0);

    print TMP (chr(0xB6),chr(0xDB),chr(0x6D)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0xDB),chr(0x6D),chr(0xB6)) x ($bits / 3);
    seek(TMP,0,0);

    close TMP;
    unlink("$file");

    print STDOUT "Done.\n";
    }

sub dod {
    print STDOUT "Seven layer overwrite: $opts{m}M\n";
    
    open TMP, "> $file" || die "Error: $!";

    print TMP chr(0x00) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xFF) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xFF) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x00) x $bits;
    seek(TMP,0,0);

    close TMP;
    unlink("$file");

    print STDOUT "Done.\n";
    }

sub gutmann {
    print STDOUT "35 layer overwrite: $opts{m}M\n";

    open TMP, "> $file" || die "Error: $!";
    
    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x55) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xAA) x $bits;
    seek(TMP,0,0);

    print TMP (chr(0x92),chr(0x49),chr(0x24)) x ($bits / 3); 
    seek(TMP,0,0);

    print TMP (chr(0x49),chr(0x24),chr(0x92)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0x24),chr(0x92),chr(0x49)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP chr(0x00) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x11) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x22) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x33) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x44) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x55) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x66) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x77) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x88) x $bits;
    seek(TMP,0,0);

    print TMP chr(0x99) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xAA) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xBB) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xCC) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xDD) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xEE) x $bits;
    seek(TMP,0,0);

    print TMP chr(0xFF) x $bits;
    seek(TMP,0,0);

    print TMP (chr(0x92),chr(0x49),chr(0x24)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0x49),chr(0x24),chr(0x92)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0x24),chr(0x92),chr(0x49)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0x6D),chr(0xB6),chr(0xDB)) x ($bits / 3); 
    seek(TMP,0,0);

    print TMP (chr(0xB6),chr(0xDB),chr(0x6D)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP (chr(0xDB),chr(0x6D),chr(0xB6)) x ($bits / 3);
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0);

    print TMP chr(rand(0xFF)) x $bits;
    seek(TMP,0,0); 

    close TMP;
    unlink("$file");

    print STDOUT "Done.\n";
    }
Replies are listed 'Best First'.
Re: Wiper
by grinder (Bishop) on Sep 30, 2002 at 08:28 UTC

    That's some serious wiping you're doing. I suspect that it must take a fierce amount of time to complete. An alternative approach would be to securely wipe the contents of sensitive files before deleting them. This will be much, much faster. Also, from the way I read it, you might scribble garbage on a large section of the free space of the disk and still manage to avoid overwriting an area where sensitive information lies waiting to be recovered.

    The US Department of Defense lays down guidelines for deleting files in what's known as the Orange Book. descartes wrote Shred to do just that.


    print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
      "That's some serious wiping you're doing. I suspect that it must take a fierce amount of time to complete."
      Yes, it might be a bit overkill for the average user to overwrite the free space 35 times (and it takes a lot of time do it's work). I based the code on the paper Secure Deletion of Data from Magnetic and Solid-State Memory by Peter Gutmann.

      "An alternative approach would be to securely wipe the contents of sensitive files before deleting them. This will be much, much faster."
      srm and wipe does just that, but that's the problem: they only wipe files, leaving your "deleted" temporary files etc in the open.

      "I read it, you might scribble garbage on a large section of the free space of the disk and still manage to avoid overwriting an area where sensitive information lies waiting to be recovered."
      Yes, i haven't added the code to overwrite the slack space for example, but i will (someday:).

      "The US Department of Defense ..."
      The whole Rainbow-series (including the Orange Book) is really good which I would recommend to anybody. However I don't really trust a 7 layer overwrite.

      Changes to be made:
      * Add 6 layer overwrite (0x49,0x24,0x92,0x6D,0xB6,0xDB)
      * Add DoD standard (7 layer overwrite)
      * Add 8 layer random owerwrite
      * Better "interface"

        Might also want to work with your `df -h` call to skip NFS and other network share types.