Entwickler-Ecke
Dateizugriff - unwiderrufbares Löschen von Dateien
derDoc - Mo 20.01.03 16:59
Titel: unwiderrufbares Löschen von Dateien
Hallo Leute
Ich will ein Programm schreiben, dass eine Liste von Dateien löscht. Da das Programm aber für sensible Daten gedacht ist, würde ich gern wissen, wie ich eine Datei dauerhaft löschen kann.
Ich habe mal was gelesen, man müsse den Bereich auf der Festplatte, auf dem die Datei lag mindestens 30 mal neu überschreiben, um sicher zu sein, dass man sie nicht mehr widerherstellen kann.
Woher weiß ich welche Bereiche meiner Festplatte belegt waren und wie kann ich genau diese neu beschreiben?
Delete - Mo 20.01.03 17:47
Das musst du nicht wissen. Du machst es nämlich wie folgt:
- Datei zuweisen und öffnen
Quelltext
1: 2:
| AssignFile(f,'Dateiname'); ReSet(f,1); |
- aktuelle Position merken!
- Einen Puffer, z.B.
Quelltext
1: 2:
| var buf : array[0..65535]of byte; |
solange mit "BlockRead" einlesen, bis ein Fehler auftaucht (dann hast du das Ende erreicht)
- den Puffer nun z.B. mit "fillchar" auf Null setzen
- an die gemerkte Position zurückspringen und den Puffer mit "BlockWrite" schreiben! Damit hast du die ursprünglichen Bytes schon das erste Mal überschrieben.
- jetzt füllst den Puffer z.B. wieder mit "fillchar" mit Einsen und wiederholst den letzten Schritt; das kannst du so oft machen, wie du möchtest. Im Prinzip überschreibst du damit immer den Speicherbereich deiner Datei auf der Platte
- durch die Endlosschleife (s. Punkt #3) wiederholt sich das Spiel, bis du endgültig das Ende der Datei erreicht hast; dann solltest du aufhören! :wink:
- du schließt die Datei
- du öffnest sie erneut, diesmal aber mit
weil du dadurch den Beginn der ursprünglichen Datei auf der Platte überschreibst
- du könntest der Datei mit "Rename" jetzt einen neuen Namen geben, der nur aus einem Zeichen besteht. (So machen das die professionellen Tools!)
- Und zu guter Letzt, löscht du die Datei mit "Erase".
Fazit: zum einen sind alle Bytes überschrieben, u.U. mehrfach; durch das schon erwähnte "ReWrite" wird der scheinbar neuen Datei ein neuer Beginn auf der Platte zugeordnet; damit ist der alte Startpunkt verloren; und durch das Umbenennen in einen 1-Zeichen-Namen mit anschließendem Löschen zeigen Hex- und Disk-Editoren auch keine Reste des Namens mehr an, von denen man auf den ursprünglichen Inhalt schließen könnte. (Will sagen: Dateien werden in der FAT ja nur als gelöscht markiert, und wenn man im Disk-Editor einen Namen wie
sieht, dann wird man neugierig.)
Ich bin nicht sicher, ob wir das Thema hier schon hatten, oder ob das noch im alten DF war. Jedenfalls sollte sich über die Suche eine funktionsfähige Routine finden lassen.
Notfalls kann ich auch mal gucken, wo ich meine Funktion habe. Aber mach dir bitte erst mal selbst einen Kopf :), das Prinzip habe ich ja beschrieben, und die Erklärungen zu den Befehlen findest du in der Hilfe.
matze - Mo 20.01.03 18:51
Folgenden Code hab ich beim EDH gefunden:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure Killdatei(Filename: string); const bufCnt=1024; var a: Array [1..bufCnt] of byte; f: file; i, sz: integer; begin assignfile(f,FileName); reset(f,1); sz:=FileSize(f); for i:=1 to sz div bufCnt do blockwrite(f, a, bufCnt); blockwrite(f, a, sz mod bufCnt); closeFile(f); erase(f); end; |
derDoc - Mo 20.01.03 21:18
Also danke an euch beide, ich werde das mal testen und wenn noch etwas unklar ist poste ich es wieder.
Delete - Di 21.01.03 08:58
@matze: Einfach, aber dennoch funktionsfähig. Ich hätte nur eine "repeat-until"-Schleife benutzt (da spart man den Quark mit der Größenberechnung); außerdem geht´s mit einem 65k-Puffer (65.535) eindeutig schneller, und "BlockRead/BlockWrite" können max. 65k lesen und schreiben.
Na ja, das andere, was ich noch vorschlug (Dateinamen auf ein Zeichen ändern, dann noch mal mit "ReWrite" öffnen, um die Verbindung in der FAT zur alten Datenposition zu löschen), ist vielleicht Schnickschnack, lässt aber dann keine Rückschlüsse mehr auf den Namen bzw. die Position auf der Platte zu.
Dargor - Di 21.01.03 10:38
Mit BlockRead/-Write können auch Dateien größer als 65k gelesen werden.
Ich hatte mir mal mit BlockRead/-Write ein Kopierprogramm geschrieben, mit dem ich mühelos 100MB-Dateien kopieren konnte (und das sogar schneller als der COPY-Befehl von DOS *g*)
Edit: Ups, falsch gelesen. Ich nehme an, die 65k bezogen sich auf die Größe des Puffers (Array), oder?
Klabautermann - Di 21.01.03 11:10
| MathiasSimmack hat folgendes geschrieben: |
- Einen Puffer, z.B.
Quelltext 1: 2:
| var buf : array[0..65535]of byte; |
solange mit "BlockRead" einlesen, bis ein Fehler auftaucht (dann hast du das Ende erreicht)
|
Das ist nicht dein Ernst oder?
1. Das ende des Buffers kennst du ansonsten kannst du mit
High(Buf) arbeiten.
2. Aber ich denke du meinst das ende der Datei.
Ob du dieses Ereicht hast solltest du mit
EOF(f) überprüfen und nicht leichtsinnig einen Fehler provozieren.
3. Wenn du aber nur wissen willst wie groß die Datei ist, reicht ein
FileSize(f) dieses liefert die Anzahl der Datensätze zurück, da du im
Reset eine Datensatzgöße von einem Byte angegeben hast, entspricht dies der Dateigröße in Byte. Diesen Wert kannst du also als Endwert für deine überschreibschleife nehmen.
| MathiasSimmack hat folgendes geschrieben: |
- durch die Endlosschleife (s. Punkt #3) wiederholt sich das Spiel, bis du endgültig das Ende der Datei erreicht hast; dann solltest du aufhören! :wink:
|
Wenn du es beendest ist es keine Endlosschleife. Generell sollte man keine Endlosschleifen in seinem Programm haben da es sich sonst Totläuft. Endlosschleifen sind ein eindeutiger Bug.
@derDoc: Ich glaube man sollte seine Dateien sogar mit bestimmten Bitmustern überschreiben. Eventuell musst du dich da noch mal schlau machen.
Gruß
Klabautermann
Delete - Di 21.01.03 12:11
@Klabautermann: Die absolut, rudimentäre Grundlage meiner Ausführung war das Kopier-Beispiel aus der Delphi-Hilfe (s. BlockRead -> F1):
Quelltext
1: 2: 3: 4:
| repeat BlockRead(FromF, Buf, SizeOf(Buf), NumRead); BlockWrite(ToF, Buf, NumRead, NumWritten); until (NumRead = 0) or (NumWritten <> NumRead); |
Ausgehend von der Grundlage lese ich einen Puffer ein und habe im letzten Parameter, o.g. "NumRead", die Anzahl der
tatsächlich gelesenen Bytes. Sagen wir, die Datei ist 1.024 Bytes groß, mein Puffer aber 65k. Dann wäre der Wert beim ersten Versuch also 1.024; und da dann nichts mehr da ist, wäre er beim zweiten Versuch 0.
Vielleicht war "Endlos-Schleife" nicht der richtige Ausdruck, aber das (s. oben) habe ich gemeint. Hier nun meine Funktion, damit´s nicht wieder Unklarheiten gibt:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| function WipeFile(const szFilename: string): boolean; var f : file; buf : array[0..65535]of byte; i, iRead, iWrite : integer; fpos : longint; begin {$I-} AssignFile(f,szFileName); ReSet(f,1);
if(IoResult = 0) then begin repeat fPos := filepos(f); // aktuelle Position merken BlockRead(f,buf,sizeof(buf),iRead); // max. 65k lesen
// der tatsächlich gelesene Wert steckt in "iRead" und // ist irgendwann Null, wenn das Ende der Datei erreicht // wurde und keine Bytes mehr gelesen werden können if(iRead > 0) then // (alte?) Methode des DOD (US-Verteidigungsministerium): // einmal 00 schreiben; einmal FF schreiben (3 Wiederholungen) // dann F6 schreiben // (Norton WipeInfo macht´s heute noch so; außer, das 0x01 // anstelle von 0xff angegeben ist) for i := 1 to 7 do begin case i of 1,3,5 : fillchar(buf,iRead, 0); // Inhalt mit 0x00 überschreiben 2,4,6 : fillchar(buf,iRead,255); // Inhalt mit 0xff überschreiben 7 : fillchar(buf,iRead,246); // Inhalt mit 0xf6 überschreiben end;
seek(f,fPos); // gespeicherte Position suchen BlockWrite(f,buf,iRead,iWrite); // Puffer schreiben if(iWrite <> iRead) then break; // Fehler! :o( end; until(iRead = 0) or (iWrite <> iRead);
CloseFile(f); // alte Datei schließen Rename(f,'D'); // alten Namen "vernichten" ReWrite(f,1); // alte Position "vernichten" CloseFile(f); Erase(f); // Datei löschen end; {$I+}
Result := (IoResult = 0); end; |
Ich hab´s mir übrigens einfach gemacht und nicht lange rumgerechnet. Deswegen die FOR-Schleife in der Form, wie sie da drin steht.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!