我是用CreateRemoteThread注入的dll
开始用了各种方法都无法在被注入程序中显示窗体
1.在dll的begin  end 里直接创建窗体 结果dll里的begin end 里的代码完成后才会出现被注入程序
也就是说begin end里的代码是在主线程里执行的?可是我明明是创建的远程线程啊???2.键盘钩子,在begin  end里安装钩子,低级键盘钩子,键盘钩子都试了,钩成功了,就是不调我的回调,加了stdcall的3.启动一个线程,既然begin end里的代码是在主线程执行的(要不然怎么会阻塞住),那我就搞个线程吧。
线程的最开始是等待主线程创建主窗体(循环查看是否有主窗体句柄,用EnumWindow)
然后用SetWindowlong替换掉程序的原有窗口过程,结果得到原有窗口过程地址是个负数,不知道是不是它Hook了这个API,
因为我注入我写的程序里可以得到正确的窗口过程地址。后来又在线程里安钩子 还是不行 返回的钩子句柄是大于0的 就是不调我的回调函数
   
KeyHookHandle := SetWindowsHookEx(WH_KEYBOARD, TFNHookProc(@KeyboardProc),
    HInstance,
    GetWindowThreadProcessId(MainFromHandle));
最后我就直接在线程里创建窗体,并以模态显示,结果,结果居然正常的显示了,而且不报错
而且依然可以正常使用主窗体虽然是模态的
难道一个程序可以有很多个消息循环吗?
在我的印象里子窗体都是在主线程里的啊
我现在都不知道怎么结束这个线程了。
有懂的解释下我这种方法是正确的dll 呼出窗体吗?
还有dll注入后 申请的内核对象 资源等 怎么在被注入程序结束前释放掉?
被注入程序不会通知我它要结束啊?
   
function InitThreadFunction(P: Pointer): Cardinal;
var
  MyProcessId: Cardinal;
begin
  Result:=0;
  MyProcessId := GetCurrentProcessId;
  //等待有主窗口句柄
  while True do
  begin
    Sleep(100);
    MainFromHandle := GetMainFormHandleFromProcessID(MyProcessId);
    if MainFromHandle <> 0 then
      Break;
  end;
   FormMain:= FormMain.Create(nil);
  SetParent( FormMain.Handle,MainFromHandle);
  FormMain.ShowModal;
end;

解决方案 »

  1.   

    1、加载DLL执行初始化的过程是有锁的,如果其中某一个线程在执行DLL的初始化,则其它线程加载DLL会被阻塞。估计是你在注入DLL后,被注入进程的主线程还需要加载其它DLL,而被阻塞了,直到你的DLL初始化结束后才继续运行。注入DLL如果要显示窗口,最好另外创建一个线程,不要在初始化过程中显示。
    2、SetWindowsHookEx不要在DLL初始化过程中调用。
    3、GetWindowlong/SetWindowlong获取的窗口过程地址有两种情况,一种是地址,另一种是表示地址的句柄(负数),用CallWindowProc调用即可。
    窗口是属于创建它的线程的,每个线程可以有自己的消息循环,线程之间互不影响,创建窗口后必须执行消息循环才能正常显示窗口。
    进程结束时,系统会自动释放进程所占用的所有资源(包括注入的程序分配的资源)。