这篇谈下c++如何hook网页中的JS函数,即网页可以执行我们修改的JS函数。

相应的步骤可分为:

1.找到需要修改函数的时机。

2.得到需要修改函数的com对象。

3.将我们新的com对象替换修改函数。

第一步,找到需要修改函数的时机,在谈这个问题之前,需要搞清楚JS执行发生在什么时候。

我们知道在网页加载过程中,会根据接收到的html文本,去解析对应里面的脚本和样式以及js。

譬如:

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>了解html页面的渲染过程 - yuezk - 博客园</title>
<link type="text/css" rel="stylesheet" href="/bundles/blog-common.css?v=Rdf1BBttS5_qVaET1myrajVTd62BSCCoJA9fZxGv1ZM1">
<link id="MainCss" type="text/css" rel="stylesheet" href="/skins/LessIsMoreRight/bundle-LessIsMoreRight.css?v=XnHJrmT6UJMtyGfeJjiTUm7BxKWcwdJrxKsGy7z3YZ81">
<link id="mobile-style" media="only screen and (max-width: 768px)" type="text/css" rel="stylesheet" href="/skins/LessIsMoreRight/bundle-LessIsMoreRight-mobile.css?v=9qDppl1UU68AUflWXI5a_NeoqamVC_84o7AG1HNc4Pg1">
<link title="RSS" type="application/rss+xml" rel="alternate" href="http://www.cnblogs.com/yuezk/rss">
<link title="RSD" type="application/rsd+xml" rel="EditURI" href="http://www.cnblogs.com/yuezk/rsd.xml">
<link type="application/wlwmanifest+xml" rel="wlwmanifest" href="http://www.cnblogs.com/yuezk/wlwmanifest.xml">
<script type="text/javascript" src="http://common.cnblogs.com/script/encoder.js"></script><script src="//common.cnblogs.com/script/jquery.js" type="text/javascript"></script>
<script type="text/javascript">var currentBlogApp = 'yuezk', cb_enable_mathjax=false;var isLogined=false;</script>
<script src="/bundles/blog-common.js?v=hH1lCMV8WaIu271Nx7jPuv36TENW9-RsSxziLxUpjtc1" type="text/javascript"></script>
</head>

在网页加载渲染过程中,本地会逐行解析脚本,css和绘制不是我们这里讨论的,略过,当执行到<scrpt>一行时,网页会停止创建DOM树,开始加载对应的js,加载过程就是把encoder.js和jquery.js里面的对象(也包括函数)会一并创建。如果我们需要修改的js函数在就是在类似的这样的头里面创建的,那么很简单了,我们只要找一个加载点没执行修改函数就行,然后执行我们的第二步。在MFC中,一般考虑OnDocumentComplete函数作为我们修改函数的时机。具体函数实现如下:

void CWebLoginDlg::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR szUrl)
{CDHtmlDialog::OnDocumentComplete(pDisp, szUrl);// TODO: Add your specialized code here and/or call the base classIUnknown*  pUnk;LPDISPATCH lpWBDisp;HRESULT    hr;pUnk = m_wndBrowser.GetControlUnknown();ASSERT(pUnk);hr = pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);ASSERT(SUCCEEDED(hr));CComPtr<IHTMLDocument2> sphtmlDoc;GetDHtmlDocument(&sphtmlDoc);if (sphtmlDoc != NULL){CWebPage web;VARIANT testV;web.SetDocument(sphtmlDoc);CComPtr<IDispatch> pDispatch = NULL;web.GetJScript(pDispatch);HRESULT result = GetProperty(pDispatch, L"TK_installPage", &testV); //得到修改函数的com对象if (result == S_OK){VARIANT params;params.vt = VT_DISPATCH;params.pdispVal = new JsFunction(button1_onclick);result = SetProperty(pDispatch, L"TK_installPage", ¶ms);//将我们的button1_onclick函数替换修改函数}}if (pDisp == lpWBDisp ){// Top-level Window object, so document has been loadedTRACE("Web document is finished downloading\n");}lpWBDisp->Release();

第二步,得到修改函数的com对象。这里TK_installPage函数就是我们的要修改的函数。首先获取doc对象,然后根据doc对象通过GetJScript获得脚本对象,再次在脚本对象上通过名字TK_installPage得到js对象。具体代码如下:

bool CWebPage::SetDocument(IDispatch* pDisp)
{CHECK_POINTER(pDisp);m_spDoc = NULL;CComPtr<IDispatch> spDisp = pDisp;HRESULT hr = spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc);if(FAILED(hr)){ShowError(L"Failed to get HTML document COM object");return false;}return true;
}bool CWebPage::GetJScript(CComPtr<IDispatch>& spDisp)
{CHECK_POINTER(m_spDoc);HRESULT hr = m_spDoc->get_Script(&spDisp);ATLASSERT(SUCCEEDED(hr));return SUCCEEDED(hr);
}DISPID CWebLoginDlg::FindId( IDispatch *pObj, LPOLESTR pName )
{DISPID id = 0;if(FAILED(pObj->GetIDsOfNames(IID_NULL,&pName,1,LOCALE_SYSTEM_DEFAULT,&id))) id = -1;return id;
}HRESULT CWebLoginDlg::GetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue )
{DISPID dispid = FindId(pObj, pName);if(dispid == -1) return E_FAIL;DISPPARAMS ps;ps.cArgs = 0;ps.rgvarg = NULL;ps.cNamedArgs = 0;ps.rgdispidNamedArgs = NULL;return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &ps, pValue, NULL, NULL);
}

