WSL2中,默认支持WSLg,可以直接打开GUI应用。但是缩放率比较小。我的WSL不知道从什么时候起突然有了毛病,再也打不开GUI应用,安装新的distro也是一样的cannot open display,大概是动了哪里的配置吧,没有自动创建WSLg的软链接。

参考

确认Windows版本

From a Windows command prompt, type ver to verify which build you are running.

1
2
>E:\wsl>ver
>Microsoft Windows [版本 10.0.26100.4349]

You must be running on Windows build version 21364+ for WSLg to work.

This version of Windows is currently only available through the Windows Insider program. See https://insider.windows.com/en-us/ to join the insider program and help us validate pre-released version of Windows.

Windows11一般都是支持WSLg的吧。

DISPLAY环境变量

WSLg's X server is running on display 0. The DISPLAY environment variable must have the value :0 for GUI application to connect to the right display. You can verify what the value of your DISPLAY environment variable is per below.

1
2
>name@hostname:~$ echo $DISPLAY
>:0

This environment variable is initialize as part of WSL's INIT. If it is unset or has a value other than :0, than you likely have a profile script that is changing it's value that you'll want to hunt down. You can also reset that environment variable like below.

1
>export DISPLAY=:0

有些教程的说法是export主机ip,但是对我的情况没什么作用。

X11 display socket

X servers create their socket under /tmp/.X11-Unix. This directory must exist and must be linked to /mnt/wslg/.X11-Unix where WSLg built-in X server create it's socket. You can verify the mapping exist and is the expected link per below.

1
2
>name@hostname:~$ ls -la /tmp/.X11-unix
>lrwxrwxrwx 1 name name 19 Apr 21 15:28 /tmp/.X11-unix -> /mnt/wslg/.X11-unix

This link is setup during WSL's INIT. If this directory doesn't exist, something likely caused it be removed in your environment that needs to be tracked down.

You can re-create the link manually to try things out.

1
2
>sudo rm -r /tmp/.X11-unix
>ln -s /mnt/wslg/.X11-unix /tmp/.X11-unix

X11 server running?

If the X server is running, you should see an X0 socket

1
2
>name@hostname:~$ ls /tmp/.X11-unix
>X0

If you don't please open an issue and attach /mnt/wslg/weston.log to the bug.

Known issues

You can verify the version of WSLg you are running per below:

1
2
3
4
5
6
7
>name@hostname:~$ cat /mnt/wslg/versions.txt
>WSLg ( x86_64 ): 1.0.17+3.Branch.master.Sha.a526dfd5ad03d126bb2d8c528f6c3563e86a40da
>Mariner: VERSION="1.0.20210224"
>FreeRDP: e4a2fc2053bd8c5f99455fcd08ffee7e5591567a
>weston: fd961f5cd116c9358d82ce94d139c1578e21bd00
>pulseaudio: 2f0f0b8c3872780f15e275fc12899f4564f01bd5
>mesa:

Complex monitor arrangement (Fixed in WSLg 1.0.19)

There is a known issue in WSLg 1.0.17 that if you have a combination of vertically and horizontally aligned monitor, Weston may hit an invalid assert and restart. Effectively crashing and restarting the X server on every connection attempt.

You can verify if this is what you are hitting per below

1
>cat /mnt/wslg/weston.log | grep isConnected_V

if you see something like

