Удаление Debug information

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор : Jordan Russell

Оформил: RT17

Статья посвящена тому, что как заставить Delphi — вские, программы стать действительно Release а не Debug.

Вот код который вычистит EXE — ник от Debug Information.

program StripReloc;

{$APPTYPE CONSOLE}

{

StripReloc v1.12

Strip relocation section from Win32 PE files

Copyright (C) 1999-2004 Jordan Russell. All rights reserved.

http://www.jrsoftware.org/

This program is free software; you can redistribute it and/or

modify it under the terms of the GNU General Public License

as published by the Free Software Foundation; either version 2

of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software

Foundation, Inc., 59 Temple Place — Suite 330, Boston, MA 02111-1307, USA.

$jrsoftware: stripreloc/StripReloc.dpr,v 1.12 2004/02/24 06:40:04 jr Exp $

}

uses

Windows, SysUtils, Classes;

{x$R *.RES}

const

Version = ‘1.12’;

var

KeepBackups: Boolean = True;

WantValidChecksum: Boolean = False;

ForceStrip: Boolean = False;

ImageHlpHandle: THandle;

CheckSumMappedFile: function(BaseAddress: Pointer; FileLength: DWORD;

HeaderSum: PDWORD; CheckSum: PDWORD): PImageNtHeaders; stdcall;

function CalcChecksum(const FileHandle: THandle): DWORD;

var

H: THandle;

M: Pointer;

OldSum: DWORD;

begin

M := nil;

H := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);

if H = 0 then

RaiseLastWin32Error;

try

M := MapViewOfFile(H, FILE_MAP_READ, 0, 0, 0);

Win32Check(CheckSumMappedFile(M, GetFileSize(FileHandle, nil), @OldSum, @Result) nil);

finally

if Assigned(M) then

UnmapViewOfFile(M);

CloseHandle(H);

end;

end;

procedure Strip(const Filename: String);

type

PPESectionHeaderArray = ^TPESectionHeaderArray;

TPESectionHeaderArray = array[0..$7FFFFFFF div SizeOf(TImageSectionHeader)-1] of TImageSectionHeader;

var

BackupFilename: String;

F, F2: File;

EXESig: Word;

PEHeaderOffset, PESig: Cardinal;

PEHeader: TImageFileHeader;

PEOptHeader: ^TImageOptionalHeader;

PESectionHeaders: PPESectionHeaderArray;

BytesLeft, Bytes: Cardinal;

Buf: array[0..8191] of Byte;

I: Integer;

RelocVirtualAddr, RelocPhysOffset, RelocPhysSize: Cardinal;

OldSize, NewSize: Cardinal;

TimeStamp: TFileTime;

begin

PEOptHeader := nil;

PESectionHeaders := nil;

try

RelocPhysOffset := 0;

RelocPhysSize := 0;

BackupFilename := Filename ‘.bak’;

Write(Filename, ‘: ‘);

AssignFile(F, Filename);

FileMode := fmOpenRead or fmShareDenyWrite;

Reset(F, 1);

try

OldSize := FileSize(F);

GetFileTime(TFileRec(F).Handle, nil, nil, @TimeStamp);

BlockRead(F, EXESig, SizeOf(EXESig));

if EXESig $5A4D {‘MZ’} then begin

Writeln(‘File isn»t an EXE file (1).’);

Exit;

end;

Seek(F, $3C);

BlockRead(F, PEHeaderOffset, SizeOf(PEHeaderOffset));

if PEHeaderOffset = 0 then begin

Writeln(‘File isn»t a PE file (1).’);

Exit;

end;

Seek(F, PEHeaderOffset);

BlockRead(F, PESig, SizeOf(PESig));

