Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Alle Resourcen aus fremder EXE richtig entfernen (https://www.delphipraxis.net/84927-alle-resourcen-aus-fremder-exe-richtig-entfernen.html)

Zacherl 23. Jan 2007 17:33


Alle Resourcen aus fremder EXE richtig entfernen
 
Hi,

wie kann ich alle Resourcen eiener fremden EXE Datei entfernen? Mittels BeginUpdateResource(Filename, true) geht dies zwar, allerdings ist die Datei noch genau so groß wie vorher, wenn auch die Resourcen nicht mehr da sind.

Kann man irgendwie die komplette Resourcen Section entfernen oder sowas?

Florian

Zacherl 25. Jan 2007 06:20

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
*push*

ErazerZ 25. Jan 2007 15:29

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Downloade dir madshi's madRes herunter (ist OpenSource) und dann benutze folgendenen Code um eine Resource aus der Anwendung zu löschen.
Delphi-Quellcode:
var
  hUpdate: THandle;
begin

  hUpdate := madres.BeginUpdateResourceW(PWideChar(WideString(sFilename)), False);
  if hUpdate <> INVALID_HANDLE_VALUE then
  begin
    madres.UpdateResourceW(hUpdate, 'TYP', 'NAME', 0, nil, 0);
    madres.EndUpdateResourceW(hUpdate, False);
   end;

Zacherl 25. Jan 2007 15:43

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Ah vielen Dank, das geht wunderbar! :thumb:

Zacherl 25. Jan 2007 16:43

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Mh wie mache ich es, dass alle Resourcen einer Datei entfernt werden. Ich liste die auf mit EnumResourceNames. Allerdings wird dort ein PChar Wert übergeben und kein PWideChar. Zudem kann der PChar ein Pointer auf einen Integer aber auch auf einen String Wert sein ..

ErazerZ 25. Jan 2007 17:28

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
schaue dir das Beispiel weiter unten an, das habe ich einmal gemacht um alle Icons zu extrahieren, hat auch mit Namen und Nummern funktioniert, sollte nicht schwer sein das umzuschreiben.
http://www.delphipraxis.net/internal...=411613#411613

Olli 25. Jan 2007 17:46

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Florian, um sie zu entfernen, musst du selbstverfreilich die PE-Datei selber modifizieren. Lies dich dazu in den entsprechenden Dokus von MS und Luevelsmeyer erstmal schlau. Danach musst du entscheiden, ob du die Ressourcen nur ausnullen oder wirklich entfernen willst (letzteres ist zu empfehlen). Was unter Umstaenden bedeutet, dass du Sektionen der PE verschieben und RVAs anpassen musst usw. Alles in allem absolut nicht trivial.

Die entsprechenden "Update"-Funktionen existieren nur fuer NT und, soweit ich mich entsinne, erlauben auch nur das ausnullen, wenn man Ressourcen entfernen will.

Zacherl 25. Jan 2007 19:49

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Ah mist .. ist wohl zu kompliziert, dafür, dass ich das ohne Beispielcode hinbekommen würde .. und die Update Funktionen tun wirklich nur ausnullen.

Die aus der madRes bekommen es sogar hin, dass einige z.B. RCDATA richtig entfernt werden, aber auch nciht alle.

@ErazerZ: So mach ichs auch, nur will mein Code nicht recht, warum weiß ich leider auch nicht.

Olli 25. Jan 2007 19:52

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Zitat:

Zitat von Florian Bernd
Ah mist .. ist wohl zu kompliziert, dafür, dass ich das ohne Beispielcode hinbekommen würde .. und die Update Funktionen tun wirklich nur ausnullen.

C'mon, du willst mir doch nicht erzaehlen, dass du deswegen aufgibst? Immerhin wuerdest du mit dieser Einstellung nie weiterkommen, denn es gibt noch vieles zu entdecken ...

Zacherl 25. Jan 2007 20:03

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Aufgeben nicht, nein .. allerdings habe ich z.B. einen Beispielcode gefunden, wie man die .reloc Section entfernen kann. Allerdings scheint dies recht kompliziert, zumal es zu Fehlern im Programm kommt, wenn man einfach die .rsrc Section komplett tilgt.

Olli 25. Jan 2007 20:15

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Zitat:

Zitat von Florian Bernd
Aufgeben nicht, nein .. allerdings habe ich z.B. einen Beispielcode gefunden, wie man die .reloc Section entfernen kann. Allerdings scheint dies recht kompliziert, zumal es zu Fehlern im Programm kommt, wenn man einfach die .rsrc Section komplett tilgt.

Was fuer ein Programm? Hast du ein Beispielprogramm bei dem das passiert? Delphis Runtime ist IMO auf bestimmte Infos aus Ressourcen angewiesen, wenn ich mich recht entsinne.

ErazerZ 25. Jan 2007 21:09

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Ich kann morgen ein Beispiel dazu machen, mal schauen ob ich weiter komme, aber wenn es überhaupt nicht geht (sollte eigentlich, weil madRes auch die Sektionen löscht) kannst du die Anwendung im Speicher laden, NtHeaders auslesen, danach den FileOffset von der Resourcen Sektion und die größe auslesen (ist alles in DataDirectory/RVA) und danach mit einer funktion von dem FileOffset bis zum FileOffset + Größe ausschneiden (ich habe bereits eine Funktion länger her gemacht um Dateien auszuschneiden, funktioniert sowie Delete jedoch mit Dateien), danach kommts erst die schwere Arbeit, du musst danach alle nachfolgenden Sektionen anpassen und du musst auf FileAlign achten, auf alles achten, das ist eine menge Arbeit. Und ob die Anwendung noch überhaupt funktioniert wenns einfach so die Resourcensektion löscht.

Zacherl 27. Jan 2007 15:07

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Irgendwas rausgefunden?

ErazerZ 2. Feb 2007 21:46

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Ja also, ich hab mal heute das gemacht, getestet habe ich es nur mit meinem kleinen nonVCL programm, das einfach einen text aus einer Resource ladet und in einer MessageBox ausgibt. Die funktion die ich gemacht habe, entfernt dabei die ganze Sektionen aus einer PE-Datei. Und hier ist der ganze Code.
Delphi-Quellcode:
{
  Friday, 2nd February 2007 (15:00 - 22:30)
  by ErazerZ ( ErazerZ[at]gmail[dot]com )
  Music listening while coding:
    Bishop Lamont
    Busta Rhymes: The Big Bang
    Dr. Dre - 2001
    Eminem - Marshall Mathers LP
}

program SectionEraser;

uses
  Windows;

function ShellExecute(hWnd: HWND; Operation, FileName, Parameters, Directory: PChar; ShowCmd: Integer): HINST; stdcall; external 'shell32.dll' name 'ShellExecuteA';

function RemoveSection(sFilename: String; wSection: Word): Boolean;
  function Align(Value, Align: Cardinal): Cardinal;
  begin
    if ((Value mod Align) = 0) then
      Result := Value
    else
      Result := ((Value + Align - 1) div Align) * Align;
  end;
 
  function RvaToFileOffset(Address: Cardinal; NtHeaders: PImageNtHeaders): Cardinal;
  var
    i: Word;
    Section: PImageSectionHeader;
  begin
    Result := 0;
    Section := PImageSectionHeader(Cardinal(NtHeaders) + sizeof(TImageNtHeaders));
    for i := 0 to NtHeaders^.FileHeader.NumberOfSections -1 do
    begin
      if (Address >= Section^.VirtualAddress) and (Address <= Section^.VirtualAddress + Section^.SizeOfRawData) then
      begin
        Result := Address - Section^.VirtualAddress + Section^.PointerToRawData;
        Break;
      end;
      Inc(Section);
    end;
  end;
 
  function FileOffsetToRva(Address: Cardinal; NtHeaders: PImageNtHeaders): Cardinal;
  var
    i: Word;
    Section: PImageSectionHeader;
  begin
    Result := 0;
    Section := PImageSectionHeader(Cardinal(NtHeaders) + sizeof(TImageNtHeaders));
    for i := 0 to NtHeaders^.FileHeader.NumberOfSections -1 do
    begin
      if (Address >= Section^.PointerToRawData) and (Address <= Section^.PointerToRawData + Section^.SizeOfRawData) then
      begin
        Result := Address + Section^.PointerToRawData + Section^.VirtualAddress + NtHeaders^.OptionalHeader.ImageBase;
        Break;
      end;
      Inc(Section);
    end;
  end;

  function CutFile(hFile: THandle; FromOffset, Count: Cardinal): Cardinal;
  var
    dwSize, dwCopyFrom, dwCopyLength,
    lpNumberOfBytesRead: Cardinal;
    lpBuffer: Pointer;
  begin
    Result := Cardinal(-1);
    if (hFile <> INVALID_HANDLE_VALUE) then
    begin
      dwSize := GetFileSize(hFile, nil);
      if (dwSize > (FromOffset + Count)) then
      begin
        dwCopyFrom := FromOffset + Count;
        dwCopyLength := dwSize - (FromOffset + Count);
        if dwCopyLength = 0 then
        begin
          SetFilePointer(hFile, FromOffset, nil, FILE_BEGIN);
          SetEndOfFile(hFile);
          Result := dwSize - Count;
        end else
        begin
          lpBuffer := VirtualAlloc(nil, dwCopyLength, MEM_COMMIT, PAGE_READWRITE);
          if (lpBuffer <> nil) then
          begin
            SetFilePointer(hFile, dwCopyFrom, nil, FILE_BEGIN);
            ReadFile(hFile, lpBuffer^, dwCopyLength, lpNumberOfBytesRead, nil);
            if (lpNumberOfBytesRead = dwCopyLength) then
            begin
              SetFilePointer(hFile, FromOffset, nil, FILE_BEGIN);
              SetEndOfFile(hFile);
              WriteFile(hFile, lpBuffer^, dwCopyLength, lpNumberOfBytesRead, nil);
              if (lpNumberOfBytesRead = dwCopyLength) then
              begin
                VirtualFree(lpBuffer, 0, MEM_RELEASE);
                Result := dwSize - Count;
              end;
            end;
          end;
        end;
      end else
      begin
        if (FromOffset < dwSize) then
        begin
          SetFilePointer(hFile, FromOffset, nil, FILE_BEGIN);
          SetEndOfFile(hFile);
          Result := FromOffset;
        end;
      end;
    end;
  end;
var
  lpBuffer: Pointer;
  x: Word;
  { PE-Stuff }
  NtHeaders: PImageNtHeaders;
  Sections: array of TImageSectionHeader;
  SectionHeader: TImageSectionHeader;
  SectionOffset, SectionSize, // FileOffset of the Section ...
  SectionAlign: Cardinal; // Alignment of Section
  ImageSize: Cardinal;
  { Datei öffnen und laden }
  hFile: THandle;
  FileSize: Cardinal;
  lpNumberOfBytesWritten,
  lpNumberOfBytesRead: DWORD;
begin
  Result := False;
  hFile := CreateFile(PChar(sFilename), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  FileSize := GetFileSize(hFile, nil);
  GetMem(lpBuffer, FileSize);
  ReadFile(hFile, lpBuffer^, FileSize, lpNumberOfBytesRead, nil);
  if (lpBuffer = nil) then
  begin
    DeleteFile(PChar(sFilename));
    ExitProcess(0);
  end;
  NtHeaders := PImageNtHeaders(Cardinal(lpBuffer) + Cardinal(PImageDosHeader(lpBuffer)._lfanew));
  if NtHeaders.Signature <> IMAGE_NT_SIGNATURE then
  begin
    DeleteFile(PChar(sFilename));
    ExitProcess(0);
  end else
  begin
    if (wSection >= NtHeaders^.FileHeader.NumberOfSections) then
    begin
      DeleteFile(PChar(sFilename));
      ExitProcess(0);
    end;
    // alle TImageSectionHeaders zwischenspeichern (leichter und übersichtlicher)
    SetLength(Sections, NtHeaders^.FileHeader.NumberOfSections);
    for x := 0 to NtHeaders^.FileHeader.NumberOfSections -1 do
      CopyMemory(@Sections[x], Pointer(Cardinal(NtHeaders) + SizeOf(TImageNtHeaders) + (SizeOf(TImageSectionHeader) * x)), SizeOf(TImageSectionHeader));
    SectionHeader := Sections[wSection];
    SectionOffset := SectionHeader.PointerToRawData;
    SectionSize := SectionHeader.SizeOfRawData;
    SectionAlign := NtHeaders^.OptionalHeader.SectionAlignment;
    if (CutFile(hFile, SectionOffset, SectionSize) <> Cardinal(-1)) then
    begin
      // Sektionen die danach sind anpassen, also deren PointerToRawData updaten
      // es müssen keine berechnungen durchgeführt werden da sowieso bei einer ausführbaren datei alles bereits berechnet ist
      // wir müssen einfach nur abziehen
      for x := 0 to wSection -1 do
      begin
        Sections[x].Misc.VirtualSize := Align(Sections[x].Misc.VirtualSize, SectionAlign);
        // Ich weiß es auch nicht warum der aufeinmal so will und nicht anders ..
        if (x = wSection -1) then
          Sections[x].Misc.VirtualSize := Align(Sections[x].Misc.VirtualSize + SectionAlign, SectionAlign);
        SetFilePointer(hFile, PImageDosHeader(lpBuffer)._lfanew + SizeOf(TImageNtHeaders) + (SizeOf(TImageSectionHeader) * x), nil, FILE_BEGIN);
        WriteFile(hFile, Sections[x], SizeOf(TImageSectionHeader), lpNumberOfBytesWritten, nil);
      end;
      // Die danach folgenden Sektionen anpassen, VirtualSize muss nicht geupdated werden, anscheinend ..
      // nur PointerToRawData updaten, einfach die größe der zu löschendenen Sektion abziehen
      // wir müssen nichts berechnen weil es bereits vom compiler getan wurde ..
      for x := wSection +1 to (NtHeaders^.FileHeader.NumberOfSections -1) do
      begin
        Sections[x].PointerToRawData := Sections[x].PointerToRawData - SectionSize;
        SetFilePointer(hFile, PImageDosHeader(lpBuffer)._lfanew + SizeOf(TImageNtHeaders) + (SizeOf(TImageSectionHeader) * (x -1)), nil, FILE_BEGIN);
        WriteFile(hFile, Sections[x], SizeOf(TImageSectionHeader), lpNumberOfBytesWritten, nil);
      end;
      // Directorys müssen nicht abgezogen werden, nur die wenns z.b. Resource ist dann auf 0 setzen
      for x := 0 to IMAGE_NUMBEROF_DIRECTORY_ENTRIES -1 do
      begin
        if (NtHeaders^.OptionalHeader.DataDirectory[x].VirtualAddress <> 0) and (NtHeaders^.OptionalHeader.DataDirectory[x].Size <> 0) then
        begin
          if (RvaToFileOffset(NtHeaders^.OptionalHeader.DataDirectory[x].VirtualAddress, NtHeaders) = SectionOffset) then
          begin
            NtHeaders^.OptionalHeader.DataDirectory[x].VirtualAddress := 0;
            NtHeaders^.OptionalHeader.DataDirectory[x].Size := 0;
            break;
          end;
        end;
      end;
      // ImageSize anpassen
      if (NtHeaders^.OptionalHeader.SizeOfHeaders mod SectionAlign = 0) then
        ImageSize := NtHeaders^.OptionalHeader.SizeOfHeaders
      else
        ImageSize := Align(NtHeaders^.OptionalHeader.SizeOfHeaders, SectionAlign);
      for x := 0 to NtHeaders^.FileHeader.NumberOfSections -1 do
      begin
        if (x <> wSection) then
        begin
          ImageSize := ImageSize + Align(Sections[x].Misc.VirtualSize, SectionAlign)
        end;
      end;
      NtHeaders^.OptionalHeader.SizeOfImage := ImageSize;
      Dec(NtHeaders^.FileHeader.NumberOfSections);
      // NtHeader noch updaten ..
      SetFilePointer(hFile, PImageDosHeader(lpBuffer)._lfanew, nil, FILE_BEGIN);
      WriteFile(hFile, NtHeaders^, SizeOf(TImageNtHeaders), lpNumberOfBytesWritten, nil);
      if (lpNumberOfBytesWritten = SizeOf(TImageNtHeaders)) then
        Result := True;
    end;
  end;      
  CloseHandle(hFile);
  FreeMem(lpBuffer, FileSize);
  // Testen ob es läuft ..
  ShellExecute(0, 'open', PChar(sFilename), nil, nil, SW_SHOWNORMAL);
end;

function ExtractFilePath(s: string): string;
var
  i: Integer;
begin
  i := Length(s);
  while ((s[i] <> '\') and (s[i] <> '/')) do
    if (i > 0) then
      Dec(i)
    else
      Break;
  if i > 0 then
    Result := Copy(s, 1, i);
end;
 
const
  SectionToRemove = 6;
var
  sFilename: String;
begin
  sFilename := ExtractFilePath(ParamStr(0));
  sFilename := sFilename + 'Resource_Test.exe';
  DeleteFile(PChar(sFilename + '_.exe'));
  CopyFile(PChar(sFilename), PChar(sFilename + '_.exe'), False);
  sFilename := sFilename + '_.exe';
  if not RemoveSection(sFilename, SectionToRemove) then
    MessageBox(HWND_DESKTOP, 'Die Sektion konnte nicht entfernt werden!', 'Fehler', MB_ICONERROR);
end.
Falls irgendjemand irgendwelche Fehler findet oder Verbesserungsvorschläge dann schreibt mir eine mail oder postet es hier!

Zacherl 2. Feb 2007 22:45

Re: Alle Resourcen aus fremder EXE richtig entfernen
 
Vielen Dank schonmal .. ich werd mir das schnellstmöglich mal ansehen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:54 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