Putty和SecureCRT都是IT人员常用的ssh客户端软件,区别在于:Putty是开源免费的,而SecureCRT则是非常完善的商业级软件,是收费的。Putty非常小巧,只有一个putty.exe就可以运行,但是它的默认字体是Courier New 10号字体。这种字体是Windows系统缺省都带的,不过这种字体并不好看。SecureCRT有一种字体叫vt100,这种字体非常适合SSH命令行,是我最爱的命令行字体,但是vt100是SecureCRT自带的字体,Windows中并没有安装。而且SecureCRT运行后你才能在别的软件的字体选择对话框中看到这种字体。当SecureCRT关闭后,这种字体就消失了。
这个问题困扰了我很多年。我一直想让Putty缺省字体是vt100,13号字体。但是你使用这种字体必须先安装而且运行SecureCRT,这非常不爽。最近我解决了这个问题。 我把vt100字体文件从SecureCRT软件中抠出来,嵌入到了putty.exe中,并设置为缺省字体。这样你只要一个putty.exe,在任何一台Windows机器上都可以使用vt100字体了。
本文章就是介绍我是如何一步步克服这个问题的,希望对大家有帮助。
首先,我们看一下两种字体的比较。第一幅图是putty的缺省字体Courier New 10号字体,第二幅图是vt100 13号字体。
如果你也觉得第二幅图的字体更好看,也想使用vt100字体,就继续往下看,否则打住。
首先,你要下载安装一个SecureCRT试用版软件。然后在它的目录下寻找vt100.fon文件。还有两个vt100的字体文件,分别是加粗加斜,我不喜欢。我只喜欢这个vt100.fon
在我的机器上,vt100.fon文件是在如下目录:
C:\Program Files\VanDyke Software\SecureCRT>dir vt100*
Volume in drive C has no label.
Volume Serial Number is E093-1844
Directory of C:\Program Files\VanDyke Software\SecureCRT
11/07/2018 10:50 AM 45,056 VT100.FON
11/07/2018 10:50 AM 62,976 VT100DB.FON
11/07/2018 10:50 AM 62,976 VT100DT.FON
11/07/2018 10:50 AM 62,976 VT100W.FON
4 File(s) 233,984 bytes
0 Dir(s) 125,151,936,512 bytes free
如果修改后的软件包含两个文件,一个是putty.exe,一个是VT100.FON,就存在第二个文件丢失的问题。所以我们需要把这个字体文件嵌入到putty.exe中,保持最终的结果只有一个putty.exe。因为VT100.FON已经在putty.exe中,你把putty.exe拷贝到任何一台Windows机器上,不需要这台机器事先安装好vt100字体,你就可以使用vt100字体了。事实上,你看到了,这个字体是SecureCRT自带的。如果你不安装SecureCRT,你的Windows系统几乎不会有这种字体。
第二步:下载和编译putty源码
putty源码的官方下载地址是:https://the.earth.li/~sgtatham/putty/latest/putty-src.zip
把这个zip文件下载到本地磁盘,并解压缩到一个目录。我假设你解压缩到了D:\Code\putty目录下。
第三步:你要安装Visual C++。我选择的是Visual C++ 2017社区版,它是免费的。微软真有良心,点赞一下!因为这是成熟软件,所以安装过程不用啰嗦。你遇到问题,在网上自行研究。
第四步:编译putty源码。
在开始菜单中选择"Developer Command Prompt for VS 2017",如下图所示:
这个会进入命令行窗口,不过Visual C++的各种环境变量都已经设置好了,你直接可以在命令行下使用C++编译器了。 在这个命令行窗口中执行如下命令:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community>d:
D:\>cd code\putty
D:\Code\putty>cd windows
D:\Code\putty\windows>nmake -f Makefile.vc
等了一会,你就会看到编译好了。你执行 dir *.exe,就会看到已经编译好的putty.exe和其它可执行文件。
通过以上过程,我们已经学习了如何编译来自官方的putty源码。 我们并没有做任何修改。下面就是拿起手术刀开始对putty源码动刀子的干货过程了。
我们的思路是把VT100.FON文件嵌入到最终的putty.exe中。这个可以通过把这个文件嵌入到Windows资源文件来完成。过程如下:
#define IDR_FONT_VT100 121
IDR_FONT_VT100 RCDATA "VT100.FON"
完成以上三步后,你再执行nmake -f Makefile.vc,最终生成的putty.exe文件中已经包含了VT100.FON的数据。因为这个VT100.FON文件才45056个字节,所以putty.exe增加的尺寸不大,才区区40K左右。
修改完毕资源文件,接下来的思路就是在putty.exe启动阶段加一些代码,读取这个字体数据,加载字体到系统中。然后在putty.exe的结束部分,卸载这个vt100字体。过程如下:
HANDLE g_fontVT100 = NULL;
static HANDLE install_VT100(HINSTANCE inst)
{
HANDLE h;
HGLOBAL res_handle = NULL;
HRSRC res;
unsigned char *res_data;
DWORD res_size, font_cnt = 0;
res = FindResource(inst, MAKEINTRESOURCE(IDR_FONT_VT100), RT_RCDATA);
h = NULL;
if (res) {
res_handle = LoadResource(NULL, res);
if (res_handle) {
res_data = (unsigned char*)LockResource(res_handle);
res_size = SizeofResource(NULL, res);
h = AddFontMemResourceEx(res_data, res_size, 0, &font_cnt);
}
}
return h;
}
static void deinstall_VT100(HANDLE h)
{
if(h) {
RemoveFontMemResourceEx(h);
}
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
{
MSG msg;
......
大家看到了,这段代码很简单。install_VT100函数是安装vt100字体。它先读取前面嵌入的vt100字体数据(此时这些数据已经在内存中了),然后使用一个函数AddFontMemResourceEx把vt100字体安装到系统中。这个函数大家自行搜索和研究,非常简单。这里不再啰嗦。 deinstall_VT100函数是卸载字体的函数。
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
{
MSG msg;
HRESULT hr;
int guess_width, guess_height;
dll_hijacking_protection();
hinst = inst;
hwnd = NULL;
flags = FLAG_VERBOSE | FLAG_INTERACTIVE;
sk_init();
init_common_controls();
g_fontVT100 = install_VT100(inst); /* 这一行是我加的。上边的是老代码,供你定位位置*/
在WinMain函数的最后,当然是卸载vt100字体了:
finished:
deinstall_VT100(g_fontVT100); /* 我就加了这一行。*/
cleanup_exit(msg.wParam); /* this doesn't return... */
return msg.wParam; /* ... but optimiser doesn't know */
}
/*
* Clean up and exit.
*/
void cleanup_exit(int code)
{
/*
* Clean up.
*/
deinit_fonts();
sfree(logpal);
if (pal)
DeleteObject(pal);
sk_cleanup();
以上代码仅仅是在putty启动的时候加载VT100字体,在putty关闭的之前卸载VT100字体。你加载的字体并不会显示在putty的字体设置对话框中。这一点微软的文档上说的很清楚:
This function allows an application to get a font that is embedded in a document or a webpage. A font that is added by AddFontMemResourceEx is always private to the process that made the call and is not enumerable.
既然vt100字体已经被putty.exe进程加载了,可以供它私用。下一步我们要找到设置putty缺省字体的地方,设置putty的字体为vt100。
3. 用文本编辑器打开D:\Code\putty\windows\windefs.c文件,找到platform_default_fontspec函数。这个函数就是设置putty缺省字体的函数。它的代码如下:
FontSpec *platform_default_fontspec(const char *name)
{
if (!strcmp(name, "Font"))
return fontspec_new("Courier New", 0, 10, ANSI_CHARSET);
else
return fontspec_new("", 0, 0, 0);
}
大家可以很清楚地看到,它设置Courier New 10号字体为缺省字体。下面我们就改动一下:
FontSpec *platform_default_fontspec(const char *name)
{
if (!strcmp(name, "Font"))
return fontspec_new("vt100", 0, 13, ANSI_CHARSET);
else
return fontspec_new("", 0, 0, 0);
}
大功告成! 你再到D:\Code\putty\windows目录下执行nmake -f Makefile.vc,生成的putty.exe就是我们想要的缺省字体是vt100的putty了。你可以nmake编译之前先删除老的putty.exe,确保编译后的putty.exe是最新的。希望这是多此一举。
当然这里的代码逻辑应该可以更加完善一些,改成下面的似乎更好:
extern HANDLE g_fontVT100;
FontSpec *platform_default_fontspec(const char *name)
{
if (!strcmp(name, "Font")) {
if(NULL== g_fontVT100) { /* vt100字体没有安装成功,依然用原来的字体 */
return fontspec_new("Courier New", 0, 10, ANSI_CHARSET);
} else { /* vt100字体安装成功,用vt100字体 */
return fontspec_new("vt100", 0, 13, ANSI_CHARSET);
}
else
return fontspec_new("", 0, 0, 0);
}
但是我编译的时候,在链接阶段,它抱怨找不到g_fontVT100这个全局变量。我懒得研究如何克服这个问题了。如果你解决了,发信到[email protected] 或者[email protected] 告诉我一下方法。我会非常感谢的。
Putty是非常敏感的安全软件,它已经有了20年的历史,久经考验。请不要随便下载非官方的putty.exe。因为可能有人植入了后门,在你登录系统的时候,把密码发到某一个邮箱。 我们的方法是编译官方的源码,整个修改过程非常简单,应该没有任何后门,也不会对整个putty软件造成重大安全问题。所以这种修改hacking putty的方法全部过程都是在阳光底下,经得住考验的。编译后的putty你可以分享给自己的朋友。
如果你有什么想法和建议,可以发信给我:[email protected]