最短的代码以确保擦除磁盘


9

让我们编写最短的代码来执行DoD 5220.22-M擦除方法的简化变体,而只需两次写入。

接受任何编程语言,但禁止使用面向磁盘擦除的库。

这是我们如何用伪代码实现它:

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

换句话说,此代码将运行两次,其中对进行一次写入和验证,对进行0一次写入和验证1

有人足够实现代码高尔夫风格吗?;)


6
我怀疑这将无法得到任何答案,因为要进行测试非常困难。
詹姆斯(James)

12
认真地说,您的SSD对您做了什么以应得这种待遇?它杀死了您的整个玩具熊收藏吗?
R. Kap

2
真的想尝试解决这个问题...也真的不想牺牲我的硬盘来测试它。
Michelfrancis Bustillos

6
我投票结束这个问题是不合时宜的,因为此挑战要求提供恶意代码。
AdmBorkBork

2
我会反驳。这项挑战要求提供促进隐私和信息安全的代码。
MathuSum Mut

Answers:


1

x86机器代码(Linux),116字节

00000000: 89cb 6a02 5931 d289 4c24 f4b0 05cd 8050  ..j.Y1..L$.....P
00000010: 5b53 6a02 5a31 c9b0 13cd 8089 c65b 5331  [Sj.Z1.......[S1
00000020: d231 c9b0 13cd 8089 f75b 53b2 018d 4c24  .1.......[S...L$
00000030: f8b0 04cd 804e 09f6 75ef 5b53 31d2 31c9  .....N..u.[S1.1.
00000040: b013 cd80 89fe 5b53 8d4c 24f4 b201 b003  ......[S.L$.....
00000050: cd80 4e09 f674 0c8a 4424 f838 4424 f474  ..N..t..D$.8D$.t
00000060: e5eb ad89 fe8a 4424 f8c6 4424 f801 3c01  ......D$..D$..<.
00000070: 759e 58c3                                u.X.

以文件名作为参数

组装(NASM):

section .text
	global func
func:			;this function uses fastcall conventions
	;seems like no enter instr needed

	;open file
	mov ebx, ecx	;first argument to func (filename)
	push 0x2	;flag O_RDWR
	pop ecx		;pushing a constant is shorter than mov
	xor edx, 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	;using 8 bit regs is smaller
	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
	xor edx, 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 esi (byte count) to 0
		or esi, esi	;cmp esi to 0
		jne write_loop	;while esi!=0, keep looping

	;reset index of file to 0
	pop ebx		;get fd
	push ebx
	xor edx, edx	;flag 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
		or esi, esi	;cmp esi to 0 
		je end_verify	;at final byte, end verification
		mov al, [esp-8]
		cmp byte [esp-12],al
		je verify_loop	 ;keep looping if expected value found
		jmp write_verify ;if byte!=expected value, restart

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

在线尝试!(使用临时文件)

通过优化移动寄存器并将堆栈用作缓冲区而不是内存中的恒定位置,可以得到-11个字节。


3

在linux系统上,不需要对设备进行特殊处理。只需使用设备文件界面。

Python 3(字节字符串)-141个字节

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

这是相当简单的,并没有真正进行重大优化,但是可以工作。这是一个基本清单。

  • 获取输入(设备文件路径)
  • 打开设备文件
  • 寻找到最后,获取文件大小(块设备始终是其实际大小)
  • 进入写检查循环
  • 构造0位和1位字符串(x)
  • 写位串
  • 刷新输出(我可以将buffering设置为0,但这要短一些)
  • 针对x测试文件,如果通过则增加循环步骤

当增量足够高时退出循环

另外,您可以针对任意数量和数量的字节修改模式进行修改,例如0x55 / 0xaa,以获得更强的覆盖效果。

我确实使用环回在设备文件上对此进行了测试。但是,我不是100%确信检查是否有效。由于存在缓冲行为,可能有必要在每次通过时关闭并重新打开文件。我希望冲洗能防止这种情况。

*编辑以在评论中纳入一些建议


1
欢迎来到该网站。您当然不需要=在python中使用空格。您还可以通过;减少缩进来减少字节数。
Ad Hoc Garf Hunter '18 -10-28

通常,我们以字节(而非字符)为单位对提交进行计数。您还可以为某些功能添加别名,例如f.seek(0);f.seek(0)(19个字节)可以是s=f.seek;s(0);s(0)(18个字节)。此外,if f.read()==x:i+=1可以是i+=f.read()==x
乔纳森·弗雷希

您也不需要将空字符串作为输入参数。
Quintec

我认为b'\0'而不是b'\x00'应该工作。
杰森

刚意识到一个重要的功能。该程序将消耗与擦除设备大小相等的RAM。
威廉希普利

2

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

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--);}}

在线尝试!

将文件名作为参数

取消高尔夫:

#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++;
	}
}

嗯...二氧化钛会擦拭互联网吗?;-D
泰特斯(Titus),

@Titus它创建一个临时文件并擦除它。
Logern

1

Tcl,286个字节

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]} {}

并没有真正优化得那么好。我尽力了,但是我对Tcl并不了解。

另存为“ f.tcl”并在Unix上使用 tclsh f.tcl "your filename"。确保只有一个参数!我在一个普通文件上对此进行了测试,但是它也应该在设备文件上也可以工作。

设置变量和索引在Tcl中更重要,因此我决定将遍历之间的通用代码放入函数中。然后我先用“ \ 0”来称呼它,然后在无法验证的情况下重复一次。我用“ \ xff”做同样的事情。

写完之后我脸红了。可能没有必要。fconfigure -translation binary -buffering none更长。

-2个字节,可删除周围的引号r+

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.