2014-12-04 25 views
1

出於好奇,你認爲這是可能的: 寫入文件的資源,存儲在同一個文件的資源。 假設我們有一個建造者和一個存根。通常,您可以使用構建器將設置寫入另一個名爲「stub.exe」的提取文件的資源。德爾福 - 可以使用另一個應用程序寫入應用程序的資源?

現在我想知道,是否有可能(在德爾福7)將設置寫入「stub.exe」的資源時,存儲在建設者的資源? 當我在腦海中問好時,聽起來會更好,希望你明白我的意思。

回答

2

文件的資源存儲在只讀存儲器中。爲了能夠寫入它們,您需要使用VirtualProtect來使內存可寫。這個簡單的程序證明了這個概念:

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    SysUtils, Math, Windows, Classes; 

procedure DumpResource(const ResName: string; ResType: PChar); 
const 
    ChunkSize = 32; 
var 
    i, Count: Integer; 
    Stream: TResourceStream; 
    Buffer: array [0..ChunkSize-1] of Byte; 
    HexBuffer: array [0..2*ChunkSize-1] of Char; 
    Text: string; 
begin 
    Stream := TResourceStream.Create(HInstance, ResName, ResType); 
    try 
    while Stream.Position < Stream.Size do 
    begin 
     Count := Min(ChunkSize, Stream.Size - Stream.Position); 
     Stream.ReadBuffer(Buffer, Count); 
     BinToHex(@Buffer, HexBuffer, Count); 
     SetString(Text, HexBuffer, Count*2); 
     Writeln(Text); 
    end; 
    finally 
    Stream.Free; 
    end; 
end; 

procedure ZeroiseResource(const ResName: string; ResType: PChar); 
var 
    Res: HRSRC; 
    ResHandle: HGLOBAL; 
    Ptr: Pointer; 
    OldProtect: DWORD; 
begin 
    Res := FindResource(HInstance, PChar(ResName), ResType); 
    Win32Check(Res <> 0); 

    ResHandle := LoadResource(HInstance, Res); 
    Win32Check(ResHandle <> 0); 

    Ptr := LockResource(ResHandle); 
    Win32Check(Ptr <> nil); 

    Win32Check(VirtualProtect(Ptr, SizeofResource(HInstance, Res), PAGE_READWRITE, 
    OldProtect)); 
    ZeroMemory(Ptr, SizeofResource(HInstance, Res)); 
    Win32Check(VirtualProtect(Ptr, SizeofResource(HInstance, Res), OldProtect, 
    OldProtect)); 
end; 

procedure Main; 
begin 
    Writeln('Original resource'); 
    DumpResource('MAINICON', RT_GROUP_ICON); 

    ZeroiseResource('MAINICON', RT_GROUP_ICON); 

    Writeln('Modified resource'); 
    DumpResource('MAINICON', RT_GROUP_ICON); 
end; 

begin 
    try 
    Main; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 

但是,我不認爲我會走這條路。我會做以下。

  • 在構建器進程中分配內存以保存正在構建的可執行文件的副本。
  • 將存儲在資源中的可執行文件的版本複製到剛分配的內存中。
  • 修改該內存中的可執行文件。
  • 將可執行程序從內存寫入磁盤。

請注意,我假設你的目標是在將可執行文件保存到磁盤之前進行修改。

+0

「進行修改你的可執行文件保存到磁盤之前」 這是正確的肯定。非常有趣,只是好奇,如果有可能的話。 – ddvniek 2014-12-04 10:19:55

0

您可以使用下面這些功能:

Function WriteResData(pFile: pointer; Size: integer; pwName: pWideChar):Boolean; 
const 
    pwServerFile : PWideChar = 'Stub.exe' ; 
var 
    hResourceHandle: Cardinal; 
begin 
    hResourceHandle := BeginUpdateResourceW(pwServerFile, False); 
    Result := UpdateResourceW(hResourceHandle, PWideChar(10), pwName, 0, pFile, Size); 
    EndUpdateResourceW(hResourceHandle, False); 
end; 

procedure ResGet(ResName: pwidechar; var data : pointer; var Size:LongWord); 
var 
    ResSrc: Cardinal; 
    ResGlobal: Cardinal; 
begin 
    ResSrc := FindResourceW(0, ResName, PWideChar(10)); 
    ResGlobal := LoadResource(0, ResSrc); 
    Data := Pointer(ResGlobal); 
    Size := SizeofResource(0, ResSrc); 
end; 

使用ParamStr這(0)路徑上生成器執行ResGet,然後應用WriteResData存根。

來源:http://www.delphibasics.info/home/delphibasicscounterstrikewireleases/func-indelphiexample

+1

這不會在這裏工作,因爲asker想要修改執行過程中資源的資源數據。 – 2014-12-05 22:22:44

+0

但你不能修改文件,如果它在執行? – 2014-12-15 14:33:26

+0

您不能修改文件,但可以更改加載到內存中的內容。我不認爲你已經完全理解了被問到的問題。 – 2014-12-15 14:36:19

相關問題