Serial Communication with Borland C++ Builder

David Poinsett
November 1999
d.poinsett@traverse.com

Introduction…

I wish this site had been around when I was trying to figure out how to make serial communications work in Windows95. I, like many programmers, was hit with the double-whammy of having to learn Windows programming and Win95 serial comm programming at the same time. I found both tasks confusing at best. It was particularly frustrating because I had, over the years, written so much stuff (including lots of serial comm software) for the DOS environment and numerous embedded applications. Interrupt driven serial comm, DMA transfer serial comm, TSR serial comm, C, assembler, various processors…you name it, it had written it. Yet, everything I knew seemed upside-down in the message-driven-callback world of Windows.

After spending lots of money on books and seemingly endless effort, I have finally gotten enough of a handle on Win95 and serial comm programming to write something usable in this environment. Borland’s C++ Builder has done a lot to help make Win95 programming easier and, once you know the tricks, the serial communications stuff is pretty easy, too.

The purpose of this site is to spare you hardship of my early efforts and get you up and running with your Win9x/NT serial comm programming as quickly as possible. If you’re already familiar with using BCB to develop Windows programs, the example code should be plenty to get you going. You can also download the source code in BCBComm.zip. Good luck.

The Example…

In the example that follows we’re going to write a bare-bones program to do serial communication. It will consist of a Form with a Memo object (for text I/O) and a Thread object that handles incoming serial data. There are no menus or other features to distract us from focusing on the serial comm aspect of the program. Obviously, you’ll want to add these and other elements to a fully functioning program.

Fire up BCB and start a New Project. Place a Memo object on Form1. Using the Object Inspector, set Memo1 properties as follows:

Alignment = alClient
MaxLength = 0
ScrollBars = ssVertical
WantReturns = true
WantTabs = false
WordWrap = true

Next, under the File | New menu, add a Thread Object. Use TRead for the class name when asked.

You should now have two Unit files: Unit1.cpp for Form1 activity and Unit2.cpp for the thread.

Using the Object Inspector again, create event handlers for the following events. The easiest way to create events handlers is as follows:

Go to the event tab sheet in Object Inspector.
Find the event of interest.
Double-click the blank space next to the event name.
If you follow this scheme, Object Inspector will create and automatically name the event handlers to the same name used in our examples. OK, here are the objects and the events we need to handle:

Form1 OnCreate
Form1 OnClose
Memo1 OnKeyPress

The framework for Unit1.cpp is now in place. Using the following listing as a guide, fill in Unit1.cpp with the following code. Be sure to note the #includes and global variables. If the framework for event handlers is missing in your program, DO NOT put it there by typing in the framework code! Go back and figure out what you missed. BCB MUST CREATE THE FRAMEWORK FOR YOU.

The Main Form…

//---------------------------------------------------------------------------
#include <vclvcl.h>
#pragma hdrstop
#include "Unit1.h"
// YOU MUST INCLUDE THE HEADER FOR UNIT2 (THE THREAD UNIT)
#include "Unit2.h"
// GLOBAL VARIABLES
HANDLE hComm = NULL;
TRead *ReadThread;
COMMTIMEOUTS ctmoNew = {0}, ctmoOld;
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
DCB dcbCommPort;
// OPEN THE COMM PORT.
// REPLACE "COM2" WITH A STRING OR "COM1", "COM3", ETC. TO OPEN
// ANOTHER PORT.
hComm = CreateFile("COM2",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
// IF THE PORT CANNOT BE OPENED, BAIL OUT.
if(hComm == INVALID_HANDLE_VALUE) Application->Terminate();
// SET THE COMM TIMEOUTS IN OUR EXAMPLE.
GetCommTimeouts(hComm,&ctmoOld);
ctmoNew.ReadTotalTimeoutConstant = 100;
ctmoNew.ReadTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &ctmoNew);
// SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
// THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST.
// IF YOU WANT TO LATER ADD CODE FOR OTHER BAUD RATES, REMEMBER
// THAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING.
// ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING.
dcbCommPort.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcbCommPort);
BuildCommDCB("9600,N,8,1", &dcbCommPort);
SetCommState(hComm, &dcbCommPort);
// ACTIVATE THE THREAD. THE FALSE ARGUMENT SIMPLY MEANS IT HITS THE
// GROUND RUNNING RATHER THAN SUSPENDED.
ReadThread = new TRead(false);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
// TERMINATE THE THREAD.
ReadThread->Terminate();
// WAIT FOR THREAD TO TERMINATE,
// PURGE THE INTERNAL COMM BUFFER,
// RESTORE THE PREVIOUS TIMEOUT SETTINGS,
// AND CLOSE THE COMM PORT.
Sleep(250);
PurgeComm(hComm, PURGE_RXABORT);
SetCommTimeouts(hComm, &ctmoOld);
CloseHandle(hComm);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
{
// TRANSMITS ANYTHING TYPED INTO THE MEMO AREA.
TransmitCommChar(hComm, Key);
// THIS PREVENTS TYPED TEXT FROM DISPLAYING GARBAGE ON THE SCREEN.
// IF YOU ARE CONNECTED TO A DEVICE THAT ECHOES CHARACTERS, SET
// Key = 0 WITHOUT THE OTHER STUFF.
if(Key != 13 && (Key < ' ' || Key > 'z')) Key = 0;
}
//---------------------------------------------------------------------------

