前言

前一段时间用印象笔记的markdown功能写笔记,写到一半,印象笔记突然卡住了一下,在卡住之后,无法继续编辑,内容无法复制,远程同步和导出的内容都是上一个历史版本的内容,而上一个历史版本相较当前版本还是差了好些内容,

作为一个看过张银奎大佬写的《格蠹汇编》的程序员来说,第一个想法便是将内容从内存中dump出来。

解决

首先需要找到印象笔记的进程,查看任务管理器,这里有好多个进程。

30176880750b0d338eabf4acd4b96c85.png

不清楚显示内容的具体对应哪个进程,这里使用spyxx,找到markdown渲染后的窗口所属的进程。

1f2ab59a04813ffa1d4fd0eef80fd086.png

07601ece6f92cfeb88db75320f91f8ab.png

571cce21f9ccf1a1225ac63995a8b9f9.png

这里显示进程是0x6D10,换算成10进制是27920,也即Evernote.exe进程。

在查看Evernote.exe进程的内存数据之前,先说明下笔记的一些关键信息。

我的笔记一开始是写了开头和结尾,之后在开头的基础上开始完善内容。在出现问题的那一时刻,我笔记的起始内容是:最近需要使用,正在编辑的内容是:Protobuf协议,文章结束内容是:protocol类型的数据。而我提到的上一个历史版本中,则只保留了开头的最近需要使用和结尾的protocol类型的数据

接下来,使用windbg附加Evernote.exe进程,使用命令s -u 0 L8000000 "最近需要使用" 在进程里面搜索,没有找到任何地址。而使用s -u 0 L8000000 "类型的数据"命令则找到了2个地址。

f0f85dd6c49290bbb2b17a4541764dce.png

只找到了结尾的内容,而没有找到开头的内容,这里肯定是哪里有问题。我后面有重启进程,重新附加试了多次均没有结果。

最终我没有办法,只能先用截图+OCR的方式将中间缺失的内容给搞出来了。在把内容搞出来之后,不死心,一定要用内存dump的方式将数据给搞出来。

我后面想到印象笔记其实有多个进程,是不是spyxx没识别对,于是我便用windbg一个个附加试了下。

直到进程20376,起始、缺失以及结尾的地址均找到了,看来确实是进程不对的问题。

起始内容的地址有这些。

1
2
3
4
5
016311a0  6700 8fd1 9700 8981 4f7f 7528 0050 0079  .g.......O(uP.y.
082070c8  6700 8fd1 9700 8981 4f7f 7528 0050 0079  .g.......O(uP.y.
0820eb78  6700 8fd1 9700 8981 4f7f 7528 0050 0079  .g.......O(uP.y.
0a8beb1a  6700 8fd1 9700 8981 4f7f 7528 0050 0079  .g.......O(uP.y.
0a93a9e8  6700 8fd1 9700 8981 4f7f 7528 0050 0079  .g.......O(uP.y.

缺失内容的地址有这些。

1
2
3
4
016436b2  0062 0075 0066 534f 8bae 3002 0000 43a9  b.u.f.OS...0...C
0820916a  0062 0075 0066 534f 8bae 3002 000a 000a  b.u.f.OS...0....
08210c1a  0062 0075 0066 534f 8bae 3002 000a 000a  b.u.f.OS...0....
0a9369f2  0062 0075 0066 534f 8bae 3002 0000 43a9  b.u.f.OS...0...C

文章结尾的地址有这些。

1
2
3
4
5
08209882  0063 006f 006c 7c7b 578b 7684 6570 636e  c.o.l.{|.W.vpenc
08211332  0063 006f 006c 7c7b 578b 7684 6570 636e  c.o.l.{|.W.vpenc
082585a0  0063 006f 006c 7c7b 578b 7684 6570 636e  c.o.l.{|.W.vpenc
0a8c74ce  0063 006f 006c 7c7b 578b 7684 6570 636e  c.o.l.{|.W.vpenc
0a93e3a0  0063 006f 006c 7c7b 578b 7684 6570 636e  c.o.l.{|.W.vpenc

每个关键字符串搜出来的地址有多个,简单梳理一下,合理的地址有这些。

1
2
3
082070c8  ->   0820916a  ->    08209882,长度27BA
0820eb78  ->   08210c1a  ->    08211332,长度27BA
0a8beb1a  ->   0a9369f2  ->    0a93e3a0,长度7F886

使用以下命令依次将内存写入文件。

1
2
3
.writemem f:\txt1.txt 082070c8 L27ba
.writemem f:\txt2.txt 0820eb78 L27ba
.writemem f:\txt3.txt 0a8beb1a L7F886

使用编辑器打开文件txt1.txt,显示乱码,在预期之中。 a6762466370049e196d69e1006d5c424.png

加载到Python中,使用chardet库看下可能是哪个编码。

1
2
3
4
5
In [42]: chardet.detect(data)
Out[42]:
{'encoding': 'Windows-1254',
 'confidence': 0.2588082816907763,
 'language': 'Turkish'}

检测可信度只有25%,大概率是错的,decode了一下,果然是乱码。 7369d885252fa23ef6446115a41815da.png

后面试了下UTF8、GBK,都不对。后面注意到,每个ASCII字符后面都会跟一个0,猜测可能是UTF16,试了下,果然。

01325779ce5e60627ef4c332717a06d2.png

依次解码上述3个内存的数据,其中数据1和数据2都是原始的markdown数据,而数据3不对,一个合理的地址范围是:0a8beb1a -> 0a8c74ce,这个是上一个历史版本的html内容。

至此,终于通过技术手段将丢失的内容找回来了😁。

参考文章

  1. 《格蠹汇编》第1章。