if PESig $00004550 {‘PE’#0#0} then begin

Writeln(‘File isn»t a PE file (2).’);

Exit;

end;

BlockRead(F, PEHeader, SizeOf(PEHeader));

if not ForceStrip and (PEHeader.Characteristics and IMAGE_FILE_DLL 0) then begin

Writeln(‘Skipping; can»t strip a DLL.’);

Exit;

end;

if PEHeader.Characteristics and IMAGE_FILE_RELOCS_STRIPPED 0 then begin

Writeln(‘Relocations already stripped from file (1).’);

Exit;

end;

PEHeader.Characteristics := PEHeader.Characteristics or IMAGE_FILE_RELOCS_STRIPPED;

GetMem(PEOptHeader, PEHeader.SizeOfOptionalHeader);

BlockRead(F, PEOptHeader^, PEHeader.SizeOfOptionalHeader);

if (PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0) or

(PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0) then begin

Writeln(‘Relocations already stripped from file (2).’);

Exit;

end;

RelocVirtualAddr := PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;

PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress := 0;

PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size := 0;

if not WantValidChecksum then

PEOptHeader.CheckSum := 0;

GetMem(PESectionHeaders, PEHeader.NumberOfSections * SizeOf(TImageSectionHeader));

BlockRead(F, PESectionHeaders^, PEHeader.NumberOfSections * SizeOf(TImageSectionHeader));

for I := 0 to PEHeader.NumberOfSections-1 do

with PESectionHeaders[I] do

if (VirtualAddress = RelocVirtualAddr) and (SizeOfRawData 0) then begin

RelocPhysOffset := PointerToRawData;

RelocPhysSize := SizeOfRawData;

SizeOfRawData := 0;

Break;

end;

if RelocPhysOffset = 0 then begin

Writeln(‘Relocations already stripped from file (3).’);

Exit;

end;

if RelocPhysSize = 0 then begin

Writeln(‘Relocations already stripped from file (4).’);

Exit;

end;

for I := 0 to PEHeader.NumberOfSections-1 do

with PESectionHeaders[I] do begin

if PointerToRawData > RelocPhysOffset then

Dec(PointerToRawData, RelocPhysSize);

if PointerToLinenumbers > RelocPhysOffset then

Dec(PointerToLinenumbers, RelocPhysSize);

if PointerToRelocations 0 then begin

{ ^ I don’t think this field is ever used in the PE format.

StripRlc doesn’t handle it. }

Writeln(‘Cannot handle this file (1).’);

Exit;

end;

end;

if PEOptHeader.ImageBase < $400000 then begin

Writeln(‘Cannot handle this file — the image base address is less than 0x400000.’);

Exit;

end;

finally

CloseFile(F);

end;

if FileExists(BackupFilename) then

Win32Check(DeleteFile(BackupFilename));

Rename(F, BackupFilename);

try

FileMode := fmOpenRead or fmShareDenyWrite;

Reset(F, 1);

try

AssignFile(F2, Filename);

FileMode := fmOpenWrite or fmShareExclusive;

Rewrite(F2, 1);

try

BytesLeft := RelocPhysOffset;

while BytesLeft 0 do begin

Bytes := BytesLeft;

if Bytes > SizeOf(Buf) then Bytes := SizeOf(Buf);

BlockRead(F, Buf, Bytes);

BlockWrite(F2, Buf, Bytes);

Dec(BytesLeft, Bytes);

end;

Seek(F, Cardinal(FilePos(F)) RelocPhysSize);

BytesLeft := FileSize(F) — FilePos(F);

while BytesLeft 0 do begin

Bytes := BytesLeft;

if Bytes > SizeOf(Buf) then Bytes := SizeOf(Buf);

BlockRead(F, Buf, Bytes);

BlockWrite(F2, Buf, Bytes);

Dec(BytesLeft, Bytes);

end;

Seek(F2, PEHeaderOffset SizeOf(PESig));

BlockWrite(F2, PEHeader, SizeOf(PEHeader));

BlockWrite(F2, PEOptHeader^, PEHeader.SizeOfOptionalHeader);

BlockWrite(F2, PESectionHeaders^, PEHeader.NumberOfSections * SizeOf(TImageSectionHeader));

if WantValidChecksum then begin

PEOptHeader.CheckSum := CalcChecksum(TFileRec(F2).Handle);

{ go back and rewrite opt. header with new checksum }

Seek(F2, PEHeaderOffset SizeOf(PESig) SizeOf(PEHeader));

BlockWrite(F2, PEOptHeader^, PEHeader.SizeOfOptionalHeader);

end;

NewSize := FileSize(F2);

SetFileTime(TFileRec(F2).Handle, nil, nil, @TimeStamp);

finally

CloseFile(F2);

end;

finally

CloseFile(F);

end;

except

DeleteFile(Filename);

AssignFile(F, BackupFilename);

Rename(F, Filename);

raise;

end;

Writeln(OldSize, ‘ -> ‘, NewSize, ‘ bytes (‘,

OldSize — NewSize, ‘ difference)’);

if not KeepBackups then

if not DeleteFile(BackupFilename) then

Writeln(‘Warning: Couldn»t delete backup file ‘, BackupFilename);

finally

FreeMem(PESectionHeaders);

FreeMem(PEOptHeader);

end;

end;

var

SR: TSearchRec;

S: String;

FilesList: TStringList;

P, I: Integer;

HasFileParameter: Boolean = False;

NumFiles: Integer = 0;

label 1;

begin

try

Writeln(‘StripReloc v’ Version ‘, Copyright (C) 1999-2004 Jordan Russell, www.jrsoftware.org’);

if ParamCount = 0 then begin

Writeln(‘Strip relocation section from Win32 PE files’);

Writeln;

1:Writeln(‘usage: stripreloc [switches] filename.exe’);

Writeln;

Writeln(‘switches: /B don»t create .bak backup files’);

Writeln(‘ /C write a valid checksum in the header (instead of zero)’);

Writeln(‘ /F force stripping DLLs instead of skipping them. do not use!’);

Halt(1);

end;

Writeln;

for P := 1 to ParamCount do begin

S := ParamStr(P);

if S[1] ‘/’ then

Continue;

Delete(S, 1, 1);

I := 1;

while I <= Length(S) do begin

case UpCase(S[I]) of

‘?’: goto 1;

‘B’: begin

KeepBackups := False;

if I < Length(S) then begin

{ For backward compatibility, do keep backups if the character

following ‘B’ is a ‘ ‘. }

if S[I 1] = ‘ ‘ then begin

KeepBackups := True;

Inc(I);

end

else if S[I 1] = ‘-‘ then

Inc(I);

end;

end;

‘C’: begin

ImageHlpHandle := LoadLibrary(‘imagehlp.dll’);

if ImageHlpHandle = 0 then begin

Writeln(‘Error: Unable to load imagehlp.dll.’);

Writeln(‘ It is required when using the /C parameter.’);

Halt(1);

end;

CheckSumMappedFile := GetProcAddress(ImageHlpHandle, ‘CheckSumMappedFile’);

if @CheckSumMappedFile = nil then begin

Writeln(‘Error: Unable to get address of CheckSumMappedFile in imagehlp.dll.’);

Writeln(‘ It is required when using the /C parameter.’);

Halt(1);

end;

WantValidChecksum := True;

end;

‘F’: ForceStrip := True;

else

Writeln(‘Invalid parameter: /’, S[I]);

Halt(1);

end;

Inc(I);

end;

end;

for P := 1 to ParamCount do begin

S := ParamStr(P);

if S[1] = ‘/’ then

Continue;

HasFileParameter := True;

FilesList := TStringList.Create;

try

FilesList.Sorted := True;

if FindFirst(S, 0, SR) 0 then begin

Writeln(‘No files matching «‘, S, ‘» found.’);

Continue;

end;

try

repeat

if CompareText(ExtractFileExt(SR.Name), ‘.bak’) 0 then

FilesList.Add(ExtractFilePath(S) SR.Name);

until FindNext(SR) 0;

finally

FindClose(SR);

end;

for I := 0 to FilesList.Count-1 do

Strip(FilesList[I]);

Inc(NumFiles);

finally

FilesList.Free;

end;

end;

if not HasFileParameter then

goto 1;

if NumFiles = 0 then

Halt(2);

except

on E: Exception do begin

Writeln(‘Fatal error: ‘, E.Message);

Halt(3);

end;

end;

end.

{/codecitation}

Добавить комментарий