@钞能力大叔
目标应用: aHR0cHM6Ly90eXBvcmEuaW8v
越来越多的应用开始使用 electron
来构建跨平台桌面应用。从实现方式上来说,其本质还是基于chrome内核的html、js、css构成的应用,基于浏览器,代码必定会暴露在用户侧,任何加密手段只是增加破解门槛跟时间成本而已。
electron打包的项目,最常见的就是 asar
格式的私有编码文件,里面包含文件名、大小、内容偏移量等数据,按文件头部的 json内容 解析即可提取出所有文件。
目前来说,官方的版本并没有提供保护源码的方法。在github开源的找到个大神提供的解决方案(https://github.com/toyobayashi/electron-asar-encrypt-demo) ,该方案可以把启动文件编译为node二进制文件,作为启动入口,来保护薄弱的js代码。在项目启动时,将加密后的代码进行解密,交回electron流程进行执行,从而避免上述步骤直接解包拿到源代码的可能。
经过分析对比,typora用的恰好是这个demo提供的思路。
找到上述步骤解压成功的 package.json
文件,main
属性就是 electron 项目启动的主入口。 把 main.node
拖到ida中, 分析执行流程。
结合 electron-asar-encrypt-demo
跟 IDA伪代码, 可以定位到两个关键函数 napi_create_string_utf8
跟 napi_call_function
已知经过编译后的node文件, 在执行前,都会调用 napi_create_string_utf8
创建js字符串,所以在调用该函数的时候,基于electron没有自带加密的特性,想要运行js流程,必定会传递明文,所以在加载流程上截断,就可以导出解密后的数据。
直接上frida大法
解包项目中的所有 asar
文件,就能拿到所有的源代码,并且把解压的文件夹,改成对应的 asar
文件名即可正常运行项目,无需重打包即可调试。
删除注册表键,让程序认为是第一次安装
不想进入注册表这个繁琐的话,可以保存下面的代码, 把名字改成 xxx.reg
, 双击运行即可无限畅玩。
将所有的网络验证给他删掉/注释掉, 也可以直接把 “是否授权” 的变量,改成true即可。
由于该示例使用了rsa解密,所以要基于官方版本编写注册机就不太行了。一定要出注册机的话,需要先替换截图部分的rsa公钥即可。
这个地方使用了node自带的公钥解密,一些语言好像不能直接生成(可能我的打开方式不对),我就直接给出node版本的创建实例。
生成后的公钥, 覆盖即可,然后编写自己的注册机。
自建网关的话,可以把应用自带的域名,替换成自己的,然后按接口需要的返回值,给他返回响应的数据格式即可。 这个实例仅需要修改两处即可。
接口就不提供了,放张效果图
把解压的文件夹打包回 asar
格式的文件即可, 这个网上一大把资料。
相对于原生开发来说,js安全做客户端毕竟薄弱,UI交互是没问题的,关键代码可以放到dll、so层去做,但是也没办法避免从js层面去剥离dll层函数的调用。所以目前来说并没有很好的解决方案,本文只是起到抛砖引玉的作用。期待electron有更好、更安全的解决方案。
let napi_create_string_utf8
=
Module.getExportByName(null,
'napi_create_string_utf8'
);
var index
=
0
;
if
(napi_create_string_utf8) {
console.log(
'绑定成功'
);
Interceptor.attach(napi_create_string_utf8, {
onEnter: function (args) {
console.log(
'napi_create_string_utf8'
,
'调用'
, args[
0
], args[
1
].readCString().substring(
0
,
100
), args[
2
], args[
3
]);
if
(args[
2
].toInt32() >
100
) {
/
/
过滤出大文件
index
+
=
1
;
var f
=
new
File
(
'export_'
+
String(index)
+
'.js'
,
'wb'
);
f.write(args[
1
].readByteArray(args[
2
].toInt32()));
f.flush();
f.close();
}
}
});
}
else
{
console.log(
'绑定失败'
);
}
let napi_create_string_utf8
=
Module.getExportByName(null,
'napi_create_string_utf8'
);
var index
=
0
;
if
(napi_create_string_utf8) {
console.log(
'绑定成功'
);
Interceptor.attach(napi_create_string_utf8, {
onEnter: function (args) {
console.log(
'napi_create_string_utf8'
,
'调用'
, args[
0
], args[
1
].readCString().substring(
0
,
100
), args[
2
], args[
3
]);
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2022-5-3 23:05
被钞能力大叔编辑
,原因: