Autor Beitrag
derDoc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 623

Win Vista Prof
D2007 Prof
BeitragVerfasst: Mo 20.01.03 17:59 
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?

_________________
MfG derDoc
There are only 10 types of people: those who understand binary and those who don't.
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 20.01.03 18:47 
Das musst du nicht wissen. Du machst es nämlich wie folgt:
  • Datei zuweisen und öffnen
    ausblenden Quelltext
    1:
    2:
    AssignFile(f,'Dateiname');
    ReSet(f,1);

  • aktuelle Position merken!
  • Einen Puffer, z.B.
    ausblenden 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
    ausblenden Quelltext
    1:
    CloseFile(f);					

  • du öffnest sie erneut, diesmal aber mit
    ausblenden Quelltext
    1:
    ReWrite(f,1);					

    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
ausblenden Quelltext
1:
~asswort.txt					

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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: Mo 20.01.03 19:51 
Folgenden Code hab ich beim EDH gefunden:

ausblenden 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;

_________________
In the beginning was the word.
And the word was content-type: text/plain.
derDoc Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 623

Win Vista Prof
D2007 Prof
BeitragVerfasst: Mo 20.01.03 22:18 
Also danke an euch beide, ich werde das mal testen und wenn noch etwas unklar ist poste ich es wieder.

_________________
MfG derDoc
There are only 10 types of people: those who understand binary and those who don't.
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 21.01.03 09: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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 59

Win2k SP4, WinXP Pro SP1
D6 Pers
BeitragVerfasst: Di 21.01.03 11: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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Di 21.01.03 12:10 
MathiasSimmack hat folgendes geschrieben:

  • Einen Puffer, z.B.
    ausblenden 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
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 21.01.03 13:11 
@Klabautermann: Die absolut, rudimentäre Grundlage meiner Ausführung war das Kopier-Beispiel aus der Delphi-Hilfe (s. BlockRead -> F1):
ausblenden 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:
ausblenden volle Höhe 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.