CEF应用典型特征——ChromiumCEF框架

  js跳转到指定页面并刷新_js刷新当前页面_js 刷新页面浏览器兼容问题

  本文为看雪论坛优秀文章

  看雪论坛作者ID:renbohan

  CEF是Chromium Embedded Framework的缩写,即“Chromium嵌入式框架”,采用c++编写,地位类似于Electron,是web开发应用程序的重要框架,被许多软件包括微信、网易云、生死狙击等采用,是一款十分优秀的嵌入式框架。

  由于一些原因,需要把js注入到某款使用CEF的应用中,通过js代码与应用web进行一些交互,于是乎研究了一下CEF这个框架,并分享注入js代码到第三方CEF应用的一些经验。

  1

  CEF应用典型特征

  文件目录特征很明显:

  <pre class="code-snippet__js" data-lang="css">[cef][10].pak`cef_100_percent.pakcef_200_percent.paklibcef.dll`</pre>

  2

  着手点

  既然CEF功能核心全部都在libcef.dll里面,那么自然首选也是从这个dll入手。

  网上简单搜索CEF的教程后发现,CEF的框架在基础libcef.dll的导出函数的基础上,增加了一层c++类的实现js刷新当前页面js刷新当前页面,实现了c2cpp接口的对接。

  观察官方给出的demo发现,创建浏览器对象,最终会调用libcef.dll!cef_browser_host_create_browser来创建出浏览器。

  而一旦得到浏览器对象,我们就可以根据CEF框架中的头文件,非常方便的执行js代码了。

  所以很自然想到把libcef.dll!cef_browser_host_create_browser给hook掉,然后从中间偷出 cef_browser_t*对象。

  <pre class="code-snippet__js" data-lang="cpp">int cef_browser_host_create_browser(` const cef_window_info_t windowInfo, struct _cef_client_t* client, const cef_string_t url, struct _cef_browser_settings_t* settings, struct _cef_request_context_t* request_context);`</pre>

  然而新的问题马上出现,cef_browser_host_create_browser 是使用异步的方法创建浏览器,因此cef_browser_t对象只会在创建成功的回调函数中才能得到,于是我准备设法从_cef_client_t client这个参数中得到回调地址,然后inline hook掉回调函数(直接改回调地址失败了,估计是地址不可写)。

  js刷新当前页面_js 刷新页面浏览器兼容问题_js跳转到指定页面并刷新

  很不幸的是,虽然获取回调地址很顺利,但是不知什么原因,回调函数始终没有得到调用,因此此路不通,只能另辟蹊径。

  此时完全没有头绪,根本不知道该如何下手了,毕竟cef_browser_t*得不到,想执行js代码根本不可能,无聊之余打开了ApiMonitor,想看看能否从应用的libcef.dll的调用情况中得到一点启发。

  ApiMonitor监视自定义dll的调用情况也非常方便,设置监视的函数为libcef.dll中的全部函数。

  js跳转到指定页面并刷新_js 刷新页面浏览器兼容问题_js刷新当前页面

  然后启动应用,由于浏览器内核特性,应用自然也是多进程的,一个个查看后,其中一个进程调用的api引起我的兴趣。

  js 刷新页面浏览器兼容问题_js跳转到指定页面并刷新_js刷新当前页面

  cef_v8context_get_current_context这个函数的调用瞬间将思路打开。

  看到V8,那这个函数传参或者返回值多半和Javascript分不开了,再去CEF的源码里找找参数或者返回值的含义。

  js跳转到指定页面并刷新_js 刷新页面浏览器兼容问题_js刷新当前页面

  <pre class="code-snippet__js" data-lang="cpp">///`// Returns the current (top) context object in the V8 context stack.///CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context();`</pre>

  惊喜的发现居然没有参数,直接反汇当前V8引擎上下文中最前的context。

  由于browser是与V8js引擎绑定的,所以也可以通过返回值cef_v8context_t*得到browser对象了。

  <pre class="code-snippet__js" data-lang="cpp">cef_browser_t* browser = NULL;`cef_v8context_t* my_cef_v8context_get_current_context() { cef_v8context_t* js_context = ori_cef_v8context_get_current_context(); Print("my_cef_v8context_get_current_context js_context: %X!!n", js_context); browser = js_context->get_browser(js_context); //Print("[!!!] browser = %Xn", browser); _cef_frame_t* frame = browser->get_main_frame(browser); //Print("[!!!] frame = %Xn", frame); CefString script = payload; CefString url = xorstr("app/wd").crypt_get(); frame->execute_java_script(frame, script.GetStruct(), url.GetStruct(), 0); return js_context;`}</pre>

  接下来的事也就水到渠成了,按照网上教程的方法,得到browser过后一切变得简单明了起来。

  而且写完后我发现这样的写法还有个好处,就是可以考虑到页面刷新的情况,因为浏览器一旦页面刷新,重启js虚拟环境,那么浏览器又会主动调取cef_v8context_get_current_context,因此只要我们hook这个函数过后,所有的页面,不管是否刷新,我们都能够注入自己想要的js代码。

  3

  总结

  在时间有限,没有足够时间去完整系统学习一个框架的时候,例如这里的CEF框架,我们依然想快速的实现目标,就必须要开拓思路,不要始终拘泥于网上别人教授的正常/官方方法,有时另辟蹊径反而可以带来意料之外的惊喜。

  研究CEF的前大半部分时间,我始终困在网上一些无比老旧,东搬西凑,复制粘贴的教程中,边抱怨作者,边复制代码,最后还实现不了功能,最后干脆还是只能放弃,进行独立思考,将成果分享给大家。

  4

  参考

  https://stackoverflow.com/questions/54398446/how-do-i-add-a-access-control-allow-origin-to-a-requested-resource-with-a-cust

  js跳转到指定页面并刷新_js 刷新页面浏览器兼容问题_js刷新当前页面

  看雪ID:renbohan

  *本文由看雪论坛 renbohan原创,转载请注明来自看雪社区

  #往期推荐

  1.

  2.

  3.

  4.

  5.

  6.

  js刷新当前页面_js 刷新页面浏览器兼容问题_js跳转到指定页面并刷新

  公众号ID:ikanxue

  官方微博:看雪安全

  商务合作:wsc@kanxue.com

  js跳转到指定页面并刷新_js刷新当前页面_js 刷新页面浏览器兼容问题

文章由官网发布,如若转载,请注明出处:https://www.veimoz.com/1911
0 评论
1.7k

发表评论

!