線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4487
推到 Plurk!
推到 Facebook!

TMemoryStream 如何執行 exe

答題得分者是:hagar
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-08-11 00:48:17 IP:118.169.xxx.xxx 未訂閱
請問各位!

如果我建立一個 TMemoryStream , 同時 LoadFormFile(Exefile) 之後,
要如何在 TMemoryStream中執行這支 exefile, 而不是在硬碟中run exe

我的系統是Delphi5, 查了兩天google, yahoo, 有找到一篇討論 MemoryStream 執行 exe,
但卻是要我刷信用卡才可以看到, 有點給他怕怕!
HikaruGo
中階會員


發表:22
回覆:69
積分:88
註冊:2007-12-09

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-08-11 17:24:32 IP:111.254.xxx.xxx 訂閱
可以說明一下為什麼要這樣做嗎?
運用領域?

編輯記錄
HikaruGo 重新編輯於 2010-08-11 17:45:05, 註解 無‧
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-08-11 18:27:28 IP:118.169.xxx.xxx 未訂閱
為了執行一些程式(如安裝, 註冊..但非駭客), 但不想user或公司執行人員可以取得該支exe檔
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2010-08-11 21:17:42 IP:111.249.xxx.xxx 未訂閱
這篇好像有提到這樣的作法,不知道是不是PD大所要的?

如何把一个EXE文件存入数据,并把它取出来执行它?

===================引 用 P.D. 文 章===================
為了執行一些程式(如安裝, 註冊..但非駭客), 但不想user或公司執行人員可以取得該支exe檔
carstyc
資深會員


發表:16
回覆:254
積分:329
註冊:2003-07-18

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-08-11 21:51:41 IP:219.84.xxx.xxx 訂閱
PD大大...

用TMemoryStream LoadFormFile(Exefile) ,那就表示執行時期必需要有那支 exe ,這樣不是也有機會被執行人員取得exe。

可以考慮把另一個exe 存在resource file 裡面,程式再去取出來執行,執行完就粑它刪掉。

http://delphi.ktop.com.tw/board.php?cid=30&fid=69&tid=98415 可以參考一下這篇,存入取出的作法都有了...


===================引 用 P.D. 文 章===================
為了執行一些程式(如安裝, 註冊..但非駭客), 但不想user或公司執行人員可以取得該支exe檔
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-08-11 22:29:36 IP:118.169.xxx.xxx 未訂閱
感謝兩位回覆, 但我並不是想知道如何把 檔案 加到 exe, 再用 resource 取出, 這方面的技術資料討論的非常多, 而且實作上也沒有問題
我現在的需求, 其實我已經把 exe1 包在 install.exe 中, 也能夠取出 exe1, 但唯獨的是, 我必須執行 exe1 執行
不是用 winexec, 就是 ShellExecute, 這都是要在 硬碟中存在 exe1 的程式, 在本站的討論區中之前也有人發過
如何在 TMemoryStream 中執行 html 的方式, 其實是一樣的想法
因為我從 resorce 中取出 exe1 後, 並不想放在硬碟上再執行, 這會有漏洞,
例如, 萬一系統當機, 使用者中途強制中斷程式等等問題, 即使我的 intall.exe 中有設定
winexec(exe1), 最後下Deletefile(exe1), 但上述的情況都會導致 exe1 無法被正常執行刪除, 而被保留
所以最好的方式是由 resorce 取出 exe1 後, 直接載入 TMemoryStream, 然後直接啟動 exe1,
但如果不行的, 可以透過 MmeoryStream.LoadformFile(exe1)之後, 立即刪除 exe1, 再到Memory中執行exe1
這樣會比存到硬碟再以winexec()執行與刪除來的更安全
而我查遍了網路的資源(我花了四天, 看了至少上萬篇), 有一篇提到有這個技術, 但要刷卡付費才能看到
討論內容, 並非不願意付費, 而是這個網站在國外, 也不清楚狀況就直接刷卡, 我曾有切身之痛, 所以不敢做!
另外, 也找到幾篇有提供 Dll 載入到 TMemoryStream中, 然後執行的, 但實作不是出現 Access Error, 就是必須
在Delphi7以上版本運作, 可惜我的是Delphi5版本!

===================引 用 GrandRURU 文 章===================
這篇好像有提到這樣的作法,不知道是不是PD大所要的?

如何把一个EXE文件存入数据,并把它取出来执行它?

===================引 用 P.D. 文 章===================
為了執行一些程式(如安裝, 註冊..但非駭客), 但不想user或公司執行人員可以取得該支exe檔
gerojeng
一般會員


發表:23
回覆:25
積分:9
註冊:2004-06-19

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-08-12 00:15:52 IP:219.71.xxx.xxx 訂閱
直接買 Themida 商業版的加殼工具,有個 XBundle 可以解決這個問題
缺點是,用T殼加密的東西很容易被誤判病毒,因為太多木馬用這個殼加密了,這是目前最強的殼吧
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-08-12 08:28:08 IP:203.75.xxx.xxx 未訂閱
那麼……興德還有在賣D7版權…怎麼不考慮買一份呢?

===================引 用 P.D. 文 章===================
...43...
在Delphi7以上版本運作, 可惜我的是Delphi5版本!
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#9 引用回覆 回覆 發表時間:2010-08-12 11:04:42 IP:118.169.xxx.xxx 未訂閱
唉! 並非是買版權的問題, 而是Delphi5到升到Delphi7, 之前用了不少3'rd元件, 不容易上去, 而且手上不是只有開發這支程式, 我開發的客戶至少有二十支不同的領域, 換上其他版本都會造成很大的困擾及成本!
===================引 用 GrandRURU 文 章===================
那麼……興德還有在賣D7版權…怎麼不考慮買一份呢?

===================引 用 P.D. 文 章===================
...43...
在Delphi7以上版本運作, 可惜我的是Delphi5版本!
hagar
版主


發表:143
回覆:4056
積分:4445
註冊:2002-04-14

發送簡訊給我
#10 引用回覆 回覆 發表時間:2010-08-12 11:43:01 IP:210.242.xxx.xxx 未訂閱
參考這篇試試: http://www.delphipages.com/forum/showthread.php?t=202067

unit Unit1;
interface
{$IMAGEBASE $10000000}
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
type
TSections = array [0..0] of TImageSectionHeader;

