破解Typora复现 上——初识AES-256加密算法

查看 60|回复 10
作者:Pologue   
目的
发表这篇帖子的目的主要是分享一些在破解Typora的AES加密过程中可能需要的背景知识和经验,希望能帮助一些和我一样的新手。
过程
背景知识

  • Typora采用的框架是Electron。

  • 调试它的可执行文件还是得用上反汇编软件,例如IDA。

  • asar是一种打包方式,可以直接用nodejs的asar提取出来,没有加密。

  • AES是一种块加密,也就是把明文划分成相同大小的块再进行加密,加密用的密钥叫key。AES-128、192、256用到的key长度分别是16byte、24byte、32byte。这里Typora用到的是AES-256,所以key的长度是32byte。[^3][^4]


    aes_details.jpg (228.91 KB, 下载次数: 0)
    下载附件
    details
    2024-11-21 00:35 上传



    aes_enc_dec.png (251.12 KB, 下载次数: 0)
    下载附件
    enc_dec
    2024-11-21 00:40 上传

  • AES加密和解密会分别用到两个256byte的矩阵,叫SBox和InvBox。它们的值是固定的,所以可以通过IDA的FindCrypt插件找出来。

  • 块加密有不同的模式,有CBC、ECB、CFB等等。其中ECB是每个明文块分别加密;CBC和CFB是把上一块的密文和当前块的明文做异或后再加密,区别是它们俩明文与密文做异或的时机不一样。在这里Typora用的是CBC模式。[^9]

  • CBC这种加密方式需要在第一个加密的周期前面再加一个初始的“与明文做异或”的块,就叫iv(initial vector)。因为AES的块是一个4x4的格子,长度为16byte,所以iv的长度就是16byte

    整体介绍
    Typora通过app.asar里的main.node模块(实际为dll动态链接库文件)加载atom.js中关于验证license的代码,atom.js通过AES-256加密后用base64编码,以密文的形式存储。解密的过程就发生在main.node中。[^1][^2]
    破解的思路是找到AES加密的key和iv,修改解密出来的验证license的代码,再将修改过的代码加密,替换掉原来的atom.js,再重新打包。所以整个过程大概可以分成两个部分:AES解密和patch JavaScript代码。因为不太熟悉后面这部分,估计还得花点时间搞,所以我打算下次再写。
    听说还有一种更方便的方法是hook,不过我还没怎么搞明白。
    文件结构
    在Typora的安装路径下,有Typora.exe可执行文件,它会使用resources/app.asar.unpacked中的main.node来动态加载app.asar,再解密里面的atom.js。我们自己打开app.asar后里面会3个文件,其他两个都不用管,重点关注这个atom.js就好了。
    Typora
    ➜  tree -L 3
    .
    ├── chrome_100_percent.pak
    ├── chrome_200_percent.pak
    ├── d3dcompiler_47.dll
    ├── DO NOT ADD FILES HERE
    ├── ffmpeg.dll
    ├── icudtl.dat
    ├── libEGL.dll
    ├── libGLESv2.dll
    ├── LICENSE
    ├── LICENSES.chromium.html
    ├── locales
    │   ├── uk.pak
    |   ...
    │   ├── zh-CN.pak
    │   └── zh-TW.pak
    ├── resources
    │   ├── app.asar
    │   ├── app.asar.unpacked
    |   |   └── main.node
    │   ├── appsrc
    │   ├── assets
    │   ├── conf.default.json
    │   ├── Docs
    │   ├── DO NOT ADD FILES HERE
    │   ├── html
    │   ├── lib.asar
    │   ├── locales
    │   ├── node_modules
    │   ├── node_modules.asar
    │   ├── package.json
    │   ├── page-dist
    │   ├── style
    │   ├── updater
    │   └── window.html
    ├── resources.pak
    ├── snapshot_blob.bin
    ├── Typora.exe
    ├── Typora.VisualElementsManifest.xml
    ├── unins000.dat
    ├── unins000.exe
    ├── v8_context_snapshot.bin
    ├── version
    ├── vk_swiftshader.dll
    ├── vk_swiftshader_icd.json
    └── vulkan-1.dll
    听说这个“chrome_100_percent.pak”“chrome_200_percent.pak”是Electron框架的一个特征。^10
    简单提取一下:npx asar extract app.asar app.asar.manual
    Typora/resources/app.asar.manual
    ➜  tree
    .
    ├── atom.js
    ├── main.node
    └── package.json
    步骤
    [ol]

  • 通过IDA打开main.node。IDA会自动识别文件类型,然后自动勾选一些选项。


    ida_open.png (78.96 KB, 下载次数: 0)
    下载附件
    2024-11-21 00:41 上传

  • Shift+F12打开字符串搜索,找到“./atom.js”,双击点进去,F5自动生成伪代码,估计就是用这个函数加载的密文。把函数名“sub_xxxx”改成“load_atomjs”这种方便理解的名字。点击函数名,按N即可修改,后面分析伪代码修改变量名也是这样。


    ida_strings.png (440.79 KB, 下载次数: 0)
    下载附件
    2024-11-21 00:41 上传



    ida_load_atomjs.png (533.38 KB, 下载次数: 0)
    下载附件
    load_atomjs
    2024-11-21 00:40 上传



    ida_load_atomjs_asm.png (524.37 KB, 下载次数: 0)
    下载附件
    asm
    2024-11-21 00:40 上传

  • Ctrl+Alt+F使用FindCrypt插件,或者在工具栏Edit/Plugins/下点开,可以找到两个RijinDaelSBox和InvBox。第二个IDA的识别有一点错误,把后面的不相干的数据也划成InvBox的了,小键盘*修改Array的大小为256byte。我们要找解密的过程,所以要找用了InvBox的函数。双击InvBox进去,可以把函数重命名为“load_invbox”。右边分号后面的是汇编代码的注释,可以看到“DATA XREF: sub_xxxx”,这是IDA自动生成的,代表IDA找到的引用了这个数据的函数,可以双击点进去。


    ida_findcrypt.png (299.5 KB, 下载次数: 0)
    下载附件
    findcrypt
    2024-11-21 00:40 上传



    ida_invbox.png (649.15 KB, 下载次数: 0)
    下载附件
    invbox
    2024-11-21 00:40 上传

  • 在汇编代码窗口按X查看当前函数的交叉引用,工具栏View/Graphs可以查看调用当前函数和当前函数调用的关系图。可以看到重命名后IDA自动把单纯调用“load_invbox”的函数命名为了“j_load_invbox”。


    ida_xref.png (500.82 KB, 下载次数: 0)
    下载附件
    2024-11-21 00:41 上传

  • “load_invbox”函数的伪代码的结构很像AES解密的流程[^8],我们把其中的循环结构标记出来后就更清晰了。将伪代码中无意义的v1、v2的变量名重命名为有实际意义的变量名,以及通过/添加注释,可以降低理解代码的难度。


    ida_load_invbox.png (431.09 KB, 下载次数: 0)
    下载附件
    load_invbox
    2024-11-21 00:40 上传

  • 找到表示密文的变量并重命名,下断点,动态调试,双击变量名。右键调试窗口的hex子窗口,synchronized with汇编窗口,再取消同步,多走几步可以看到数据一行一行地变为“require…”开头的明文。因为AES-256的key在做key expansion的时候,头两轮的key分别是原key的前后两段;而在解密中这两段key会用在最后两次AddRoundKey中。因为第一次找的时候我没找到key具体存放在哪里,所以我们可以异或密文和明文得到key来曲线救国。


    ida_debug.png (466.29 KB, 下载次数: 0)
    下载附件
    debug
    2024-11-21 00:40 上传

  • 在旧版的Typora中,iv就是密文的前16byte,在1.9.5中已经不是了。奈何我实在没看懂iv到底是在哪里,所以我就求助于比较新的教程^5^7,把教程中标注为iv的变量标注为iv,动态调试得到它的值。

  • 在CyberChef中选择cbc模式解密失败,选择cbc/no padding模式成功了,但是明文的末尾有一串非ascii字符串。我猜测是CyberChef自动去除padding时不能判断哪里是padding。
    [/ol]
    其他

  • IDA的颜色
    1,2两篇教程的ida的theme都设置成了护眼的黑色,而非默认的米黄色,第2篇米黄色背景的软件是x64dbg

  • CyberChef
    第1篇教程保存按钮的软件是notepad++,两篇都用到了CyberChef(BAKE!)

    参考链接
    [^1]: [原创] Typora 授权解密与剖析
    [^2]: [原创] Typora 1.0.4版本破解复现
    [^4]: CTF Wiki AES
    [^5]: [原创]Typora 破解 之 逆向分析(上)
    [^8]: 从零实现 AES 加密算法
    [^9]: Block cipher mode of operation Wiki

    下载次数, 函数

  • Tobychen123   

    属实有点看不懂
    wantwill   

    学习虚席
    Dylanzhaoer   

    感谢分享
    tnancy2kk   

    这个不错,下载测试一下,先谢谢楼主了
    chishingchan   

    恕我眼拙,没看懂!
    Qinmuyi   

    学习学习
    Azuria   


    在旧版的Typora中,iv就是密文的前16byte,在1.9.5中已经不是了。奈何我实在没看懂iv到底是在哪里,所以我就求助于比较新的教程^5^7,把教程中标注为iv的变量标注为iv,动态调试得到它的值。

    现在高版本 Typora 的 IV 都是计算出来的了,动调方便些,具体逻辑就在 Key 赋值之前。
    重打包的话反正iv只影响前十六字节的解密,只用提取 Key 就行。


    QQ20241121-122115.png (47.55 KB, 下载次数: 0)
    下载附件
    2024-11-21 12:40 上传



    QQ20241121-122354.png (43.11 KB, 下载次数: 0)
    下载附件
    2024-11-21 12:40 上传


    在CyberChef中选择cbc模式解密失败,选择cbc/no padding模式成功了,但是明文的末尾有一串非ascii字符串。我猜测是CyberChef自动去除padding时不能判断哪里是padding。

    高版本 Typora 在 base64 解码后的密文末尾加了一个字节,导致密文不是 16 bytes 对齐,不过似乎并不会影响解密和重打包。很久以前动调的时候好像发现这个字节会被去掉还是会被直接无视来着。


    QQ20241121-122243.png (23.12 KB, 下载次数: 0)
    下载附件
    2024-11-21 12:40 上传

    betcom   

    真没看懂。
    ijack2001   

    非常有帮助,感谢教学。
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部