原文:https://www.pediy.com/kssd/pediy10/57428.html
上周搞了一个flexLM的程序, 打算发破解笔记的时候, 抓软件新版发现Lz0放了一个注册机, 还是开源的.
所以岁末第一篇只好改这个了.
话说从Windows3.1开始我就对Windows的取色框欲求不满了, 曾经热切盼望2000和XP的取色框有所改观, 到了Windows 2008的时候我终于彻底失望了.
这个取色框的缺点就不用我一一说了吧, 很多软件里面, 提供自己的选色功能外, 都会提供自由选色功能, 绝大多数小软件都会乖乖的使用系统的这个取色框, 一个如时间机器般的莫名其妙的存在.
首先不能输入十六进色值就可以毙了他了, 更不要说只有HSB模式而且只是其中B柱条一种了, 而且这个模式下面取色区的显示还有bug.
终于某一年, 心存不满的我看到了当时很绚的Whistler并且失望后, 无意中装了一个Photoshop(做网页用).
当然看到鸟可耻的photoshop的取色框, 而且开始暗暗期待M$把取色框改这样了.
花开两陀, 各表一枝. 后来随着俺开始做软件, 也要用到取色功能, 自然为了向Adobe致敬, 俺克隆了一个92%相似度的取色框.
又后来, 随着俺发现LordPE等工具可以添加导入表, 也就开始将其制成一个dll, 提供和系统取色框相同的接口, 用来替换使用了系统对话取色框的程序.
这么平安无事的过了几年, 除了vista和2008带来的失望外, 我只是偶尔在群里面上抱怨一下. 直到某天世纪的群里面有人说看雪坛子上有个M$安全聚会, 问俺要不要去演示改造取色框的故事, 这么着俺就造了一个话题, 蹭了一个名额去了.
其实之前我也有分享我的修改, 只不过多半是给做设计的朋友. 因为Fireworks, Dreamweaver等软件除了在固定的色票选取以外, 要自由选色, 也会跟其他小公司软件一样无畏地弹出系统的取色框, 毫不悔改, 毫不以为耻. 有鸟Adobe的取色框后, 这些一蹶不振的软件配起色来又重新焕发鸟青春, 代价就是俺每次都要拿到软件都要修改一遍, 还有就是还给别人的时候, 多了一个libpicker.dll .
这里先声明一句, 此对话框完全不包括Adobe公司任何源代码, (这也要得搞得到啊).
那次的话题就是将系统的comdlg32.dll里面提供的取色框功能替代成自己的. 取代和改变系统API的功能, 俺用过的有若干方法,
其一, 各种全局挂钩的方式, 这或许是最无聊的办法了吧, 连普通用户都晓得这么干, 多半是流氓软件普及的结果吧.
比较洁净点的, 在程序目录放置空壳comdlg32.dll, 其他函数全部指向system32目录下的comdlg32, 仅仅实现ChooseColorW的功能. (这办法是宇宙杰出青年告诉的, 不过用户看到后还是觉得郁闷吧. )
其三, 在系统的comdlg32.dll里面插入libpicker.dll的导入项, 然后修改ChooseColorW的入口, 调用新的取色框. 这个跟前面的修改需要美化的程序没有大的区别, 同样会在系统目录留下把柄, 被人指摘.
厄, 果然最后就是比较绿色的办法, 跟系统dll进行合体, 溶解在comdlg32.dll的体内, 无声无息, 今天要表的段子就是这段大和谐了.
因为播出规制的原因, 先用一个非系统dll, MFC42u.dll来做演示, 好吧我马上承认了其实是上次的话题就是这个比较跟M$没有关系的MFC的运行库, comdlg32.dll的修改虽然和这个一样, 但是俺没有写笔记, 预计留给明年的自动修改工具发布贴了~~
选这个dll是因为开始打算做一个合并取色框dll到exe的演示作为话题的第一部分, 结果发现这个exe本身没有调用Win32 API, 是使用MFC的dll的功能, 就拿来作dll互相百合的例子了.
各位请看这个MFC42u.dll
我打算将libpicker的段拆出来, 合并到MFC42u.dll里面, Libpicker的text插入到.data结尾的107000处, 资源段和重定位段进行合并, 放在两者的后面.
当然俺的dll的第一个段起始RVA并不是7D307000, 这本身没法是个合法的基址, 有看官可能要说了, 设置链接器属性可以将基址和首段的起始位置结合起来得到7D307000, 那前提是要合并的dll是我写得, 很多情况只是凑巧了.
不过dll身为女儿身, 最美妙的地方是带了一个重定位表, 根据这个东西我们完全可以把dll里面的段都给重定位到完全不合理的地址去.
原MFC的载入基址是7D200000,
(7D200000+107000) - (400000+1000) = 7CF06000
俺打开Rejacker, 使用固态重定位功能将文件重定位这个不伦不类的地址, 并且将CODE,DATA,BSS几个段合并到原dll中.
然后两个dll里面的各种非代码部分的段和表需要合并, 计有资源表, 导入表, 重定位表, 而libpicker的导出表就不需要了, 内部消化了.
在以前合并exe/dll时候, 我通常会用Rejacker导出原始程序的重定位表, 其中要合并入受方的模块使用表地址重定位功能导出, 然后粘贴在一起, 用ImpRec直接重建一个新的, 不过在这个MFC的dll面前, ImpRec倒下了, 重建后的dll完全不能载入.
那好吧我只能重建Descriptor来干了. 2个模块都各有10个描述项(10个导入的dll), 合并在一起就是10*20+10*20 = 21*20 = 420字节.
如果用手来量就是C8(@F2598) + C8(@17200) + 14(结束) = 1A4, 尺寸是一样的.
粘贴下来后, 后面的C8里面修正一下抠过来后导致的偏差, 106000(107000-1000?), 这个可以用010的批量计算完成的.
每个记录中的最后的0190DC倒不需要修正.
然后找到内部使用ChooseColorW的地方, 修改为调用自身的
7D31BD68(合并后的libpicker新取色框功能)
7D24A471 . 50 PUSH EAX ; /pChooseColor 7D24A472 . FF15 A817307D CALL NEAR DWORD PTR DS:[7D3017A8] ; \ChooseColorW
7D31FF30 >/$ 55 PUSH EBP 7D31FF31 |. 8BEC MOV EBP, ESP 7D31FF33 |. 53 PUSH EBX 7D31FF34 |. 56 PUSH ESI 7D31FF35 |. 57 PUSH EDI 7D31FF36 |. 8B5D 10 MOV EBX, DWORD PTR [EBP+10] 7D31FF39 |. 8B75 0C MOV ESI, DWORD PTR [EBP+C] 7D31FF3C |. 8B7D 08 MOV EDI, DWORD PTR [EBP+8] 7D31FF3F |. 53 PUSH EBX ; /pReserved 7D31FF40 |. 56 PUSH ESI ; |CallReason 7D31FF41 |. 57 PUSH EDI ; |hDLLInstance 7D31FF42 |. E8 8A54FBFF CALL <mfcoep> ; \Assumed DllEntryPoint 7D31FF47 |. 50 PUSH EAX 7D31FF48 |. 53 PUSH EBX ; /pReserved 7D31FF49 |. 56 PUSH ESI ; |CallReason 7D31FF4A |. 57 PUSH EDI ; |hDLLInstance 7D31FF4B |. E8 2CC0FFFF CALL <pickeroep> ; \Assumed DllEntryPoint 7D31FF50 |. 5B POP EBX 7D31FF51 |. 21D8 AND EAX, EBX 7D31FF53 |. 83E0 01 AND EAX, 1 7D31FF56 |. 5F POP EDI 7D31FF57 |. 5E POP ESI 7D31FF58 |. 5B POP EBX 7D31FF59 |. C9 LEAVE 7D31FF5A \. C2 0C00 RETN 0C
for I := 0 to Length(Descriptor) - 1 do begin INC(Descriptor[I].OrginalfirstThunk, $E84); end;
占楼贴相关附件
后话: 安装程序的故事的标题是看Tango Icon Patcher时候想到的, 安装程序来提供对系统dll的处理, 并且提供reloader功能来适应hotfix和service pack的安装,当然他修改的是资源, 用的是reshacker的脚本方式进行的替换, 而我所作的, 完全脚本化起来就要比较复杂, 只能等来年将Rejacker强健并脚本化后, 这个才能成为正标题吧.
选用的例子的测试程序, mspaint, 来自windows2000中文版.
附件: mspaint_lite.rar
您可以观察vista的mspaint, 只是面板位置动了一下, 实在不容易啊, 连2008中字体视图(文件夹)的安装字体还是跟取色框同期的3.1风格文件打开框呢, 特征是盘符, 路径和文件名都是单独的选择框, 啥时候去色对话框也能这么改一下呢...
从当时的对大将说得作战来说, 应该是失败了, 其中还提到.net的另外一个bug, M$的人问为啥不去报告, 俺就讲了以前报告apploc的bug的一次情况, M$回信说bug确实存在, 不过这东西不是系统的一部分不给修.
上面的附件包含了添加重定位表和合并两种方式.
如果你跑不起来, 可能你的系统不是windows 2k3中文版, 重新bind一次好了.
按理说是bind的时候没有排除不该绑的dll, 可是bind.exe的参数说明比较诡异, 排除选项用了几次不知为啥没有效果.
说起参数说明, chkdsk的参数说明更诡异
volume Specifies the drive letter (followed by a colon),
mount point, or volume name.
我问了N多牛人, 每人都以为是卷名就是卷名, 可是谁都试不出来volume name怎么用, 而mount point按照diskpart里面的point弄出来也完全不行, 直到在Acronis Disk Director里面检查没有挂载的分区时候, 才抓出来他是这么的格式\\?\Volume{44f250d3-d206-11da-8451-00e04c03d25a}, 这个应该是volume name了, 偶地神哪, 这是name么??
bind我是执行两遍的,
bind -o -u MFC42u.dll
bind -u MFC42u.dll
不然第二次执行加入boundimport是不会提示binding MFC42u.dll的, 文件也不会更新, 为啥我也不知道, 那参数也没告诉我...
上面有使用过的rejacker几个月前传到了sourceforge, 以前是私下分享代码, 干脆改了改bug开源了, 教程准备翻译一篇合并skin程序到unaspack到sf上面, 却迟迟没有动手. 果然没有好人们愿意加入这种项目啊...