Thema: Delphi MBR überschreiben?

Einzelnen Beitrag anzeigen

CCRDude
Online

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

AW: MBR überschreiben?

  Alt 6. Jan 2012, 11: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