外挂框架开发(1)HOOKAPI

来源:互联网 发布:熟女交友软件 编辑:程序博客网 时间:2024/05/16 07:22

这一篇是外挂开发的基础。可能对初学者而言听起来很麻烦,其实不然。因为这方面的技术也已很成熟了,源码都是公开的,剩下来就是怎么用了。在多线程环境下,理论上有两种方法实现挂截API,一是Jeffery的修改IAT算法,二是用detours开发包。我建议大家用detours。因为只需要少量几行代码就可实现挂截。以1.5版本为例:

typedef int (WINAPI *PFN_TCP)(SOCKET s,const char FAR *buf,int len,int nflag);
PFN_TCP  _send  = NULL;
 int WINAPI mysend(SOCKET s,const char FAR *buf,int len,int nflag)
{
   //your code goes here:
   //...
   return ((PFN_TCP)_send)(s,buf,len,nflag);

这样实现挂截   

 PBYTE pfn = (PBYTE)GetProcAddress( hwsock32,"send");
   _send = (PFN_TCP)DetourFunction(pfn,(PBYTE)mysend);

这样清除挂截

  DetourRemove((PBYTE)_send,(PBYTE)mysend);

到这里,如果通过别的什么工具知道send函数的buf里传输的是什么含义后,在mysend中加入你的补丁代码,已经完成核心功能了。恭喜你。

可是,以上代码用什么方法组织起来呢?答案是DLL。写法如下:

extern BOOL SpyInit();
extern BOOL SpyInit();
BOOL APIENTRY DllMain( HANDLE hModule, DWORD  r, LPVOID lpReserved )
{
 
 if( r==DLL_PROCESS_ATTACH )
 {
  return SpyInit();
 }
 
 else if( r==DLL_PROCESS_DETACH )
 {
  SpyExit();
 }
    return TRUE;
}
其中,SpyInit()就是DetourFunction包装后的样子;

接下来,我们得考虑怎么把以上代码“安装”到目标进程中去。好在算法Jerffrey早就为我们准备好了(见《windows核心编程》),用这个算法写个工具,专门用来装/卸动态库。这样做的好处是,当我们的DLL成功安装到指定进程后,这个工具就可以关掉了。

#include "stdafx.h"
#include "Injectlib.h"
//#include "tlhelp32.h"
//#include "string.h"

///////////////////////////////////////////////////////////////////////////////

BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {

   BOOL fOk = FALSE; // Assume that the function fails
   HANDLE hProcess = NULL, hThread = NULL;
   PWSTR pszLibFileRemote = NULL;

   __try {
      // Get a handle for the target process.
      hProcess = OpenProcess(
         PROCESS_QUERY_INFORMATION |   // Required by Alpha
         PROCESS_CREATE_THREAD     |   // For CreateRemoteThread
         PROCESS_VM_OPERATION      |   // For VirtualAllocEx/VirtualFreeEx
         PROCESS_VM_WRITE,             // For WriteProcessMemory
         FALSE, dwProcessId);
      if (hProcess == NULL) __leave;

      // Calculate the number of bytes needed for the DLL's pathname
      int cch = 1 + lstrlenW(pszLibFile);
      int cb  = cch * sizeof(WCHAR);

      // Allocate space in the remote process for the pathname
      pszLibFileRemote = (PWSTR)
         VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
      if (pszLibFileRemote == NULL) __leave;

      // Copy the DLL's pathname to the remote process's address space
      if (!WriteProcessMemory(hProcess, pszLibFileRemote,
         (PVOID) pszLibFile, cb, NULL)) __leave;

      // Get the real address of LoadLibraryW in Kernel32.dll
      PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
         GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
      if (pfnThreadRtn == NULL) __leave;

      // Create a remote thread that calls LoadLibraryW(DLLPathname)
      hThread = CreateRemoteThread(hProcess, NULL, 0,
         pfnThreadRtn, pszLibFileRemote, 0, NULL);
      if (hThread == NULL) __leave;

      // Wait for the remote thread to terminate
      WaitForSingleObject(hThread, INFINITE);

      fOk = TRUE; // Everything executed successfully
   }
   __finally { // Now, we can clean everthing up

      // Free the remote memory that contained the DLL's pathname
      if (pszLibFileRemote != NULL)
         VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

      if (hThread  != NULL)
         CloseHandle(hThread);

      if (hProcess != NULL)
         CloseHandle(hProcess);
   }

   return(fOk);
}


///////////////////////////////////////////////////////////////////////////////


BOOL WINAPI InjectLibA(DWORD dwProcessId, PCSTR pszLibFile) {

   // Allocate a (stack) buffer for the Unicode version of the pathname
   PWSTR pszLibFileW = (PWSTR)
      _alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));

   // Convert the ANSI pathname to its Unicode equivalent
   wsprintfW(pszLibFileW, L"%S", pszLibFile);

   // Call the Unicode version of the function to actually do the work.
   return(InjectLibW(dwProcessId, pszLibFileW));
}


