AGB  ·  Datenschutz  ·  Impressum  







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

MBR überschreiben?

Ein Thema von CCRDude · begonnen am 5. Jan 2012 · letzter Beitrag vom 6. Jan 2012
Antwort Antwort
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#1

MBR überschreiben?

  Alt 5. Jan 2012, 17:49
Vorweg: es geht nicht um einen Virus, im Gegenteil. Mein Code prüft den Hash des zu schreibenden MBRs (des Code-Anteils darin) gegen eine Liste von bekannten MBRs, bzw. akzeptiert noch solche, die als Teil eines gültig von MS signierten diskpart.exe, dmadmin.exe, etc. kommen, keine anderen.

Meine Frage: wie kann ich den MBR etwa von \\.\PhysicalDrive0 überschreiben? Ein einfaches CreateFile wie zum Lesen hilft scheinbar nicht. Wo ist der Fehler in meinem Code (weiter unten, keine Fehlermeldungen oder Exceptions vom System)?

Der Hintergrund: ein kleines Tool, das ich die letzte Woche geschrieben habe, zeigt mir Platteninhalte direkt vom Gerät, aber auch einfach nur den jeweiligen MBR, von einem Device oder aus einer Datei, an. Der komplette MBR-Inhalt wird strukturiert angezeigt, disassembliert, dazu kommen etwa SMART-Infos u.ä..

Nun will ich aber ein MBR-Restore einbauen, d.h. dem Benutzer die Möglichkeit geben, einen Original-MBR wiederherzustellen. Die Copyright-Frage umgehe ich, indem ich diesen in Betriebssystemdateien auffinde und von dort kopiere.

Mein Ansatz: zuerst den Lesecode kopiert und auf Schreiben umgebaut, d.h. ein TFileStream z.B. auf \\.\PhysicalDrive0, die ersten 512 Byte auslesen (sektorweise halt), im Ausgelesenen die ersten 440 Byte ersetzen (um Partitionstabelle und alles danach zu erhalten) und dann alles zurückzuschreiben.

Funktioniert super, wenn ich als Ziel eine Datei angebe, aber nicht mit \\.\PhysicalDrive0.

Ich bin dann auf CreateFile/ReadFile/WriteFile umgestiegen, das funktioniert aber auch nicht.

Delphi-Quellcode:
function TMasterBootRecordRecordStream.WriteToDrive(const ADiskDeviceName: string; var AErrorCode: cardinal): boolean;
var
   fs: TFileStream;
   iBytesCopied: Int64;
   ms: TMemoryStream;

   cWritten, cRead: cardinal;
   h: THandle;
   p: Pointer;
