<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

文章分类

导航

订阅

从堆里寻找丢失的数据

这是刚刚发生的一个故事,笔者亲历。

因为年底一个月很忙碌,所以久未写博客了,这几天放假,略有空闲,于是想写点东西出来,一来练练手,免得本来就不熟练的文笔变得更加生疏;二来与大家交流一下,免得朋友也生疏了。于是上网,打开网页,准备写个短文。写什么呢?这几天放假,就写点闲话吧,放假前去了次闵行老街,就写这个吧,怀怀旧。:-)

写文章不是件简单的话,很多时候的确像赵本山说的那样,半天憋不出俩字。:-)于是乎,就一篇简简单单的《重访闵行老街》,前前后后也用了几个小时。当然中间有一些停顿,有时陪女儿玩一会,有时喝杯茶,这样到中午时,基本写好了,检查一遍就可以发出去了;但中饭时间到了,女儿强烈要求煮意大利面给她吃,于是只好把写完大半的文章放下了。

“老爸,意大利面煮的很棒”,女儿怪腔怪调的表扬是最好的奖励:-)

吃过午饭,又想起写文章的事,看了一遍,改掉几个错别字,部分语句润色一下,自我感觉可以了,点击发送。

鼠标点下去后我就后悔了,应该先保存一下,因为是在网页上写的,没有自动保存,如果发送失败,后果可能很严重。但是这时已经没有机会取消了,虽然还可以看到编辑的文字,可以选中,但是菜单中的Copy命令已经不管用了。

接下来看到的是浏览器与服务器艰难对话的过程,速度很慢,过了几秒钟,问题真的出现了,“Cannot find server”,无语。

打开另一个浏览器,试图访问服务器,真的连不上,后来证明,服务器确实不知道啥时候宕了,但肯定是在我写文章的过程中,因为开始写时还是连得上的。

根据经验,有时回退还可以退回到刚才编辑的页面,救回所写的内容。于是点击Back按钮,但是浏览器并没有老老实实的回退到刚才的编辑页面,可能是因为页面上的“智能脚本”又触发了连接服务器的动作,于是浏览器让人失望的试图连接服务器,连接失败,又显示 “Cannot find server”,糟糕的软件!

向前又向后来回了几次,我意识到,刚才几个小时的功夫要白费了。这时老婆从书桌路过,听说刚才写的东西丢了,哈哈大笑,“你也会烦这种错误的啊,我还以为只有我们这些人才烦这种错误哪,呵呵呵”

是啊,这个错误是够低级的,要么应该用更好一点的工具来写,要么该先保存一下......

怎么办,重写一遍?不可接受。放弃拉倒?不可接受。

上调试器!

相信数据还在内存里,找得到就可以读出来,读出来了就可以找办法恢复成可读的形式。

把WinDBG附加到IE进程后,首先看到的是进程中有几十个模块;列一下线程,五十几个线程;列一下堆,有45个。

茫茫2GB用户态空间,在哪里找自己写的文章哪?搜索吧!就从当前进程用户态空间的较低地址开始搜,找文章里的一句有特色的话:

0:045> s -u 10000 L80000 "当年在交大"

什么都没找到,扩大搜索范围:

0:045> s -u 10000 L8000000 "当年在交大"

延迟一刹那后,刷刷出来很多结果,搜到了。这让人很高兴,说明数据还在内存里。

