10
\$\begingroup\$

Let's write the shortest code to perform a simplified variant of the DoD 5220.22-M Wipe Method with only two writing passes.

Any programming language accepted, but the use of disk-wiping-oriented libraries is prohibited.

Here's how we are to implement it in pseudocode:

Set x to 0

[Start]
'Write Pass
For each sector in disk write the content of x
'Verification Pass
For each sector in disk {
    If sector does not contain the content of x then goto [Start]
}
'Check whether we already did the pass with 1
If x is not 1 then {
    Set x to 1
    GoTo [Start]
}
Else end

In other words, this code will run twice, with a write pass and verification pass for 0, and a write pass and verification pass for 1.

Anyone ballsy enough to implement it code-golf style? ;)

\$\endgroup\$
12
  • 6
    \$\begingroup\$ I doubt this will get any answers because of how hard it will be to test. \$\endgroup\$
    – DJMcMayhem
    Apr 3 '16 at 15:16
  • 13
    \$\begingroup\$ Seriously, what did your SSD do to you to deserve this kind of treatment? Did it kill your entire teddy bear collection or something? \$\endgroup\$
    – R. Kap
    Apr 4 '16 at 0:41
  • 2
    \$\begingroup\$ Really want to try and tackle this...also really don't want to sacrifice my HDD to test it. \$\endgroup\$ Apr 15 '16 at 12:16
  • 6
    \$\begingroup\$ I'm voting to close this question as off-topic because this challenge asks for malicious code. \$\endgroup\$ Aug 4 '16 at 13:45
  • 3
    \$\begingroup\$ I would argue otherwise. This challenge asks for code that promotes privacy and information security. \$\endgroup\$ Aug 4 '16 at 13:48
3
\$\begingroup\$

On a linux system there's no need for special handling of devices. Just use the device file interface.

Python 3 (byte strings) - 141 bytes

d=input()
f=open(d,'r+b')
z=f.seek
z(0,2)
s=f.tell()
i=0
while i<2:
 z(0);f.write([b'\0',b'\xff'][i]*s);f.flush();z(0)
 if f.read()==x:i+=1

It's fairly straightforward, and not really optimised heavily, but it works. Here's a basic rundown.

  • Get input (device file path)
  • Open device file
  • Seek to the end, get filesize (block devices are always their real size)
  • enter write-and-check loop
  • construct 0-bit and 1-bit strings (x)
  • write bitstring
  • flush output (I could have set buffering=0 but this is shorter)
  • test file against x, and increment step of loop if it passes

exit loop when the increment is high enough

As a bonus, you could modify this for any set and number of byte-modification patterns, like 0x55/0xaa for stronger overwriting effects.

I did actually test this on a device file, using loopback. However, I'm not 100% sure the checking actually works. It might be necessary to close and reopen the file each pass, due to buffering behaviors. I would hope flush prevents this.

*edited to incorporate some suggestions in the comments

\$\endgroup\$
6
  • 1
    \$\begingroup\$ Welcome to the site. You certainly don't need whitespace around an = in python. You can also reduce your byte count by using ; to reduce indentation. \$\endgroup\$
    – Grain Ghost
    Oct 28 '18 at 17:26
  • \$\begingroup\$ Normally, we count submissions in bytes, not characters. You can also alias some of your functions, e.g. f.seek(0);f.seek(0) (19 bytes) can be s=f.seek;s(0);s(0) (18 bytes). Furthermore, if f.read()==x:i+=1 can be i+=f.read()==x. \$\endgroup\$ Oct 28 '18 at 17:53
  • \$\begingroup\$ You also shouldn’t need the empty string as an argument to input. \$\endgroup\$
    – Quintec
    Oct 28 '18 at 18:18
  • \$\begingroup\$ I think b'\0' instead of b'\x00' should work. \$\endgroup\$
    – Jason
    Oct 29 '18 at 8:29
  • \$\begingroup\$ Just realized an important feature. This program will consume RAM equal to the size of the device wiped. \$\endgroup\$ Oct 30 '18 at 0:26
2
\$\begingroup\$

x86 machine code (Linux), 116 109 106 bytes