第三步,将我们新的com对象替换修改函数。

首先需要构造我们新的com对象,

typedef void _stdcall JsFunction_Callback();class JsFunction:public IDispatch
{long _refNum;JsFunction_Callback *m_pCallback;
public:JsFunction(JsFunction_Callback *pCallback){_refNum = 1;m_pCallback = pCallback;}~JsFunction(void){}
public:// IUnknown MethodsSTDMETHODIMP QueryInterface(REFIID iid,void**ppvObject){*ppvObject = NULL;if (iid == IID_IOleClientSite)    *ppvObject = (IOleClientSite*)this;else if (iid == IID_IUnknown)    *ppvObject = this;if(*ppvObject){AddRef();return S_OK;}return E_NOINTERFACE;}STDMETHODIMP_(ULONG) AddRef(){return ::InterlockedIncrement(&_refNum);}STDMETHODIMP_(ULONG) Release(){::InterlockedDecrement(&_refNum);if(_refNum == 0){delete this;}return _refNum;}// IDispatch MethodsHRESULT _stdcall GetTypeInfoCount(unsigned int * pctinfo) {return E_NOTIMPL;}HRESULT _stdcall GetTypeInfo(unsigned int iTInfo,LCID lcid,ITypeInfo FAR* FAR* ppTInfo) {return E_NOTIMPL;}HRESULT _stdcall GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId ){//令人费解的是,网页调用函数的call方法时,没有调用GetIDsOfNames获取call的ID,而是直接调用Invokereturn E_NOTIMPL;}HRESULT _stdcall Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,unsigned int* puArgErr){//这里执行我们的替换函数m_pCallback();return S_OK;}
};static void _stdcall button1_onclick()
{ATLTRACE("test");
}

其次,通过com对象的invoke函数进行替换。代码如下:

HRESULT CWebLoginDlg::SetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue )
{DISPID dispid = FindId(pObj, pName);if(dispid == -1) return E_FAIL;DISPID dispidNamed = DISPID_PROPERTYPUT;DISPPARAMS ps;ps.cArgs = 1;ps.rgvarg = pValue;ps.cNamedArgs = 1;ps.rgdispidNamedArgs = &dispidNamed;return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &ps, NULL, NULL, NULL);
}

最终效果,在网页在执行TK_installPage函数时候,实际上是执行的我们的函数button1_onclick。

