ezgdi – gdi++移植到64位Windows
ezgdi是我最近做的一个小项目, 将用于字体美化的gdi++动态链接库移植到x64平台上. 原始想法来源于极限主题论坛的相关讨论[1][2][3].
gdi++移植到64位windows, 为什么?
gdi++替换了操作系统的gdi接口功能, 可以提供更加伤心悦目的字体渲染效果. 而gdi++的一个重要特点, 即操作系统接口替换, 是依赖于微软研究院发布的一个库, 叫detours, 现在detours版本号是2.1, express版可以免费使用, 但不支持64位程序. 而支持64位的Professional版本不免费, 要$1000, 而且有钱也不能用, 因为微软禁止你用detours开发GPL类开源软件. 据我所知, 很多很好的项目都依赖于detours, 以至于迟迟不能提供对64位的支持.
64位是未来的趋势, Linux, Windows现在发布, 都主推64位版本. 如果gdi++不支持64, 会严重影响我升级64位操作系统的决心. 所以我觉得gdi++移植到64位windows, 是一件挺有意义的事情.
怎么移植? 为什么选择easyhook?
首先, easyhook提供与detours类似的操作系统API劫持功能. 并且开源, 支持x64平台. 所以将gdi++对detours的依赖移植到easyhook上, 可以编译出64位的gdi++.dll, 用于渲染64位Windows程序.
截止到8月26日, 从detours到easyhook的移植工作基本完成雏形. 这意味着, 使用easyhook代替detours的方案是可行的.
ezgdi 怎么用?
将来64位的gdi++.dll和32位的gdi++.dll会并存, 分别负责渲染64/32位程序. 虽然目前只支持注册表加载, 但实现成gditray的支持那种也是可行的.
虽然我目前是基于freetype版做出的修改, 但其实修改的内容都和freetype没关系, 所以推广到其他版本应该也不是问题.
总的来说, 从使用来讲没什么不一样的. 想试用当前的版本, 可以参见安装说明.
移植当前是什么状态? 什么时候可以用?
目前把gdi++从detours移植到easyhook的工作已经基本完成, 32-bit和64-bit的DLL都能正确生成. 但运行不稳定. 尤其是x64的dll, 会导致IE crash. 即使这样, 如果你还是感兴趣, 可以下载试用.
现在我有两个忧虑, 一是性能, 我怕easyhook相对detours的实现会产生明显的性能瓶颈, 二是全面性, 目前已经发现有些操作系统的界面easyhook不能渲染, 不知道是不是easyhook做不到.
上述两个问题有可能是植根于easyhook本身的技术实现, 无法解决的. 所以最坏的结果是, 走了一圈, 发现此路不通.
需要帮忙么?
非常需要, 我一个人的精力能力毕竟有限. 如果觉得ezgdi有一点价值, 可以关注ezgdi项目的主页. 上面有一些文档, 和我改动之后的代码
目前的缺陷
目前的ezgdi尚有很多较为严重的问题没有解决, 大概有下面几点:
1. 只支持注册表加载, 需要将gditray这种也用easyhook改写才能支持其他加载方式
2. 有些程序中渲中文字体不能渲染(SVN中r27应该已经解决, 至少一部分)
3. x64的DLL非常不稳定, 肯定有从32位到64位移植遗留的bug没有发现. 访问中文站点会导致IE 64-bit崩溃
4. 不能正常截获开始菜单, IE等Windows主界面的内容, 怀疑和easyhook有关, 还未确认.
下步计划
完善, 不断完善. 尤其是改善x64的DLL稳定性, 因为移植到easyhook的优点就是支持x64平台.
您好!
我最近也在做一个X64的移植项目。该项目以前是用Detours做的拦截,现在要移植到64位的系统下,我用EasyHook库替换Detours.遇到一个问题:无法拦截到系统调用API函数,能够拦截到64位程序调用API函数。
请问您知道什么原因吗?
我是仿照EasyHook提供的例子UnmanagedHook做的,删除了以下两个部分:
Installing test driver
Testing stealth thread creation
接下来就是仿照例子进行安装钩子,请问有什么问题吗?
期待您的指导。
我也是照着UnmanagedHook例子改的. 也是删除了你说的那几段代码, 截获MessageBeep函数成功.
不过, 没太理解你说的”无法拦截到系统调用API函数”, “能够拦截64位程序调用API函数”之间的区别.
@dipplum
就是我拦截了函数NetShareAdd,制作成DLL后,可以拦截64位对话框调用NetShareAdd,但无法拦截系统进行设置共享操作。
用Detours拦截NetShareAdd,是可以拦截到系统进行共享的。
原来是这样, 这个问题恐怕我也遇到了, 就是ezgdi渲染范围好像没有gdi++全. 当时就猜测是不是easyhook原理和detours不太一样, 导致有些程序的调用截获不了.
有一阵没看了, 这问题也都都没解决呢. 抱歉啊.
我觉得, 应该搞清楚为什么拦截不了. 要么从原理出发, 分析分析easyhook和detours的原理. 要么看看设置共享的是哪个进程, 如有可能调试一下, 看看dll是否正常载入, installhook函数是否执行了之类的.
@dipplum
我注入技术的选用的是建立系统范围的Windows钩子,可以成功地拦截到CreateProcess这个函数,当系统创建新的进程时,都可以拦截到。
难道EasyHook只能拦截一部分API?
您好!
再问一个问题:EasyHook库中的RhCreateAndInject可以代替Detours库中的DetourCreateProcessWithDll吗?
RhCreateAndInject怎么调用?我老是不成功。
谢谢!
我没试过, 不过我猜测是可以替代的.
但是在64位系统下, 好像easyhook的RhCreateAndInject是要装一个driver, 绕过Windows的PatchGuard, 不知道你装了没有.
@dipplum
哦,还得装driver,装哪个driver?我没用过。
从README摘出来的, 应该是叫EasyHookXXDrv.sys. 不过没编译出来, 可能是要WDK才能编译吧, 猜想.
(optional; only required for kernel hooking)
"Debug\x86\EasyHook32Drv.sys" -> "Deploy\EasyHook32Drv.sys"
"Debug\x64\EasyHook64Drv.sys" -> "Deploy\EasyHook64Drv.sys"
我在http://www.codeplex.com/easyhook网站上下载的EasyHook 2.6 Binaries中找到了EasyHook64Drv.sys,并用RhInstallSupportDriver()和RhInstallDriver装的。但RhCreateAndInject还是没有执行成功。
另外,EasyHook可以挂载控制台程序吗?
这样啊, 我哪天编译一个RhCreateAndInject的例子看看.
Easyhook可以挂载控制台程序, 我确信.
你们好,我有个问题,在easyhook中非托管代码只有hook api的例子,但是不知道,在hook的api怎么执行原api的方法,想问下这个是怎么实现的?
@dipplum
EasyHook挂载控制台程序是靠哪个函数实现的?
您如果编译RhCreateAndInject成功的话,请告诉我一声。谢谢了。
我调用RhCreateAndInject报的错位”Unable to find the required native entry point in the given 64-bit library.”.
RhCreateAndInject我已经调用成功了,不需要安装驱动。就是需要一个入口,在API里有介绍。
现在就是无法拦截控制台程序,是不是和LhSetGlobalInclusiveACL,LhSetExclusiveACL,LhSetGlobalInclusiveACL,LhSetInclusiveACL有关?它们的调用顺序是什么?
我拦截的控制台程序不是通过RhCreateAndInject注射之后调用LhSetGlobalInclusiveACL的方法拦截的, 我改编gdi++的时候, 是用在注册表中设置AppInit_DLLs的方法拦截的. 所以我不需要调用RhCreateAndInject, 可以直接让命令行程序载入时运行我的dll, 运行注册钩子等函数. 这样做是可以的.
如果你可以用你的方法正常拦截Win32程序, 不能拦截控制台程序, 那就是另一个问题了.
@dipplum
我可以成功地在运行命令行程序时载入我的DLL,但就是无法拦截。
再者,我试过了拦截应用程序调用,用的是LhSetInclusiveACL,而拦截系统调用用的是LhSetExclusiveACL。但两个函数都调用时,只是后调用的函数起作用。无法实现同时拦截。
您好,
請教您一個比較題外的問題,如果我不是用VC++寫的程式,有辦法調用gdi++.dll而讓我寫的程式開始執行時原生就有字體渲染的功能嗎?如果可以的話能給點實作的提示嗎?
謝謝!
不是VC++写的,应该有办法调用WIN32 API吧。在程序最开始,用LoadLibrary函数调用把gdi++.dll载入内存,参见 http://is.gd/4Z5Lq
你好, 我想反应一些关于EZGDI的问题, 我是WIN7x64 的用户, 安装了SQL数据库,EZGDI对SQL字体可以渲染,但当我进入SSMS(企业管理器)对数据库点右键属性时,会使Ssms做成崩溃并弹出窗口[尝试读取或写入受保护的内存].这是我证实上述问题的经过:本来一直用EZGDI渲染我喜欢的字体,没有出现过什么问题,但因为需要,安装了SQL数据库,但安装后发现,SQL出现上述的问题,我就立即上百度搜索,一直得不到解决方法,就在这问题耗了几天,最后别无它法,重做系统. 做好系统,立即换字体,用上EZGDI,安装一些常用的软件,最后就安装SQL数据库,噢,晴天霹雳的事情出现了, 打开SSMS对数据库管理,令我抓狂的问题出现了,NND~~~ 再重做系统,好了,吸取教训,第一时间把SQL安装上,再打开SSMS,爽歪歪的,没事,一切正常!!! 那我就一完装软件,就立即创建系统还原点,就这样到最后一步,换字体,安装上EZGDI. 重启后,问题再次出现!!! 我就想,我的妈…没有漂亮字体啦!!! 就把原来字体换回去,EZGDI没有理会,因为有它,字体不会难看. 可是不如意啊,问题还在,我想,不会是它吧(EZGDI). 就把它关闭了…再用试一试的心抬来一遍….竟然成功了….我哭……折腾几天就因为它…请您一定要联络一下EZGDI作者,再修改一下这个问题嘛…麻烦你了..就是觉得EZGDI不错..很有感情, 最后,这么多的字,你能看到这里,十分感谢!!
;字体载入方法
; 0:FreeType 1:WIN32
FontLoader=1
把配置更改成这样就没问题了,不过许多字体变得大小不一….好难看…
最新版r83无法渲染visual studio 2010 界面,
望解决!
r87 have a problem with EasyHook32.dll
EasyHook32.dll > EasyHook32d.dll XD…
请问有办法只渲染浏览器吗
我机子安装ezgdi或gdipp都会感到不顺畅
不知道能不能支持类似http://free.flop.jp/gdi++/的程序
可以只支持单个程序渲染