通过前述可知,枚举出系统中所有进程以及它们所打开的端口,这完成木马病毒的检测与清除工作的关键任务。要做到这一点方法有多种,但最简单的就是调用 NTDLL.dll中的几个未公开API,如NtQuerySystemInfomation,NtQueryInfomationProcess。其中 NtQuerySystemInfomation函数提供了一个简单的途径以获得系统中所有的HANDLE(句柄),只要找到系统中的SOCKET句柄,就可以通过这个句柄得到该进程所使用的端口号,这样就完成了进程与端口之间的关联,我们正是通过这种关联来判断一个进程是否为木马进程。 NtQuerySystemInfomation函数的原型如下:
DWORD NtQuerySystemInformation( DWORD dwRecordType, PDWORD pdwHandleList, DWORD dwNumBytes, PDWORD pdwNumBytesRet );
其中,第一个参数dwRecordType用于指定所要查询的系统信息类型,为了查询系统HANDLE列表,此项参数要设置为16,此数值是来自网上资料,由于这个函数是未公开函数暂时无法得到更详细的资料,第二个参数是一个指针,用来返回系统句柄列表,在调用函数之前,必须为这个指针分配足够的内存空间,否则函数调用会出错;第三个参数是指定为HandleList预先所分配的内存空间大小,单位是byte;第四个参数是函数调用后返回的 HandleList的大小,如果函数调用成功,返回值将是0,否则可以使用GetLastError()获得详细的错误代码。
一旦NtQuerySystemInformation函数调用成功,系统中所有的句柄将被存放在pdwHandleList所指向内存空间中,其中, pdwHandleList所指向的第一个32位数,是这个缓冲区所包含的句柄数量,之后是顺序排列的句柄指针pHandleInfo,指向的是 HANDLEINFO结构。HANDLEINFO结构定义如下:
typedef struct _HandleInfo
{
USHORT dwPid;
USHORT CreatorBackTraceIndex;
BYTE ObjType;
BYTE HandleAttributes;
USHORT HndlOffset;
DWORD dwKeObject;
ULONG GrantedAccess;
}HANDLEINFO, *PHANDLEINFO;
这个结构定义表明,句柄信息中包括了句柄所属进程的PID,只要获取句柄信息可以关联进程和端口了。不过,在NT系统中包含有各种各样的句柄:进程句柄、令牌句柄、文件句柄、窗口句柄……怎样才能判断出一个句柄究竟是不是SOCKET句柄呢?这就要通过HANDLEINFO结构中的ObjType属性了,根据已有资料分析,SOCKET句柄的类型值为0x1A,所以,只要将所有类型为0x1A的句柄取出,进行GetSockName操作就可以得到当前的进程/端口对应列表。不过此时我们得到的句柄都是属于其他的进程,根据在NT系统中进程保护的原则,一个进程不能够直接得到其他进程的各种信息,特别是句柄,不同进程中的同一句柄(句柄的数值相同)可能有完全不样同的意义。因此,得到SOCKET句柄后还必须进行一次转换,将其他进程的句柄转换为本进程的句柄,这个转换工作只要简单地调用DuplicateHandle函数就可以完成了。DuplicateHandle函数的调用方法略。
这样才可以通过getsockname、getsockopt等函数来获得SOCKET的各种属性了。示例代码段如下:
......
sockaddr_in name = {0};
name.sin_family = AF_INET;
int namelen = sizeof(sockaddr_in);
SOCKET s = (SOCKET)hMyHandle;
char szSockType[6][6] = { "NUL", "TCP", "UDP", "RAW", "RDM","SEQ" };
iRet = getsockname( s, (sockaddr*)&name, &namelen );
if ( iRet != SOCKET_ERROR )
{
int sockType = 0;
int optlen = 4;
iRet = getsockopt( s,SOL_SOCKET, SO_TYPE, (char*)&sockType, &optlen );
printf("PID=%4d PORT=%5d %s ",pHandleInfo->dwPid,
ntohs( name.sin_port ), szSockType[sockType] );
}
......
得到系统中正在运行的进程与其打开的端口信息后,就可以通过病毒库并结合黑白端口表来决定什么进程应该清除,什么进程可以放行了。
近来,在网上不断有新型木马病毒出现,有些可以隐藏到DLL或正常程序;有些则改变通信方式,进程间不再通过端口进行联系,而将要传递的信息嵌入到 IGMP包中发出,以躲避杀毒软件的检测与清除,由于要编制这样的木马病毒程序有相当的难度,并非一般的编程爱好者可以胜任,因而这样的木马病毒还比较少见。但这意味着,木马病毒的检测与清除将是一个长期的话题。本文浅述了木马病毒的工作原理与其基本的检测与清除方法,希望能有助于读者的研究、学习,同时欢迎大家一块探讨木马病毒的预防与清除技术。
【责 |