论坛风格切换切换到宽版
  • 7511阅读
  • 1回复

【求助】进程内 API “Hook”应怎么写? [复制链接]

上一主题 下一主题
离线溪流
 

发帖
565
金钱
-10380
威望
-1038
只看楼主 倒序阅读 0 发表于: 2012-08-12
最近写一个需要嵌入 WebBrowser 的东西,可是 WebBrowser 控件会直接继承 IE 的 Cookies,我想摆脱这一点。网上查了下 WebBrowser 是通过一个注册表设置读取 Cookies 存储路径的,经测试确实如此,使用了 RegQueryValue 来读取 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Cookies 里的路径。

于是我想 Hook RegQueryValue,做法如下——

InprocAPIHook 实现:
  1. class InprocAPIHook : public xl::NonCopyable
  2. {
  3. public:
  4.     InprocAPIHook() : m_hProcess(nullptr), m_lpProc(nullptr), m_bHooked(false)
  5.     {
  6.     }
  7.     ~InprocAPIHook()
  8.     {
  9.         StopHook();
  10.     }
  11. public:
  12.     bool SetHook(FARPROC lpProc, FARPROC lpNewAddr)
  13.     {
  14.         StopHook();
  15.       
  16.         if (lpProc == nullptr)
  17.         {
  18.             return false;
  19.         }
  20.         m_lpProc = lpProc;
  21.         
  22.         TCHAR szAddr[MAX_PATH] = {};
  23.         _stprintf_s(szAddr, _T("RegQueryValueW Addr: %08x"), lpProc);
  24.         OutputDebugString(szAddr);
  25.         CopyMemory(&m_thunkOrig, m_lpProc, sizeof(APIThunk));
  26.         m_thunkNew.m_addr = (DWORD)lpNewAddr - (DWORD)m_lpProc - sizeof(APIThunk);
  27.         m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
  28.         if (m_hProcess == nullptr)
  29.         {
  30.             return false;
  31.         }
  32.         return true;
  33.     }
  34.     bool StartHook()
  35.     {
  36.         if (m_bHooked)
  37.         {
  38.             return true;
  39.         }
  40.         DWORD dwOldProtect = 0;
  41.         
  42.         if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), PAGE_READWRITE, &dwOldProtect))
  43.         {
  44.             return false;
  45.         }
  46.         
  47.         SIZE_T cbWritten = 0;
  48.         if (!WriteProcessMemory(m_hProcess, m_lpProc, &m_thunkNew, sizeof(APIThunk), &cbWritten) || cbWritten != sizeof(APIThunk))
  49.         {
  50.             return false;
  51.         }
  52.         if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), dwOldProtect, &dwOldProtect))
  53.         {
  54.             return false;
  55.         }
  56.         m_bHooked = true;
  57.         return true;
  58.     }
  59.     bool StopHook()
  60.     {
  61.         if (!m_bHooked)
  62.         {
  63.             return true;
  64.         }
  65.         DWORD dwOldProtect = 0;
  66.         if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), PAGE_READWRITE, &dwOldProtect))
  67.         {
  68.             return false;
  69.         }
  70.         if (!WriteProcessMemory(m_hProcess, m_lpProc, &m_thunkOrig, sizeof(APIThunk), nullptr))
  71.         {
  72.             return false;
  73.         }
  74.         if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), dwOldProtect, &dwOldProtect))
  75.         {
  76.             return false;
  77.         }
  78.         m_bHooked = false;
  79.         return true;
  80.     }
  81. private:
  82. #ifdef _WIN64
  83. #pragma pack(push, 1)
  84.     typedef struct _APIThunk
  85.     {
  86.         USHORT  m_mov_rax;  // mov rax, addr
  87.         ULONG64 m_addr;
  88.         USHORT  m_jmp;      // jmp addr
  89.         _APIThunk() : m_mov_rax(0xb848), m_addr(0), m_jmp(0xe0ff)
  90.         {
  91.         }
  92.     } APIThunk;
  93. #pragma pack(pop)
  94. #else
  95. #pragma pack(push, 1)
  96.     typedef struct _APIThunk
  97.     {
  98.         BYTE    m_jmp;      // jmp addr
  99.         DWORD   m_addr;
  100.         _APIThunk() : m_jmp(0xe9), m_addr(0)
  101.         {
  102.         }
  103.     } APIThunk;
  104. #pragma pack(pop)
  105. #endif
  106. private:
  107.     APIThunk m_thunkOrig;
  108.     APIThunk m_thunkNew;
  109.     HANDLE   m_hProcess;
  110.     FARPROC  m_lpProc;
  111.     bool     m_bHooked;
  112. };


