向Typora學習electron安全攻防
本文為看雪論壇優秀文章
看雪論壇作者ID:鈔能力大叔
目標應用: aHR0cHM6Ly90eXBvcmEuaW8v
越來越多的應用開始使用 electron 來構建跨平臺桌面應用。從實現方式上來說,其本質還是基於chrome核心的html、js、css構成的應用,基於瀏覽器,程式碼必定會暴露在使用者側,任何加密手段只是增加破解門檻跟時間成本而已。
認識electron專案檔案目錄特徵
electron打包的專案,最常見的就是 asar 格式的私有編碼檔案,裡面包含檔名、大小、內容偏移量等資料,按檔案頭部的 json內容 解析即可提取出所有檔案。
electron asar解包
目前來說,官方的版本並沒有提供保護原始碼的方法。在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。
萬能js提取方案
已知經過編譯後的node檔案, 在執行前,都會呼叫 napi_create_string_utf8 建立js字串,所以在呼叫該函式的時候,基於electron沒有自帶加密的特性,想要執行js流程,必定會傳遞明文,所以在載入流程上截斷,就可以匯出解密後的資料。
直接上frida大法:
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('繫結失敗');
}
解包專案中的所有 asar檔案,就能拿到所有的原始碼,並且把解壓的資料夾,改成對應的 asar 檔名即可正常執行專案,無需重打包即可除錯。
無限試用思路
刪除登錄檔鍵,讓程式認為是第一次安裝。
不想進入登錄檔這個繁瑣的話,可以儲存下面的程式碼, 把名字改成 xxx.reg, 雙擊執行即可無限暢玩。
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Typora]
"IDate"="1/24/9999"
"SLicense"=""
去除授權功能實現單機版本思路
將所有的網路驗證給他刪掉/註釋掉, 也可以直接把 “是否授權” 的變數,改成true即可。
註冊機思路
由於該示例使用了rsa解密,所以要基於官方版本編寫註冊機就不太行了。一定要出注冊機的話,需要先替換截圖部分的rsa公鑰即可。
這個地方使用了node自帶的公鑰解密,一些語言好像不能直接生成(可能我的開啟方式不對),我就直接給出node版本的建立例項。
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const keyPair = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: ''
}
});
fs.writeFileSync("public_key.pem", keyPair.publicKey);
fs.writeFileSync("private_key.pem", keyPair.privateKey);
生成後的公鑰, 覆蓋即可,然後編寫自己的註冊機。
自建授權閘道器實現註冊機思路
自建閘道器的話,可以把應用自帶的域名,替換成自己的,然後按介面需要的返回值,給他返回響應的資料格式即可。這個例項僅需要修改兩處即可。
介面就不提供了,放張效果圖:
重打包發版思路
把解壓的資料夾打包回 asar格式的檔案即可, 這個網上一大把資料。
對於electron加密方式的思考
相對於原生開發來說,js安全做客戶端畢竟薄弱,UI互動是沒問題的,關鍵程式碼可以放到dll、so層去做,但是也沒辦法避免從js層面去剝離dll層函式的呼叫。所以目前來說並沒有很好的解決方案,本文只是起到拋磚引玉的作用。期待electron有更好、更安全的解決方案。
看雪ID:鈔能力大叔
https://bbs.pediy.com/user-home-860779.htm
*本文由看雪論壇 鈔能力大叔 原創,轉載請註明來自看雪社群
往期推薦
1. 遊戲安全之借坡下驢
5. Android Hook技術學習——常見的Hook技術方案總結
球分享
球點贊
球在看

點選“閱讀原文”,瞭解更多!
- android so檔案攻防實戰-libDexHelper.so反混淆
- 利用Frida破解黑盒環境的Dex函式抽取殼
- 繞過iOS 基於svc 0x80的ptrace反除錯
- Android APP漏洞之戰——SQL注入漏洞初探
- House of apple 一種新的glibc中IO攻擊方法
- 從PWN題NULL_FXCK中學到的glibc知識
- 指令級工具Dobby原始碼閱讀
- sql注入學習筆記
- Android題目分析部分思路總結
- 恭喜ID[飛翔的貓咪]獲看雪安卓應用安全能力認證高階安全工程師!
- React Native Hermes 逆向實踐
- 2022CISCN初賽 ez_usb WriteUp
- Flutter APP逆向實踐
- BattlEye核心驅動檢測模組深入分析
- CVE-2019-1458提權漏洞學習筆記
- PWN 堆利用 unlink 學習筆記
- Frida工作原理學習
- CTF反序列化入門
- CVE-2017-0263提權漏洞學習筆記
- Android漏洞之戰——整體加殼原理和脫殼技巧詳解