1
>weston: ../libweston/backend-rdp/rdpdisp.c:481: disp_monitor_validate_and_compute_layout: Assertion `isConnected_V == true' failed.

Then you are hitting this problem. The workaround at the moment is to stack all of your monitor either vertically, or horizontally, but not use a mix of both.

Setting /tmp in /etc/fstab

There is a known issue at the moment (https://github.com/microsoft/wslg/issues/43) where configuring /tmp in /etc/fstab will overwrite the /tmp/.X11-unix link previously described. The workaround at the moment is to either avoid configuring /tmp, or manually recreating the link

1
>ln -s /mnt/wslg/.X11-unix /tmp/.X11-unix

Still having a problem?

Please open an issue and include the following

  • Run the following command and provide the output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>spronovo@OFFICE:~$ cat /mnt/wslg/versions.txt
>WSLg ( x86_64 ): <current>
>Mariner: VERSION="1.0.20210224"
>FreeRDP: 5f083fa0b97d433d6204985f6047886e29c1c61e
>weston: 16de531f00aa3dfd17e0de74c8f49e9fd7cec617
>pulseaudio: 2f0f0b8c3872780f15e275fc12899f4564f01bd5
>mesa: 2ad0684038f5732f7e4bd1a391ec9d833685fb48

>spronovo@OFFICE:~$ echo $DISPLAY
>:0

>spronovo@OFFICE:~$ ls -la /tmp/.X11-unix
>lrwxrwxrwx 1 root root 19 Apr 21 12:12 /tmp/.X11-unix -> /mnt/wslg/.X11-unix

>spronovo@OFFICE:~$ ls -la /tmp/.X11-unix/
>total 0
>drwxrwxrwx 2 root root 60 Apr 21 12:22 .
>drwxrwxrwt 5 root root 220 Apr 21 12:22 ..
>srwxrwxrwx 1 spronovo users 0 Apr 21 12:22 X0
  • Attach your /mnt/wslg/weston.log file

动机

其实很久之前就有逆向Typora的打算了,但是苦于当时找到的网上的教程不是非常细致,很多地方都看不懂是在干嘛,所以一直没有进度。虽然这学期还是有各种长线的大作业吊着,近期也有编译原理和英语听说两个临近deadline的作业,但我还是忍不住干了,尤其是已经看了新找到的一些教程后。趁记忆消退前,成功后先记下来。

在新电脑上通过修改注册表得到的(实际只记得移动了安装的位置)Typora的无限试用期重置了,今天(2024年11月17日)刚好只剩1天,也是折腾这个的理由。本来想用Typora作为英语听说present的准备的编辑器,也是理由。

过程

背景知识

  • Typora采用的框架是Electron。

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

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

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

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

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

    BlockCipherModesofOperation
  • 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中。45

破解的思路是找到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就好了。

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
39
40
41
42
43
44
45
46
47
48
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框架的一个特征。6

简单提取一下:npx asar extract app.asar app.asar.manual

1
2
3
4
5
6
Typora/resources/app.asar.manual
➜ tree
.
├── atom.js
├── main.node
└── package.json

步骤

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

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

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

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

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

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

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

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

其他

  • IDA的颜色

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

  • CyberChef

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

参考链接


  1. 高级加密标准Wiki↩︎

  2. CTF Wiki AES↩︎

  3. Block cipher mode of operation Wiki↩︎

  4. [原创] Typora 授权解密与剖析↩︎

  5. [原创] Typora 1.0.4版本破解复现↩︎

  6. Electron程序逆向(asar归档解包)↩︎

  7. 从零实现 AES 加密算法↩︎

  8. [原创]Typora 破解 之 逆向分析(上)↩︎

  9. Typora破解复现↩︎

  10. [原创]【最新】Typora最新版的逆向过程分析↩︎

背景

想用VMware里的Kali跑一下数图的一篇论文的项目EAGLE, 因为在WSL上尝试配了一下环境, 但是conda env create -f environment.yml的报错里有一个windows_support.py, 所以我 怀疑是什么东西把WSL当成了Windows. (现在在VMware里搞完了, 报错跟之前的一摸一样, 首先都是一个找不到libffi.so.6, 但是symlink到libffi.so.8.1.2在跑 download_dataset.py时又会报IOT的什么错)

但是虚拟机里没装代理, conda的速度非常慢, create env的时候直接结束了, 没有成功创 建. 代理软件更新后, 我没有打开允许局域网连接. 浏览器可以通过代理上网, 但我没有 找到配置系统代理的设置界面(像Ubuntu那种).

proxychains

在网上随便找一篇proxychains的教程都可以, 过程就是在/etc/proxychains.conf中把 strict_chain禁用, 把dynamic_chain启用, 再在最后加入形如"socks5 xxxx xxxx"的一句 . 使用proxychains firefox确实有效果. 但是proxychains ping xxx没有用.

还有比较麻烦的一点是设置的代理ip要到宿主机上面看一眼, 再手动修改.

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

版本管理

在 WSL 上,我用 n 管理 node 版本;在 Win 上,我用 nvm 管理 node。如果用 nvm 要重新给全局的 node_module 设置环境变量,因为 nvm 会把它删掉😵

sudo n latest 会很慢,下载到 40% 左右就会断掉,因为它不会走代理

sudo -E n latest 就很快,像喝水一样

目前我的 WSL 可以正常走 Win 的代理,git 一般没问题。不过配置的过程断断续续的,我没有记下来,可能只是在 %USERPROFILE%\.wslconfig 里加了 networkingMode=mirrored 和 autoProxy=true

build 内存溢出

build Open-WebUI 的时候,出现了如下报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
rendering chunks (179)...
<--- Last few GCs --->

[34877:0x76335a0] 48848 ms: Scavenge 2020.6 (2076.4) -> 2019.7 (2086.2) MB, 14.60 / 0.00 ms (average mu = 0.663, current mu = 0.876) allocation failure;
[34877:0x76335a0] 48892 ms: Scavenge 2027.0 (2086.6) -> 2024.4 (2087.2) MB, 15.86 / 0.00 ms (average mu = 0.663, current mu = 0.876) allocation failure;
[34877:0x76335a0] 48952 ms: Scavenge 2028.3 (2087.6) -> 2026.5 (2106.6) MB, 42.90 / 0.00 ms (average mu = 0.663, current mu = 0.876) allocation failure;


<--- JS stacktrace --->

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

1: 0xcc08f6 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
2: 0x1054130 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
3: 0x1054417 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
4: 0x1273655 [node]
5: 0x128a178 [node]
6: 0x126167e v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
7: 0x1262964 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
8: 0x1240625 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
9: 0x1670bec v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
10: 0x7f20326653f6
Aborted

这是 ChatGPT 的回答

试了前两种方法,似乎只有第一种 NODE_OPTIONS="--max-old-space-size=4096" npm run build 有用

开头

事情的起因是我想玩玩一个 魔改的pvz ,但是卡巴斯基报毒说有木马。为了安全起见,我想试一试用前段时间装的 Sandboxie 来运行一下。因为不会设置隔离的沙盒,搞到一般就放弃了。(后面的问题可能是这里修改了注册表的什么地方吧)

中间

然后我想看一看数据库实验的手册,结果 Microsoft 365 报 0x426-0x0 的错误码。我看了 帖子,装了个 Microsoft Support and Recovery Assistant (没有什么用),打算卸载了重新安装。结果这个 Assistant 卸载了老半天还没卸载完,我就中途取消了。

而后我把沙盒的设置修改回去了,启用了 MS ClickToRun 的服务,还有 Windows Module Installer 服务。然后把 Office 365 卸载了,又在微软商店装了回来。尝试打开文档,还是失败了。

然后我看到了 这个 教程,想试一下 msconfig 里面的“诊断启动”,导致了今天最惊险的情况😇。电脑启动后唯二的两种登录方式都不可用了:人脸和 PIN 码(选择 PIN 会弹出一个弹窗问你是否从商店里安装一个什么,有点太幽默了点)。电脑险些直接变成薄薄的板砖。

结果

多次物理重启后,我根据 教程 进入恢复环境,把 Utilman.exe 换成 cmd.exe,重启后点右下角的小人就打开了 cmd,再打开 msconfig 改成正常启动,再重启就恢复正常了。

最后 Office 是根据 教程官网 重新安装好了。Office 已卸载的时候搜索 WINWORD 可以找到在 C:\Program Files\Microsoft Office\root\Office16 的疑似本体的文件。

因为想把电脑上的一些图片转成 ASCII 图片, 在复制 Windows 的文件地址到 WSL 上时, 没有找到像 cygpath 这样的工具, 所以我在 .zshrc 里加了下面的内容:

1
2
3
4
5
# cygpath-like func
w2nix()
{
echo "$1" | sed -e 's/\\/\//g' -e 's/E:/\/mnt\/e/g'
}

在我想把这件事写进 blog 时, 我又发现我的 hexo 命令找不到了。

一番排查后发现是 nvm 修改系统变量的时候连着 node_global 也给改掉了。蒸 🦐 头

参考链接

Linux技巧:sed命令替换、删除、同时匹配多个模式的方法

zsh自定义命令并传递参数

问题

尝试在 Hexo 中显示公式,采用了 pandoc + mathjax 的方法。 但是在下标中仍然不能有 # 或 \# ,现在也没有找到解决办法

详细信息

安装的 node_modules :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ npm ls
hexo-site@0.0.0 E:\Document\Blog
├── hexo-deployer-git@4.0.0
├── hexo-filter-flowchart@1.0.4
├── hexo-filter-mathjax@0.9.0
├── hexo-generator-archive@2.0.0
├── hexo-generator-category@2.0.0
├── hexo-generator-index@3.0.0
├── hexo-generator-tag@2.0.0
├── hexo-renderer-ejs@2.0.0
├── hexo-renderer-pandoc@0.4.0
├── hexo-renderer-stylus@3.0.1
├── hexo-server@3.0.0
├── hexo-theme-next@8.19.2
└── hexo@7.1.1

在 _config.yml 中添加:

1
2
3
4
5
6
7
8
9
10
11
12
# Mathjax
mathjax:
tags: none # or 'ams' or 'all'
single_dollars: true # enable single dollar signs as in-line math delimiters
cjk_width: 0.9 # relative CJK char width
normal_width: 0.6 # relative normal (monospace) width
append_css: true # add CSS to pages rendered by MathJax
every_page: false # if true, every page will be rendered by MathJax regardless the `mathjax` setting in Front-matter
packages: # extra packages to load
extension_options: {}
# you can put your extension options here
# see http://docs.mathjax.org/en/latest/options/input/tex.html#tex-extension-options for more detail

通过 winget 安装了 pandoc 3.1.12.2

如果开启代理时打开 WSL ,会提示 “wsl: 检测到 localhost 代理配置,但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理。”

参考链接

%USERHOME%/.wslconfig 中添加如下内容

1
2
3
4
5
6
[experimental]
autoMemoryReclaim=gradual | dropcache | disabled
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true

例题

有三个表

学生

课程

选课

  1. 检索不学 C2 课的学生姓名,年龄
  2. 检索学习全部课程的学生学号

笔记

  1. 错误的做法是

    这意味着检索出“选了不是 C2 的课程”的学生姓名、年龄,而非所有学生中“没有选 C2 课程”的学生

    正确的做法是

  2. 错误的做法是

    这意味着检索出“学习全部课程且成绩相同”的学生学号,因为 S 和 Grade 共同作为除法“ ”中的

    正确的做法是

0%