![]() |
MBR überschreiben?
Liste der Anhänge anzeigen (Anzahl: 3)
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:
Self ist jeweils ein Stream, der den zu schreibenden Code enthält, MasterBootRecordCodeSize eine Konstante mit der Größe der Code-Anteils (440).
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; 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:
Die ShowMessage waren bereits drin, genauso wie weitere, die positive Ergebnisse zeigen sollten. Alle Calls liefern True.
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; PS: Die Suchfunktion habe ich natürlich schon bemüht, auch ein ähnliches Thema gefunden, aber keine Antwort auf genau diese Frage. |
AW: MBR überschreiben?
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 |
AW: MBR überschreiben?
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.
![]() |
AW: MBR überschreiben?
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. |
AW: MBR überschreiben?
Zitat:
Gruß K-H |
AW: MBR überschreiben?
Wieso sollte es?
Du wertest z.B. die Rückgabewerte vom CreateFile auch nicht aus. :stupid: |
AW: MBR überschreiben?
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. |
AW: MBR überschreiben?
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 ![]() Zitat:
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; |
AW: MBR überschreiben?
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 :oops: :oops: :oops: 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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:38 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