最近写一个需要嵌入 WebBrowser 的东西,可是 WebBrowser 控件会直接继承 IE 的 Cookies,我想摆脱这一点。网上查了下 WebBrowser 是通过一个注册表设置读取 Cookies 存储路径的,经测试确实如此,使用了 RegQueryValue 来读取 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Cookies 里的路径。
于是我想 Hook RegQueryValue,做法如下——
InprocAPIHook 实现:
class InprocAPIHook
{
public:
InprocAPIHook() : m_hProcess(nullptr), m_lpProc(nullptr), m_bHooked(false)
{
}
~InprocAPIHook()
{
StopHook();
}
public:
bool SetHook(FARPROC lpProc, FARPROC lpNewAddr)
{
StopHook();
if (lpProc == nullptr)
{
return false;
}
m_lpProc = lpProc;
CopyMemory(&m_thunkOrig, m_lpProc, sizeof(APIThunk));
m_thunkNew.m_addr = (DWORD)lpNewAddr - (DWORD)m_lpProc - sizeof(APIThunk);
m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
if (m_hProcess == nullptr)
{
return false;
}
return true;
}
bool StartHook()
{
if (m_bHooked)
{
return true;
}
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), PAGE_READWRITE, &dwOldProtect))
{
return false;
}
SIZE_T cbWritten = 0;
if (!WriteProcessMemory(m_hProcess, m_lpProc, &m_thunkNew, sizeof(APIThunk), &cbWritten) || cbWritten != sizeof(APIThunk))
{
return false;
}
if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), dwOldProtect, &dwOldProtect))
{
return false;
}
m_bHooked = true;
return true;
}
bool StopHook()
{
if (!m_bHooked)
{
return true;
}
DWORD dwOldProtect = 0;
if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), PAGE_READWRITE, &dwOldProtect))
{
return false;
}
if (!WriteProcessMemory(m_hProcess, m_lpProc, &m_thunkOrig, sizeof(APIThunk), nullptr))
{
return false;
}
if (!VirtualProtectEx(m_hProcess, m_lpProc, sizeof(APIThunk), dwOldProtect, &dwOldProtect))
{
return false;
}
m_bHooked = false;
return true;
}
private:
#pragma pack(push, 1)
typedef struct _APIThunk
{
BYTE m_jmp; // jmp addr
DWORD m_addr;
_APIThunk() : m_jmp(0xe9), m_addr(0)
{
}
} APIThunk;
#pragma pack(pop)
private:
APIThunk m_thunkOrig;
APIThunk m_thunkNew;
HANDLE m_hProcess;
FARPROC m_lpProc;
bool m_bHooked;
};
使用处:
InprocAPIHook apiHook;
InprocAPIHook *g_pApiHook = &apiHook;
LONG WINAPI MyRegQueryValue(
__in HKEY hKey,
__in_opt LPCTSTR lpSubKey,
__out_opt LPTSTR lpValue,
__inout_opt PLONG lpcbValue
)
{
if (lpSubKey != nullptr &&_tcsicmp(lpSubKey, _T("Cookies")) != 0)
{ //这里条件写的比较粗,这个先不管了。
g_pApiHook->StopHook();
LONG lRes = RegQueryValue(hKey, lpSubKey, lpValue, lpcbValue);
g_pApiHook->StartHook();
return lRes;
}
g_pApiHook->StopHook();
LONG lRes = RegQueryValue(hKey, lpSubKey, nullptr, nullptr);
g_pApiHook->StartHook();
if (lRes != ERROR_SUCCESS && lRes != ERROR_MORE_DATA)
{
return lRes;
}
if (lpcbValue == nullptr && lpValue != nullptr)
{
return ERROR_INVALID_PARAMETER;
}
xl::String strPath = _T("%APPDATA%");
strPath += _T("\\");
strPath += FOLDER_COMPANY;
strPath += _T("\\");
strPath += FOLDER_APPLICATION;
strPath += _T("\\");
strPath += FOLDER_COOKIES;
if (lpcbValue != nullptr)
{
LONG dwGivenSize = *lpcbValue;
*lpcbValue = (strPath.Length() + 1) * sizeof(xl::Char);
if (dwGivenSize < *lpcbValue)
{
return ERROR_MORE_DATA;
}
}
if (lpValue != nullptr)
{
CopyMemory(lpValue, strPath.GetAddress(), *lpcbValue);
}
return ERROR_SUCCESS;
}
上面这个函数时我准备用来替换的函数
apiHook.SetHook((FARPROC)RegQueryValue, (FARPROC)MyRegQueryValue);
apiHook.StartHook(); // 这里开始使用 Hook
RegQueryValue(0,0,0,0); // 这一行测试正常进入 MyRegQueryValue
HRESULT hr = StgCreateDocfile(nullptr,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_CREATE,
0,
&m_pStorage);
if (FAILED(hr))
{
return false;
}
hr = OleCreate(CLSID_WebBrowser, IID_IOleObject, OLERENDER_DRAW, 0, this, m_pStorage, (LPVOID *)&m_pOleObj);
if (FAILED(hr))
{
return false;
}
hr = m_pOleObj->QueryInterface(IID_IOleInPlaceObject, (LPVOID *)&m_pInPlaceObj);
if (FAILED(hr))
{
return false;
}
RECT rect = {};
GetClientRect(&rect);
hr = m_pOleObj->DoVerb(OLEIVERB_INPLACEACTIVATE, nullptr, this, 0, m_hWnd, &rect);
if (FAILED(hr))
{
return false;
}
// ...
但是,现在的情况是,只有我自己写的那行测试代码 RegQueryValue 能进入 MyRegQueryValue,WebBrowser 加载过程中没有一次进入 MyRegQueryValue。不知道为什么,各位高手帮忙分析下?
顺求其他将 WebBrowser 的Cookies 和 IE 隔离开来的方案。
先谢过了
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)