使用处:
  1.     InprocAPIHook apiHook;
  2.     InprocAPIHook *g_pApiHook = &apiHook;
  3.     LONG WINAPI MyRegQueryValue(
  4.         __in         HKEY hKey,
  5.         __in_opt     LPCTSTR lpSubKey,
  6.         __out_opt    LPTSTR lpValue,
  7.         __inout_opt  PLONG lpcbValue
  8.         )
  9.     {
  10.         OutputDebugString(lpSubKey);
  11.         return ERROR_SUCCESS;
  12.         if (lpSubKey != nullptr &&_tcsicmp(lpSubKey, _T("Cookies")) != 0)
  13.         {
  14.             g_pApiHook->StopHook();
  15.             LONG lRes = RegQueryValue(hKey, lpSubKey, lpValue, lpcbValue);
  16.             g_pApiHook->StartHook();
  17.             return lRes;
  18.         }
  19.         
  20.         g_pApiHook->StopHook();
  21.         LONG lRes = RegQueryValue(hKey, lpSubKey, nullptr, nullptr);
  22.         g_pApiHook->StartHook();
  23.         if (lRes != ERROR_SUCCESS && lRes != ERROR_MORE_DATA)
  24.         {
  25.             return lRes;
  26.         }
  27.         if (lpcbValue == nullptr && lpValue != nullptr)
  28.         {
  29.             return ERROR_INVALID_PARAMETER;
  30.         }
  31.         xl::String strPath = _T("%APPDATA%");
  32.         strPath += _T("\\");
  33.         strPath += FOLDER_COMPANY;
  34.         strPath += _T("\\");
  35.         strPath += FOLDER_APPLICATION;
  36.         strPath += _T("\\");
  37.         strPath += FOLDER_COOKIES;
  38.         if (lpcbValue != nullptr)
  39.         {
  40.             LONG dwGivenSize = *lpcbValue;
  41.             *lpcbValue = (strPath.Length() + 1) * sizeof(xl::Char);
  42.             if (dwGivenSize < *lpcbValue)
  43.             {
  44.                 return ERROR_MORE_DATA;
  45.             }
  46.         }
  47.         if (lpValue != nullptr)
  48.         {
  49.             CopyMemory(lpValue, strPath.GetAddress(), *lpcbValue);
  50.         }
  51.         return ERROR_SUCCESS;
  52.     }


上面这个函数时我准备用来替换的函数上面这个函数时我准备用来替换的函数
  1.     apiHook.SetHook((FARPROC)RegQueryValue, (FARPROC)MyRegQueryValue);
  2.     apiHook.StartHook();  // 这里开始使用 Hook
  3.     RegQueryValue(0,0,0,0);  // 这一行测试正常进入 MyRegQueryValue
  4.     HRESULT hr = StgCreateDocfile(nullptr,
  5.                                   STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_CREATE,
  6.                                   0,
  7.                                   &m_pStorage);
  8.     if (FAILED(hr))
  9.     {
  10.         return false;
  11.     }
  12.     hr = OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, 0, this, m_pStorage, (LPVOID *)&m_pOleObj);
  13.     if (FAILED(hr))
  14.     {
  15.         return false;
  16.     }
  17.     hr = m_pOleObj->QueryInterface(IID_IOleInPlaceObject, (LPVOID *)&m_pInPlaceObj);
  18.     if (FAILED(hr))
  19.     {
  20.         return false;
  21.     }
  22.     RECT rect = {};
  23.     GetClientRect(&rect);
  24.     hr = m_pOleObj->DoVerb(OLEIVERB_INPLACEACTIVATE, nullptr, this, 0, m_hWnd, &rect);
  25.     if (FAILED(hr))
  26.     {
  27.         return false;
  28.     }
  29.     // 。。。


但是,现在的情况是,只有我自己写的那行测试代码 RegQueryValue 能进入 MyRegQueryValue,WebBrowser 加载过程中没有一次进入 MyRegQueryValue。不知道为什么,各位高手帮忙分析下?

顺求其他将 WebBrowser 的Cookies 和 IE 隔离开来的方案。

先谢过了
因为用纸过大不利环保,2009年6月1日起,禁止使用纸质材料擦屁股,提倡公民养成不擦屁股或自带可重用抹布的习惯。违者最高可处以菊爆。
离线溪流

发帖
565
金钱
-10380
威望
-1038
只看该作者 1 发表于: 2012-08-12
ProcessMonitor骗了我,不是RegQueryValue,是RegQueryValueEx。

现在我已经能勾住RegQueryValueEx了,也能截获一些注册表访问,但还是勾不到读取Cookies的那次访问。

OD跟踪发现,其实是 WinInet.dll 在调用 shell32.dll 的 SHGetFolderPathW,shell32.dll调用了RegQueryValueExW。能解惑到 SHGetFolderPath 了( nFolder == CSIDL_FLAG_PER_USER_INIT | CSIDL_COOKIES)

不过还是疑惑,为啥勾不到RegQueryValueEx了读取Cookies路径的那次访问呢?
因为用纸过大不利环保,2009年6月1日起,禁止使用纸质材料擦屁股,提倡公民养成不擦屁股或自带可重用抹布的习惯。违者最高可处以菊爆。