02fbc78a  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
02fd3fb2  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
0379c138  5f53 5e74 5728 4ea4 5927 0022 0020 ff0c  S_t^(W.N'Y". ...
03d266c6  5f53 5e74 5728 4ea4 5927 0022 003c 002f  S_t^(W.N'Y".<./.
03d44daa  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
03d75662  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
03d7d7ba  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
03dcc012  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
03e247ae  5f53 5e74 5728 4ea4 5927 0022 003c 002f  S_t^(W.N'Y".<./.
03e623ca  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
03e67ffa  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
05b1633a  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
05b54d1a  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
05b9076e  5f53 5e74 5728 4ea4 5927 0022 003c 002f  S_t^(W.N'Y".<./.
05b907f8  5f53 5e74 5728 4ea4 5927 0022 003c 002f  S_t^(W.N'Y".<./.
05b99d02  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
05bc143a  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
05bd77ea  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....
05bf3c62  5f53 5e74 5728 4ea4 5927 0022 003c 002f  S_t^(W.N'Y".<./.

....

07288632  5f53 5e74 5728 4ea4 5927 4e8c 90e8 8bfb  S_t^(W.N'Y.N....

....

因为WinDBG不支持中文显示,所以有点不确认上面搜到的信息,为了确认,在记事本里输入上面的中文字符,保存让后用二进制查看工具查看,证实上面搜索到的结果是对的,5f53就是“当”字的编码, 4ea4 5927 就是“交大”。

搜到很多处,看来这个数据被复制了很多次,使用哪一处的数据呢?

当然希望是完整的,于是又搜索了一下文章末尾的一个特征字:

0:045> s -u 10000 L8000000 "曙光"

......

0723225a  66d9 5149 7167 76f8 9986 5f88 5927 ff0c  .fIQgq.v..._'Y..
0723befe  66d9 5149 7167 76f8 9986 7684 4f4d 7f6e  .fIQgq.v...vMOn.
0723bf2e  66d9 5149 7167 76f8 9986 5f88 5927 ff0c  .fIQgq.v..._'Y..
0728985a  66d9 5149 7167 76f8 9986 7684 4f4d 7f6e  .fIQgq.v...vMOn.
0728988a  66d9 5149 7167 76f8 9986 5f88 5927 ff0c  .fIQgq.v..._'Y..

.......

也找到很多份,看来只要用对了工具和方式,刚刚苦苦寻找不可见的数据现在可以变得俯拾便是。

找两个结果中都有一个地址,观察一下属性:

0:045> !address 0728988a 
    06fa0000 : 07288000 - 00005000
                    Type     00020000 MEM_PRIVATE
                    Protect  00000004 PAGE_READWRITE
                    State    00001000 MEM_COMMIT
                    Usage    RegionUsageHeap
                    Handle   00150000

在堆上,靠谱!

接下来的目标的是将数据从内存堆保存到文件,WinDBG已经帮我准备好了一条命令:

0:045> .writemem c:\dumps\blog.txt 07288600  L2000
Writing 2000 bytes....

写好了,打开看一下:

乱码,应该高兴还是失望?

看到这个样子,老实说,我当时挺高兴的,根据经验这很像是中文,Unicode编码的,只不过没有按中文显示罢了。

怎么让编辑器程序按中文显示呢?方法很简单,对于文本文件,只要在文件开头加入Unicode文件的两个标识字符就行了,也就是0xFF FE。

怎么加入这两个字符呢?使用任何二进制编辑工具都可以,手头最方便的就是VC6。右键选择使用VC6打开,文件开头刚好有几个空闲的字符(<P>之类),将其修改为0xFF FE后,另存为blog_u.txt。再打开观看:

哦,成功了!

整理一下,前面那篇文章便发出了,再把失而复得的经过写一下,便有了这一篇,一篇怀旧,一篇技术,送给喜欢不同口味的朋友们!

 

posted on 2010年1月3日 15:13 由 Raymond

# re: 从堆里寻找丢失的数据 @ 2010年1月3日 19:37

好办法啊,张老师!

xiaowei

# re: 从堆里寻找丢失的数据 @ 2010年1月4日 9:23

嘿嘿,学习了.

kwok

# re: 从堆里寻找丢失的数据 @ 2010年1月5日 17:51

赞,有意思

skyNirvana

# re: 从堆里寻找丢失的数据 @ 2010年1月10日 13:31

老师真强!
我有一次也是类似问题,我用天天日记本这个软件记录信息,可惜一天出问题了,难道刚才写的东西要被丢失么,于是也上调试器,不过我当时用的是ollydbg,调试了半天,真的是4个多小时,才搞定,我很笨的哈,搞定的时候,那个心里滋味真是爽!

jlflyfox

# re: 从堆里寻找丢失的数据 @ 2010年1月14日 17:54

请问下,为什么IE会复制很多份呢? "搜到很多处,看来这个数据被复制了很多次,使用哪一处的数据呢?'

是因为点 后退 按钮想返回造成的吗?

sctianhu

# re: 从堆里寻找丢失的数据 @ 2010年1月15日 16:49

老强大了
胆大心细
佩服佩服

neilhsu

# re: 从堆里寻找丢失的数据 @ 2010年1月21日 13:42

厉害~
技术改变生活,这就是很好的例子,呵呵~
我们知道,从windows回收站里清空的文件,也是可以找回来的,基于的前提是:文件内容还在硬盘上。
张老师能找回博文数据,基于的前提是:数据还在内存里:)
现在搜索硬盘并自动恢复误删文件的工具软件已经有了,看了张老师的博文,我在想,能不能写个搜索内存导出数据的工具,让更多人可以享受技术带来的便捷生活呢:)

dos

# re: 从堆里寻找丢失的数据 @ 2010年3月4日 19:56

呵呵,同是闵行交大的飘过。目前正在学习学长的软件调试。。。

jyly

# re: 从堆里寻找丢失的数据 @ 2013年9月4日 16:35

这个例子太经典了。每次看到张老师的文章都给人感觉灵气十足,给人鼓舞。让人有种想认真学习调试的感觉,调试实在是太有用了。

shi jia.

sgyhmsly

# re: 从堆里寻找丢失的数据 @ 2013年9月4日 16:55

突然想到一个问题,如果我正在编写word文档,写了很多很多,然后不当心按了关闭按钮,又选择了不保存。这个进程被关掉了,那是不是内存里的数据已经没有了呢?????还是说该段内存只是标记为可用,实际上还是可以搜索到我刚才的内容呢???
如果是,我留意到您是attach到ie进程。
可是word进程已经被关掉了,还能找到它么?????

sgyhmsly

Powered by Community Server Powered by CnForums.Net