• 【electron】【附排查清单】记录一次逆向过程中,fetch无法请求http的疑难杂症(net::ERR_BLOCKED_BY_CLIENT)


    🛫 导读

    需求

    逆向某electron应用,需要在其中执行http请求,结果返回错误net::ERR_BLOCKED_BY_CLIENT,为了解决该问题,又遇到无数其它问题,特此记录,以敬后效。

    开发环境

    版本号描述
    文章日期2023-11-07
    操作系统Win10 - 22H219045.3570
    示例工作目录J:\_ALL\JOB\sw\_nginx\map-ys执行json-server服务器

    1️⃣ Adblock等插件拦截

    搜索net::ERR_BLOCKED_BY_CLIENT,网上给出最多的结论就是各种插件拦截。可是小编用的软件,在dev tools中很明显没有加载任何插件。
    也查了很多dev tools选项,修改后都没有解决问题。

    2️⃣ 【失败】Content-Security-Policy

    紧接着,查到的就是CORS(Cross-Origin Resource Sharing),也就是传说中的跨域问题。

    启动服务器json-server

    这里先说下,小编用的是json-server搭建的服务器,启动命令为:json-server -p 16010 db.json -s .

    请求的js语句为fetch('http://127.0.0.1:16010/posts')

    html中的meta字段

    参考文章《MDN:CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP》,我们可以知道,html中的meta会设置CSP,目标应用的内容如下:

    我们可以看出,它并不包含目标地址127.0.0.1:16010,于是执行了下述两种尝试:

    1. 将目标请求地址给它加上去,如下所示:
    2. 删除上述meta项。

    重新编译打包后测试,依然不能成功。

    3️⃣ 【失败】https vs http

    目标electron应用本身需要请求https,小编请求的是http,于是猜测应用对http做了限制。
    于是增加了下面两次尝试,均以失败告终。

    webPreferences & allowRunningInsecureContent

    参考文章《electron配置允许跨域(前端解决方案) https://blog.csdn.net/sinat_39826352/article/details/108537797
    将main.js中,所有的webPreferences对象增加下面属性。

    new BrowserWindow({
    	webPreferences:{//网页功能的设置
    	  // nodeIntegration: true,//是否集成node
    	  // devTools:false,//是否开启 DevTools
    	  webSecurity: false, //是否禁用同源策略(上线时删除此配置)
    	  allowRunningInsecureContent: true,
    	  // ...
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    disable-features

    添加命令行

    	//解决10.X版本跨域不成功问题(上线删除)
    	app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors');
    
    • 1
    • 2

    4️⃣ 【失败】检测fetch

    fetch被魔改了

    执行fetch,发现该命令如下,指向某函数,说明被魔改了。
    在这里插入图片描述

    正常的fetch应该如下所示:
    ps: bh.fetch是小编备份的一个fetch代码,为native code
    在这里插入图片描述

    将fetch被赋值的地方注释掉,依然无法访问。

    5️⃣ 【失败】使用axios

    虽然上面修正了fetch,但是依然担心fetch有问题,于是乎,尝试用第三方库axios测试。

    插入axios库

    在本地任意找一份node_modules\axios\dist\browser\axios.cjs,将代码添加到目标进程的render中(如:app-bundle.js),这样我们就可以使用axios了,不过依然返回net::ERR_BLOCKED_BY_CLIENT错误。

    6️⃣ 【成功】require(‘http’)

    从上面的各种尝试中,我们可以看出,通过浏览器js各种失败,那么通过nodejs呢。
    require加载模块,发现可以加载http模块,使用下面代码请求,终于可以请求到数据了。
    不过该方案太过繁琐,继续分析吧

    var http = require('http');
     
    function post(action,send,callback){
    	var options = {
    	  hostname: '127.0.0.1',
    	  port: 16010,
    	  path: action,
    	  method: 'POST',
    	  headers: {
    		'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'/* ,
    		'Content-Length': send.length */
    	  }
    	};
    	var req = http.request(options, function (res) {
    		// console.log('STATUS: ' + res.statusCode);  
    		// console.log('HEADERS: ' + JSON.stringify(res.headers));  
            // 定义了一个post变量,用于暂存请求体的信息
    		var body="";
    		res.setEncoding('utf8');
            // 通过res的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
    		res.on('data', function (chunk) {
    			// console.log('BODY: ' + chunk);
                body += chunk;
    		});
            // 在res的end事件触发后,通过JSON.parse将post解析为真正的POST请求格式,然后调用传递过来的回调函数处理数据
    		res.on('end', function(){
    			// console.log("body = "+body);
    			var json = JSON.parse(body);
    			callback(json);
    		});
    	});
    	req.on('error', function (e) {
    	  console.log('problem with request: ' + e.message);
    	});
    	req.write(send);
    	req.end();
    }
    post('/posts', '{"id":3}', ()=>{})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    7️⃣ 【完美解决】取消webRequest.onBeforeRequest

    还是从httphttps思考,为什么唯独http无法访问,难道是electron中有代码拦截了http请求?

    • 使用其它electron应用,http可以正常访问。更加确信猜想。
    • 在electron应用的主进程代码中,搜索http关键字,找到如下代码,注释掉居然真的可以访问了。
    function blockHttpRequests() {
    	// 注释掉
    	return;
    	var e;
    	i()
    	  .session.fromPartition(
    	    (e = g.windowOptions.webPreferences.partition) !== null &&
    	      e !== void 0
    	      ? e
    	      : ""
    	  )
    	  .webRequest.onBeforeRequest({ urls: ["http://*/*"] }, (e, t) => {
    	    t({
    	      cancel:
    	        e.webContents && e.webContents.getURL().startsWith("file://"),
    	    });
    	  });
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    🛬 文章小结

    文章中的每一次尝试都有大量的知识点,每次都查了大量的文章。
    electron很复杂,尤其是像本次遇到的问题,可以通过多种方式实现,所以我们需要一次次的尝试,排除错误答案,最终找到正确的解决方案。

    📖 参考资料

    ps: 文章中内容仅用于技术交流,请勿用于违规违法行为。

  • 相关阅读:
    vite.config.js或者vue.config.js配置
    如何在快节奏的生活下摆脱焦虑?
    【Python】python中多进程处理
    C/C++内存管理
    【Kotlin 协程】协程的挂起和恢复 ② ( 协程挂起 和 线程阻塞 对比 )
    1.3 矩阵
    git worktree与分支依赖隔离
    python中json.dumps将中文变成unicode字符的解决办法
    【Python】pyecharts 模块 ② ( 命令行安装 pyecharts 模块 | PyCharm 安装 pyecharts 模块 )
    【云原生 】Kubernetes(k8s)标签详解
  • 原文地址:https://blog.csdn.net/kinghzking/article/details/134274358