Delphi 将项目添加到其他应用程序的最佳方式';什么是模态窗口?
向其他应用程序的模式窗口添加项目的最佳方式是什么 我为此编写的一个简单示例(作为概念证明)使用了一种方法,我怀疑对于一个微不足道的后台进程来说,这种方法占用了太多太多的处理器,但我很难找到替代方法 例如,假设您是一名医生,在模式窗口中填写处方数据。你输入它30天,11次再填充,然后患者说他们想要90天,3次再填充。原始应用程序(您没有访问源代码的权限)不容易转换。我编写了一个小实用程序,它监视这个特定的窗口(使用计时器和findwindow),当它找到它时,使自己可见,并将自己放置在目标模式窗口的一个空白位置。当按下“30”按钮时,Rx将被写入30天,并有11次重新填充,当按下“90”按钮时,它将执行您预期的操作。如果模式窗口移动,则30和90按钮将随之移动。虽然这是可行的,但我担心在计时器上反复运行findwindow所涉及的开销 1) 有更好的办法吗? 2) 我担心这件事对吗? 3) 你是不是在嘲笑我的克鲁格有多低效Delphi 将项目添加到其他应用程序的最佳方式';什么是模态窗口?,delphi,timer,modal-dialog,findwindow,sticky-windows,Delphi,Timer,Modal Dialog,Findwindow,Sticky Windows,向其他应用程序的模式窗口添加项目的最佳方式是什么 我为此编写的一个简单示例(作为概念证明)使用了一种方法,我怀疑对于一个微不足道的后台进程来说,这种方法占用了太多太多的处理器,但我很难找到替代方法 例如,假设您是一名医生,在模式窗口中填写处方数据。你输入它30天,11次再填充,然后患者说他们想要90天,3次再填充。原始应用程序(您没有访问源代码的权限)不容易转换。我编写了一个小实用程序,它监视这个特定的窗口(使用计时器和findwindow),当它找到它时,使自己可见,并将自己放置在目标模式窗口
提前谢谢-这里的人给我留下了深刻的印象 最好的方法是。。。DLL注入
// The DLL:
library dll_inj;
uses
ShareMem,
System.SysUtils,
System.Classes, Vcl.Dialogs,
windows, messages;
{$R *.res}
var
hWndMain, hDemoButton, hEdit, hNewButton, hWndEnter: THandle;
OldWndProc: TFarProc;
hBtnFont: hFont;
Times: integer;
dwThreadId: DWORD;
function NewWndProc(hWnd: hWnd; Msg: UINT; wParam: wParam; lParam: lParam)
: Longint; stdcall;
begin
if Times = 0 then
begin
Times := Times + 1;
hWndMain := FindWindowEx(0, 0, 'TForm1', 'Injection test');
if hWndMain = 0 then
OutputDebugString('hWndMain is 0!');
hNewButton := CreateWindow('button', 'NewBtn', WS_CHILD or WS_VISIBLE, 20,
20, 100, 24, hWndMain, 2000, GetWindowLong(hWndMain, GWL_HINSTANCE), nil);
if hNewButton = 0 then
OutputDebugString('CreateWindow failed!')
else
begin
hWndEnter := FindWindowEx(hWndMain, 0, 'TBitBtn', 'Enter');
if hWndEnter <> 0 then
hBtnFont := SendMessage(hWndEnter, WM_GETFONT, 0, 0);
if hBtnFont <> 0 then
SendMessage(hNewButton, WM_SETFONT, hBtnFont, 1);
end;
hDemoButton := FindWindowEx(hWndMain, 0, 'TButton', 'Demo');
if hDemoButton <> 0 then
begin
if not EnableWindow(hDemoButton, true) then
OutputDebugString('EnableWindow failed!');
end
else
OutputDebugString('hDemoButton is 0!');
hEdit := FindWindowEx(hWndMain, 0, 'TEdit', 'Serial');
if hEdit = 0 then
OutputDebugString('hEdit is 0!')
else if not SetWindowText(hEdit, 'You have been hacked') then
OutputDebugString('SetWindowText failed!');
end;
case Msg of
WM_COMMAND:
if (hNewButton <> 0) and (DWORD(lParam) = hNewButton) then
MessageBox(HWND_DESKTOP, 'You pressed a new button!', 'Yay!', MB_OK)
else if (hWndEnter <> 0) and (DWORD(lParam) = hWndEnter) then
begin
MessageBox(HWND_DESKTOP, 'This message is not default anymore!',
'Override!', MB_OK);
Exit(0); // Suppress default event completely
end;
end;
Result := CallWindowProc(OldWndProc, hWnd, Msg, wParam, lParam);
end;
procedure EntryPoint(Reason: integer);
begin
hWndMain := FindWindowEx(0, 0, 'TForm1', 'Injection test');
if hWndMain = 0 then
begin
OutputDebugString('hWndMain is 0!');
Exit;
end;
OldWndProc := TFarProc(SetWindowLong(hWndMain, GWL_WNDPROC,
LONG(@NewWndProc)));
MessageBox(0, 'DLL Injected', 'OK', 0);
end;
begin
CreateThread(nil, 0, @EntryPoint, nil, 0, &dwThreadId);
end.
// The injector:
program exe_inj2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, windows, TLHelp32;
Function EnumThreadProc(wnd: HWND; Var appHwnd: HWND): LongBool; stdcall;
Var
buf: array [0 .. 256] of Char;
Begin
Result := LongBool(1);
if GetClassname(wnd, buf, sizeof(buf)) > 0 then
If StrComp(buf, 'TApplication') = 0 Then
Begin
appHwnd := wnd;
Result := False;
End;
End;
Function FindApplicationWindow(forThreadID: DWORD): HWND;
Begin
Result := 0;
EnumThreadWindows(forThreadID, @EnumThreadProc, lparam(@Result));
End;
Function ProcessIDFromAppname32(appname: String): DWORD;
{ Take only the application filename, not full path! }
Var
snapshot: THandle;
processEntry: TProcessEntry32;
Begin
Result := 0;
appname := UpperCase(appname);
snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
If snapshot <> 0 Then
try
processEntry.dwSize := sizeof(processEntry);
If Process32First(snapshot, processEntry) Then
Repeat
If Pos(appname,
UpperCase(ExtractFilename(StrPas(processEntry.szExeFile)))) > 0 Then
Begin
Result := processEntry.th32ProcessID;
Break;
End; { If }
Until not Process32Next(snapshot, processEntry);
finally
CloseHandle(snapshot);
End; { try }
End;
function InjectDLL(dwPID: DWORD; DLLPath: PWideChar): integer;
var
dwThreadID: Cardinal;
hProc, hThread, hKernel: THandle;
BytesToWrite, BytesWritten: SIZE_T;
pRemoteBuffer, pLoadLibrary: Pointer;
begin
if not FileExists(DLLPath) then
begin
MessageBox(0, PWideChar('File ' + DLLPath + ' does not exist'), 'Error', 0);
Exit(0);
end;
hProc := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or
PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ, False, dwPID);
if hProc = 0 then
Exit(0);
try
BytesToWrite := sizeof(WideChar) * (Length(DLLPath) + 1);
pRemoteBuffer := VirtualAllocEx(hProc, nil, BytesToWrite, MEM_COMMIT,
PAGE_READWRITE);
if pRemoteBuffer = nil then
Exit(0);
try
if not WriteProcessMemory(hProc, pRemoteBuffer, DLLPath, BytesToWrite,
BytesWritten) then
Exit(0);
hKernel := GetModuleHandle('kernel32.dll');
pLoadLibrary := GetProcAddress(hKernel, 'LoadLibraryW');
hThread := CreateRemoteThread(hProc, nil, 0, pLoadLibrary, pRemoteBuffer,
0, dwThreadID);
try
WaitForSingleObject(hThread, INFINITE);
finally
CloseHandle(hThread);
end;
finally
VirtualFreeEx(hProc, pRemoteBuffer, 0, MEM_RELEASE);
end;
finally
CloseHandle(hProc);
end;
Exit(1);
end;
const
PROCESS_NAME = 'Default_project.exe';
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
WriteLn(PROCESS_NAME + ' PID: ' +
IntToSTr(ProcessIDFromAppname32(PROCESS_NAME)));
InjectDLL(ProcessIDFromAppname32(PROCESS_NAME), 'dll_inj.dll');
ReadLn;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.
//DLL:
图书馆动态链接库;
使用
ShareMem,
System.SysUtils,
系统类,Vcl对话框,
窗口、消息;
{$R*.res}
变量
hWndMain、hDemoButton、hEdit、hNewButton、hWndEnter:THandle;
OldWndProc:TFarProc;
hBtnFont:hFont;
次数:整数;
dwid:DWORD;
函数NewWndProc(hWnd:hWnd;Msg:UINT;wParam:wParam;lParam:lParam)
:Longint;stdcall;
开始
如果时间=0,则
开始
次数:=次+1;
hWndMain:=FindWindowEx(0,0,'TForm1','Injection test');
如果hWndMain=0,则
OutputDebugString('hWndMain为0!');
hNewButton:=CreateWindow('button','NewBtn',WS_CHILD或WS_VISIBLE,20,
20,100,24,hWndMain,2000,GetWindowLong(hWndMain,GWL_HINSTANCE),无;
如果HNEWBUTON=0,则
OutputDebugString('CreateWindow失败!')
其他的
开始
hWndEnter:=FindWindowEx(hWndMain,0,'TBitBtn','Enter');
如果Hwdender为0,则
hBtnFont:=发送消息(hwdender,WM_GETFONT,0,0);
如果hBtnFont为0,则
SendMessage(hNewButton、WM_SETFONT、hBtnFont、1);
结束;
hDemoButton:=FindWindowEx(hWndMain,0,'TButton','Demo');
如果HDEMO按钮为0,则
开始
如果未启用窗口(hDemoButton,true),则
OutputDebugString('EnableWindow失败!');
结束
其他的
OutputDebugString('hDemoButton为0!');
hEdit:=FindWindowEx(hWndMain,0,'TEdit','Serial');
如果hEdit=0,则
OutputDebugString('hEdit为0!')
否则,如果没有设置WindowText(hEdit,“您已被黑客攻击”),则
OutputDebugString('SetWindowText失败!');
结束;
味精案例
WM_命令:
如果(hNewButton 0)和(DWORD(lParam)=hNewButton),则
MessageBox(HWND_桌面,“你按下了一个新按钮!”,“耶!”,MB_OK)
否则,如果(hWndEnter 0)和(DWORD(lParam)=hWndEnter),则
开始
MessageBox(HWND_桌面,'此消息不再是默认消息!',
“覆盖!”,MB_OK);
退出(0);//完全抑制默认事件
结束;
结束;
结果:=CallWindowProc(OldWndProc、hWnd、Msg、wParam、lParam);
结束;
过程入口点(原因:整数);
开始
hWndMain:=FindWindowEx(0,0,'TForm1','Injection test');
如果hWndMain=0,则
开始
OutputDebugString('hWndMain为0!');
出口
结束;
OldWndProc:=TFarProc(SetWindowLong(hWndMain,GWL_WNDPROC,
长(@NewWndProc));
MessageBox(0,'DLL注入','确定',0);
结束;
开始
CreateThread(nil,0,@EntryPoint,nil,0,&dwThreadId);
结束。
//喷油器:
程序exe_inj2;
{$APPTYPE控制台}
{$R*.res}
使用
System.SysUtils,windows,TLHelp32;
函数EnumThreadProc(wnd:HWND;Var appHwnd:HWND):LongBool;stdcall;
变量
buf:字符的数组[0..256];
开始
结果:=LongBool(1);
如果GetClassname(wnd、buf、sizeof(buf))>0,则
如果StrComp(buf,'TApplication')=0,则
开始
appHwnd:=wnd;
结果:=假;
结束;
结束;
函数FindApplicationWindow(forThreadID:DWORD):HWND;
开始
结果:=0;
EnumThreadWindows(forThreadID、@EnumThreadProc、LPRAM(@Result));
结束;
函数ProcessIDFromAppname32(appname:String):DWORD;
{仅获取应用程序文件名,而不是完整路径!}
变量
快照:坦德尔;
processEntry:TProcessEntry32;
开始
结果:=0;
appname:=大写(appname);
快照:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
如果快照为0,则
尝试
processEntry.dwSize:=sizeof(processEntry);
如果Process32先出现(快照、processEntry),则
重复
如果Pos(appname,
大写(ExtractFilename(StrPas(processEntry.szExeFile)))>0然后
开始
结果:=processEntry.th32ProcessID;
打破
结束;{If}
直到不是Process32Next(快照、processEntry);
最后
CloseHandle(快照);
结束;{try}
结束;
函数InjectDLL(dwPID:DWORD;DLLPath:PWideChar):整数;
变量
dwThreadID:基数;
hProc,hThread,hKernel:THandle;
BytesToWrite,byteswrited:SIZE\u T;
pRemoteBuffer,pLoadLibrary:指针;
开始
如果文件不存在(DLLPath),则
开始
MessageBox(0,PWideChar('File'+DLLPath+'不存在'),'Error',0);
出口(0);
结束;
hProc:=OpenProcess(进程\创建\线程或进程\查询\信息或
进程\虚拟机\操作或进程\虚拟机\写入或进程\虚拟机\读取,False,dwPID);
如果hProc=0,则
出口(0);
尝试
BytesToWrite:=sizeof(WideChar)*(长度(DLLPath)+1);
pRemoteBuffer:=VirtualAllocEx(hProc,nil,BytesToWrite,MEM_COMMIT,
页面(读写);
如果pRemoteBuffer=nil,则
出口(0);