刚写完了一个全局的inline hook 库, 易用性感觉还不是很好。  但是"全局"2字是亮点。
先说一下全局的思路。
首先遍历当前所有的进程。当然我们想到的大多数方法是用一些枚举进程的api来做,我想到了另一种方法。暴力穷举,这样可以把隐藏进程也给揪出来。
//暴力穷举进程(进程ID都是4的整数倍,而且小于0x0000ffff)

代码:
    HANDLE hProcess = 0;
    for (DWORD dwProcessID = 0; dwProcessID<=0x0000FFFF; dwProcessID+=4)
    {
      hProcess =::OpenProcess(
        PROCESS_QUERY_INFORMATION |  // Required by Alpha
        PROCESS_CREATE_THREAD     |    // For CreateRemoteThread
        PROCESS_VM_OPERATION      |    // For VirtualAllocEx/VirtualFreeEx
        PROCESS_VM_WRITE      |    // For WriteProcessMemory
        PROCESS_VM_READ ,        //  For CreateRemoteThread
        FALSE, dwProcessID);
      if (hProcess == 0)
      {
        continue;
      }
      //有进程句柄了。。远程线程注入啥的。。。
       }
那么问题来了,新创建的进程如何hook? 我见到过很多所谓的全局hook   仅仅是 SetWindowsHook 挂了一个消息钩子   这样的烂钩子不要也罢。
我想到了hook CreateProcess  于是就想了想创建进程的方法 WinExec  ShellExcute 等等  用OD简单的跟踪了一下  发现最终都会调用Kernel32!CreateProcessInternalW函数 好了 就勾他吧。
在 我们的 MyCreateProcessInternalW中如何处理才能让新建立的线程也能Load我们的dll呢
方法有很多  我挑了一种最简单的  先用CREATE_SUSPENDED属性挂起进程  然后修改入口点  然后构造shellcode 完成load我们的dll的任务 最后在返回入口点之前把入口点修改过的代码恢复过去。
具体代码如下(shellcode代码写的太挫了 - -!):
代码:
BOOL __stdcall MyCreateProcessInternalW(
                      HANDLE hToken,
                      LPCTSTR lpApplicationName,       
                      LPTSTR lpCommandLine,       
                      LPSECURITY_ATTRIBUTES lpProcessAttributes,
                      LPSECURITY_ATTRIBUTES lpThreadAttributes,       
                      BOOL bInheritHandles,       
                      DWORD dwCreationFlags,
                      LPVOID lpEnvironment,       
                      LPCTSTR lpCurrentDirectory,       
                      LPSTARTUPINFO lpStartupInfo,       
                      LPPROCESS_INFORMATION lpProcessInformation ,
                      PHANDLE hNewToken)
{
  //以CREATE_SUSPENDED属性先挂起进程
  BOOL bRet = (BOOL)g_ApiInfo[Index_CreateProcessInternalW].InvokeApi( hToken, 
                                  lpApplicationName, 
                                  lpCommandLine, 
                                  lpProcessAttributes, 
                                  lpThreadAttributes,
                                  bInheritHandles, 
                                  dwCreationFlags|CREATE_SUSPENDED, 
                                  lpEnvironment, 
                                  lpCurrentDirectory, 
                                  lpStartupInfo, 
                                  lpProcessInformation, 
                                  hNewToken);
  if (bRet == FALSE)
  {
    return bRet;
  }

  //得到入口点。
  DWORD dwEntry = GetProcessEntryPoint(lpProcessInformation->hProcess);
  if (dwEntry == 0)
  {
    ResumeThread(lpProcessInformation->hThread);
    return TRUE;
  }
  DWORD dwLoadLibrary = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
  DWORD dwVirtualProtect = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualProtect");

  //保存前5个字节 以后好恢复
  BYTE bSave[5] = {0};
  DWORD dwRead = 0;
  bRet = ReadProcessMemory(lpProcessInformation->hProcess, (LPVOID)dwEntry, bSave, 5, &dwRead);

  //编写shellcode  
  /*cc
        9c        pushfd
  0040101D    50              push eax                                 ; 保存eax寄存器   ;;data offset + 0 
  0040101E    834424 08 FB    add dword ptr ss:[esp+8],-5              ; 修改跳回去的地址为原入口点(在ret之前修正入口点)
  00401023    E8 0C000000     call 00401034                            ; 将后面的字符串push进去

  00401028    6D 79 68 6F 6F 6B 2E 64 6C 6C 00 00       "myhook.dll"

  00401034    E8 3E0D407C     call kernel32.LoadLibraryA               ; 加载dll    ;;data offset + 24
  00401039    6A 00           push 0                                   ; 修改入口点页属性  这里是申请一个空间
  0040103B    54              push esp                                 ; old 属性地址 即0的地址
  0040103C    6A 40           push 40                                  ; PAGE_EXECUTE_READWRITE
  0040103E    6A 05           push 5
  00401040    68 99999999     push 99999999                            ; 入口点地址  ;;data offset + 36
  00401045    E8 860A407C     call kernel32.VirtualProtect   ; 修改入口点前5字节属性为可写 否则崩  ;;data offset + 41  
  0040104A    58              pop eax                                  ; 平衡堆栈
  0040104B    B8 99999999     mov eax,99999999                    ;;data offset 47
  00401050    C600 11         mov byte ptr ds:[eax],11  ;恢复入口点的5字节  ;;data offset 53
  00401053    40              inc eax
  00401054    C700 88888808   mov dword ptr ds:[eax],8888888              ;;data offset 57
  0040105A    58              pop eax
              9d        popfd
  0040105B    C3              retn
  */
  //第一个字节是为了用WinDbg调试而添加的,调试完成了就置为0x90了
  BYTE shellcode[66] = { 0x90, 0x9c, 0x50, 0x83, 0x44, 0x24, 0x08, 0xfb, 0xe8, 0x0c, 0x00, 0x00, 0x00, 0x6d, 0x79, 0x68, 
               0x6f, 0x6f, 0x6b, 0x2e, 0x64, 0x6c, 0x6c, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00,
               0x6a, 0x00, 0x54, 0x6a, 0x40, 0x6a, 0x05, 0x68, 0x00, 0x00, 0x00, 0x00, 
               0xe8, 0x00, 0x00, 0x00, 0x00, 0x58,
               0xb8, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x40, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00,
               0x58, 0x9d, 0xc3};

  //申请空间
  LPVOID lpRomateAddress = VirtualAllocEx(lpProcessInformation->hProcess, 0, 66, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  
  //修改call library地址
  PBYTE pOffset = (PBYTE)shellcode + 2;
  *(DWORD*)(pOffset+24) = dwLoadLibrary - ((DWORD)lpRomateAddress + 2 + 23) - 5;
  *(DWORD*)(pOffset+36) = dwEntry;
  *(DWORD*)(pOffset+41) = dwVirtualProtect -((DWORD)lpRomateAddress + 2 + 40) -5;

  *(DWORD*)(pOffset+47) = dwEntry;

  *(BYTE*)(pOffset+53) = bSave[0];
  *(DWORD*)(pOffset+57) = *(DWORD*)(bSave+1);

  //写入进程空间
  bRet = WriteProcessMemory(lpProcessInformation->hProcess, lpRomateAddress, shellcode, 66, 0);

  //修改前5字节
  //call  xxx
  BYTE bSet[5] = {0};
  bSet[0] = 0xe8;
  *(DWORD*)(bSet+1) = (DWORD)lpRomateAddress - dwEntry - 5;
  bRet = WriteProcessMemory(lpProcessInformation->hProcess, LPVOID(dwEntry), bSet, 5, 0);

  ResumeThread(lpProcessInformation->hThread);
  return TRUE;
}
见过一些帖子说 从入口点开始找0xe8(相对地址 call 指令) 然后修改他的代码  让他跳到我们构造的shellcode中 然后xxxx   这个方法感觉还是不太好   就像附件中我给的一个 最简单PE.exe 这个例子就挂不起来   还是修改入口点比较通用。
在.h文件中用到  了一个  GetOpcodeSize函数   貌似是海风大侠的   谢谢了  否则就得用反汇编引擎。 
ps  一般来说这样的需求要用WinDbg来调试子进程。 OllyDbg不太好用。
上传的附件 Ring3 Global Inline Hook.rar