首页
社区
课程
招聘
[原创]向Typora学习electron安全攻防
发表于: 2022-5-3 23:02 21834

[原创]向Typora学习electron安全攻防

2022-5-3 23:02
21834

@钞能力大叔

目标应用: 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_utf8napi_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]);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2022-5-3 23:05 被钞能力大叔编辑 ,原因:
收藏
免费 9
支持
分享
打赏 + 80.00雪花
打赏次数 1 雪花 + 80.00
 
赞赏  Editor   +80.00 2022/06/23 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (30)
雪    币: 2324
活跃值: (5093)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
frida 怎么在这里使用?
2022-5-4 09:48
0
雪    币: 439
活跃值: (422)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
值得怀疑 frida 怎么在这里使用?
frida "安装路径/Typora.exe" -l 脚本
2022-5-4 10:42
0
雪    币: 302
活跃值: (928)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4

学习了

最后于 2022-5-4 13:00 被pUnicorn编辑 ,原因:
2022-5-4 12:59
0
雪    币: 4049
活跃值: (3093)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
5

楼主可否用最新版本的Typora详细解释一下,有些看不懂啊,我尝试在内存代码中加入 s = true ; 但是失败了,报错提示 意外的标识符

最后于 2022-5-4 15:06 被yumoqaq编辑 ,原因:
2022-5-4 15:04
0
雪    币: 439
活跃值: (422)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
yumoqaq 楼主可否用最新版本的Typora详细解释一下,有些看不懂啊,我尝试在内存代码中加入 s = true ; 但是 ...
最新版可用哦,内存替换没试过,不过意外的标识符,应该是语法错了,你可以把替换后的js存出来,检查下语法。
2022-5-4 16:09
0
雪    币: 4049
活跃值: (3093)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
7
钞能力大叔 最新版可用哦,内存替换没试过,不过意外的标识符,应该是语法错了,你可以把替换后的js存出来,检查下语法。

我测试的是1.25版,前几天下的,真不行啊。。所有关联的地方都调整了,报错 无效或意外的token , 楼主方便的话可以交流一下吗 ,我现在的疑惑是 版本问题还是内存破解不可行。。 或者楼主可以发我一份1.25破解的版本让我研究一下吗。。

最后于 2022-5-4 18:10 被yumoqaq编辑 ,原因:
2022-5-4 18:01
0
雪    币: 439
活跃值: (422)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
yumoqaq 钞能力大叔 最新版可用哦,内存替换没试过,不过意外的标识符,应该是语法错了,你可以把替换后的js存出来,检查下语法。 我测试的是1.25版,前几 ...
你说的这种情况,每次启动都会调用接口校验的,内存补丁的方案并没有直接改代码来的方便。 我这边测试1.2.5 32、64都没问题。
2022-5-4 18:25
0
雪    币: 231
活跃值: (640)
能力值: ( LV4,RANK:41 )
在线值:
发帖
回帖
粉丝
9

按照该篇写的crack,复制到 C:\Program Files\Typora 运行 typora_with_pro.exe 即可


将 "hasActivated=${s||!1}"修改为"hasActivated=${s||!0}"

上传的附件:
2022-5-5 16:03
0
雪    币: 439
活跃值: (422)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
wx_卖女孩的小火柴_588616 按照该篇写的crack,复制到 C:\Program Files\Typora 运行 typora_with_pro.exe 即可将 "hasAc ...
s是全局变量,这么改只是在激活页面呈现出“已激活”的效果而已。
2022-5-6 09:29
0
雪    币: 231
活跃值: (640)
能力值: ( LV4,RANK:41 )
在线值:
发帖
回帖
粉丝
11
钞能力大叔 s是全局变量,这么改只是在激活页面呈现出“已激活”的效果而已。

我又改了一下,可以完美破解了


替换字符串如下:

;; 移除签名
const n;;/*
`,t\);;*/
JSON\.parse\(n\.;;JSON.parse(t.

;; 破解网络验证, 本机自动生成
async function\(e,t,n\){.*}\(t,n,o\);;async function(e,t,n){t={fingerprint:await M(),email:e,license:t,type:global.devVersion?"dev":""};return await Z(await Buffer.from(JSON.stringify(t),"utf8").toString("base64"))?[!0,""]:[!1,"Please input a valid license code"];}(t,n,o)

;; 破解renew
\(H\(o,n,i\),B\(t,e\)\);;H(o,n,i)

修改后,需要激活一次(本机)就可以了,再次启动不会弹框。


如果版本更新了,可以修改 typora_with.txt 导出最新的js,然后做相应的补丁,当前版本: 1.2.5 。

上传的附件:
2022-5-6 15:51
0
雪    币: 4049
活跃值: (3093)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
12
wx_卖女孩的小火柴_588616 我又改了一下,可以完美破解了替换字符串如下:;; 移除签名 const n;;/* `,t\);;*/ JSON\.parse\(n\.;;JSON.pars ...
大哥能发我一份修改后的js代码吗
2022-5-6 18:31
0
雪    币: 231
活跃值: (640)
能力值: ( LV4,RANK:41 )
在线值:
发帖
回帖
粉丝
13
yumoqaq 大哥能发我一份修改后的js代码吗

0.js 是修改后的, 1.js 是修改前的,实际上可以查看补丁直接替换就好了

上传的附件:
  • 0.js (260.76kb,73次下载)
  • 1.js (260.73kb,57次下载)
2022-5-7 09:09
0
雪    币: 11093
活跃值: (3030)
能力值: ( LV5,RANK:71 )
在线值:
发帖
回帖
粉丝
14
请教下electron能不能动态执行个runjavascript,可以的话该怎么跟踪呢
2022-5-7 15:36
0
雪    币: 5354
活跃值: (3582)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15

赞!

最后于 2022-5-7 17:00 被lylxd编辑 ,原因:
2022-5-7 16:16
0
雪    币: 461
活跃值: (2808)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
赞!
2022-5-10 09:00
0
雪    币: 5301
活跃值: (9873)
能力值: ( LV9,RANK:181 )
在线值:
发帖
回帖
粉丝
17

看之前的破解,有人提出来对asar可以进行文件劫持,直接将修改后的License.js放置到"resources\node_modules\"下面,加载优先级会先加载这个文件。不用再打包回去了!

最后于 2022-5-10 09:46 被nevinhappy编辑 ,原因:
上传的附件:
2022-5-10 09:44
0
雪    币: 2119
活跃值: (1890)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
18
赞!
2022-5-10 15:45
0
雪    币: 58
活跃值: (1145)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
nevinhappy 看之前的破解,有人提出来对asar可以进行文件劫持,直接将修改后的License.js放置到"resources\node_modules\"下面,加载优先级会先加 ...
这个不行,放进去还是没激活
2022-5-10 21:02
0
雪    币: 3386
活跃值: (1413)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
20
这个是老版本的,新版的叫Atom.js。而且还加了AES解密,所以之前的劫持是不能用的了。
2022-5-10 21:33
0
雪    币: 247
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21

楼主,1.25版本修改了js,运行程序后,报错显示解密后的js文件最前部有乱码。猜测是我的加密和打包方式有误,想请教一下您用的方法

最后于 2022-5-11 01:46 被Y4WN编辑 ,原因:
2022-5-10 23:31
0
雪    币: 439
活跃值: (422)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
Y4WN 楼主,1.25版本修改了js,运行程序后,报错显示解密后的js文件最前部有乱码。猜测是我的加密和打包方式有误,想请教一下您用的方法
检查下是不是 utf8编码 跟 utf8-bom编码的问题。 
2022-5-11 10:51
0
雪    币: 247
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
钞能力大叔 检查下是不是 utf8编码 跟 utf8-bom编码的问题。

问题解决,加解密的脚本问题(需要好好学汇编

最后于 2022-5-12 11:53 被Y4WN编辑 ,原因:
2022-5-11 12:23
0
雪    币: 38
活跃值: (1931)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
Y4WN 检查了,不是utf编码原因,但乱码16字节,之后是正确的js代码
我的也是执行0.js失败的,我的是utf8编码
2022-5-11 15:33
0
雪    币: 228
活跃值: (183)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
wx_卖女孩的小火柴_588616 我又改了一下,可以完美破解了替换字符串如下:;; 移除签名 const n;;/* `,t\);;*/ JSON\.parse\(n\.;;JSON.pars ...
可以发份源码么,想学习一下
2022-7-17 02:04
0
游客
登录 | 注册 方可回帖
返回
//