///////////////////////////////////////////////////////////////////////////////


BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) {

   BOOL fOk = FALSE; // Assume that the function fails
   HANDLE hthSnapshot = NULL;
   HANDLE hProcess = NULL, hThread = NULL;

   __try {
      // Grab a new snapshot of the process
      hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
      if (hthSnapshot == NULL) __leave;

      // Get the HMODULE of the desired library
      MODULEENTRY32W me = { sizeof(me) };
      BOOL fFound = FALSE;
      BOOL fMoreMods = Module32FirstW(hthSnapshot, &me);
      for (; fMoreMods; fMoreMods = Module32NextW(hthSnapshot, &me)) {
         fFound = (lstrcmpiW(me.szModule,  pszLibFile) == 0) ||
                  (lstrcmpiW(me.szExePath, pszLibFile) == 0);
         if (fFound) break;
      }
      if (!fFound) __leave;

      // Get a handle for the target process.
      hProcess = OpenProcess(
         PROCESS_QUERY_INFORMATION |   // Required by Alpha
         PROCESS_CREATE_THREAD     |
         PROCESS_VM_OPERATION,  // For CreateRemoteThread
         FALSE, dwProcessId);
      if (hProcess == NULL) __leave;

      // Get the real address of LoadLibraryW in Kernel32.dll
      PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
         GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
      if (pfnThreadRtn == NULL) __leave;

      // Create a remote thread that calls LoadLibraryW(DLLPathname)
      hThread = CreateRemoteThread(hProcess, NULL, 0,
         pfnThreadRtn, me.modBaseAddr, 0, NULL);
      if (hThread == NULL) __leave;

      // Wait for the remote thread to terminate
      WaitForSingleObject(hThread, INFINITE);

      fOk = TRUE; // Everything executed successfully
   }
   __finally { // Now we can clean everything up

      if (hthSnapshot != NULL)
         CloseHandle(hthSnapshot);

      if (hThread     != NULL)
         CloseHandle(hThread);

      if (hProcess    != NULL)
         CloseHandle(hProcess);
   }

   return(fOk);
}


///////////////////////////////////////////////////////////////////////////////


BOOL WINAPI EjectLibA(DWORD dwProcessId, PCSTR pszLibFile) {

   // Allocate a (stack) buffer for the Unicode version of the pathname
   PWSTR pszLibFileW = (PWSTR)
      _alloca((lstrlenA(pszLibFile) + 1) * sizeof(WCHAR));

   // Convert the ANSI pathname to its Unicode equivalent
   wsprintfW(pszLibFileW, L"%S", pszLibFile);

   // Call the Unicode version of the function to actually do the work.
   return(EjectLibW(dwProcessId, pszLibFileW));
}


///////////////////////////////////////////////////////////////////////////////

好,我们的初级外挂准备好了。进程dwProcessId可以先在任务管理器中查查,填写进去。大家按着上面试试,体会一下,有缺点不怕,咱们慢慢改进。

(如有意交流,请发EMAIL至hotmail的cg328信箱交流)

原创粉丝点击