AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

File Eraser programmieren

Ein Thema von 3_of_8 · begonnen am 29. Dez 2005 · letzter Beitrag vom 4. Jan 2011
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.360 Beiträge
 
Delphi 12 Athens
 
#1

Re: File Eraser programmieren

  Alt 29. Dez 2005, 13:00
Da meine Variante eh mal als OpenSource auslaufen wird, kann ich dat hier ja ruhig mal zeigen ^^

Alao aktuell mach ich dat so:
Delphi-Quellcode:
Type TDelFlags = Set of (cdfOverride1, cdfOverride3, cdfOverride7, cdfOverride15, cdfOverride31,
  cdfSplit, cdfSplitLarge, cdfFileTable); // cdfFileTable do not use on Win NT file system.

Const cdfDefault = [cdfOverride7 {, cdfFileTable}];
  cdfDefaultLarge = [cdfOverride1, cdfSplitLarge {, cdfFileTable}];



Function ClearAndDeleteFile(FileName: WideString; Flags: TDelFlags = cdfDefault): ByteBool;
  Var Handle: THandle;
    Len, LF: TLargeIntRec;
    DecSize, BufSize, i, i2: LongInt;
    Buffer: PLongWordArray;

  Begin
    Result := False;
    FileName := _ExpandFileName(FileName);
    Handle := CreateFileW(Pointer(FileName), amGenericWrite or amGenericRead,
      amFileShareRead or amFileShareWrite or amFileShareDelete, nil, cdOpenExisting, 0, 0);
    If Handle = InvalidHandle Then Exit;
    Buffer := nil;
    Try
      Len.Lo := GetFileSize(Handle, @Len.Hi);
      If Len.Org = InvalidFileSizeLI Then Exit;
      If (Len.Hi = 0) and (Len.Lo <= $00A00000) Then BufSize := Len.Lo shr 2 Else BufSize := $00280000;
      Buffer := Memory.Get((BufSize + 1) shl 2);
      Memory.Fill1(Buffer, BufSize shl 2, LongWord(_Random(-1)));
      If cdfOverride31 in Flags Then i := 31 Else If cdfOverride15 in Flags Then i := 15
      Else If cdfOverride7 in Flags Then i := 7 Else If cdfOverride1 in Flags Then i := 1 Else i := 3;
      For i := i downto 0 do Begin
        For i2 := BufSize - 1 downto 0 do Buffer^[i2] := Buffer^[i2] xor LongWord(_Random(-1));
        i2 := BufSize shl 2 - _Random(BufSize);
        LF.Org := Len.Org;
        SetFilePointer(Handle, 0, nil, mmFileBegin);
        While LF.Org >= i2 do Begin
          WriteDataNE(Handle, Buffer, i2, nil, nil);
          Dec(LF.Org, i2);
        End;
        WriteDataNE(Handle, Buffer, LongInt(LF.Lo), nil, nil);
        FlushFileBuffers(Handle);
      End;
      If (cdfSplit in Flags) or (cdfSplitLarge in Flags) Then Begin
        DecSize := GetClusterSize(_ExtractFileDrive(FileName), 512);
        LF.Org := Len.Org;
        SetFilePointer(Handle, LF.Lo, @LF.Hi, mmFileBegin);
        If cdfSplitLarge in Flags Then Begin
          i := DecSize;
          While LF.Org > i do Begin
            Dec(LF.Org, i);
            SetFilePointer(Handle, -i, nil, mmFileCurrent);
            SetEndOfFile(Handle);
            FlushFileBuffers(Handle);
            i := DecSize + LF.Org shr 10;
          End
        End Else While LF.Org > DecSize do Begin
          Dec(LF.Org, DecSize);
          SetFilePointer(Handle, -DecSize, nil, mmFileCurrent);
          SetEndOfFile(Handle);
          FlushFileBuffers(Handle);
        End;
      End;
      SetFilePointer(Handle, 0, nil, mmFileBegin);
      SetEndOfFile(Handle);
    Finally
      Memory.Free(Pointer(Buffer));
      CloseHandle(Handle);
    End;
    DeleteFileW(Pointer(FileName));
    If cdfFileTable in Flags Then Begin
      For i := 0 to 99 do Begin
        FileName := WideString('CF') + WideChar(i div 10 or $30) + WideChar(i mod 10 or $30) + WideString('.FNSClearDir');
        Handle := CreateFileW(Pointer(FileName), amGenericWrite,
          amFileShareRead or amFileShareWrite or amFileShareDelete, nil, cdCreateAlways, 0, 0);
        If Handle <> InvalidHandle Then CloseHandle(Handle);
      End;
      For i := 99 downto 0 do Begin
        FileName := WideString('CF') + WideChar(i div 10 or $30) + WideChar(i mod 10 or $30) + WideString('.FNSClearDir');
        DeleteFileW(Pointer(FileName));
      End;
    End;
    Result := True;
  End;
