福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器


福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图

0、引言“讨伐”的背景是这样的 , 福昕pdf阅读器打开看着某某文档 , 然后其中有一段文字我想复制下 , 大概四五十个字吧 , 然后就莫名其妙的Crash了 。由于之前工作的原因 , 我的注册表里一直挂着JIT , 所以 , Windbg就跳出来 , 静静的等着我来干点啥 。分析之余 , 想不到为什么会有这样的“怪异写法” 。

1、案发的第一现场先来看下案发时 , 当时的上下文是什么样子的 , 如下图所示 , 根据经验 , 基本可判断是个0xC0000005异常了 。
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
出bug的模块名为frdvpr_drv , 出bug的函数据Windbg报告为DrvQueryDriverInfo , 但这个肯定是不对的 , 函数内部偏移为0x2c681即181889 , 都快180K了 , 常规的函数不可能这么大 。造成Windbg出错的原因是没有合适的PDB 。好了 , 先看下frdvpr_drv这个模块的具体信息 , 如下:
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
根据时间戳来看 , 还挺新 , 版本也不是特别老 。官网的最新版如下;
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
好了 , 现在可以确认下具体触发此次异常的原因了 , 执行如下指令:
0:007> .exr -1ExceptionAddress: 00007ff87380cb21 (frdvpr_drv!DrvQueryDriverInfo+0x000000000002c681)ExceptionCode: c0000005 (Access violation)ExceptionFlags: 00000000NumberParameters: 2Parameter[0]: 0000000000000000Parameter[1]: 00000000067e5044Attempt to read from address 00000000067e5044没错了 , 就是Access violation错误导致的此次惨状 。看下00000000067e5044地址附近的数据:
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
看来这个page的状态是free或者reserved的 。反正就是不可访问的 , 至于到底是哪种状态 , 下边来详谈 。再来看下堆栈 , 看看哪里过来的 。
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
貌似是新开的一个线程 , 刚开始干点事情就挂了 。但有一个数据引起了我的注意 , 就是红框上边的这个数据 , 看看与之前错问题的Addr , 貌似比较接近 。你先不要着急 , 我知道x64下 , 函数的调用约定规定前四个参数是通过寄存器传递的 , 但不意味着就不能在home栈中备份一下某些数据 , 比如这里的数据 。我们来看下这个地址附近的数据:
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
是个unicode串 , 也正是我复制的那一段话 , 原文如下:
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
好了 , 案发第一现场到此结束 , 下边开始溯源吧 。

2、触发此bug的罪魁祸首溯源之前 , 我们先来看下当前这一帧函数在干啥 , 根据异常地址 , 在Windbg的反汇编界面中往上稍微翻译下 , 可以找到该函数的开头 , 如下:
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
其实 , 看到这个函数sig , 我基本可以确认这是个memcpy或者memmove之类的函数 , 因为之前遇到过类似的问题 , 看过这两个函数的源码 , 印象深刻 。不知道也没关系 , 下边用IDA来打开下 , 因为IDA可以根据sig识别出库函数 。
0:007> ?00007ff8`7380cb21-frdvpr_drvEvaluate expression: 314145 = 00000000`0004cb21把0004cb21偏移加到Imagebase上即可跳转到对应的位置 , 如下:
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
颜色就已经出卖了这个函数 , 意味着他是一个库函数 , 旁边的注释表明它是一个memmove函数 。翻到函数开头 , 如下:
福昕pdf阅读器和编辑器区别 福昕pdf阅读器 福昕高级pdf编辑器

文章插图
有两个重要信息需要说明下:
1、r11中存储的是原始的rcx的值 , 即r11—->Dst;
2、rdx中存储的是rdx-rcx的值 , 可通过他找到Src的值;
另外 , 简单分析下就可知道 , 在该函数的下边 , r11 , rdx和r8三个寄存器都是作为只读寄存器存在的 , 没有被修改过 。现在还原这三个寄存器的值 , 如下: