麻煩大家幫忙看下,dll注入后,可自動顯示視窗,但是 鍵盤鉤子也勾上了,但是沒法呼出視窗,加了個 MessageBox(0,'直接顯示' ,'顯示',0);,會顯示。還有動態呼叫dll會提示找不到函式,靜態沒問題,函式有帶引數的,搞的有點暈
dll代碼入下
library mydll;
uses
SysUtils,
Windows,
Classes,
Forms,
myform in 'myform.pas',
var
keyhhk:HHOOK;
{$R *.res}
function keyproc(icode,wp,lp:integer):dword;stdcall;
begin
if (icode=HC_ACTION) then
begin
if (wp=VK_HOME)and ((1 shl 31)and lp=0) then
begin
if form1=nil then
begin
form1:=tform1.Create(nil);
//MessageBox(0, PChar(IntToStr(Application.Handle)), PChar('Test'), MB_OK);
MessageBox(0,'成功' ,'顯示',0);
end;
form1.Show;
MessageBox(0,'顯示' ,'顯示',0);
end;
end;
keyproc:=CallNextHookEx(keyhhk,icode,wp,lp);
end;
procedure DllEnterProc(reason:DWord); //卸載函式表單
begin
case reason of
windows.DLL_PROCESS_ATTACH:
begin
//hookdlla:=Thookdll.Create(false);
form1:=tform1.Create(nil);
form1.Show;
MessageBox(0,'進入' ,'顯示',0);
end;
windows.DLL_PROCESS_DETACH: begin form1.Free; form1:=nil; end;
end;
end;
function installKeyProcy(tid:dword):boolean;stdcall;
begin
Result:=false;
keyhhk:=setwindowshookex(WH_KEYBOARD,@Keyproc,GetModuleHandle('123.dll'),Tid);
if keyhhk>0 then Result:=true;
end;
function uninstallKeyProc():boolean;stdcall;
begin
Result:=UnhookWindowsHookEx(keyhhk);
end;
exports
installKeyProcy,
uninstallKeyProc;
begin
dllproc:=@DllEnterProc;
DllEnterProc(DLL_PROCESS_ATTACH);
end.
exe視窗用上 InjectDll(ExtractFilePath(Application.ExeName) +'123.dll',lsPid);
會運行 windows.DLL_PROCESS_ATTACH 的內容。
我再同時用上
installKeyProcy(tid) 是會鉤住程式,也會顯示 MessageBox(0,'顯示' ,'顯示',0);的內容,但是視窗不會顯示出來。我的目的是要注入后能自動能顯示視窗,并且我按鍵時也能彈出視窗,不知哪里出錯了,請大家指導下。
還有 installKeyProcy(tid)用靜態呼叫沒問題,用
hModule:=LoadLibrary(123.dll');
Pcall:=GetProcAddress(hModule, installKeyProcy);
installKeyProcy:=Pcall;
if (Pcall=nil) then
begin
self.Caption:='未成功獲取函式地址';
exit;
end;
會彈出 '未成功獲取函式地址',如果是呼叫不帶引數的卻沒有問題,這個也請大家指導下
uj5u.com熱心網友回復:
既然MessageBox(0,'顯示' ,'顯示',0)uj5u.com熱心網友回復:
樓上是說什么呢?uj5u.com熱心網友回復:
Pcall:=GetProcAddress(hModule, installKeyProcy);// 第二個引數錯了當然取不到函式地址,而且根本不能通過編譯,你是怎么編譯成功的??改:
Pcall:=GetProcAddress(hModule, 'installKeyProcy'); // 第二個引數是函式名
uj5u.com熱心網友回復:
樓上好眼力,那個是我復制下來時改錯了,程式是有加''的,要不是沒法編譯成功,問題不是出在這的,會不會 第一次 form1:=tform1.Create(nil); 創建的form1 跟 弟2次 form1.Show 不是同一個form,但是 if form1=nil then 這句判定不為空,也就是說弟2次只運行了 form1.Show,但是不會顯示出來,很糾結啊uj5u.com熱心網友回復:
給郵箱我把,給你個完整實作的例子uj5u.com熱心網友回復:
論壇真奇怪。。把我#1老長的一段話截成一句。。我想說:試試把form1.show改成form1.showmodaluj5u.com熱心網友回復:
論壇真奇怪。。把我#1老長的一段話截成一句。。我想說:試試把form1.show改成form1.showmodaluj5u.com熱心網友回復:
論壇真奇怪。。把我#1老長的一段話截成一句。。我想說:試試把form1.show改成form1.showmodaluj5u.com熱心網友回復:
function keyproc(icode, wp, lp: integer): DWORD; stdcall;
begin
if (icode = HC_ACTION) then
begin
if (wp = VK_HOME) and ((1 shl 31) and lp = 0) then
begin
if form1 = nil then
form1:= tform1.Create(nil);// 按鍵注入dll后立即創建表單
else
form1.Visible := not form1.Visible; //如果之前已經創建過那么就切換顯示狀態
end;
end;
keyproc:=CallNextHookEx(keyhhk,icode,wp,lp);
end;
uj5u.com熱心網友回復:
切換完狀態視窗要置頂:form1.bringtofrontuj5u.com熱心網友回復:
keyproc中的執行環境應當是被注入執行緒的執行環境,這樣相當于在非主執行緒操作界面,不是執行緒安全的。試試在主執行緒中創建表單,然后keyproc中用SendMessage發送一個自定義訊息給表單,表單回應訊息時Show表單,這樣就是在主執行緒操作界面了。
uj5u.com熱心網友回復:
to ls, lz看來是想做網游外掛,而又不想用寫入遠程代碼的方式,用注入宿主(游戲)行程以使用各種便利是它的目的(而且不少網游都是做過禁止寫入遠程代碼處理的)。LZ那個只不過是很簡單的邏輯問題,安小弟上面的代碼就可以解決了。uj5u.com熱心網友回復:
感謝各位的指導,sololie 的代碼跟我的是一樣的,只用 keyproc鉤子的話 如果按下 home鍵時可以運行,問題是我的目的是要,注入后就能先創建視窗,按下home也能顯示出那個視窗而不是等按下home再來運行創建視窗的代碼,把dll注入到程式我是用的是 InjectDll(ExtractFilePath(Application.ExeName) +'123.dll',lsPid); 代碼入下,function InjectDll(const DllFullPath : string;
const dwRemoteProcessId : Cardinal): boolean;
var
hRemoteProcess, hRemoteThread: THANDLE;
pszLibFileRemote : Pointer;
pszLibAFilename: PwideChar;
pfnStartAddr : TFNThreadStartRoutine;
memSize, WriteSize, lpThreadId : Cardinal;
begin
result := FALSE;
// 調整權限,使程式可以訪問其他行程的記憶體空間
if EnableDebugPriv then
begin
//打開遠程執行緒 PROCESS_ALL_ACCESS 引數表示打開所有的權限
hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId );
try
// 為注入的dll檔案路徑分配記憶體大小,由于為WideChar,故要乘2
GetMem(pszLibAFilename, Length(DllFullPath) * 2 + 1);
// 之所以要轉換成 WideChar, 是因為當DLL位于有中文字符的路徑下時不會出錯
StringToWideChar(DllFullPath, pszLibAFilename, Length(DllFullPath) * 2 + 1);
// 計算 pszLibAFilename 的長度,注意,是以位元組為單元的長度
memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
//使用VirtualAllocEx函式在遠程行程的記憶體地址空間分配DLL檔案名空間
pszLibFileRemote := VirtualAllocEx( hRemoteProcess, nil, memSize,
MEM_COMMIT, PAGE_READWRITE);
if Assigned(pszLibFileRemote) then
begin
//使用WriteProcessMemory函式將DLL的路徑名寫入到遠程行程的記憶體空間
if WriteProcessMemory(hRemoteProcess, pszLibFileRemote,
pszLibAFilename, memSize, WriteSize) and (WriteSize = memSize) then
begin
lpThreadId := 0;
// 計算LoadLibraryW的入口地址
pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'LoadLibraryW');
// 啟動遠程執行緒LoadLbraryW,通過遠程執行緒呼叫創建新的執行緒
hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0,
pfnStartAddr, pszLibFileRemote, 0, lpThreadId);
// 如果執行成功回傳 True;
if (hRemoteThread <> 0) then
result := TRUE;
// 釋放句柄
CloseHandle(hRemoteThread);
end;
end;
finally
// 釋放句柄
CloseHandle(hRemoteProcess);
end;
end;
end;
也是網上找的,可以把dll直接注入到程式里面,查詢了程式的模塊,dll已經被注入了,
這個注入后會呼叫 DllEnterProc里面的代碼,視窗也有創建了,但是當我按下home鍵時 視窗是不會顯示的,但是會彈出‘顯示’這個框框,也就是說 form1.show 有運行,但是沒效果,用上了form1.Visible := not form1.Visible也一樣,用了 728 指導的那個 showmodal 注入的程式直接卡住,是不是 DllEnterProc代碼里面創建的form1和keyproc代碼里面創建的form1不一樣呢?本人愚鈍,還請大家多多指導
uj5u.com熱心網友回復:
唉盡力了。。我只懂遠程攔截不懂遠程本地攔截。。不過我怎么都覺得在DLL用類有點不妥,我寫dll都直接用API的uj5u.com熱心網友回復:
還是那句話,既然MessageBox顯示出來了說明其他地方邏輯沒問題,有問題的地方只是類的創建那兒。。uj5u.com熱心網友回復:
類是指視窗嗎,本人基礎實在是薄弱,還有 function installKeyProcy(tid:dword):boolean;stdcall;,這個用靜態的可以,動態的就不行了
hModule:=LoadLibrary(123.dll');
Pcall:=GetProcAddress(hModule, 'installKeyProcy');
installKeyProcy:=Pcall;
if (Pcall=nil) then
begin
self.Caption:='未成功獲取函式地址';
exit;
end;
會提示 '未成功獲取函式地址',沒帶引數的函式卻是可以的,這個也是很讓人郁悶,諸多問題困擾著我,唉
uj5u.com熱心網友回復:
s11ss兄,你說的方法有個例子代碼嗎,’試試在主執行緒中創建表單,然后keyproc中用SendMessage發送一個自定義訊息給表單,表單回應訊息時Show表單,這樣就是在主執行緒操作界面了。‘,這句話我看得蒙蒙的,怎么實作呢,‘SendMessage發送一個自定義訊息給表單’這個怎么弄,’表單回應訊息時Show表單‘這個要如何實作,唉uj5u.com熱心網友回復:
type TinstallKeyProcy function(tid:dword):booleanuj5u.com熱心網友回復:
type TinstallKeyProcy function(tid:dword):boolean;stdcall;var
installKeyProcy:TinstallKeyProcy;
begin
hModule:=LoadLibrary(123.dll'); installKeyProcy:=GetProcAddress(hModule, 'installKeyProcy');
if (installKeyProcy=nil) then
begin
self.Caption:='未成功獲取函式地址';
exit;
end;
end;
這樣才行,這才是標準呼叫,還有GetProcAddress的引數名'installKeyProcy'要和DLL中命名大小寫一致。
uj5u.com熱心網友回復:
type TinstallKeyProcy= function(tid:dword):boolean;stdcall;uj5u.com熱心網友回復:
謝謝728兄,'installKeyProcy'的動態呼叫可以了,我只是依葫蘆畫瓢,呵呵。請大家幫忙看下另外一個問題,就是上面那個視窗不會顯示的問題,這個問題有點糾結uj5u.com熱心網友回復:
第一次加載DLL時 MessageBox(0,'成功' ,'顯示',0);有沒有顯示?uj5u.com熱心網友回復:
哦,對了,盡量不要使用form1這個變數,你應該在dll工程檔案中定義一個form變數取代form1。。我以前就是因為這樣出了問題。。對了,你還可以監控一下:既然form.show無法顯示,那你試試MessageBox(0,IntToStr(form.Handle),'Tips',MB_OK);顯示什么?這個方法可以查看你的視窗是否正常創建。
uj5u.com熱心網友回復:
function keyproc(icode, wp, lp: integer): DWORD; stdcall;
begin
if (icode = HC_ACTION) then
begin
if (wp = VK_HOME) and ((1 shl 31) and lp = 0) then
begin
if form1 = nil then
form1:= tform1.Create(nil);// 按鍵注入dll后立即創建表單
else
form1.Visible := not form1.Visible; //如果之前已經創建過那么就切換顯示狀態
end;
end;
keyproc:=CallNextHookEx(keyhhk,icode,wp,lp);
end;
表單執行create就已經包含能顯示了,你掛鉤后按下home鍵的同時就把創建表單和顯示表單一并完成了,
也就是說你首次按下home,dll中的表單就會顯示出來,如果已經不是第一次按下home就證明form1已經存在一個實體,你只需要改變它的Visible屬性即可,都說了這根本就是邏輯問題而已。
你都沒搞清楚你是怎么注入的,你用的是鍵盤鉤子,你不按鍵dll就根本沒有注入,你必須按鍵home了才把dll注入進去,然后才能做其他的事。
我用上面的代碼測驗把dll注入寫字板,首次按下home就能顯示表單,再按下就隱藏。
uj5u.com熱心網友回復:
“注入后就能先創建視窗,按下home也能顯示出那個視窗而不是等按下home再來運行創建視窗的代碼”那你試試在dll的入口函式中行程附加那個case中處理看看
uj5u.com熱心網友回復:
超強。。有時間發全代碼給我們學習一下吧。。
uj5u.com熱心網友回復:
給lz你個完整的示例,注入系統自帶的計算器的,按home鍵顯示dll中的表單,完全滿足本貼的需求http://pan.baidu.com/share/link?shareid=98237&uk=1124482001uj5u.com熱心網友回復:
謝謝大家的解答,sololie兄發的程式 是一個單純按鍵鉤子的程式,和我只運行installKeyProcy是一樣的效果,要等按下home鍵才回建立并顯示視窗,而我的需要時,注入后立即創建視窗,按下home鍵也能顯示視窗,而不是單純等到按下home鍵才來創建。下面這個就是入口函式,
procedure DllEnterProc(reason:DWord);
begin
case reason of
windows.DLL_PROCESS_ATTACH:
begin
//hookdlla:=Thookdll.Create(false);
form1:=tform1.Create(nil);
form1.Show;
MessageBox(0,'進入' ,'顯示',0);
end;
windows.DLL_PROCESS_DETACH: begin form1.Free; form1:=nil; end;
end;
end;
當我用 InjectDll(ExtractFilePath(Application.ExeName) +'123.dl,這個注入dll到程式時是會彈出提示的,入口函式有運行,同時我在InjectDll這句后面加了個安裝鉤子的installKeyProcy,這樣按下home才有反應,但是,按下home鍵后視窗卻沒有顯示出來,只彈出提示,如果只運行installKeyProcy而沒運行InjectDll,要等按下home時dll才會在程式里面找到,并且視窗有顯示,不會只彈出提示,我的主要問題就是,既要第一次注入后馬上創建視窗,而不是等我按下home再來創建
uj5u.com熱心網友回復:
終歸還是得在鉤子的回呼函式中做事情,你還是鉤其他的訊息吧,隨便鉤個密集的訊息模擬注入后立即創建。uj5u.com熱心網友回復:
還是不行,有誰能給我個思路或代碼嗎?uj5u.com熱心網友回復:
樓主是否解決這個問題, 我也遇到了 頭都大了uj5u.com熱心網友回復:
樓主解決沒 求方法轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/122324.html
下一篇:delphi opc 異步讀代碼