Das meiste dürfte ja selbsterklärend sein, von den Namen her.
- WriteDataNE entspricht dabei WriteFile (WinAPI incl. 'ner winzigen Fehlerbehandling)
- Memory geht direkt an den MemoryManager in etwa kann man das so sehn: Memory.Get=GetMem, ...

Ein Problem hab ich allerdings noch beim entfernen der Daten aus dem Verzeichnis.
Bei den älteren Dateisystemen (FAT...) konnte man den Eintrag dadurch entfernen, daß man die Tabelle überfüllt hat.
Leider führt NTFS 'ne Art LogBuch, oder wie man das nennen kann, wo ich bisher noch nicht weiß, wie ich da rannkomme, um den entsprechenden Eintrag entfernen zu können -.-''


Na ja, mal sehn ob jemand noch ein paar Tipps hat
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Micha88
(Gast)

n/a Beiträge
 
#2

AW: Re: File Eraser programmieren

  Alt 3. Jan 2011, 20:35
Da meine Variante eh mal als OpenSource auslaufen wird, kann ich dat hier ja ruhig mal zeigen ^^

Alao aktuell mach ich dat so:
Delphi-Quellcode:
Type TDelFlags = Set of (cdfOverride1, cdfOverride3, cdfOverride7, cdfOverride15, cdfOverride31,
  cdfSplit, cdfSplitLarge, cdfFileTable); // cdfFileTable do not use on Win NT file system.

Const cdfDefault = [cdfOverride7 {, cdfFileTable}];
  cdfDefaultLarge = [cdfOverride1, cdfSplitLarge {, cdfFileTable}];



Function ClearAndDeleteFile(FileName: WideString; Flags: TDelFlags = cdfDefault): ByteBool;
  Var Handle: THandle;
    Len, LF: TLargeIntRec;
    DecSize, BufSize, i, i2: LongInt;
    Buffer: PLongWordArray;

  Begin
    Result := False;
    FileName := _ExpandFileName(FileName);
    Handle := CreateFileW(Pointer(FileName), amGenericWrite or amGenericRead,
      amFileShareRead or amFileShareWrite or amFileShareDelete, nil, cdOpenExisting, 0, 0);
    If Handle = InvalidHandle Then Exit;
    Buffer := nil;
    Try
      Len.Lo := GetFileSize(Handle, @Len.Hi);
      If Len.Org = InvalidFileSizeLI Then Exit;
      If (Len.Hi = 0) and (Len.Lo <= $00A00000) Then BufSize := Len.Lo shr 2 Else BufSize := $00280000;
      Buffer := Memory.Get((BufSize + 1) shl 2);
      Memory.Fill1(Buffer, BufSize shl 2, LongWord(_Random(-1)));
      If cdfOverride31 in Flags Then i := 31 Else If cdfOverride15 in Flags Then i := 15
      Else If cdfOverride7 in Flags Then i := 7 Else If cdfOverride1 in Flags Then i := 1 Else i := 3;
      For i := i downto 0 do Begin
        For i2 := BufSize - 1 downto 0 do Buffer^[i2] := Buffer^[i2] xor LongWord(_Random(-1));
        i2 := BufSize shl 2 - _Random(BufSize);
        LF.Org := Len.Org;
        SetFilePointer(Handle, 0, nil, mmFileBegin);
        While LF.Org >= i2 do Begin
          WriteDataNE(Handle, Buffer, i2, nil, nil);
          Dec(LF.Org, i2);
        End;
        WriteDataNE(Handle, Buffer, LongInt(LF.Lo), nil, nil);
        FlushFileBuffers(Handle);
      End;
      If (cdfSplit in Flags) or (cdfSplitLarge in Flags) Then Begin
        DecSize := GetClusterSize(_ExtractFileDrive(FileName), 512);
        LF.Org := Len.Org;
        SetFilePointer(Handle, LF.Lo, @LF.Hi, mmFileBegin);
        If cdfSplitLarge in Flags Then Begin
          i := DecSize;
          While LF.Org > i do Begin
            Dec(LF.Org, i);
            SetFilePointer(Handle, -i, nil, mmFileCurrent);
            SetEndOfFile(Handle);
            FlushFileBuffers(Handle);
            i := DecSize + LF.Org shr 10;
          End
        End Else While LF.Org > DecSize do Begin
          Dec(LF.Org, DecSize);
          SetFilePointer(Handle, -DecSize, nil, mmFileCurrent);
          SetEndOfFile(Handle);
          FlushFileBuffers(Handle);
        End;
      End;
      SetFilePointer(Handle, 0, nil, mmFileBegin);
      SetEndOfFile(Handle);
    Finally
      Memory.Free(Pointer(Buffer));
      CloseHandle(Handle);
    End;
    DeleteFileW(Pointer(FileName));
    If cdfFileTable in Flags Then Begin
      For i := 0 to 99 do Begin
        FileName := WideString('CF') + WideChar(i div 10 or $30) + WideChar(i mod 10 or $30) + WideString('.FNSClearDir');
        Handle := CreateFileW(Pointer(FileName), amGenericWrite,
          amFileShareRead or amFileShareWrite or amFileShareDelete, nil, cdCreateAlways, 0, 0);
        If Handle <> InvalidHandle Then CloseHandle(Handle);
      End;
      For i := 99 downto 0 do Begin
        FileName := WideString('CF') + WideChar(i div 10 or $30) + WideChar(i mod 10 or $30) + WideString('.FNSClearDir');
        DeleteFileW(Pointer(FileName));
      End;
    End;
    Result := True;
  End;
Das meiste dürfte ja selbsterklärend sein, von den Namen her.
- WriteDataNE entspricht dabei WriteFile (WinAPI incl. 'ner winzigen Fehlerbehandling)
- Memory geht direkt an den MemoryManager in etwa kann man das so sehn: Memory.Get=GetMem, ...

Ein Problem hab ich allerdings noch beim entfernen der Daten aus dem Verzeichnis.
Bei den älteren Dateisystemen (FAT...) konnte man den Eintrag dadurch entfernen, daß man die Tabelle überfüllt hat.
Leider führt NTFS 'ne Art LogBuch, oder wie man das nennen kann, wo ich bisher noch nicht weiß, wie ich da rannkomme, um den entsprechenden Eintrag entfernen zu können -.-''


Na ja, mal sehn ob jemand noch ein paar Tipps hat
Kann mir mal wer sagen, welche USES ich dafür alles einbinden muss??
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3

AW: File Eraser programmieren

  Alt 3. Jan 2011, 20:39
Wenn du uns sagst, welche Funktionen nicht erkannt werden...
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Micha88
(Gast)

n/a Beiträge
 
#4

AW: File Eraser programmieren

  Alt 3. Jan 2011, 20:42
Funktionen werden generell garkeine in dieser "Function" erkannt.
Sowie TLargeIntRec und PLongWordArray werden nicht erkannt.
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#5

AW: File Eraser programmieren

  Alt 3. Jan 2011, 20:47
Das wird irgendwas eigenes sein wie z.B. das folgende, vermute ich.
Delphi-Quellcode:
type
  TLongWordArray = array of LongWord;

var
  LongWordArray: TLongWordArray;
Delphi-Quellcode:
type
  TLargeIntRect: record
    Hi: LargeInt; // gibt's LargeInt?
    Lo: LargeInt;
    Ord: LargeInt;
  end;
Oder so ähnlich.

Geändert von Matze ( 3. Jan 2011 um 20:50 Uhr)
  Mit Zitat antworten Zitat
Micha88
(Gast)

n/a Beiträge
 
#6

AW: File Eraser programmieren

  Alt 3. Jan 2011, 20:49
Wieso wird das dann nicht mit in den Post gepackt?
Sehr nett ...
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#7

AW: File Eraser programmieren

  Alt 3. Jan 2011, 20:52
Weil es himi vermutlich darum ging, das Vorgehen des Algorithmusses zu zeigen.
Da sind die genauen Typen weniger wichtig.

Wie ich himi und seine ganzen Open-Source-Klassen kenne, möchte er dir das keinesfalls vorenthalten.
Wenn du ihn lieb fragst, verrät er dir sicher, was genau hinter den Typen steckt.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.360 Beiträge
 
Delphi 12 Athens
 
#8

AW: File Eraser programmieren

  Alt 3. Jan 2011, 21:07
Jupp, dahinter stecken teilweise einige eigene Definitionen/API-Implementationen.

Delphi-Quellcode:
PLongWordArray = ^TLongWordArray;
TLongWordArray = Array[0..0] of LongWord;
TLargeIntRec = Delphi-Referenz durchsuchenInt64Rec

Memory.Fill1 = Delphi-Referenz durchsuchenFillMemory usw.


Aber Aufgrund der aktuellen Datendichte und wegen dem exzessiven Logging von NTFS, reicht ein einfaches überschreiben.

Delphi-Quellcode:
var
  s: TFileStream;
  a: array[0..$FFFF] of Byte;
  i: Int64;
begin
  FillChar(a, SizeOf(a), 0);
  s := TFileStream.Create(TheFileName, fmOpenReadWrite);
  try
    i := (s.Size + $FFFF) and not Int64($FFFF);
    while i > 0 do begin
      s.Write(a, SizeOf(a));
      if i mod $03FFFFFF = 0 then
        FlushFileBuffers(s.Handle);
      Dec(i, SizeOf(a));
    end;
    FlushFileBuffers(s.Handle);
  finally
    s.Free;
  end;
PS: Wirklich sicher löschen geht aber nicht.
OK, die Daten in dieser Datei mögen weg sein, aber es können noch Kopien der Dateidaten vorhanden sein.
(Fragmentierung, Pagefile usw.)

Aber den Grund dafür hatte ich in irgendeinem dieser Sicher-Löschen-Threads schonmal ausführlich benannt.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Assarbad
Assarbad

Registriert seit: 8. Okt 2010
Ort: Frankfurt am Main
1.234 Beiträge
 
#9

AW: File Eraser programmieren

  Alt 4. Jan 2011, 00:40
Aber Aufgrund der aktuellen Datendichte und wegen dem exzessiven Logging von NTFS, reicht ein einfaches überschreiben.
???

Also daß einfaches Löschen reicht, wissen wir. Aber was hat das mit dem (USN-)Journal (welches im Gegensatz zum Tx-Log ab Vista standardmäßig nichtmal aktiv ist) oder der Datendichte zu tun? Das Tx-Log würde ich hingegen nichtmal als relevant ansehen, da diese Daten ja nur bis zum Commit wichtig sind.

PS: Wirklich sicher löschen geht aber nicht.
OK, die Daten in dieser Datei mögen weg sein, aber es können noch Kopien der Dateidaten vorhanden sein.
(Fragmentierung, Pagefile usw.)
Fragmentierung ist kein Argument. Es gibt IOCTLs die man ans Dateisystem schicken kann um entweder selektiv die "cluster tips" (Cluster lesen, berechnen wieviel genullt werden muß, schreiben) zu überschreiben oder eben anderweitig die Fragmente einer Datei und die entsprechenden Einträge in der MFT/FAT zu überschreiben.

Pagefile ist hingegen durchaus ein gutes Argument, dürfte aber praktisch kaum Einfluß haben. Fragmente hingegen werden ja nicht nachträglich angelegt ... hier könnte höchstens eine Defragmentierung das Problem erzeugen indem die Dateidaten in als leer registrierten Clustern noch existieren. Da kann man wiederum mit dem Parsen der MFT Bitmap und Löschen entsprechender Cluster Abhilfe schaffen.
Oliver
"... aber vertrauen Sie uns, die Physik stimmt." (Prof. Harald Lesch)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.360 Beiträge
 
Delphi 12 Athens
 
#10

AW: File Eraser programmieren

  Alt 4. Jan 2011, 11:08
Zitat:
Delphi-Quellcode:
For i := 99 downto 0 do Begin
  FileName := WideString('CF') + WideChar(i div 10 or $30) + WideChar(i mod 10 or $30) + WideString('.FNSClearDir');
  DeleteFileW(Pointer(FileName));
End;
Die damalige Idee hinter diese, Teil lag darin, daß man Windows dazu zwingt den alten Datei-Eintrag in der Verzeichnisstruktur zu überschreiben.
Was jetzt aber nicht mehr viel bringt und eher nur die Logs auffüllt.


Nja, im Grunde müßte man auch noch alle leeren Cluster und idealer Weise auch noch die Anteile der ungenutzen Cluster hinter den sonstigen Dateien, sowie die ungenutzen Clusterteile innerhalb von SparseFiles und komprimierten Dateien (via NTFS-Compression) auch noch löschen, um wirklich möglichst sicher gehn zu können, daß von der Datei nichts mehr vorhanden ist.

Das meine ich damit. Es kann ja sein, daß z.B. durch's Defragmentieren, bei Speichern/Verändern der Datei oder beim Ansehn der Datei (MS Office z.B. legt sich gern 'ne Arbeitskopie an) irgendwo noch Daten/Datenfragmente in anderen Clustern existieren
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz