首页
社区
课程
招聘
[求助]进程内 API “Hook”应怎么写?
发表于: 2012-8-12 00:55 11870

[求助]进程内 API “Hook”应怎么写?

2012-8-12 00:55
11870
最近写一个需要嵌入 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 隔离开来的方案。

先谢过了

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (14)
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
2
扫描一下WebBrowser 进程是否有hook验证~
2012-8-12 01:30
0
雪    币: 194
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
同一进程阿,webbrowset也是我起的
2012-8-12 09:10
0
雪    币: 142
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
RegQueryValue有两个版本RegQueryValueA和RegQueryValueW,你可能勾的是RegQueryValueA
2012-8-12 11:49
0
雪    币: 194
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
确认勾的是是W。

ProcessMonitor骗了我,不是RegQueryValue,是RegQueryValueEx。
现在我已经能勾住RegQueryValueEx了,也能截获一些注册表访问,但还是勾不到读取Cookies的那次访问。
OD跟踪发现,其实是 WinInet.dll 在调用 shell32.dll 的 SHGetFolderPathW,shell32.dll调用了RegQueryValueExW。也能钩住对SHGetFolderPath的一些调用,但还是劫不住nFolder==CSIDL_COOKIES的那次调用
2012-8-12 12:21
0
雪    币: 194
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
OK了,能接获 SHGetFolderPath nFolder == CSIDL_FLAG_PER_USER_INIT | CSIDL_COOKIES

不过还是疑惑,为啥勾不到RegQueryValueEx了读取Cookies路径的那次访问。
2012-8-12 12:49
0
雪    币: 142
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
那样啊,实在不行就猥琐点,启动时把键保存起来,然后修改成指定的,退出时再还原.
2012-8-12 18:22
0
雪    币: 235
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
大概看了下,不针对楼主的问题做直接解答,只说明我个人看法。

楼主解决问题就是在解决问题,要争取达到把解决问题变成在解域空间做选择题。
1、楼主的hook代码是我见过的hook中最差实现。线程同步、重复hook,解hook等问题。关于好的hook代码楼主可以搜索资料,好像我以前回答过的问题里也有一些比你这个实现好的。实在找不到,我可以帮你找一份。
2、首先楼主进行的ie编程,首先要采用的方式是ie COM技术,如果我记忆没错,cookie可以再ie中操作(禁用,设置等)。
3、楼主实际是懂得com编程的,只是对ie com还不熟悉。退一步的作法也不是操作注册表,而是wininet编程。ie底层调用wininet接口,hook在wininet api上远比注册表接口强
2012-8-12 19:08
0
雪    币: 13
活跃值: (59)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
自己做着玩还行,公司产品就不行了,要报毒的,MS的IE做的真懒,都没接口,猥琐一点去做吧,又要被杀,郁闷,俺们最近做一个IE代理也遇到类似问题,现在是启动之前保存注册表,然后修改注册表,启动IE,再还原,囧死了
2012-8-13 11:55
0
雪    币: 194
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
那这样的话,在你启动的过程中,我开个IE,岂不是读不到原来的Cookies了?
2012-8-13 12:40
0
雪    币: 194
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
感谢批评。
1、为了便于调试问题,我没有加入诸如线程同步之类的干扰代码,,,至于重复hook解hook之类的,应该是略有处理,如果有不足之处,敬请指点~ 总之,我只是为了说明问题。
2、我找了好久的文档,就是没找到合法的文档化的接口。我不是写IE插件,我是写独立应用,内部内嵌一个WebBrowser控件,我不需要加载IE的Cookies,这是我的需求,请理解。
3、很好的提示,非常感谢,我第一次尝试是Hook RegQueryValueEx,没Hook住,第二次尝试是Hook SHGetFolderPath,成功了,这在上面有说明,我回头再找找更高层的函数。可是我仍然现存一个疑惑,为啥Hook RegQueryValueEx 会失败呢?
2012-8-13 12:46
0
雪    币: 235
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
没有批评,只是建议。另外不知是我没明白楼主的意思,还是楼主没明白我的意思。不用ie的cookie要么就是完全禁用cookie,要么就是建立一个与ie cookie独立的一个cookie存储机制。这两种都可以通过ie的cookie对象处理。你的那个为什么的问题,我可能没有兴趣调试解答。
2012-8-13 13:27
0
雪    币: 13
活跃值: (59)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
对,可能出现这中问题,但是如果你能保证上面的操作是连贯的,就行了呗,这问题避免不了.不然只能挂钩了
2012-8-13 14:46
0
雪    币: 194
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
我需要Cookies。建立一个与IE独立的Cookie存储机制,符合我的需求的。你确定能做到?有公开合法的接口吗?
2012-8-13 19:46
0
雪    币: 194
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
嗯,也是一种方案吧
2012-8-13 19:46
0
游客
登录 | 注册 方可回帖
返回
//