Now we turn our attention to the thread code in Unit2.cpp. The framework should already be in place. Use this listing as a guide and fill in Unit2.cpp with the following code.

The Thread…

//---------------------------------------------------------------------------
#include <vclvcl.h>
#pragma hdrstop
// YOU MUST INCLUDE THE HEADER FOR UNIT1
#include "Unit1.h"
#include "Unit2.h"
extern HANDLE hComm;
char InBuff[100];
//---------------------------------------------------------------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall TRead::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------
__fastcall TRead::TRead(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TRead::DisplayIt()
{
// NOTE THAT IN THIS EXAMPLE, THERE IS NO EFFORT TO MONITOR
// HOW MUCH TEXT HAS GONE INTO Memo1. IT CAN ONLY HOLD ABOUT 32K.
// ALSO, NOTHING IS BEING DONE ABOUT NON-PRINTABLE CHARACTERS
// OR CR-LF'S EMBEDDED IN THE STRING.
// DISPLAY THE RECEIVED TEXT.
Form1->Memo1->SetSelTextBuf(InBuff);
}
//---------------------------------------------------------------------------
void __fastcall TRead::Execute()
{
//---- Place thread code here ----
DWORD dwBytesRead;
// MAKE THE THREAD OBJECT AUTOMATICALLY DESTROYED WHEN THE THREAD
// TERMINATES.
FreeOnTerminate = true;
while(1)
{
// TRY TO READ CHARACTERS FROM THE SERIAL PORT.
// IF THERE ARE NONE, IT WILL TIME OUT AND TRY AGAIN.
// IF THERE ARE, IT WILL DISPLAY THEM.
ReadFile(hComm, InBuff, 50, &dwBytesRead, NULL);
if(dwBytesRead)
{
InBuff[dwBytesRead] = 0; // NULL TERMINATE THE STRING
Synchronize(DisplayIt);
}
}
}
//---------------------------------------------------------------------------

One last thing…

To do a synchronized call to DisplayIt() from within the thread’s Execute() function, DisplayIt() it must be declared as a __fastcall type in the header file. Here’s how to do it.

Open the header file “unit2.h” and add the DisplayIt() line as shown below:

//---------------------------------------------------------------------------
class TRead : public TThread
{
private:
protected:
void __fastcall DisplayIt(void); // ADD THIS LINE
void __fastcall Execute();
public:
__fastcall TRead(bool CreateSuspended);
};
//---------------------------------------------------------------------------

Notes…

As mentioned earlier this example focuses strictly on the core elements that make the serial communication functions work. In its present form it’s unlikely to be particularly useful or acceptable in an actual application. In other words, you need to add what’s missing. If you’ve followed along this far, that should not be too difficult. To minimize any confusion on what’s missing, I’ll highlight some of the areas that should be addressed:

There is little or no provision for error handling
The 32K display limit of the Memo object is not handled
For proper text display in Memo, ignore linefeeds and replace carriage returns with a CR-LF pair
Menus
Storing incoming serial data to disk
Sending disk contents out serial port
Handshaking
Protocol (Xmodem, Zmodem, etc.)
There are several ways to test your work. One method is to perform a loop-back test by jumping pins 2 and 3 on your computer’s RS-232 connector. With the loop-back connection anything you type into the Memo area will be echoed back.

Here are some online references that you might find useful:

Serial Communications in Win32 . This is a comprehensive reference.
www.ontrak.net . Excellent example of simple serial port access.
www.temporaldoorway.com . Good example of threaded serial program with overlapped I/O.
www.codeguru.com . Yet another example (more for VC++).
Good luck.
==============================================================================

IIS 5安全清单

IIS的安全性首先要基于Windows系统的安全性,详细部分请见相关文档。对IIS的安全控制可从以下四个方面进行:

* IP地址的域名安全限制(目录/文件安全性):视需求而定,可暂时阻止DOS;
* IIS身份验证安全限制(目录/文件安全性):
匿名访问:帐号IUSR_HOSTNAME,不过期,不能更改口令,Guest组成员;
基本身份验证:服务器上的真实用户名/密码,明文传输;
Digest身份验证:哈希散列值传输;(只使用Windows2k的域)
集成Windows验证:需要用相同用户名和密码登录;
* IIS权限
* NTFS权限

一、 为虚拟目录设置适当的 ACL

虽然一般情况下,虚拟目录的ACL取决于应用程序的需要,但一些通常的规则依然适用;

1、脚本和动态内容
可读
可执行脚本
2、静态内容
可读
3、可执行程序
可读
可执行
4、类数据库内容
可读
可写

推荐为每一种文件类型创建新的目录,在这些目录上仔细设置 ACL,并允许 ACL 继承到文件。至少建站第一步就应该在ACL中删除虚拟目录和Web页面的Everyone组。

例如,目录结构可能如下所示:
* myserverstatic (.html)
* myserverinclude (.inc)
* myserverscript (.asp)
* myserverexecutable (.dll)
* myserverimages (.gif, .jpeg)

此外,有两个目录需要特别注意:
* ftproot (FTP server)
* mailroot (SMTP server)

这两个目录上的 ACL 都是“Everyone(完全控制)”,应当根据您的功能设置更加严格的ACL,若不使用则不要安装。

对于仅开启IIS的主机,可以参考下列ACL设置(下面ACL采用的是极其严格的ACL,可能会对管理及SQL等的使用造成不便,应在此基础上逐项添加权限,才能做到权限最小化):

1.对于所有硬盘分区:
System 完全控制
Administrator 完全控制
允许继承
2.Program FilesCommon Files
Everyone 读取及运行 列出文件目录 读取
允许继承
3.webroot
IUSR_HOSTNAME 读取及运行 列出文件目录 读取
允许继承
4.Winntsystem32下除Inetsrv,Centsrv以外的所有目录
不允许继承
5.Winnt下除Downloaded Program Files、Help、IIS Temporary Compressed Files、Offline Web Pages、system32、Tasks、Temp、Web以外的所有目录
不允许继承
6.Winnt
Everyone 读取及运行 列出文件和目录 读取
允许继承
7.WinntTemp
Everyone 修改
允许继承

除上面提到的权限外,删除所有用户、组的权限。

二、 设置适当的 IIS 日志文件 ACL

请确保 IIS 生成的日志文件 (%systemroot%system32LogFiles) 上的 ACL 是:
Administrators(完全控制)
System(完全控制)
Everyone (RWC)

三、 启用日志记录

通过下列步骤使用 W3C 扩展日志记录格式:

1. 站点|属性|网站|启用日志
2. 活动日志格式|W3C 扩展日志文件格式|属性|扩展属性:
客户端 IP 地址
用户名
方法
URI 资源
Win32 状态
用户代理
服务器 IP 地址(如果多网卡)
服务器端口

当您检查日志时,请注意错误5,即被拒绝的访问。

[小知识]
如何察看错误代码所代表的意义?net helpmsg

四、 验证可执行内容的可信度

用 DumpBin 工具来查看可执行内容是否调用了某些 API。许多 Win32 开发工具都含有 DumpBin(tdump,dumpbin…)。

五、 在 IIS 服务器上更新根目录的 CA 证书

该过程包括两个步骤:

第一步:添加所有信任的新根目录证书颁发机构 (CA) 证书;
第二步:删除所有不信任的根目录 CA 证书;

请注意如果您不知道发布根目录证书的公司名称,那么就不应当信任他们!

注意: 不要删除 Microsoft 或 VeriSign 根目录。操作系统会大量使用它们。

六、 禁用或删除所有示例应用程序

例如Internet Information Server 5 中的示例文件:

IIS 示例 IISSamples c:inetpubiissamples
IIS 文档 IISHelp c:winnthelpiishelp
数据访问 MSADC c:program filescommon filessystemmsadc

七、 禁用或删除不需要的COM 组件

考虑禁用“文件系统对象”组件(FSO),但需要注意的是这样也会删除 Dictionary 对象。通常禁用COM组件的发式是直接卸载其链接文件(撤消注册),具体步骤是:regsvr32 *** /u;

例如:
下列命令将禁用“文件系统对象”:regsvr32 scrrun.dll /u

八、 删除 IISADMPWD 虚拟目录

该目录允许您重新设置 Windows NT 和 Windows 2000 密码。这主要是为 Intranet 方案设计的,并且不作为 IIS 5 的一部分来安装,但是在 IIS 4 服务器升级到 IIS 5 时将不会被删除。如果您不使用 Intranet 或者您将服务器连接到网站上,则应当将其删除。

有关此功能的详细信息,请参考Microsoft Knowledge Base文章Q184619。

九、 删除不使用的脚本映射

当 IIS 接收到针对其中某一类型文件的请求时,该调用由 DLL 进行处理。如果您不会用到其中某些扩展名或功能,请进行删除,方法如下:网站|属性|主目录|配置,然后删除下列引用:

* 基于网站的密码重置 .htr
* Internet 数据库连接器(所有 IIS 5 网站应当使用 ADO 或相似技术) .idc
* 采用SSI技术的服务器端包含程序 .stm, .shtm 和 .shtml
* Internet 打印 .printer
* 索引服务器 .htw, .ida , .idq

注意: 关于“Internet 打印”可以通过组策略和 Internet 服务管理器来配置。如果组策略设置和 Internet 管理器设置有冲突,那么组策略设置优先。默认组策略既不启用也不禁用“Internet 打印”。请选择“计算机配置”|“管理模板”|“打印”|“基于 Web 的打印”来禁用它。

十、 禁用父路径

父路径允许您在调用诸如 MapPath 等功能时使用“..”。默认状态下,该选项是启用的,您应当禁用它:网站|属性|主目录|配置|选项|启用父路径;

十一、 在“Content-Location”中禁用 IP 地址

“Content-Location”首部会暴露通常隐藏在网络地址转换 (NAT) 防火墙或代理服务器后的内部 IP 地址。如下设置后可以使服务器返回URL而不是IP地址:

将UseHostName添加到Metabase中的W3SVC键上;

例如: Set IISSchemaObject = GetObject(“IIS://Axqd/Schema/w3svc”)…

更简单的方法是使用IIS5.0提供的默认情况下安装在InetpubAdminscripts下面的ADSUTIL程序
(IIS 4.0在winntsystem32inetsrvadminsamples):

Adsutil set w3svc/UseHostName True

然后必须重启Web服务器。

有关禁用该选项的详细信息,请参阅知识库文章Q218180。IIS6.0目前没有提供这个问题的解决方案;

最后,关于针对DOS攻击的压力测试可以采用Microsoft Web Application Stress Tool;

关于IIS安全方面的工具,特别推荐IISLockDown以及URLSCAN(可从IISLockDown中分离出来);

Windows 2000安全清单

1.物理安全
确保每次本机登录服务器后的SignOut过程;设置BIOS密码且修改引导次序禁止从软盘或光盘引导系统;

2.停掉Guest 账号
把guest账号停用掉,最好给guest 账号加一个极其复杂的密码;

3.限制不必要的用户数量
经常检查系统的账号,删除已经不再使用的账号,并注意检查相应账号的权限设置;
应注意检查各个账号的实际权限,而不只是系统用户账号界面或者cmd命令显示出来的权限,严防账号克隆;

4.创建2个管理员所使用的账号
创建一个一般权限账号用来检查日志等一些日常事物,另一个拥有Administrators 权限的账号只在需要的时候使用;届时可让管理员使用 “ RunAS ” 命令来执行一些需要特权才能进行的一些工作,以方便管理;

5.把系统administrator账号改名
把Administrator账号改名,不要使用Admin之类的名字,尽量把它伪装成普通用户,例如:guestone ;

6.创建一个陷阱账号
创建一个名为” Administrator ”的本地账号,把它的权限设置成最低,并且加上一个极其复杂的密码,更进一步的可以在其的login scripts上面做点手脚,达到HoneyPot的效果;

7.把共享文件的权限从“ everyone ”组改成“ 授权用户 ”
任何时候都不要把共享文件的存取权限设置成“ everyone ”组,包括打印共享;
如果没有必要,请关闭默认共享(见附录);
机器重新启动后,这些共享又会重新开启的,如果想要自动关闭,请使用WSH脚本或者BAT脚本;
也可以直接更改注册表,如下:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceslanmanserverparameters]
"AutoShareServer"=dword:00000000
"AutoSharewks"=dword:00000000

REM 禁止建立空连接(限制对公用的本地安全权限 (LSA) 信息的访问)
[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLSA]
"RestrictAnonymous"=dword:1

8.使用安全密码
包括对密码长度和密码复杂度的相应要求;

9.设置屏幕保护密码
不要使用OpenGL和一些复杂的屏幕保护程序,浪费系统资源,黑屏就可以了;

10. 使用NTFS格式分区
把服务器的所有分区都改成NTFS格式;
首先,性能上有较大提升;(簇小于4K条件不同:FAT <256M FAT32 <32G NTFS NIL)
其次,2000以前身份验证协议只有NTLM(NT Lan Manager),NTFS为2000用户提供了更多样的选择—Kerberos v5协议以及附加身份验证工具Crypto API、Secure Sockets Layer(SSL)、公共密钥加密;

NTFS基本安全性数据结构:
(1)SID(安全标识符):唯一的标识用户和组;使用一次,即使删除也不会分发给其他用户;
(2)ACE(访问控制项目):定义了SID怎样才能与安全对象交互,允许或拒绝;可帮忙传递其他参数;
(3)ACL(访问控制列表):数组,包含0-多个ACE;
(4)DACL(自选访问控制列表):权限;
(5)SACL(系统访问控制列表):审核;
(6)SECURITY_DESCRIPTOR(安全描述):如与对象相关的DACL,SACL等等;

多条ACE冲突原则:
(1)组之间的许可可累加;
(2)文件许可优先于目录许可;
(3)拒绝优先于许可;

账户权力:详见本地安全设置->用户权利指派

由于NTFS与FAT相比,支持更多的数据流,所以请注意时常检查数据流信息,防止木马伪装;(可采用stream.exe或者lads.exe工具)

11.运行防毒软件
经常升级病毒库;
微软关于防治病毒的建议请参见:
http://www.microsoft.com/windowsxp/downloads/updates/sp2/antivirus/default.mspx

12.保障备份盘的安全
备份完资料后,把备份盘放在安全的地方;不要把资料备份在同一台服务器上,至少不要备份在同一个驱动器下;
Windows的密码文件(SAM)也有备份,不要忽略备份文件的安全性;

13.利用win2000的安全配置工具来配置策略
请参见控制台(MMC)和组策略(GPEDIT.MSC)的帮助文档

14.关闭不必要的服务
留意服务器上面开启的所有服务,定期检查他们以及他们的默认启动方式;下面是C2级别安装的默认服务,仅供参考:

* Computer Browser service TCP/IP NetBIOS Helper
* Microsoft DNS server Spooler
* NTLM SSP Server
* RPC Locator WINS
* RPC service Workstation
* Netlogon Event log

对于仅运行IIS主机而言,情况如下:
必要服务:
* DNS Client
* Event Log
* License Logging Services
* Windows NTLM Security Support Provider
* Remote Procedure Call(RPC) Services
* Windows NT Server or Windows NT Workstation
* IIS Admin Service
* MSDTC
* World Wide Web Publishing Service
* Protected Storage
* COM+ Event System
* Network Connections
* Windows Management Instrumentation Driver Extensions
* Windows Management Instrumentation

一般需禁用服务:
* Remote Registry Service
* Server
* Schedule
* FTP Publishing Service
* Telnet
* Terminal Service
* Telephony
* Alerter
* ClipBook Server
* Computer Browser
* DHCP Client
* Directory Replicator
* License Logging Service
* Messenger
* Netlogon
* Network DDE
* Network DDE DSDM
* Network Monitor
* Remote Access Server
* Remote Procedure Call(RPC) locator
* Spooler
* TCP/IP Netbios Helper
* Telephone Service

还有一些服务,如:SNMP Service,UPS等,应根据具体情况,如果不能确定可以选择手动,这样系统在需要的时候会自己启动这些服务;

此外,应该时常注意进程列表,特别注意名称与正常进程相近或者有迷惑性名称的进程;

15.关闭不必要的端口
用端口扫描器扫描系统所开放的端口,确定开放了哪些端口;%system%driversetcservices 文件中有知名端口和服务的对照表可供参考;

关闭某端口具体方法为:
网上邻居->属性->本地连接->属性->internet 协议(tcp/ip)->属性->高级->选项->tcp/ip筛选->属性 打开tcp/ip筛选,添加需要的tcp,udp协议即可;

可以利用fport等第三方工具列出端口与进程的对应表,然后直接杀掉进程;对于不能关掉的进程则采用防火墙屏蔽相应端口;

16.打开审核策略
策略 设置
审核系统登陆事件 成功,失败
审核账号管理 成功,失败
审核登陆事件 成功,失败
审核对象访问 成功
审核策略更改 成功,失败
审核特权使用 成功,失败
审核系统事件 成功,失败

17.开启密码密码策略
策略 设置
密码复杂性要求 启用
密码长度最小值 6位
强制密码历史 5 次
强制密码历史 42 天

18.开启账号策略
策略 设置
复位账号锁定计数器 20分钟
账号锁定时间 20分钟
账号锁定阈值 3次

对于IIS主机,请不要开启此策略,否则可能锁定IUSR_HOSTNAME帐号,导致IIS不能访问,目前微软还没有提供解决方案;

注:
关于策略的统一设置,可以使用统一的安全模板。
模板配置下载地址:http://download.microsoft.com/download/win2000srv/SCM/1.0/NT5/EN-US/hisecweb.exe

值得注意的是对于Windows终端服务的审核未包含连接的IP地址的记录,故可采用登录脚本进行记录(例如:netstat –n –p tcp | find “:3389”;记住登录脚本的最后要start Explorer,因为默认的登录脚本就是Explorer)

19.设定安全记录的访问权限
应该设置成只有Administrator和必要的系统账号才有权访问;

20.把敏感文件存放在另外的文件服务器中
考虑是否有必要把一些重要的用户数据(文件,数据表,项目文件等)存放在另外一个安全的服务器中,并且经常备份它们;

21.不让系统显示上次登陆的用户名
具体做法是:
HKLMSoftwareMicrosoftWindows NTCurrentVersionWinlogonDontDisplayLastUserName
把 REG_SZ 的键值改成 1;
或者使用本地安全设置->安全选项;

22.到微软网站下载最新的补丁程序
经常访问微软和一些安全站点,下载最新的service pack和漏洞补丁;
另注:除非确保有安全的SUS Server否则请不要使用Windows Update进行更新,而采用手工方式;
具体网址:http://support.microsoft.com/support/contact/default.asp
最简单的方式是订阅Microsoft 安全通知服务:
http://www.microsoft.com/technet/security/bulletin/notify.mspx

23.关闭 DirectDraw
此为C2级安全标准对视频卡和内存的要求;
具体做法:
HKLMSYSTEMCurrentControlSetControlGraphicsDriversDCI
将Timeout(REG_DWORD)设置为 0 即可;

24.禁止dump file的产生
打开 控制面板>系统属性>高级>启动和故障恢复 把 写入调试信息 改成无;要用的时候,可以再重新打开它;
另外,还需关闭华生医生(DrWaston—drwtsn32)产生的日志文件(故障转储文件);

25.使用文件加密系统EFS
注意要给文件夹也使用EFS, 而不仅仅是针对单个文件; 有关EFS的具体信息可以查看
http://www.microsoft.com/windows2000/techinfo/howitworks/security/encrypt.asp
请一定保管好证书,若遗失,恢复过程会极其繁琐(安装证书颁发机构然后创建附加数据恢复代理),而且还不一定能够修复(例如:WIN2K PRO)

26.关注temp、%windir%repair文件夹
注意随时关注temp文件夹,在进行危险操作后记得删除temp文件夹相应内容;
%windir%repair下面的备份文件存在很大危险;

27.锁住注册表
详细信息请参考:
http://support.microsoft.com/support/kb/articles/Q153/1/83.asp

28.关机时清除掉页面文件
编辑注册表
HKLMSYSTEMCurrentControlSetControlSession ManagerMemory Management
把ClearPageFileAtShutdown的键值设置成1;

29.考虑使用IPSec
有关IPSec的详细信息可以参考:
http://www.microsoft.com/china/technet/security/ipsecloc.asp
IPSec简化版为TCP/IP筛;

30、迁移以下程序
迁移下列程序到一个单独的目录,限定该目录ACL为Admin(完全控制)
xcopy.exe wscript.exe cscript.exe net.exe ipconfig.exe ftp.exe arp.exe edlin.exe rcp.exe ping.exe route.exe at.exe posix.exe rsh.exe cmd.exe qbasic.exe syskey.exe secfixup.exe nslookup.exe runonce.exe tracert.exe nbtstat.exe regedt32.exe regedit.exe finger.exe telnet.exe netstat.exe rexec.exe atsvc.exe cacls.exe edit.com debug.exe command.com cmd.exe

31、关闭子系统
Windows2000内核支持五个子系统:OS/2、POSIX、Win32、MS-DOS VDM、Win16 VDM,大多数用户不需要OS/2和POSIX子系统,删除如下子键:
[HKEY_LOCAL_MACHINESoftwareMicrosoftOS/2 Subsystem for NT]
[HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironmentOs2LibPath]
[HKEY_LOCAL_MACHINESystemCurrentControlSetContrlSession ManagerSubSystemsOptional]
[HKEY_LOCAL_MACHINESystemCurrentControlSetContrlSession ManagerSubSystemsPosix]
[HKEY_LOCAL_MACHINESystemCurrentControlSetContrlSession ManagerSubSystemsOs2]

再删除目录%SystemRoot%System32OS2

32、经常察看日志
* 安全日志文件 %systemroot%system32configSecEvent.EVT
* 系统日志文件 %systemroot%system32configSysEvent.EVT
* 应用程序日志文件 %systemroot%system32configAppEvent.EVT

定位、设置日志文件:
[HKEY_LOCAL_MACHINESystemCurrentControlSetServicesEventlog]
注意修改maxsize子键,如果超出大小,会报错并且不会再记录,默认大小512K。

下面给出脚本设置日志最大25MB,并且允许日志自行覆盖15天前的日志:
strComputer = “.”
Set objWMIService = GetObject(“winmgmts:” & “{impersonationLevel=impersonate,(Security)}!” & strComputer & “rootcimv2”) ‘获得VMI对象
Set colLogFiles = objWMIService.ExecQuery(“Select * from Win32_NTEventLogFile”) ‘获得LogFiles
‘-------------------------
For each objLogfile in colLogFiles
strLogFileName = objLogfile.Name
Set wmiSWbemObject = GetObject(“winmgmts:{impersonationLevel=Impersonate}!.rootcimv2:” & “Win32_NTEventlogFile.Name=’” & strLogFileName & “’”)
wmiSWbemObject.MaxFileSize = 2500000000
wmiSWbemObject.OverwriteOutdated = 15 ‘未找到
wmiSWbemObject.Put
Next
‘----------------------------

最简单的察看日志的方式是使用事件察看器;

最后有三点需要注意:
1、安全方面“管理永远大于技术,态度永远大于能力”;
2、安全与易用性永远是一对矛盾,需要在其间权衡利弊;
3、安全界有一个著名的理论,即所谓的“木桶原理”,请杜绝麻痹大意,不拘小节。

对于安全配置的检测,推举使用:
Microsoft 基准安全分析器 (MBSA)
并将 MBSA 添加到每周维护计划中,并按照计划中的任何安全建议操作。

附录:
默认共享目录路径和功能:

[C$ D$ E$]
每个分区的根目录;Win2000 Pro版中,只有Administrator和Backup Operators组成员才可连接,Win2000 Server版本Server Operatros组也可以连接到这些共享目录;

[ADMIN$ %SYSTEMROOT%]
远程管理用的共享目录;它的路径永远都指向Win2000的安装路径,比如 c:winnt;

[FAX$]
在Win2000 Server中,FAX$在fax客户端发传真的时候会到;

[IPC$ 空连接]
IPC$共享提供了登录到系统的能力;

[NetLogon]
这个共享在Windows 2000 服务器的Net Login 服务在处理登陆域请求时用到;

[PRINT$ %SYSTEMROOT%SYSTEM32SPOOLDRIVERS]
用户远程管理打印机;

连比尔盖茨都不知道的Word功能

据说,连比尔盖茨都不知道为什么会这样!

在一个新开的Word文件里面输入:
=rand(200,99)
然后回车看看会发生什么?
机器慢者勿试!

Word的预测:(准确的说是字体的预测)
首先,打开一个Microsoft Word文件;
然后, 输入 Q33NY(必须大写) (注意!这是9.11撞击世界贸易中心的其中一个航班号);
第三,将字体大小改到初号;
最后,将字体转成 Wingdings字体;
你看到了什么?