麻烦大家帮忙看下,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;exportsinstallKeyProcy,
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;
会弹出 '未成功获取函数地址',如果是调用不带参数的却没有问题,这个也请大家指导下
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;exportsinstallKeyProcy,
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;
会弹出 '未成功获取函数地址',如果是调用不带参数的却没有问题,这个也请大家指导下
Pcall:=GetProcAddress(hModule, 'installKeyProcy'); // 第二个参数是函数名
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;
试试在主线程中创建窗体,然后keyproc中用SendMessage发送一个自定义消息给窗体,窗体响应消息时Show窗体,这样就是在主线程操作界面了。
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不一样呢?本人愚钝,还请大家多多指导
,这个用静态的可以,动态的就不行了
hModule:=LoadLibrary(123.dll');
Pcall:=GetProcAddress(hModule, 'installKeyProcy');
installKeyProcy:=Pcall;
if (Pcall=nil) then
begin
self.Caption:='未成功获取函数地址';
exit;
end;
会提示 '未成功获取函数地址',没带参数的函数却是可以的,这个也是很让人郁闷,诸多问题困扰着我,唉
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中命名大小写一致。
对了,你还可以监控一下:既然form.show无法显示,那你试试MessageBox(0,IntToStr(form.Handle),'Tips',MB_OK);显示什么?这个方法可以查看你的窗口是否正常创建。
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就能显示窗体,再按下就隐藏。
那你试试在dll的入口函数中进程附加那个case中处理看看
下面这个就是入口函数,
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再来创建