模拟网页行为之实践四相关推荐

  1. 网页图表Highcharts实践教程之图表区

    网页图表Highcharts实践教程之图表区 网页图表Highcharts图表区 图表区是图表的基本区域.所有的数据和图形都是绘制在图表区中.从图形绘制范围来分,图表区域分为外层图表区和绘图区.本章将 ...

  2. 网页图表Highcharts实践教程之外层图表区

    网页图表Highcharts实践教程之外层图表区 Highcharts图表区 图表区是图表的基本区域.所有的数据和图形都是绘制在图表区中.从图形绘制范围来分,图表区域分为外层图表区和绘图区.本章将详细 ...

  3. html从入门到精通胡菘,高职电商网页设计教学实践(共2831字).doc

    高职电商网页设计教学实践(共2831字) 高职电商网页设计教学实践(共2831字) 摘要:电商网页设计课程是电子商务专业的核心课程,在教学中要根据高职学生的特点和网页制作的要求,合理安排教学内容,教学 ...

  4. html从入门到精通胡菘,高职电商网页设计教学实践.docx

    高职电商网页设计教学实践 高职电商网页设计教学实践 摘要:电商网页设计课程是电子商务专业的核心课程,在教学中要根据高职学生的特点和网页制作的要求,合理安排教学内容,教学过程中要求新.求美,教学实践中要 ...

  5. c# 模拟 网页实现12306登陆、自动刷票、自动抢票完全篇(转)

    这一篇文章,我将从头到尾教大家使用c#模拟网页面登陆12306网站,自动刷票,选择订票人,到最后一步提交订单.研究过HTTP协议的童鞋们都 知道,我们在访问网站时,是有两种方式的,POST和GET方式 ...

  6. c#模拟网页实现12306登陆、自动刷票、自动抢票完全篇

    这一篇文章,我将从头到尾教大家使用c#模拟网页面登陆12306网站,自动刷票,选择订票人,到最后一步提交订单.研究过HTTP协议的童鞋们都知道,我们在访问网站时,是有两种方式的,POST和GET方式, ...

  7. c# 模拟 网页实现12306登陆、自动刷票、自动抢票完全篇

    这一篇文章,我将从头到尾教大家使用c#模拟网页面登陆12306网站,自动刷票,选择订票人,到最后一步提交订单.研究过HTTP协议的童鞋们都知道,我们在访问网站时,是有两种方式的,POST和GET方式, ...

  8. ​网页图表Highcharts实践教程之标签组与载入动画

    ​网页图表Highcharts实践教程之标签组与载入动画 Highcharts标签组 在图表的大部分元素都提供了标签功能.但很多时候,我们需要额外说明一些信息.这个时候借助原有的图表元素的标签功能就不 ...

  9. ​网页图表Highcharts实践教程标之添加题副标题版权信息

    ​网页图表Highcharts实践教程标之添加题副标题版权信息 Highcharts辅助元素 辅助元素图表的非必要元素,如标题.版权信息.标签.载入动态.它们不和图表数据发生关联,只是额外说明一些基本 ...

最新文章

  1. 白噪音和粉红噪音煲机_白噪音真的有助于睡眠?这款可以自定义的应用给你答案...
  2. 用 Hadoop 进行分布式并行编程, 第 1 部分 基本概念与安装部署
  3. python区块链开发_10个开源的Python区块链项目
  4. 2009年全国计算机软件考试推荐用书目录
  5. python降维之时间类型数据的处理_python学习笔记之使用sklearn进行PCA数据降维
  6. Bzoj3628: [JLOI2014]天天酷跑
  7. 违反GPL协议,法院判罚了!国内首例
  8. Source Insight之Relation Window Properties配置和一些快捷键
  9. 高德地图调用和添加标注
  10. 【计算机网络】电路交换网络中,每条电路独占其经过的物理链路?
  11. gm怎么刷东西 rust_网游GM被玩家暴打,无奈为自己特制无敌BUFF,技能介绍格外嘚瑟...
  12. 最棒的Hyper-V监控工具 - Hyper-V Gadget
  13. pythonsearch方法_python正则表达式(4)--search方法
  14. linux使用中的问题 --- (cp: missing destination file operand after xxxx)
  15. 趣味项目—MyQQ机器人(二)关于python的pandas根据索引读写指定数据的方法实现签到功能
  16. 斗战神 琵琶之怨获取攻略
  17. esp32--无线控制灯
  18. 当代偷车贼分两种,剪电线的和用智能设备的
  19. 哪种变压器好-如何选择好的变压器-有哪几种型号和规格呢?
  20. 使用全局变量有什么好处?有什么坏处?_一起来了解下:喝贡菊花茶有什么好处、喝菊花茶的好处和坏处...

热门文章

  1. 论文学习20-End-to-end Sequence Labeling via Bi-directional LSTM-CNNs-CRF(序列标注,2016ACL
  2. excel保存超过15位数据不变科学计数法的方法
  3. 如何判断两个IP地址是不是处于同一网段?
  4. Python系列之入门篇——python2.7.13安装
  5. 操作文件 -------JavaScrip
  6. LintCode 373: Partition Array
  7. swiper链接href无效
  8. 哀悼地震遇难者--5月19至21日为全国哀悼日
  9. 数据库高级知识——主从复制
  10. Leetcode--1160.拼写单词(Java)