00000000: 89cb 6a02 5999 894c 24f4 b005 cd80 505b  ..j.Y..L$.....P[
00000010: 536a 025a 31c9 b013 cd80 89c6 5b53 9931  Sj.Z1.......[S.1
00000020: c9b0 13cd 8089 f75b 53b2 018d 4c24 f8b0  .......[S...L$..
00000030: 04cd 804e 75f1 5b53 9931 c9b0 13cd 8089  ...Nu.[S.1......
00000040: fe5b 538d 4c24 f4b2 01b0 03cd 804e 740c  .[S.L$.......Nt.
00000050: 8a44 24f8 3844 24f4 74e7 ebb3 89fe b001  .D$.8D$.t.......
00000060: 8644 24f8 3c01 75a7 58c3                 .D$.<.u.X.

Function that takes filename as argument, uses fastcall convention.

Assembly (NASM):

section .text
	global func
func:

	;open file
        mov ebx, ecx	;first argument to func (filename)
	push 0x2	;flag O_RDWR
	pop ecx		;pushing a constant is shorter than mov
	cdq	        ;edx=mode=0
	mov [esp-12], ecx ;set first byte (msg) to write to 0. msg later in esp-8, buf in esp-12
	mov al, 5
	int 0x80	;syscall open
	push eax	;save file descriptor

	write_verify:

	;get file size
	pop ebx		;get fd
	push ebx
	push 0x2	;flag SEEK_END
	pop edx
	xor ecx, ecx 	;offset 0
	mov al, 0x13
	int 0x80	;syscall lseek
	mov esi, eax	;save file byte count in esi
	

	;reset index of file to 0
	pop ebx		;get fd
	push ebx
	cdq	        ;edx=flag SEEK_SET=0
	xor ecx, ecx	;ecx=0
	mov al, 0x13
	int 0x80	;syscall lseek

	;***write pass***
	mov edi, esi
	write_loop:	;for each byte in byte count, write [msg]
		;write to file
		pop ebx		;file descriptor
		push ebx
		mov dl, 1	;bytes to write
		lea ecx, [esp-8] ;buffer to write from
		mov al, 4
		int 0x80	;syscall write
		dec esi		;decrement (byte count) to 0
		jne write_loop	;while esi!=0, loop

	;reset index of file to 0
	pop ebx		;get fd
	push ebx
	cdq 	        ;edx=SEEK_SET=0
	xor ecx, ecx	;ecx=0
	mov al, 0x13
	int 0x80	;syscall lseek

	
	;***verification pass***
	mov esi, edi
	verify_loop:	;for each byte in byte count, verify written byte
		pop ebx		;get fd
		push ebx
		lea ecx, [esp-12] ;buffer to store read byte
		mov dl, 1	;read 1 byte
		mov al, 3
		int 0x80	;syscall read
		dec esi
		je end_verify	;at final byte, end verification
		mov al, [esp-8]
		cmp byte [esp-12],al
		je verify_loop	 ;loop if expected value found
		jmp write_verify ;if byte!=expected value, restart

	end_verify:
	mov esi, edi
	mov al, 1
	xchg byte [esp-8],al	;set new byte to write to 1
	cmp al, 1
	jne write_verify	;if old byte to write!=1, goto start
	
	pop eax			;reset stack
	ret

Try it online!

-7 bytes and -3 bytes thanks to @EasyasPi

\$\endgroup\$
2
2
\$\begingroup\$

C (clang), -DZ=lseek(d,0 + 139 = 152 bytes

g,j,x,d,s,i,c;f(n){x=0;d=open(n,2);s=Z,2);for(j=2;j--;x++){Z,0);for(i=s;i--;write(d,&x,1));Z,0);for(i=s;i--;read(d,&c,1),c!=x&&x--&&j--);}}

Try it online!

Takes the filename as an argument

Ungolfed:

#include <unistd.h>
int g,j,x,d,s,i,c;
void f(char*n){
	x=0; /*Byte to write*/
	d=open(n,O_RDWR);
	s=lseek(d,0,SEEK_END); /*Get size of file*/
	j=0;
	for(j=0;j<2;j++){
		/*Write Pass*/
		lseek(d,0,SEEK_SET); /*Start writing from start of file*/
		for(i=0;i<s;i++){
			write(d,&x,1);
		}
		
		/*Verification Pass*/
		lseek(d,0,SEEK_SET);
		for(i=0;i<s;i++){
			read(d,&c,1);
			if(c!=x)x--,j--; /*If verification fails, repeat loop with the same value*/
		}
		x++;
	}
}
\$\endgroup\$
2
  • \$\begingroup\$ Hmm ... will the TiO wipe the internet? ;-D \$\endgroup\$
    – Titus
    Oct 30 '18 at 0:21
  • \$\begingroup\$ @Titus It creates a temporary file and wipes it. \$\endgroup\$
    – Logern
    Oct 30 '18 at 0:21
1
\$\begingroup\$

Tcl, 286 bytes

proc f {o i l} {seek $o 0
set s [string repeat $i $l]
puts -nonewline $o $s
flush $o
seek $o 0
return [string equal [read $o $l] $s]}
set n [open $argv r+]
fconfigure $n -translation binary
seek $n 0 end
set m [tell $n]
while {![f $n "\0" $m]} {}
while {![f $n "\xff" $m]} {}

Not really optimized that well. I tried what I could, but I don't know that much about Tcl.

Save as "f.tcl" and run on Unix with tclsh f.tcl "your filename". Make sure there's exactly one argument! I tested this on a plain file, but it should work on a device file as well.

Setting variables and indexing is more involved in Tcl, so I decided to put the common code between the passes into a function. Then I call it first with "\0", and repeat while it fails to verify. I do the same thing with "\xff".

I flushed after writes; it might not be necessary. fconfigure -translation binary -buffering none is longer.

-2 bytes by removing quotes around r+.

\$\endgroup\$

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.