vc++ 向其他进程注入代码的三种方法(转)


vc++ 向其他进程注入代码的三种方法(转)
2010年06月29日
  vc++ 向其他进程注入代码的三种方法
  导言:
  我们在Code project上可以找到许多密码间谍程序(那些可以看到别的程序中密码框内容的软件),他们都依赖于Windows钩子技术。要实现这个还有其他的方法吗?有!但是,首先,让我们简单回顾一下我们要实现的目标,以便你能弄清楚我在说什么。
  要读取一个控件的内容,不管它是否属于你自己的程序,一般来说需要发送 WM_GETTEXT 消息到那个控件。这对edit控件也有效,但是有一种情况例外。如果这个edit控件属于其他进程并且具有 ES_PASSWORD 风格的话,这种方法就不会成功。只有“拥有(OWNS)”这个密码控件的进程才可以用 WM_GETTEXT 取得它的内容。所以,我们的问题就是:如何让下面这句代码在其他进程的地址空间中运行起来:
  ::SendMessage( hPwdEdit, WM_GETTEXT, nMaxChars, psBuffer );
  一般来说,这个问题有三种可能的解决方案:
  1. 把你的代码放到一个DLL中;然后用 windows 钩子把它映射到远程进程。
  2. 把你的代码放到一个DLL中;然后用 CreateRemoteThread 和 LoadLibrary 把它映射到远程进程。
  3. 不用DLL,直接复制你的代码到远程进程(使用WriteProcessMemory)并且用CreateRemoteThread执行之。在这里有详细的说明:
  Ⅰ. Windows 钩子
  示例程序:HookSpy 和 HookInjEx
  Windows钩子的主要作用就是监视某个线程的消息流动。一般可分为:
  1. 局部钩子,只监视你自己进程中某个线程的消息流动。
  2. 远程钩子,又可以分为:
  a. 特定线程的,监视别的进程中某个线程的消息;
  b. 系统级的,监视整个系统中正在运行的所有线程的消息。
  如果被挂钩(监视)的线程属于别的进程(情况2a和2b),你的钩子过程(hook procedure)必须放在一个动态连接库(DLL)中。系统把这包含了钩子过程的DLL映射到被挂钩的线程的地址空间。Windows会映射整个DLL而不仅仅是你的钩子过程。这就是为什么windows钩子可以用来向其他线程的地址空间注入代码的原因了。
  在这里我不想深入讨论钩子的问题(请看MSDN中对SetWindowsHookEx的说明),让我再告诉你两个文档中找不到的诀窍,可能会有用:
  1.当SetWindowHookEx调用成功后,系统会自动映射这个DLL到被挂钩的线程,但并不是立即映射。因为所有的Windows钩子都是基于消息的,直到一个适当的事件发生后这个DLL才被映射。比如:
  如果你安装了一个监视所有未排队的(nonqueued)的消息的钩子(WH_CALLWNDPROC),只有一个消息发送到被挂钩线程(的某个窗口)后这个DLL才被映射。也就是说,如果在消息发送到被挂钩线程之前调用了UnhookWindowsHookEx那么这个DLL就永远不会被映射到该线程(虽然SetWindowsHookEx调用成功了)。为了强制映射,可以在调用SetWindowsHookEx后立即发送一个适当的消息到那个线程。
  同理,调用UnhookWindowsHookEx之后,只有特定的事件发生后DLL才真正地从被挂钩线程卸载。
  2.当你安装了钩子后,系统的性能会受到影响(特别是系统级的钩子)。然而如果你只是使用的特定线程的钩子来映射DLL而且不截获如何消息的话,这个缺陷也可以轻易地避免。看一下下面的代码片段:
  BOOL APIENTRY DllMain( HANDLE hModule,
  DWORD  ul_reason_for_call,
  LPVOID lpReserved )
  {
  if( ul_reason_for_call == DLL_PROCESS_ATTACH )
  {
  //用 LoadLibrary增加引用次数
  char lib_name[MAX_PATH];
  ::GetModuleFileName( hModule, lib_name, MAX_PATH );
  ::LoadLibrary( lib_name );
  // 安全卸载钩子
  ::UnhookWindowsHookEx( g_hHook );
  } 
  return TRUE;
  }
  我们来看一下。首先,我们用钩子映射这个DLL到远程线程,然后,在DLL被真正映射进去后,我们立即卸载挂钩(unhook)。一般来说当第一个消息到达被挂钩线程后,这DLL会被卸载,然而我们通过LoadLibrary来增加这个DLL的引用次数,避免了DLL被卸载。
  剩下的问题是:使用完毕后如何卸载这个DLL?UnhookWindowsHookEx不行了,因为我们已经对那个线程取消挂钩(unhook)了。你可以这么做:
  ○在你想要卸载这个DLL之前再安装一个钩子;
  ○发送一个“特殊”的消息到远程线程;
  ○在你的新钩子的钩子过程(hook procedure)中截获该消息,调用FreeLibrary 和(译者注:对新钩子调用)UnhookwindowsHookEx。
  现在,钩子只在映射DLL到远程进程和从远程进程卸载DLL时使用,对被挂钩线程的性能没有影响。也就是说,我们找到了一种(相比第二部分讨论的LoadLibrary技术)WinNT和Win9x下都可以使用的,不影响目的进程性能的DLL映射机制。
  但是,我们应该在何种情况下使用该技巧呢?通常是在DLL需要在远程进程中驻留较长时间(比如你要子类[subclass]另一个进程中的控件)并且你不想过于干涉目的进程时比较适合使用这种技巧。我在HookSpy中并没有使用它,因为那个DLL只是短暂地注入一段时间

猜你喜欢

转载自ekj676mq.iteye.com/blog/1357585