高考后的第一次发帖^-^
CEF
是Chromium Embedded Framework
的缩写,即“Chromium嵌入式框架”,采用c++编写,地位类似于Electron,是web开发应用程序的重要框架,被许多软件包括微信,网易云,生死狙击等采用,是一款十分优秀的嵌入式框架
由于一些原因,需要把js注入到某款使用CEF的应用中,通过js代码与应用web进行一些交互,于是乎研究了一下CEF这个框架,并分享注入js代码到第三方CEF应用的一些经验
文件目录特征很明显
既然CEF功能核心全部都在libcef.dll里面,那么自然首选也是从这个dll入手
网上简单搜索CEF的教程后发现,CEF的框架在基础libcef.dll的导出函数的基础上,增加了一层c++类的实现,实现了c2cpp接口的对接
观察官方给出的demo发现,创建浏览器对象,最终会调用libcef.dll!cef_browser_host_create_browser
来创建出浏览器
而一旦得到浏览器对象,我们就可以根据CEF框架中的头文件,非常方便的执行js代码了
所以很自然想到把libcef.dll!cef_browser_host_create_browser
给hook掉,然后从中间偷出 cef_browser_t*
对象
然而新的问题马上出现,cef_browser_host_create_browser
是使用异步的方法创建浏览器,因此cef_browser_t*
对象只会在创建成功的回调函数中才能得到,于是我准备设法从_cef_client_t* client
这个参数中得到回调地址,然后inline hook掉回调函数(直接改回调地址失败了,估计是地址不可写)
很不幸的是,虽然获取回调地址很顺利,但是不知什么原因,回调函数始终没有得到调用,因此此路不通,只能另辟蹊径
此时完全没有头绪,根本不知道该如何下手了,毕竟cef_browser_t*
得不到,想执行js代码根本不可能,无聊之余打开了ApiMonitor,想看看能否从应用的libcef.dll
的调用情况中得到一点启发
ApiMonitor监视自定义dll的调用情况也非常方便,设置监视的函数为libcef.dll
中的全部函数

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


cef_v8context_get_current_context
这个函数的调用瞬间将思路打开
看到V8,那这个函数传参或者返回值多半和Javascript分不开了,再去CEF的源码里找找参数或者返回值的含义
惊喜的发现居然没有参数,直接反汇当前V8引擎上下文中最前的context
由于browser是与V8js引擎绑定的,所以也可以通过返回值cef_v8context_t*
得到browser对象了
接下来的事也就水到渠成了,按照网上教程的方法,得到browser过后一切变得简单明了起来
而且写完后我发现这样的写法还有个好处,就是可以考虑到页面刷新的情况,因为浏览器一旦页面刷新,重启js虚拟环境,那么浏览器又会主动调取cef_v8context_get_current_context
,因此只要我们hook这个函数过后,所有的页面,不管是否刷新,我们都能够注入自己想要的js代码
在时间有限,没有足够时间去完整系统学习一个框架的时候,例如这里的CEF框架,我们依然想快速的实现目标,就必须要开拓思路,不要始终拘泥于网上别人教授的正常/官方方法,有时另辟蹊径反而可以带来意料之外的惊喜
研究CEF的前大半部分时间,我始终困在网上一些无比老旧,东搬西凑,复制粘贴的教程中,边抱怨作者的脑瘫,边复制着脑瘫的代码,最后还实现不了脑瘫的功能,最后干脆还是只能放弃,进行独立思考,将成果分享给大家
c3fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8X3N6S2k6$3p5K6z5e0t1@1y4U0b7%4z5o6u0Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0b7&6y4o6V1H3x3e0l9I4i4K6y4r3M7%4m8E0i4K6y4p5x3e0l9H3x3g2)9J5k6e0t1H3x3e0c8Q4x3X3f1K6x3o6l9I4i4K6u0W2y4e0f1H3x3R3`.`.
fcfK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6*7K9s2g2S2L8X3I4S2L8W2)9J5k6i4A6Z5K9h3S2#2i4K6u0W2j5$3!0E0i4K6u0r3M7q4)9J5c8U0t1&6x3o6M7%4y4U0R3$3
b8aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6N6r3q4U0K9$3!0$3k6i4u0X3L8r3!0%4i4K6u0W2j5$3!0E0i4K6u0r3M7i4g2W2M7%4c8A6L8$3&6K6i4K6u0r3y4e0b7K6z5e0R3@1y4o6k6Q4x3V1k6Z5L8%4N6Q4x3X3c8V1L8#2)9J5k6r3W2Q4x3X3c8S2k6r3c8Q4x3X3c8S2i4K6u0V1j5h3y4U0k6i4y4K6i4K6u0V1j5$3!0F1N6s2u0G2L8q4)9J5k6r3q4D9L8r3!0%4i4K6u0V1L8%4u0A6k6$3W2F1i4K6u0V1N6r3!0Q4x3X3c8S2i4K6u0V1M7X3g2I4N6h3g2K6N6r3g2V1i4K6u0V1M7X3g2K6L8%4g2J5j5$3g2Q4x3X3c8%4K9i4c8Z5i4K6u0V1j5g2)9J5k6r3y4#2M7%4b7`.
3dfK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8X3N6S2k6$3p5K6z5e0t1@1y4U0b7%4z5o6u0Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0b7&6y4o6V1H3x3e0l9I4i4K6y4r3M7%4m8E0i4K6y4p5x3e0l9H3x3g2)9J5k6e0t1H3x3e0c8Q4x3X3f1K6x3o6l9I4i4K6u0W2y4e0f1H3x3R3`.`.
cef.pak
cef_100_percent.pak
cef_200_percent.pak
libcef.dll
cef.pak
cef_100_percent.pak
cef_200_percent.pak
libcef.dll
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);
int
cef_browser_host_create_browser(
const cef_window_info_t
*
windowInfo,
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课