function GetAlignedSize(Size: dword; Alignment: dword): dword;
begin
if ((Size mod Alignment) = 0) then
Result := Size
else
Result := ((Size div Alignment) 1) * Alignment;
end;
function ImageSize(Image: pointer): dword;
var
Alignment: dword;
ImageNtHeaders: PImageNtHeaders;
PSections: ^TSections;
SectionLoop: dword;
begin
ImageNtHeaders := pointer(dword(dword(Image)) dword(PImageDosHeader(Image)._lfanew));
Alignment := ImageNtHeaders.OptionalHeader.SectionAlignment;
if ((ImageNtHeaders.OptionalHeader.SizeOfHeaders mod Alignment) = 0) then
begin
Result := ImageNtHeaders.OptionalHeader.SizeOfHeaders;
end
else
begin
Result := ((ImageNtHeaders.OptionalHeader.SizeOfHeaders div Alignment) 1) * Alignment;
end;
PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
begin
if PSections[SectionLoop].Misc.VirtualSize <> 0 then
begin
if ((PSections[SectionLoop].Misc.VirtualSize mod Alignment) = 0) then
begin
Result := Result PSections[SectionLoop].Misc.VirtualSize;
end
else
begin
Result := Result (((PSections[SectionLoop].Misc.VirtualSize div Alignment) 1) * Alignment);
end;
end;
end;
end;
procedure CreateProcessEx(FileMemory: pointer);
var
BaseAddress, Bytes, HeaderSize, InjectSize, SectionLoop, SectionSize: dword;
Context: TContext;
FileData: pointer;
ImageNtHeaders: PImageNtHeaders;
InjectMemory: pointer;
ProcInfo: TProcessInformation;
PSections: ^TSections;
StartInfo: TStartupInfo;
begin
ImageNtHeaders := pointer(dword(dword(FileMemory)) dword(PImageDosHeader(FileMemory)._lfanew));
InjectSize := ImageSize(FileMemory);
GetMem(InjectMemory, InjectSize);
try
FileData := InjectMemory;
HeaderSize := ImageNtHeaders.OptionalHeader.SizeOfHeaders;
PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
begin
if PSections[SectionLoop].PointerToRawData < HeaderSize then HeaderSize := PSections[SectionLoop].PointerToRawData;<br /> end;
CopyMemory(FileData, FileMemory, HeaderSize);
FileData := pointer(dword(FileData) GetAlignedSize(ImageNtHeaders.OptionalHeader.SizeOfHeaders, ImageNtHeaders.OptionalHeader.SectionAlignment));
for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
begin
if PSections[SectionLoop].SizeOfRawData > 0 then
begin
SectionSize := PSections[SectionLoop].SizeOfRawData;
if SectionSize > PSections[SectionLoop].Misc.VirtualSize then
SectionSize := PSections[SectionLoop].Misc.VirtualSize;
CopyMemory(FileData, pointer(dword(FileMemory) PSections[SectionLoop].PointerToRawData), SectionSize);
FileData := pointer(dword(FileData) GetAlignedSize(PSections[SectionLoop].Misc.VirtualSize, ImageNtHeaders.OptionalHeader.SectionAlignment));
end
else
begin
if PSections[SectionLoop].Misc.VirtualSize <> 0 then FileData := pointer(dword(FileData) GetAlignedSize(PSections[SectionLoop].Misc.VirtualSize, ImageNtHeaders.OptionalHeader.SectionAlignment));
end;
end;
ZeroMemory(@StartInfo, SizeOf(StartupInfo));
ZeroMemory(@Context, SizeOf(TContext));
CreateProcess(nil, pchar(ParamStr(0)), nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo);
Context.ContextFlags := CONTEXT_FULL;
GetThreadContext(ProcInfo.hThread, Context);
ReadProcessMemory(ProcInfo.hProcess, pointer(Context.Ebx 8), @BaseAddress, 4, Bytes);
VirtualAllocEx(ProcInfo.hProcess, pointer(ImageNtHeaders.OptionalHeader.ImageBase), InjectSize, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(ProcInfo.hProcess, pointer(ImageNtHeaders.OptionalHeader.ImageBase), InjectMemory, InjectSize, Bytes);
WriteProcessMemory(ProcInfo.hProcess, pointer(Context.Ebx 8), @ImageNtHeaders.OptionalHeader.ImageBase, 4, Bytes);
Context.Eax := ImageNtHeaders.OptionalHeader.ImageBase ImageNtHeaders.OptionalHeader.AddressOfEntryPoint;
SetThreadContext(ProcInfo.hThread, Context);
ResumeThread(ProcInfo.hThread);
finally
FreeMemory(InjectMemory);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
MyStream: TMemoryStream;
begin
MyStream := TMemoryStream.Create;
try
MyStream.LoadFromFile('C:\windows\system32\wordpad.exe');
//MyStream.LoadFromStream(yourstream);
CreateProcessEx(MyStream.Memory);
finally
MyStream.Free;
end;
end;
end.

P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#11 引用回覆 回覆 發表時間:2010-08-12 17:43:37 IP:118.169.xxx.xxx 未訂閱
再度感謝hager兄提供資訊, 接二連三都麻煩hager兄真是不好意思!

另外, 請教一下, 有關 {$IMAGEBASE $10000000}
是否固定都要為這個值,
這個設定主要的目的與 exe 程式的載入大小有關嗎?
hagar
版主


發表:143
回覆:4056
積分:4445
註冊:2002-04-14

發送簡訊給我
#12 引用回覆 回覆 發表時間:2010-08-13 10:12:49 IP:210.242.xxx.xxx 未訂閱
客氣了! 剛好有找到這篇連結..

老實說, IMAGEBASE 這個詞在這一題之前小弟是完全沒聽過. 所以它是怎麼作用的, 小弟完全不了解..
ddy
站務副站長


發表:262
回覆:2105
積分:1169
註冊:2002-07-13

發送簡訊給我
#13 引用回覆 回覆 發表時間:2010-09-07 09:37:08 IP:122.147.xxx.xxx 訂閱
看到這篇覺得挺有意思的
ImageBase 指的是載入PE的位址
一般EXE載入位址是0x10000000,DLL為0x04000000... 此值在程式編譯後連結的時候可以透過連結參數更改

所以沒有一定要0x10000000, 與exe載入大小無關~
===================引 用 P.D. 文 章===================
再度感謝hager兄提供資訊, 接二連三都麻煩hager兄真是不好意思!

另外, 請教一下, 有關 {$IMAGEBASE $10000000}
是否固定都要為這個值,
這個設定主要的目的與 exe 程式的載入大小有關嗎?
hagar
版主


發表:143
回覆:4056
積分:4445
註冊:2002-04-14

發送簡訊給我
#14 引用回覆 回覆 發表時間:2010-09-08 07:26:12 IP:61.218.xxx.xxx 未訂閱
好久不見! 感謝 ddy 的釋疑!
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#15 引用回覆 回覆 發表時間:2010-09-08 11:15:31 IP:210.64.xxx.xxx 訂閱
很好的一篇進階文章!  有趣 ! 頂一下。

稍微看了一下,註解一下: 它大致上是採用「以己身的exe檔來請windows創出另一個process的空間」,這很妙,就是先搞個分身。

然後再去寫該分身的記憶體,包含修正裡面的PE內容,最後有寫入寄生的exe檔的內容(比如例子中的wordpad)。

然後再把分身process的thread從suspend轉resume,正式開跑…

ps 我的註解也許會有錯誤,因為我花了幾分大致看了一下。想說若有一天有需要,再仔細看,所以有錯也請指正 :-)

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2010-09-08 11:19:11, 註解 無‧
dd_zhouqian
一般會員


發表:0
回覆:1
積分:0
註冊:2010-11-26

發送簡訊給我
#16 引用回覆 回覆 發表時間:2010-11-26 12:21:53 IP:218.94.xxx.xxx 訂閱
不错的帖子,收藏了
系統時間:2024-11-23 11:37:15
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!