begin
   try
      Seek(0, soFromBeginning);
      fs := TFileStream.Create('\\.\' + ADiskDeviceName, fmOpenReadWrite);
      ms := TMemoryStream.Create;
      try
         fs.Seek(0, soFromBeginning);
         ms.CopyFrom(fs, 512);
         ms.Seek(0, soFromBeginning);
         ms.CopyFrom(Self, MasterBootRecordCodeSize);
         ms.Seek(0, soFromBeginning);
         fs.Seek(0, soFromBeginning);
         iBytesCopied := fs.CopyFrom(ms, 512);
         Result := (iBytesCopied = 512);
         (*
        iBytesCopied := fs.CopyFrom(Self, MasterBootRecordCodeSize);
        Result := (iBytesCopied = MasterBootRecordCodeSize);
         *)

      finally
         ms.Free;
         fs.Free;
      end;
   except
      on E: Exception do begin
         Result := false;
         ShowMessage(E.Message);
      end;
   end;
end;
Self ist jeweils ein Stream, der den zu schreibenden Code enthält, MasterBootRecordCodeSize eine Konstante mit der Größe der Code-Anteils (440).

Erschwerend kommt hinzu, daß dieser Code keinerlei Fehler liefert (war schon mit etlichen Debugausgaben gespickt).

Testen tue ich u.a. auf einer frischen XP-VM, d.h. die erschwerten Schreibbedingungen von Vista & höher treffen hier nicht zu, und, da ganz frisch, auch kein hinderndes Antivirenprogramm.
Delphi-Quellcode:
function TMasterBootRecordRecordStream.WriteToDrive(const ADiskDeviceName: string; var AErrorCode: cardinal): boolean;
var
   fs: TFileStream;
   iBytesCopied: Int64;
   ms: TMemoryStream;

   cWritten, cRead: cardinal;
   h: THandle;
   p: Pointer;
begin
   try
      Seek(0, soFromBeginning);
      h := CreateFile(PChar('\\.\' + ADiskDeviceName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0);
      // h := CreateFile(PChar('C:\testout.mbr'), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_ALWAYS, 0, 0);
      ms := TMemoryStream.Create;
      try
         ms.SetSize(512);
         p := ms.Memory;
         Result := Windows.ReadFile(h, ms.Memory^, 512, cRead, nil);
         if Result then begin
            Result := (cRead = 512);
            if Result then begin
               ms.Seek(0, soFromBeginning);
               ms.CopyFrom(Self, MasterBootRecordCodeSize);
               ms.Seek(0, soFromBeginning);
               Result := Windows.WriteFile(h, Self.Memory^, 512, cWritten, nil);
               if Result then begin
                  Result := (cWritten = 512);
               end else begin
                  // TODO : improve error handling, not just ShowMessage('Error.3');
               end;
            end else begin
               // TODO : improve error handling, not just ShowMessage('Error.2');
            end;
         end else begin
            // TODO : improve error handling, not just ShowMessage('Error.1');
         end;
      finally
         ms.Free;
         Windows.CloseHandle(h);
      end;
   except
      on E: Exception do begin
         Result := false;
         ShowMessage(E.Message);
      end;
   end;
end;
Die ShowMessage waren bereits drin, genauso wie weitere, die positive Ergebnisse zeigen sollten. Alle Calls liefern True.

PS: Die Suchfunktion habe ich natürlich schon bemüht, auch ein ähnliches Thema gefunden, aber keine Antwort auf genau diese Frage.
Miniaturansicht angehängter Grafiken
discalyzer2-mbr-code.png   discalyzer2-mbr-disassembler.png   discalyzer2-mbr-replaceselection.png  
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#2

AW: MBR überschreiben?

  Alt 5. Jan 2012, 22:32
Schau mal nach ob Dein BIOS einen Kopierschutz auf den ersten Sektor oder die erste Spur realisieren kann.
Sollte es da nichts geben, dann versuch doch mal im zweiten dritten.. Sektor die Daten zu schreiben.
Hast Du vielleicht eine Partition in de du "üben" kannst?

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

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

AW: MBR überschreiben?

  Alt 5. Jan 2012, 22:37
Ich habe mal ein Programm geschrieben, mit dem man Diskimages erstellen und zurück schreiben kann. Ich habe es damals nur mit Disketten getestete, aber es sollte auch mit Festplatten funktionieren. http://www.michael-puff.de/Programmi...lphi/Programme -> DiskImageNT.zip eventuell kannst du dir das mal angucken und es hilft dir.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: MBR überschreiben?

  Alt 5. Jan 2012, 23:10
Für einen direkten Schreibzugriff auf Festplatten braucht man, im Gegensatz zum billigen Zugriff auf Disketten oder Speichersticks, gewisse Rechte.

Außerdem steht in Win7 die Systempartition/Systemplatte unter einem erweitertem Schutz.
$2B or not $2B

Geändert von himitsu ( 5. Jan 2012 um 23:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#5

AW: MBR überschreiben?

  Alt 5. Jan 2012, 23:36
Für einen direkten Schreibzugriff auf Festplatten braucht man, im Gegensatz zum billigen Zugriff auf Disketten oder Speichersticks, gewisse Rechte.

Außerdem steht in Win7 die Systempartition/Systemplatte unter einem erweitertem Schutz.
Und dann gibt es keine Fehlermeldung?

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: MBR überschreiben?

  Alt 6. Jan 2012, 00:07
Wieso sollte es?
Du wertest z.B. die Rückgabewerte vom CreateFile auch nicht aus.
$2B or not $2B

Geändert von himitsu ( 6. Jan 2012 um 00:10 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#7

AW: MBR überschreiben?

  Alt 6. Jan 2012, 00:23
Also ich würde einen THandleStream mit der CreateFile() Funktion kombinieren.
Das ergibt die volle Kontrolle beim Öffnen des Diskdevive mit dem einfachen Handling eines TStream-Objekts.

Ansonsten ist es wohl so, dass der MBR durch Windows geschützt wird und man besondere Anstrengungen unternehmen muss um ihn zu ändern.
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#8

AW: MBR überschreiben?

  Alt 6. Jan 2012, 12:12
Erstmal vorab vielen Dank für alle Antworten

@p80286: klar habe ich eine Übungspartition - ich teste das alles mit VMWare 8 (XP) in einer virtuellen Maschine. Gute Idee, das mit dem Kopierschutz, habe leider im VMWare-Bios keinen gefunden.

@Luckie: großartig, danke! Auch wenn Du da mit Volumes arbeitest, weswegen es mir hier konkret nicht hilft - das kann ich später sicher nochmal als Referenz gebrauchen (Bootsektoren und Teile des NTFS-Dateisystems kann der Code auch schon lesen, aber da hab ich mich ums Schreiben noch gar nicht kümmern können bisher, und in der GUI isses noch lange nicht).

@himitsu, sx2008: In Sachen Rechte hatte ich das hier im MSDN gefunden:
Zitat:
A write on a volume handle will succeed if the volume does not have a mounted file system, or if one of the following conditions is true:
  • The sectors to be written to are boot sectors.
  • The sectors to be written to reside outside of file system space.
  • You have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
  • The volume has no actual file system. (In other words, it has a RAW file system mounted.)

A write on a disk handle will succeed if one of the following conditions is true:
  • The sectors to be written to do not fall within a volume's extents.
  • The sectors to be written to fall within a mounted volume, but you have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
  • The sectors to be written to fall within a volume that has no mounted file system other than RAW.
Um ein Volume-Handle handelt es sich nicht, aber der Bootsektor bei Volumes wird lockerer gehandhabt, und ich habe auch zu Disk-Handles (ich glaube sogar hier im Forum) gelesen, daß man ausgerechnet da einfacher drauf schreiben darf. Siehe auch da oben: fällt nicht in den Bereich eines Volumes.

Unter XP ein Admin, unter Win7 ein Admin mit dem Programm elevated ist natürlich selbstverständlich, das Manifest passt entsprechend. Unter Win7 bekomme ich auch noch ein Access Denied, aber solange es unter XP nicht läuft, muss ich da erstmal nicht ran (denke ich?).

@himitsu: stimmt, ich werte den Rückgabewert von CreateFile nicht aus. War aber auch nur der alternative Ansatz, im TFileStream-Mopped gäbe es ja False als Rückgabewert, und die Handle-Variante hätte spätestens beim ReadFile einen Error, wenn das CreateFile scheitern würde. Egal, habe das mal nachgeholt.

@sx2008: THandleStream? Oh, der ist mir neu, was für ne praktische Sache!

Habe das ganze als dritte Alternative nun auch noch mit THandleStream geschrieben:
Delphi-Quellcode:
function TMasterBootRecordStream.WriteToDriveFileHandleStream(const ADiskDeviceName: string; var AErrorCode: cardinal): boolean;
var
   h: THandle;
   hs: THandleStream;
   ms: TMemoryStream;
   iBytesCopied: Int64;
begin
   AErrorCode := 0;
   try
      Seek(0, soFromBeginning);
      h := CreateFile(PChar('\\.\' + ADiskDeviceName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
      Result := (h <> INVALID_HANDLE_VALUE);
      if Result then begin
         hs := THandleStream.Create(h);
         ms := TMemoryStream.Create;
         try
            {$IFDEF MBRWriteOnlyAffectedBytes}
            iBytesCopied := hs.CopyFrom(Self, MasterBootRecordCodeSize);
            Result := (iBytesCopied = MasterBootRecordCodeSize);
            if not Result then begin
               AErrorCode := ERROR_BAD_LENGTH;
            end;
            {$ELSE MBRWriteOnlyAffectedBytes}
            hs.Seek(0, soFromBeginning);
            iBytesCopied := ms.CopyFrom(hs, SectorSize);
            Result := (iBytesCopied = SectorSize);
            if Result then begin
               ms.Seek(0, soFromBeginning);
               iBytesCopied := ms.CopyFrom(Self, MasterBootRecordCodeSize);
               Result := (iBytesCopied = MasterBootRecordCodeSize);
               if Result then begin
                  ms.Seek(0, soFromBeginning);
                  hs.Seek(0, soFromBeginning);
                  iBytesCopied := hs.CopyFrom(ms, SectorSize);
                  Result := (iBytesCopied = SectorSize);
                  if not Result then begin
                     AErrorCode := ERROR_BAD_LENGTH;
                  end;
               end else begin
                  AErrorCode := ERROR_BAD_LENGTH;
               end;
            end else begin
               AErrorCode := ERROR_BAD_LENGTH;
            end;
            {$ENDIF MBRWriteOnlyAffectedBytes}
         finally
            ms.Free;
            hs.Free;
         end;
      end else begin
         AErrorCode := GetLastError;
      end;
   except
      on E: Exception do begin
         Result := false;
         ShowMessage(E.Message);
      end;
   end;
end;
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#9

AW: MBR überschreiben?

  Alt 6. Jan 2012, 12:23
Nachtrag (ich will das oben jetzt nicht löschen, weil es für den nächsten suchenden evtl. noch hilfreiche Informationen enthält):

Wie so oft im Leben lag das Problem viel einfacher. Im Code, in dem Quelle und Ziel übergeben werden, hatte ich indirekt letztendlich mit Ziel=Quelle gearbeitet. Klar, daß das ohne Fehler gutging, sich aber der eigentliche MBR nicht verändert hat.

Ich such mir mal ne Ecke zum schämen, und bedanke mich
Und ich muss mir echt den Remote Debugger mal wieder angewöhnen, irgendwie steckt mir noch in den Knochen, daß der (D2006-geschädigt) eh nicht funktionierte.
  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 08:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz