首页
社区
课程
招聘
[原创]修改vft设置MFC程序的属性页字体
发表于: 2012-12-10 15:07 9756

[原创]修改vft设置MFC程序的属性页字体

2012-12-10 15:07
9756

前几天因为工作关系要用到IAR Embedded workbench for ARM(EWARM), 然后经常的修改编译选项, 所以对工程选项对话框的MS Sans Serif字体看的很不顺眼; 这要不改掉, 简直没法干活了!
首先是把一堆带对话框资源的语言文件丢到Sisulizer里面批量改了字体, 然后替换以后, 点开一看, 左边的列表变Tahoma了, 右边的选项卡还一直保持着MS Sans Serif.
看起来不妙啊. 于是拽出了ApiMonitor, 勾了CreateFont和CreateFontIndirect四个函数.
然后启动改造版的LibSpy, 查看右边选项页的字体.



将hFont的值填入ApiMonitor搜索, 这个选项卡果然是ComCtl32的属性卡.



看到这里懂行的可能要说了, MS Shell Dlg不是会自动映射为Tahoma或者Segoe UI么? 这个解释起来就不是三言两语能说清的了, 这里最后显示用的是Microsoft Reference Sans Serif, 可以看成是开了抗锯齿的MS Sans Serif.
调用MFC90的地址是10042300+0x2521B = 1006751B, 因为ApiMonitor只能识别导出表, 这里的函数名并不是代码所在的函数.

从Call Stack可以看出, 是CreatePropertySheetPage时候, 从对话框资源读到的, 当然这个对话框资源, 就是WinSxs和System32下面的comctl32.dll.
用了v6以上的就是WinSxs, 否则是System32目录下的.

在以前的系统, 我是直接修改这comctrl32文件里面的对话框字体的, 但是后来看到过MSDN blog上的一篇文章, 介绍了因为历史失误, 选项卡显示出来后和资源按编辑器中大小不一致, 边缘被裁掉, 导致很多软件作者在使用选项卡时候, 反向拉伸对话框来撑到正确尺寸, 当然基本所有程序选项卡中显示字体都是Microsoft Reference Sans Serif (由MS Shell Dlg匹配而来), 除非特地处理了字体.
所以我以前那样改了以后, 字体是变到我想要的Tahoma了, 但是那些针对缩放bug做了放大的程序, 属性页会变大, 当年在群里也讨论了半天, 也没整出个两全其美的办法.
PS: 微软在CPropertySheet的构造和DoModal里用DS_SHELLFONT标志来指定自身不使用缩放workaround, 另外提供了一个PrpFont例子来演示修改字体, 就是派生自己的类, 重载CPropertySheet的OnInitDialog函数, 查找所有子控件并修改字体.
不过我们这里没有代码, 要修改的话, 直接修改这个创建链条中的任一环节, 也就是修改ProjectManagerGui.dll, mfc90.dll, comctl32.dll之中任意一个, 应该可行.
剩下还有个另外的方法, 就是重载这个纯虚函数, 正好我们有一个语言文件, ProjectManagerGui.ENU.dll, 先看看是什么方式使用的吧, 是LoadLibrary还是LoadLibraryEx的DATAFILE方式.
照样请出ApiMonitor, 监视LoadLibrary/EX这四个函数, 可以看到是IdeFramework.dll载入ProjectManagerGui.dll时候他直接用LoadLibraryA载入的.



LordPE查看ProjectManagerGui.ENU.dll, 是一个没有入口代码的纯资源dll.
因为LoadLibrary没有办法指定只加载资源, 这样我们可以把代码加到资源dll里面, 载入时候hook掉已经在内存中的ProjectManagerGui.dll.
先去看看第一次的CallStack发起的地方, 也就是前面算出来的1006751B,

    // PropertySheet
    // mfc90.dll 1711
    // __declspec(dllimport) public: virtual int __thiscall CPropertySheet::Create(class CWnd *, unsigned long, unsigned long)
    // virtual BOOL Create(
    //    CWnd* pParentWnd = NULL,
    //    DWORD dwStyle = (DWORD)–1,
    //    DWORD dwExStyle = 0 
    // );
    thiz->sheet3C.vft0->Create144(&thiz->sheet3C, parentcwnd, (parentcwnd != 0 ? 0x40000000 : 0) | 0x10400, 65536u);
.text:100674F4 8B 57 3C                                mov     edx, [edi+3Ch]
.text:100674F7 8B 92 44 01 00 00                       mov     edx, [edx+144h]
struct FooPropertySheet
{
  FooPropertySheet_VFT *vft0;
  unsigned int rev4, rev8, revC;
  unsigned int rev10, rev14, rev18, rev1C;
  HWND m_hWnd20;
...
}
struct FooPropertySheet_VFT
{
  void *GetRuntimeClass0;
  void *_GC4;
...
  BOOL (__thiscall *Create144)(FooPropertySheet *this, CWnd *pParentWnd, unsigned __int32 dwStyle, unsigned __int32 dwExStyle);
  void *DoModal148;
  void *OnInitDialog14C;
...
}
    // CPropertySheet::CPropertySheet(char const *,CWnd *,uint)
    CPropertySheet::CPropertySheet((struct CPropertySheet *)this, title, parent, iSelectPage);
    v8 = 0;
    thiz->vft0 = (FooPropertySheet_VFT *)&MyPropertySheet_vft;
.rdata:100C9834 90 C5 06 10             MyPropertySheet_vft dd offset MyPropertySheet__GetRuntimeClass
.rdata:100C9834                                                                 ; DATA XREF: func_createsheet_1006C5A0+4B o
.rdata:100C9834                                                                 ; sub_1006C670+28 o
.rdata:100C9838 20 CD 06 10                             dd offset sub_1006CD20
.rdata:100C983C 70 26 00 10                             dd offset nullsub_9
.rdata:100C9840 90 26 00 10                             dd offset nullsub_10
.rdata:100C9844 A0 26 00 10                             dd offset nullsub_11
.rdata:100C9848 3C 57 0A 10                             dd offset CPropertySheet::OnCmdMsg(uint,int,void *,AFX_CMDHANDLERINFO *)
.rdata:100C984C B6 4C 0A 10                             dd offset CWnd::OnFinalRelease(void)
.rdata:100C9850 BC 4C 0A 10                             dd offset CCmdTarget::IsInvokeAllowed(long)
.rdata:100C9854 C2 4C 0A 10                             dd offset CCmdTarget::GetDispatchIID(_GUID *)
.
.
.
.rdata:100C9978 54 57 0A 10                             dd offset CPropertySheet::Create(CWnd *,ulong,ulong)
.rdata:100C997C 5A 57 0A 10                             dd offset CPropertySheet::DoModal(void)
.rdata:100C9980 C0 C9 06 10                             dd offset MyPropertySheet__OnInitDialog

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 6
支持
分享
最新回复 (2)
雪    币: 26
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感觉很深奥!!
2012-12-10 20:51
0
雪    币: 58782
活跃值: (21926)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
很好的文章,感谢 曾半仙
2012-12-16 18:46
0
游客
登录 | 注册 方可回帖
返回