| 導購 | 订阅 | 在线投稿
分享
 
 
 

sniffer技術原理及應用,包括編程方法和工具使用(1)

來源:互聯網網民  2006-04-18 05:20:35  評論

很久沒有更新專欄了,關鍵是寫不出什麽好東西,也怕大家見笑!

雖然我還沒被人罵過,但我見過別人被人罵,哎。不是說,這在csdn好像很正常哈!

今天把這個貼子整理一下,這本是專題開發版的一個專題討論貼:http://expert.csdn.net/Expert/topic/2333/2333459.xml?temp=.3382532,其實這個貼子也沒有挖出更深入的

東西,關鍵是專題版目前人氣不太好吧。我發這個貼是希望更多的人能到專題版,參與和組織討論,但結果並不是太理想。

kingzai:

sniffer中文翻譯過來就是嗅探器,在當前網絡技術中使用得非常得廣泛。sniffer既可以做爲網絡故

障的診斷工具,也可以作爲黑客嗅探和監聽的工具。最近兩年,網絡監聽(sniffer)技術出現了新的

重要特征。傳統的sniffer技術是被動地監聽網絡通信、用戶名和口令。而新的sniffer技術出現了主

動地控制通信數據的特點,把sniffer技術擴展到了一個新的領域。Sniffer 技術除了目前在傳統的

網絡偵測管理外,也開始被應用在資訊保全的領域。可以這樣說,sniffer技術是一把雙刃劍,如何

更好的利用它,了解它的一些特性,將能使這項技術更好的爲我們帶來便利。

sniffer的編程方法比較通用的有以下幾種,1.winpcap 這是一個比較通用的庫,相信做過抓包的

工具大多數人都不會太陌生 2.raw socket 在2000以後的版本都支持此項功能,2000 server有

個網絡監視器就是基于raw socket 3.tdi,ndis,spi,hook socket技術,這種技術比較大的不同是

,可以將包截取而不是僅僅獲得包的一份拷貝

。總的說來,一般以前兩者居多。

我這裏提的都還比較片面,更多的需要大家來補充。我辦這個專題的目的是希望大家共同來了解

,討論sniffer技術,讓更多的人參與進來,讓大家知道,這個板塊能夠給大家帶來真正想要的東西

warton:

libpcap是個好東西,linux,windows下都能用,很多入侵檢測之類的安全系統都是以這爲核心。不

過我一直沒用過它,不知道它的跨平台性如何?

要用spi的話,看看xfilter的代碼和書,特別是那本書上講得不錯,可惜一直沒用它做出什麽東西來

raw socket寫的sniffer比較多,網上代碼也很多!

昨天見csdn首頁有幾篇關于sniffer的文章,保存了,還沒來得及看...

俺明天來說說目前常用的sniffer類工具和它們的技術實現!

csdn首頁的兩篇文章,大家可以看看,裏面好像還有幾篇,暫時找不到了

http://www.csdn.net/develop/article/21/21363.shtm

http://www.csdn.net/develop/article/21/21352.shtm

http://www.csdn.net/develop/article/15/15919.shtm

netsys2:

一)winpcap驅動簡介

winpcap(windows packet capture)是windows平台下一個免費,公共的網絡訪問系統。開

發winpcap這個項目的目的在于爲win32應用程序提供訪問網絡底層的能力。它提供了以下的各項

功能:

1> 捕獲原始數據報,包括在共享網絡上各主機發送/接收的以及相互之間交換的數據報;

2> 在數據報發往應用程序之前,按照自定義的規則將某些特殊的數據報過濾掉;

3> 在網絡上發送原始的數據報;

4> 收集網絡通信過程中的統計信息。

winpcap的主要功能在于獨立于主機協議(如TCP-IP)而發送和接收原始數據報。也就是說,winp

cap不能阻塞,過濾或控制其他應用程序數據報的發收,它僅僅只是監聽共享網絡上傳送的數據報

。因此,它不能用于QoS調度程序或個人防火牆。

目前,winpcap開發的主要對象是windows NT/2000/XP,這主要是因爲在使用winpcap的

用戶中只有一小部分是僅使用windows 95/98/Me,並且M$也已經放棄了對win9x的開發。因

此本文相關的程序T-ARP也是面向NT/2000/XP用戶的。其實winpcap中的面向9x系統的概念和

NT系統的非常相似,只是在某些實現上有點差異,比如說9x只支持ANSI編碼,而NT系統則提倡使

用Unicode編碼。

zzhong2:

有個軟件叫sniffer pro.可以作網管軟件用,有很多功能,可監視網絡運行情況,每台網內機器的數據

流量,實時反映每台機器所訪問IP以及它們之間的數據流通情況,可以抓包,可對過濾器進行設置,以便

只抓取想要的包,比如POP3包,smtp包,ftp包等,並可從中找到郵箱用戶名和密碼,還有ftp用戶名和

密碼.它還可以在使用交換機的網絡上監聽,不過要在交換機上裝它的一個軟件.

還有一個簡單的監聽軟件叫 Passwordsniffer,可截獲郵箱用戶名和密碼,還有ftp用戶名和密碼,它

只能用在用HUB網絡上

以上兩個軟件都可在小鳳居上下載到:http://www.chinesehack.org/

warton:

libpcap的最新版本是0.7.2,下載很多(基于linux/unix)

winpcap的最新版本是3.0

這裏有winpcap的源代碼:http://download.pchome.net/php/dl.php?sid=11474

著名軟件tcpdump及ids snort都是基于libpcap編寫的,此外Nmap掃描器也是基于libpcap來捕

獲目標主機返回的數據包的。

winpcap提供給用戶兩個不同級別的編程接口:一個基于libpcap的wpcap.dl,另一個是較底層的

packet.dll。對于一般的要與unix平台上libpcap兼容的開發來說,使用pacap.dll是當然的選擇

下面幾個庫是與lipcap相關的:

libnet1.0.2:數據包的發送個構造過程

libnids:實現了ids的一些框架

libicmp:icmp數據包處理

一些著名的嗅探器:

tcpdump/windump:支持多種unix,後者支持windows。基于libpcap

Sniffit:unix,windows,libpcap

Ngrep:libpcap,unixwindows.可以用規則表達式,識別PPP,SLIP及FDDI數據包

Sniffer pro/NetXray:專業的協議分析工具,是NAI提供的網絡分析方案中的一部分

其它:

Iris

LanExplorer

NetMOnitor

CommView

單一用途的噢探器

口令嗅:winsniffer,典型的黑客工具,嗅探並解析ftp,pop3,http,icq,smtp,telnet,IMAP,NNTP

等口令

password sniffer for NetHackerIII

專用嗅探器:

SMB嗅探器:L0phtcrack,SMPRelay

TCP連接會話嗅探器:CommView ,Iris,Juggernaut

SSL嗅探器:SSLDump--sslv3/tls網絡協議分析工具

RIDIUS嗅控器:一個基于udp的論證記賬協議,Radiusniff是其代表

PPTP嗅控器:Anger,PPTP-sniff(solaris)

SNMP嗅探器:Snmpsniff

交換網絡嗅探器:Ettercap

綜合:Dsniff

其它交換網絡嗅探器:

snarp,parasite

嗅探對策.........

netsys2:

網絡上流傳的GUNIFFER是個基本的原型:

http://asp.6to23.com/nowcan/code/guniffer.zip

void main(int argc, char ** argv)

{

int iErrorCode;

char RecvBuf[MAX_PACK_LEN] = {0};

usage();

if(GetCmdLine(argc, argv)==CMD_PARAM_HELP) exit(0);

//初始化SOCKET

WSADATA wsaData;

iErrorCode = WSAStartup(MAKEWORD(2,1),&wsaData);

CheckSockError(iErrorCode, "WSAStartup");

SockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);

CheckSockError(SockRaw, "socket");

//獲取本機IP地址

char FAR name[MAX_HOSTNAME_LAN];

iErrorCode = gethostname(name, MAX_HOSTNAME_LAN);

CheckSockError(iErrorCode, "gethostname");

struct hostent FAR * pHostent; //注意下面這三句,這裏先對pHostent分配了一塊

pHostent = (struct hostent * )malloc(sizeof(struct hostent));

//內存,然後有讓它等于gethostbyname函數的返回

pHostent = gethostbyname(name); //值,但gethostbyname函數是自己在函數內部分配內

存的,因此上一句根本就是多余,把上一句刪除後一切正常。但此程序用VC6編譯運行都沒有問題

,不知爲何?也許是VC6的編譯器優化在起作用。

SOCKADDR_IN sa;

sa.sin_family = AF_INET;

sa.sin_port = htons(6000);

memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length);

free(pHostent); //由于前面分配內存的語句已經刪除,所以這一句也要去掉,否則出錯。感謝網

友 Heyuming 發現這個問題。

iErrorCode = bind(SockRaw, (PSOCKADDR)&sa, sizeof(sa));

CheckSockError(iErrorCode, "bind");

//設置SOCK_RAW爲SIO_RCVALL,以便接收所有的IP包

DWORD dwBufferLen[10] ;

DWORD dwBufferInLen = 1 ;

DWORD dwBytesReturned = 0 ;

iErrorCode=WSAIoctl(SockRaw, SIO_RCVALL,&dwBufferInLen,

sizeof(dwBufferInLen),

&dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );

CheckSockError(iErrorCode, "Ioctl");

//偵聽IP報文

while(1)

{

memset(RecvBuf, 0, sizeof(RecvBuf));

iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf), 0);

CheckSockError(iErrorCode, "recv");

iErrorCode = DecodeIpPack(RecvBuf, iErrorCode);

CheckSockError(iErrorCode, "Decode");

}

}

它有2個不方便之處:

1)不能選擇網卡

2)采用死循環方式讀數據,改編到WINDOWS窗口模式下時有死機的感覺。

sevencat():

上次找了一些資料整理了一下,不過人氣不旺,而且最近比較忙,暫時還沒繼續下去。

http://expert.csdn.net/Expert/topic/2299/2299615.xml?temp=.2761499

WINDOWS網絡包過濾技術

(原文:http://www.ndis.com/papers/winpktfilter.htm)

一、user-mode網絡包過濾

1、winsock分層service provider

參照Microsoft Platform SDK上有關文檔和例子

(http://www.microsoft.com/msdownload/platformsdk/sdkupdate/)

這裏有好幾個microsoft lsp 例子,最新(可能最bug-free)的經常在這裏能找到。需要知道的是

可以通過TDI調用核心TCPIP驅動,而且可以完全繞開WINSOCK,在大多數情況下這不是一個問

題。例如:QOS的實現可以在WINSOCKLSP上。

然而,這樣做的話,程序必須察看和操作每個包,而不能依靠WINSOCKLSP,他們要以一種接

近核心態的方法來實現。

2、win2000包過濾接口

WIN2000包過濾接口提供了一種機制,這種機制允許用戶態程序或者服務指定一系列的"過濾

原則",這些過濾原則會被低層的TCPIP實現用來過濾包。這種過濾工主要是對IP原地址、目標地址

、端口號(或者端口號範圍)進行pass或者drop操作。

Windows Developer's Journal

《用iphlpapi.dll進行包過濾》作者:Ton plooy,October,2000,Volume 11, Number 10。

WIN2000提供了一個較好對TCPIP的可編程控制,其中包括包過濾。不幸的是,有關這個新

的API的文檔並不是很容易能找到。這篇文章向你演示了怎樣對特定IP地址或者特定TCP端口的包

進行阻塞的編程。

鏈接:www.wdj.com

上面這個例子的下載:ftp://ftp.wdj.com/pub/webzip/1110/plooy.zip

Hollis 的解決方案:

HTSW2KIpHook例子演示了IP過濾和它的HOOKAPI,包含原文件,而且是免費的,

需要HtsCpp運行時庫(免費),下載地址:http://www.hollistech.com/

3、winsock替代DLL

在使用WINSOCKLSP之前,唯一的辦法是用自己的DLL取代微軟的WINSOCKDLL,假

如實現順利的話,自己的DLL會接收用戶的WINSOCK調用請求,然後還可以調用原來的WINSOC

KDLL來處理。

不過這樣的實現是比較費力的,其中有個困難就是微軟的WINSOCKDLL裏面經常有一些未

公開的內部使用的函數,一個WINSOCK代替DLL至少要處理其中的一些未公開函數。

隨著WINDOWS系統結構的變化,有些方面得到了加強,比如系統文件保護,這使得這種技術

變得不太可行。總的說來,使用WINSOCKDLL替換不是一個壞主意。(Xfilter就是用的這種技

術,原代碼可能在網上有流傳,我以前看到過的)

二、kernel-mode網絡包過濾

1、Transport Data Interface (TDI)

這主要是一個直接在核心TCPIP驅動上面的一層過濾驅動。在WINXP上TDI驅動是一種傳統的

NT風格的驅動,使用了基于IRP的API,這裏有兩種方法來實現。

A、使用核心模式服務的IoAttachDeviceXYZ函數族在TDI上實現一個過濾。

B、對TDI驅動IRPDISPATCH表進行過濾。

IoAttachDeviceXYZ函數在許多WINNT驅動開發的書上提到。這兩種技術都需要對WINNT驅

動開發編程技術十分了解,對TDI函數也要相當的了解。

2、NDIS中間層(IM)

具體請看NDIS IM FAQ:http://www.pcausa.com/resources/ndisimfaq.htm

3、WIN2000FILTER-HOOK

請參照有關DDK文檔,系統中只能有一個活動的Filter-Hook存在,這點使這種技術的使用有

嚴重的限制。(平時所見的drvipflt就是用的這個)

4、WIN2000FIREWALL-HOOK

Firewall-Hook Driver函數在文檔裏介紹得很少,而且在有些win2000版本中不可用。請參

照微軟有關文檔:http://msdn.microsoft.com/library/default.asp?url=/library/en-us

/network/hh/network/firewall_3wfb.asp

5、NDIS-HOOKING (費爾防火牆就是用的這種技術吧,據我所知,雖然我沒看過原碼。)

NDIS-Hooking驅動攔截或者叫"HOOK"一些由NDIS封裝程序導出的函數。雖然從實現手段上來

說有些不正規,但一個有系統的NDIS-Hooking過濾會非常有效。

另外:NDIS-Hooking過濾驅動有下面的好處:

A、容易安裝(可以動態裝卸,不過有時候會出問題,裏面有些情況現在還未知。)

B、支持撥號-ppp適配器。

Ndis-Hooking技術在98和ME系統下非常有效和實用。在這些平台上,DDK文檔和provide

d services都能很有用的幫你HOOK由Ndis wrapper導出的函數。

Ndis-Hooking技術在NT,2000和XP上同樣有效和實用。這種技術很像核心模式的調試器。

文檔支持較少,而且基本上不會被WHQL認證。

PCAUSA提供了一套NDISPIM驅動例子,這些例子能在現有的WIN平台上運行成功(從95到X

P)。地址:http://www.pcausa.com/ndispim/Default.htm

其他:

Network操作和進程信息:

有許多人想知道網絡上的操作和WIN進程(就是應用程序啦)之間怎樣聯系起來,舉例來說,

可能會想知道是哪個進程在一個特定的IP端口上發送或接收數據。

先不考慮這種技術是否有用,或者是否可靠,我們認爲核心模式TCPIP驅動上層的過濾程序可

以處理這個問題。而TCPIP驅動下層的過濾程序根本看不到進程信息。特別要注意的是有些網絡服

務操作生成一個新的進程attach到系統進程上的。在這種情況下進程信息並不能告訴我們原先是哪

個進程生成的。特別是單獨在核心模式下的WIN服務(TDI客戶)

最後,有必要看看下面的資料United States Patent 5,987,611; "System and

methodology for managing internet access on a per application basis for client

computers connected to the internet "

我們並不知道這項專利的價值,也不知道他是否能用在包過濾上。詳情請參閱:http://www.

uspto.gov/patft/index.html

www.pcausa.com

============================================

drvipflt具體解析,就是上面所提到的吧(2-3就是說的這東東)。

假定大家對驅動框架已經有了一定的理解。IRP分配程序如下:

NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

{

...

switch (irpStack->MajorFunction)

{

...

case IRP_MJ_DEVICE_CONTROL:

ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

switch (ioControlCode)

{

// ioctl code to start filtering

//這裏可以從用戶模式程序發送這樣的請求。

//直接用DeviceIoControl這個函數,就像下面這樣調用就可

以了吧,我想。

//DeviceIoControl(drivehandle,START_IP_HOOK,NULL,0,NULL,0,&bytereturned,NU

LL)

case START_IP_HOOK:

{

//這個應該是最主要的函數了。

SetFilterFunction(cbFilterFunction);

break;

}

// ioctl to stop filtering

case STOP_IP_HOOK:

{

SetFilterFunction(NULL);

break;

}

// ioctl to add a filter rule

case ADD_FILTER:

{

if(inputBufferLength == sizeof(IPFilter))

{

IPFilter *nf;

nf = (IPFilter *)ioBuffer;

AddFilterToList(nf);

}

break;

}

// ioctl to free filter rule list

case CLEAR_FILTER:

{

ClearFilterList();

break;

}

default:

Irp->IoStatus.Status =

STATUS_INVALID_PARAMETER;

break;

}

break;

...

}

SetFilterFunction(cbFilterFunction)可能是最重要的一個程序了。具體如下:

實際上這個做法相當在系統中注冊了一個回調函數。

NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction)

{

NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS;

UNICODE_STRING filterName;

PDEVICE_OBJECT ipDeviceObject=NULL;

PFILE_OBJECT ipFileObject=NULL;

PF_SET_EXTENSION_HOOK_INFO filterData;

KEVENT event;

IO_STATUS_BLOCK ioStatus;

PIRP irp;

//首先獲得一個設備指針。

//first of all, we have to get a pointer to IpFilterDriver Device

RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME);

status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL,

&ipFileObject, &ipDeviceObject);

if(NT_SUCCESS(status))

{

//一些初始化工作,填充filterData。

//initialize the struct with functions parameters

filterData.ExtensionPointer = filterFunction;

//we need initialize the event used later by the IpFilterDriver to

signal us

//when it finished its work

KeInitializeEvent(&event, NotificationEvent, FALSE);

//這個就是最重要的注冊回調函數過程。DDK中具體講述是這樣的

//IOCTL_PF_SET_EXTENSION_POINTER registers filter-hook callback functions to

the IP filter driver

//to inform the IP filter driver to call those filter hook callbacks for every IP packet

//that is received or transmitted. Also, IOCTL_PF_SET_EXTENSION_POINTER

clears filter-hook

//callback functions from the IP filter driver. (看到了吧,最後一句話,注冊新的回調函

數,就將原先的清除掉了,

//所以說系統中只存在一個這樣的驅動有用。)

//we build the irp needed to establish fitler function這個地方僅

僅是生成這樣的IRP,並沒有注冊

irp =

IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,

ipDeviceObject,

(PVOID) &filterData,

sizeof(PF_SET_EXTENSION_HOOK_INFO),

NULL,

0,

FALSE,

&event,

&ioStatus);

if(irp != NULL)

{

// we send the IRP

//這個地方才是真正的注冊呀。

status = IoCallDriver(ipDeviceObject, irp);

//and finally, we wait for "acknowledge" of

IpDriverFilter

if (status == STATUS_PENDING)

{

waitStatus = KeWaitForSingleObject(&event,

Executive, KernelMode, FALSE, NULL);

if (waitStatus != STATUS_SUCCESS )

{}

}

status = ioStatus.Status;

if(!NT_SUCCESS(status)){}

}

else

{

//if we cant allocate the space, we return the

corresponding code error

status = STATUS_INSUFFICIENT_RESOURCES;

}

if(ipFileObject != NULL)

ObDereferenceObject(ipFileObject);

ipFileObject = NULL;

ipDeviceObject = NULL;

}

else

return status;

}

//真正的過濾函數是這個,在最早的IRPdispatch裏面傳遞的這個函數。

//這個函數就是系統傳遞了一個包頭和包內容和包長度之類的東西,你可以在裏面進行一些處理,

//假如你想讓這個包通過的話,就返回PF_FORWARD,或者你不想讓包通過的話,就返回PF_D

ROP就攔住了。是不是

//聽起來很簡單,

PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN

unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int

RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long

RecvLinkNextHop, IN unsigned long SendLinkNextHop)

{

IPPacket *ipp;

TCPHeader *tcph;

UDPHeader *udph;

int countRule=0;

struct filterList *aux = first;

//we "extract" the ip Header

ipp=(IPPacket *)PacketHeader;

// dprintf("Source: %x\nDestination: %x\nProtocol: %d", ipp->ipSource,

ipp->ipDestination, ipp->ipProtocol);

//TCP -> protocol = 6

//we accept all packets of established connections

if(ipp->ipProtocol == 6)

{

tcph=(TCPHeader *)Packet;

// dprintf("FLAGS: %x\n", tcph->flags);

//if we havent the bit SYN activate, we pass the packets

if(!(tcph->flags & 0x02))

return PF_FORWARD;

}

//otherwise, we compare the packet with our rules

while(aux != NULL)

{

// dprintf("Comparing with Rule %d", countRule);

//if protocol is the same....

if(aux->ipf.protocol == 0 || ipp->ipProtocol ==

aux->ipf.protocol)

{

//we look in source Address

if(aux->ipf.sourceIp != 0 && (ipp->ipSource &

aux->ipf.sourceMask) != aux->ipf.sourceIp)

{

aux=aux->next;

countRule++;

continue;

}

// we look in destination address

if(aux->ipf.destinationIp != 0 && (ipp->ipDestination

& aux->ipf.destinationMask) != aux->ipf.destinationIp)

{

aux=aux->next;

countRule++;

continue;

}

//if we have a tcp packet, we look in ports

//tcp, protocol = 6

if(ipp->ipProtocol == 6)

{

if(aux->ipf.sourcePort == 0 ||

tcph->sourcePort == aux->ipf.sourcePort)

{

if(aux->ipf.destinationPort == 0

|| tcph->destinationPort == aux->ipf.destinationPort) //puerto tcp destino

{

//now we decided what

to do with the packet

if(aux->ipf.drop)

return PF_DROP;

else

return PF_FORWARD;

}

}

}

//udp, protocol = 17

else if(ipp->ipProtocol == 17)

{

udph=(UDPHeader *)Packet;

if(aux->ipf.sourcePort == 0 ||

udph->sourcePort == aux->ipf.sourcePort)

{

if(aux->ipf.destinationPort == 0

|| udph->destinationPort == aux->ipf.destinationPort)

{

//now we decided what

to do with the packet

if(aux->ipf.drop)

return

PF_DROP;

else

return

PF_FORWARD;

}

}

}

else

{

//for other packet we dont look more and

....

//now we decided what to do with the

packet

if(aux->ipf.drop)

return PF_DROP;

else

return PF_FORWARD;

}

}

//compare with the next rule

countRule++;

aux=aux->next;

}

//we accept all not registered

return PF_FORWARD;

}

winpcap也是用的NDIS,將自己注冊爲一個協議處理驅動。(在原代碼的driverentry裏面能看到)

又:上面這個drvipflt這個代碼的過濾部分不知道大家是不是看起來很熟悉,是的,是抄的那個nu

mege的驅動開發包裏面的一個包過濾程序裏的,看來老外也是喜歡到處抄的。

ruike:

讀研的時候專門搞過nids,因此對winpcap可以說是情有獨鍾,這個東東確實好用,但也確實很煩

人,它有一個致命的缺陷就是只適用于共享式以太網絡,對于交換式網絡下的數據則無能爲力,我

專門做過測試,在使用交換機連接的局域網下,只能監聽到本網段內的數據,而對于來自其他網段

的數據則無法監聽,除非你把probe接到交換機之前或者接到交換機的console口上,不過那樣的

弊端是顯而易見的。

所以,winpcap的應用還是很有局限性的!

kingzai:

實現交換網絡的嗅探也有不少方法的

1.將你的抓包程序放在網關或代理服務器上,這樣抓到整個局域網的包。

2.對交換機實行端口映射,將該端口的數據包全部映射到某個監控機器上。

3.在交換機和路由器之間連接一個HUB,這樣數據將以廣播的方式發送。

4.實行ARP欺騙,即在你的機器上實現整個包的轉發,不過會降低整個局域網的效率。

warton:

嗅探對策:

光說嗅探了,我說說反嗅探吧:)

1.檢查網內的主機上是否將網卡設置爲混合模式(有很多工具可以做到,AntiSniff,Promiscan,S

entinel等)

2.對EtterCap這樣的交換網絡嗅探器(進行ARP欺騙),可以采用防止ARP欺騙的方法來對待

3.SSH加密通道

4.SSL

5.VPN

6.PGP等

目前這用利用網卡混合模式來進行sniffer的軟件看來作用不太大了,所以應該多考慮交換網絡的可

行辦法:

MAC Flooding,MAC Duplicating,ARP欺騙等等

這些方法實現起來就不怎麽容易了,歡迎有興趣的朋友提供相關的資料,呵呵!

netsys:

難道沒人用過RAW SOCKET 嗎?

雖然WINPCP功能很大,但RAW SOCKET可以讓你直接了SOCKET的原生機制。

實際上我提的那兩個問題是很容易解決的。。

netsys2:

對于一些混合模式的SNIFFER,大多采用發送特殊ARP包的方式,正確的網卡不會響應,而處于

混合模式的網卡則會響應。

當然,ARP與IP處于同層,因此你不能用RAW SOCKET完成,你需WinPcap支持工作。

下面是部分代碼

AnsiString msgStatus;

extern TArpFuncParam wParams;

int BuildARPPacket(PArpPacket ArpPacket, unsigned char *dst_etheraddr,

unsigned char *src_etheraddr, int ar_op, unsigned

char *ar_sha,

unsigned char *ar_sip, unsigned char *ar_tha,

unsigned char *ar_tip,unsigned short int ar_hw)

{

memcpy(&(ArpPacket->eth_dst_addr), dst_etheraddr, ETH_ADD_LEN);

memcpy(&(ArpPacket->eth_src_addr), src_etheraddr, ETH_ADD_LEN);

ArpPacket->eth_type = htons(ETH_TYPE_ARP);

ArpPacket->ar_hrd = htons(ar_hw);

ArpPacket->ar_pro = htons(ARP_PRO_IP);

ArpPacket->ar_hln = ARP_ETH_ADD_SPACE;

ArpPacket->ar_pln = ARP_IP_ADD_SPACE;

ArpPacket->ar_op = htons(ar_op);

memcpy(&(ArpPacket->ar_sha), ar_sha, ARP_ETH_ADD_SPACE);

memcpy(&(ArpPacket->ar_spa), ar_sip, ARP_IP_ADD_SPACE);

memcpy(&(ArpPacket->ar_tha), ar_tha, ARP_ETH_ADD_SPACE);

memcpy(&(ArpPacket->ar_tpa), ar_tip, ARP_IP_ADD_SPACE);

memset(ArpPacket->eth_pad, 32, ETH_PADDING_ARP);

return(EXIT_SUCCESS);

}

int OpenAdapter(LPADAPTER *lpAdapter)

{

*lpAdapter =

PacketOpenAdapter(wParams.AdapterList[wParams.SelectedAdapter]);

if(!(*lpAdapter) || ((*lpAdapter)->hFile == INVALID_HANDLE_VALUE))

{

msgStatus = "Error : unable to open the driver.";

SHOWSTAT(msgStatus);

return(EXIT_FAILURE);

}

return(EXIT_SUCCESS);

}

void CloseAdapter(LPADAPTER lpAdapter)

{

PacketCloseAdapter(lpAdapter);

}

void GetLocalMAC(LPADAPTER lpAdapter, unsigned char *ether_addr)

{

ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA) + sizeof(ULONG) - 1);

PPACKET_OID_DATA OidData;

OidData = (struct _PACKET_OID_DATA *)malloc(IoCtlBufferLength);

OidData->Oid = OID_802_3_CURRENT_ADDRESS;

OidData->Length = 6;

if(PacketRequest(lpAdapter, FALSE, OidData) == FALSE)

memcpy(ether_addr, 0, 6);

else

memcpy(ether_addr, OidData->Data, 6);

free(OidData);

}

int GetARPReply(LPPACKET lpPacket, unsigned char *iptarget, unsigned char

*result)

{

unsigned short int ether_type;

unsigned char ipsender[4];

unsigned int off=0;

unsigned int tlen;

struct bpf_hdr *hdr;

char *pChar;

char *buf;

buf = (char *)lpPacket->Buffer;

hdr = (struct bpf_hdr *)(buf + off);

tlen = hdr->bh_caplen;

off += hdr->bh_hdrlen;

pChar = (char*)(buf + off);

off = Packet_WORDALIGN(off + tlen);

memcpy(&ether_type, pChar + 12, 2);

ether_type = ntohs(ether_type);

if(ether_type == ETH_TYPE_ARP)

{

memcpy(ipsender, pChar + 28, 4);

if((iptarget[0] == ipsender[0])&&(iptarget[1] == ipsender[1])&&

(iptarget[2] == ipsender[2])&&(iptarget[3] == ipsender[3]))

memcpy(result, pChar + 22, 6);

else

return(EXIT_FAILURE);

}

else

return(EXIT_FAILURE);

return(EXIT_SUCCESS);

}

int CheckPROMode(LPADAPTER lpAdapter, unsigned char *iptarget, unsigned char

*remotemac)

{

LPPACKET lpPacketRequest;

LPPACKET lpPacketReply;

char buffer[256000];

TArpPacket ArpPacket;

unsigned char magicpack[ETH_ADD_LEN]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFE};

unsigned char mactarget[ARP_ETH_ADD_SPACE];

DWORD timestamp = 0;

int numPacks = 0;

/* Init fields */

memset(mactarget, 0, 6);

/* Allocate PACKET structure for ARP Request packet */

if((lpPacketRequest = PacketAllocatePacket()) == NULL)

{

msgStatus = "Error : failed to allocate the LPPACKET structure..";

SHOWSTAT(msgStatus);

return(EXIT_FAILURE);

}

/* Init packet structure */

memset(&ArpPacket, 0, sizeof(TArpPacket));

/* Build ARP Request packet */

BuildARPPacket(&ArpPacket, magicpack, wParams.srcMAC, ARP_OP_REQUEST,

wParams.srcMAC, wParams.srcIPAdd, mactarget, iptarget,wParams.ar_hw);

/* Init ARP Request packet */

PacketInitPacket(lpPacketRequest, &ArpPacket, sizeof(ArpPacket));

/* Set number of ARP Request packets to send */

if(PacketSetNumWrites(lpAdapter, 1) == FALSE)

{

msgStatus = "Warning : unable to send more than one packet in a single write..";

SHOWSTAT(msgStatus);

}

/* Set hardware filter to directed mode */

if(PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED) == FALSE)

{

msgStatus ="Warning: unable to set directed mode..";

SHOWSTAT(msgStatus);

}

/* Set a 512K buffer in the driver */

if(PacketSetBuff(lpAdapter, 512000) == FALSE)

{

msgStatus = "Error: unable to set the kernel buffer..";

SHOWSTAT(msgStatus);

PacketFreePacket(lpPacketRequest);

return(EXIT_FAILURE);

}

/* Set a 1 second read timeout */

if(PacketSetReadTimeout(lpAdapter, -1) == FALSE)

{

msgStatus = "Warning: unable to set the read tiemout..";

SHOWSTAT(msgStatus);

}

/* Allocate PACKET structure for ARP Reply packet */

if((lpPacketReply = PacketAllocatePacket()) == NULL)

{

msgStatus = "Error: failed to allocate the LPPACKET structure..";

SHOWSTAT(msgStatus);

PacketFreePacket(lpPacketRequest);

return(EXIT_FAILURE);

}

/* Init ARP Reply packet */

PacketInitPacket(lpPacketReply, (char*)buffer, 256000);

/* Allocate memory for remote MAC address */

timestamp = GetTickCount();

/* Main capture loop */

for(;;)

{

if(numPacks < wParams.numPacks)

{

/* Send packet */

if(PacketSendPacket(lpAdapter, lpPacketRequest, TRUE) == FALSE)

{

msgStatus ="Error : unable to send the packets..";

SHOWSTAT(msgStatus);

PacketFreePacket(lpPacketRequest);

PacketFreePacket(lpPacketReply);

return(EXIT_FAILURE);

}

/* Free packet */

PacketFreePacket(lpPacketRequest);

numPacks += 1;

}

/* Capture the packets */

if(PacketReceivePacket(lpAdapter, lpPacketReply, TRUE) == FALSE)

{

msgStatus = "Error: PacketReceivePacket failed..";

SHOWSTAT(msgStatus);

PacketFreePacket(lpPacketReply);

return(EXIT_FAILURE);

}

if(lpPacketReply->ulBytesReceived > 0)

if(GetARPReply(lpPacketReply, iptarget, remotemac) == EXIT_SUCCESS)

break;

if((GetTickCount() - timestamp) > wParams.delay)

{

PacketFreePacket(lpPacketReply);

return(EXIT_FAILURE);

}

}

/* Free packet */

PacketFreePacket(lpPacketReply);

return(EXIT_SUCCESS);

}

sunxufei:

哦,交換機是以MAC地址進行交換的,不是IP那一層的,要IP已經路由器了

現在交換機便宜了,因此以後你想用sniffer抓密碼概率不大了,不過還能多公司仍然是交換機和H

UB一起用的,這樣小範圍內是有效地,至于ADSL CABLE FTTB,我的FTTB是用華爲設計的設備

,呵呵,不僅僅工網IP,只有我和交換機兩個MAC(這次中國人幹的不錯),沒希望找到第三者,很安全,但

不都這樣安全,很多人的網絡還是很糟糕的.

很多加密協議可以用來提高安全性,但老的POP3,SMTP,HTTP,FTP這種協議應用廣泛,不可能在短

時間內完全取代,而且加密也是有待價的,所以對于要求較高的場合,才會加密.

不過sniffer不是給大家偷密碼用的,我當初用來學習網絡,看看包的樣子,後來就用來當作網管工具,

分析網絡的健康與否,其實這樣的話,你知道,很有可能sniffer就是接在我需要探測的網絡上,聽診器

嗎,到處都聽聽,呵呵,因此即使用了交換機,sniffer仍然是有用處的,但不是抓密碼!!

Wincap很簡單,大3的學生不要怕,去他的網站看看,有例子的,VC6編譯,BCB也行的,把lib的格式轉

換一下,不過寫這種程序,你最好先熟悉協議,很多協議在linux裏有現成的源代碼,主要是一些struct

吧,移植時注意VC可不是gcc,有些c的高級語法,編譯選項要注意,否則差一個byte你就得不到正確的

結果.

如果你搞不到sniffer,Win2000 Server也有網絡包查看器的,不比sniffer強大,但簡單的東西入手

也快.

反嗅探和嗅探技術其實很old了,呵呵,不過CSDN經常old的.

注意不要幹壞事,有矛必有盾

 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
很久沒有更新專欄了,關鍵是寫不出什麽好東西,也怕大家見笑! 雖然我還沒被人罵過,但我見過別人被人罵,哎。不是說,這在csdn好像很正常哈! 今天把這個貼子整理一下,這本是專題開發版的一個專題討論貼:http://expert.csdn.net/Expert/topic/2333/2333459.xml?temp=.3382532,其實這個貼子也沒有挖出更深入的 東西,關鍵是專題版目前人氣不太好吧。我發這個貼是希望更多的人能到專題版,參與和組織討論,但結果並不是太理想。 kingzai: sniffer中文翻譯過來就是嗅探器,在當前網絡技術中使用得非常得廣泛。sniffer既可以做爲網絡故 障的診斷工具,也可以作爲黑客嗅探和監聽的工具。最近兩年,網絡監聽(sniffer)技術出現了新的 重要特征。傳統的sniffer技術是被動地監聽網絡通信、用戶名和口令。而新的sniffer技術出現了主 動地控制通信數據的特點,把sniffer技術擴展到了一個新的領域。Sniffer 技術除了目前在傳統的 網絡偵測管理外,也開始被應用在資訊保全的領域。可以這樣說,sniffer技術是一把雙刃劍,如何 更好的利用它,了解它的一些特性,將能使這項技術更好的爲我們帶來便利。 sniffer的編程方法比較通用的有以下幾種,1.winpcap 這是一個比較通用的庫,相信做過抓包的 工具大多數人都不會太陌生 2.raw socket 在2000以後的版本都支持此項功能,2000 server有 個網絡監視器就是基于raw socket 3.tdi,ndis,spi,hook socket技術,這種技術比較大的不同是 ,可以將包截取而不是僅僅獲得包的一份拷貝 。總的說來,一般以前兩者居多。 我這裏提的都還比較片面,更多的需要大家來補充。我辦這個專題的目的是希望大家共同來了解 ,討論sniffer技術,讓更多的人參與進來,讓大家知道,這個板塊能夠給大家帶來真正想要的東西 。 warton: libpcap是個好東西,linux,windows下都能用,很多入侵檢測之類的安全系統都是以這爲核心。不 過我一直沒用過它,不知道它的跨平台性如何? 要用spi的話,看看xfilter的代碼和書,特別是那本書上講得不錯,可惜一直沒用它做出什麽東西來 。 raw socket寫的sniffer比較多,網上代碼也很多! 昨天見csdn首頁有幾篇關于sniffer的文章,保存了,還沒來得及看... 俺明天來說說目前常用的sniffer類工具和它們的技術實現! csdn首頁的兩篇文章,大家可以看看,裏面好像還有幾篇,暫時找不到了 http://www.csdn.net/develop/article/21/21363.shtm http://www.csdn.net/develop/article/21/21352.shtm http://www.csdn.net/develop/article/15/15919.shtm netsys2: 一)winpcap驅動簡介 winpcap(windows packet capture)是windows平台下一個免費,公共的網絡訪問系統。開 發winpcap這個項目的目的在于爲win32應用程序提供訪問網絡底層的能力。它提供了以下的各項 功能: 1> 捕獲原始數據報,包括在共享網絡上各主機發送/接收的以及相互之間交換的數據報; 2> 在數據報發往應用程序之前,按照自定義的規則將某些特殊的數據報過濾掉; 3> 在網絡上發送原始的數據報; 4> 收集網絡通信過程中的統計信息。 winpcap的主要功能在于獨立于主機協議(如TCP-IP)而發送和接收原始數據報。也就是說,winp cap不能阻塞,過濾或控制其他應用程序數據報的發收,它僅僅只是監聽共享網絡上傳送的數據報 。因此,它不能用于QoS調度程序或個人防火牆。 目前,winpcap開發的主要對象是windows NT/2000/XP,這主要是因爲在使用winpcap的 用戶中只有一小部分是僅使用windows 95/98/Me,並且M$也已經放棄了對win9x的開發。因 此本文相關的程序T-ARP也是面向NT/2000/XP用戶的。其實winpcap中的面向9x系統的概念和 NT系統的非常相似,只是在某些實現上有點差異,比如說9x只支持ANSI編碼,而NT系統則提倡使 用Unicode編碼。 zzhong2: 有個軟件叫sniffer pro.可以作網管軟件用,有很多功能,可監視網絡運行情況,每台網內機器的數據 流量,實時反映每台機器所訪問IP以及它們之間的數據流通情況,可以抓包,可對過濾器進行設置,以便 只抓取想要的包,比如POP3包,smtp包,ftp包等,並可從中找到郵箱用戶名和密碼,還有ftp用戶名和 密碼.它還可以在使用交換機的網絡上監聽,不過要在交換機上裝它的一個軟件. 還有一個簡單的監聽軟件叫 Passwordsniffer,可截獲郵箱用戶名和密碼,還有ftp用戶名和密碼,它 只能用在用HUB網絡上 以上兩個軟件都可在小鳳居上下載到:http://www.chinesehack.org/ warton: libpcap的最新版本是0.7.2,下載很多(基于linux/unix) winpcap的最新版本是3.0 這裏有winpcap的源代碼:http://download.pchome.net/php/dl.php?sid=11474 著名軟件tcpdump及ids snort都是基于libpcap編寫的,此外Nmap掃描器也是基于libpcap來捕 獲目標主機返回的數據包的。 winpcap提供給用戶兩個不同級別的編程接口:一個基于libpcap的wpcap.dl,另一個是較底層的 packet.dll。對于一般的要與unix平台上libpcap兼容的開發來說,使用pacap.dll是當然的選擇 。 下面幾個庫是與lipcap相關的: libnet1.0.2:數據包的發送個構造過程 libnids:實現了ids的一些 框架 libicmp:icmp數據包處理 一些著名的嗅探器: tcpdump/windump:支持多種unix,後者支持windows。基于libpcap Sniffit:unix,windows,libpcap Ngrep:libpcap,unixwindows.可以用規則表達式,識別PPP,SLIP及FDDI數據包 Sniffer pro/NetXray:專業的協議分析工具,是NAI提供的網絡分析方案中的一部分 其它: Iris LanExplorer NetMOnitor CommView 單一用途的噢探器 口令嗅:winsniffer,典型的黑客工具,嗅探並解析ftp,pop3,http,icq,smtp,telnet,IMAP,NNTP 等口令 password sniffer for NetHackerIII 專用 嗅探器: SMB嗅探器:L0phtcrack,SMPRelay TCP連接會話嗅探器:CommView ,Iris,Juggernaut SSL嗅探器:SSLDump--sslv3/tls網絡協議分析工具 RIDIUS嗅控器:一個基于udp的論證記賬協議,Radiusniff是其代表 PPTP嗅 控器:Anger,PPTP-sniff(solaris) SNMP嗅探器:Snmpsniff 交換網絡嗅探器:Ettercap 綜合:Dsniff 其它交換網絡嗅探器: snarp,parasite 嗅探對策......... netsys2: 網絡上流傳的GUNIFFER是個基本的原型: http://asp.6to23.com/nowcan/code/guniffer.zip void main(int argc, char ** argv) { int iErrorCode; char RecvBuf[MAX_PACK_LEN] = {0}; usage(); if(GetCmdLine(argc, argv)==CMD_PARAM_HELP) exit(0); //初始化SOCKET WSADATA wsaData; iErrorCode = WSAStartup(MAKEWORD(2,1),&wsaData); CheckSockError(iErrorCode, "WSAStartup"); SockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP); CheckSockError(SockRaw, "socket"); //獲取本機IP地址 char FAR name[MAX_HOSTNAME_LAN]; iErrorCode = gethostname(name, MAX_HOSTNAME_LAN); CheckSockError(iErrorCode, "gethostname"); struct hostent FAR * pHostent; //注意下面這三句,這裏先對pHostent分配了一塊 pHostent = (struct hostent * )malloc(sizeof(struct hostent)); //內存,然後有讓它等于gethostbyname函數的返回 pHostent = gethostbyname(name); //值,但gethostbyname函數是自己在函數內部分配內 存的,因此上一句根本就是多余,把上一句刪除後一切正常。但此程序用VC6編譯運行都沒有問題 ,不知爲何?也許是VC6的編譯器優化在起作用。 SOCKADDR_IN sa; sa.sin_family = AF_INET; sa.sin_port = htons(6000); memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length); free(pHostent); //由于前面分配內存的語句已經刪除,所以這一句也要去掉,否則出錯。感謝網 友 Heyuming 發現這個問題。 iErrorCode = bind(SockRaw, (PSOCKADDR)&sa, sizeof(sa)); CheckSockError(iErrorCode, "bind"); //設置SOCK_RAW爲SIO_RCVALL,以便接收所有的IP包 DWORD dwBufferLen[10] ; DWORD dwBufferInLen = 1 ; DWORD dwBytesReturned = 0 ; iErrorCode=WSAIoctl(SockRaw, SIO_RCVALL,&dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL ); CheckSockError(iErrorCode, "Ioctl"); //偵聽IP報文 while(1) { memset(RecvBuf, 0, sizeof(RecvBuf)); iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf), 0); CheckSockError(iErrorCode, "recv"); iErrorCode = DecodeIpPack(RecvBuf, iErrorCode); CheckSockError(iErrorCode, "Decode"); } } 它有2個不方便之處: 1)不能選擇網卡 2)采用死循環方式讀數據,改編到WINDOWS窗口模式下時有死機的感覺。 sevencat(): 上次找了一些資料整理了一下,不過人氣不旺,而且最近比較忙,暫時還沒繼續下去。 http://expert.csdn.net/Expert/topic/2299/2299615.xml?temp=.2761499 WINDOWS網絡包過濾技術 (原文:http://www.ndis.com/papers/winpktfilter.htm) 一、user-mode網絡包過濾 1、winsock分層service provider 參照Microsoft Platform SDK上有關文檔和例子 (http://www.microsoft.com/msdownload/platformsdk/sdkupdate/) 這裏有好幾個microsoft lsp 例子,最新(可能最bug-free)的經常在這裏能找到。需要知道的是 可以通過TDI調用核心TCPIP驅動,而且可以完全繞開WINSOCK,在大多數情況下這不是一個問 題。例如:QOS的實現可以在WINSOCK LSP上。 然而,這樣做的話,程序必須察看和操作每個包,而不能依靠WINSOCK LSP,他們要以一種接 近核心態的方法來實現。 2、win2000包過濾接口   WIN2000包過濾接口提供了一種機制,這種機制允許用戶態程序或者服務指定一系列的"過濾 原則",這些過濾原則會被低層的TCPIP實現用來過濾包。這種過濾工主要是對IP原地址、目標地址 、端口號(或者端口號範圍)進行pass或者drop操作。 Windows Developer's Journal 《用iphlpapi.dll進行包過濾》作者:Ton plooy,October,2000,Volume 11, Number 10。   WIN2000提供了一個較好對TCPIP的可編程控制,其中包括包過濾。不幸的是,有關這個新 的API的文檔並不是很容易能找到。這篇文章向你演示了怎樣對特定IP地址或者特定TCP端口的包 進行阻塞的編程。 鏈接:www.wdj.com 上面這個例子的下載:ftp://ftp.wdj.com/pub/webzip/1110/plooy.zip Hollis 的解決方案:   HTS W2K IpHook例子演示了IP過濾和它的HOOK API,包含原文件,而且是免費的, 需要HtsCpp運行時庫(免費),下載地址:http://www.hollistech.com/ 3、winsock替代DLL   在使用WINSOCK LSP之前,唯一的辦法是用自己的DLL取代微軟的WINSOCK DLL,假 如實現順利的話,自己的DLL會接收用戶的WINSOCK調用請求,然後還可以調用原來的WINSOC K DLL來處理。   不過這樣的實現是比較費力的,其中有個困難就是微軟的WINSOCK DLL裏面經常有一些未 公開的內部使用的函數,一個WINSOCK代替DLL至少要處理其中的一些未公開函數。   隨著WINDOWS系統結構的變化,有些方面得到了加強,比如系統文件保護,這使得這種技術 變得不太可行。總的說來,使用WINSOCK DLL替換不是一個壞主意。(Xfilter就是用的這種技 術,原代碼可能在網上有流傳,我以前看到過的) 二、kernel-mode網絡包過濾 1、Transport Data Interface (TDI)   這主要是一個直接在核心TCPIP驅動上面的一層過濾驅動。在WINXP上TDI驅動是一種傳統的 NT風格的驅動,使用了基于IRP的API,這裏有兩種方法來實現。 A、使用核心模式服務的IoAttachDeviceXYZ函數族在TDI上實現一個過濾。 B、對TDI驅動IRP DISPATCH表進行過濾。   IoAttachDeviceXYZ函數在許多WINNT驅動開發的書上提到。這兩種技術都需要對WINNT驅 動開發編程技術十分了解,對TDI函數也要相當的了解。 2、NDIS中間層(IM) 具體請看NDIS IM FAQ:http://www.pcausa.com/resources/ndisimfaq.htm 3、WIN2000 FILTER-HOOK   請參照有關DDK文檔,系統中只能有一個活動的Filter-Hook存在,這點使這種技術的使用有 嚴重的限制。(平時所見的drvipflt就是用的這個) 4、WIN2000 FIREWALL-HOOK    Firewall-Hook Driver函數在文檔裏介紹得很少,而且在有些win2000版本中不可用。請參 照微軟有關文檔:http://msdn.microsoft.com/library/default.asp?url=/library/en-us /network/hh/network/firewall_3wfb.asp 5、NDIS-HOOKING  (費爾防火牆就是用的這種技術吧,據我所知,雖然我沒看過原碼。) NDIS-Hooking驅動攔截或者叫"HOOK"一些由NDIS封裝程序導出的函數。雖然從實現手段上來 說有些不正規,但一個有系統的NDIS-Hooking過濾會非常有效。 另外:NDIS-Hooking過濾驅動有下面的好處: A、容易安裝(可以動態裝卸,不過有時候會出問題,裏面有些情況現在還未知。) B、支持撥號-ppp適配器。   Ndis-Hooking技術在98和ME系統下非常有效和實用。在這些平台上,DDK文檔和provide d services都能很有用的幫你HOOK由Ndis wrapper導出的函數。   Ndis-Hooking技術在NT,2000和XP上同樣有效和實用。這種技術很像核心模式的調試器。 文檔支持較少,而且基本上不會被WHQL認證。 PCAUSA提供了一套NDIS PIM驅動例子,這些例子能在現有的WIN平台上運行成功(從95到X P)。地址:http://www.pcausa.com/ndispim/Default.htm 其他: Network操作和進程信息:   有許多人想知道網絡上的操作和WIN進程(就是應用程序啦)之間怎樣聯系起來,舉例來說, 可能會想知道是哪個進程在一個特定的IP端口上發送或接收數據。   先不考慮這種技術是否有用,或者是否可靠,我們認爲核心模式TCPIP驅動上層的過濾程序可 以處理這個問題。而TCPIP驅動下層的過濾程序根本看不到進程信息。特別要注意的是有些網絡服 務操作生成一個新的進程attach到系統進程上的。在這種情況下進程信息並不能告訴我們原先是哪 個進程生成的。特別是單獨在核心模式下的WIN服務(TDI客戶)   最後,有必要看看下面的資料United States Patent 5,987,611; "System and methodology for managing internet access on a per application basis for client computers connected to the internet "   我們並不知道這項專利的價值,也不知道他是否能用在包過濾上。詳情請參閱:http://www. uspto.gov/patft/index.html www.pcausa.com ============================================ drvipflt具體解析,就是上面所提到的吧(2-3就是說的這東東)。 假定大家對驅動框架已經有了一定的理解。IRP分配程序如下: NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { ... switch (irpStack->MajorFunction) { ... case IRP_MJ_DEVICE_CONTROL: ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; switch (ioControlCode) { // ioctl code to start filtering //這裏可以從用戶模式程序發送這樣的請求。 //直接用DeviceIoControl這個函數,就像下面這樣調用就可 以了吧,我想。 //DeviceIoControl(drivehandle,START_IP_HOOK,NULL,0,NULL,0,&bytereturned,NU LL) case START_IP_HOOK: { //這個應該是最主要的函數了。 SetFilterFunction(cbFilterFunction); break; } // ioctl to stop filtering case STOP_IP_HOOK: { SetFilterFunction(NULL); break; } // ioctl to add a filter rule case ADD_FILTER: { if(inputBufferLength == sizeof(IPFilter)) { IPFilter *nf; nf = (IPFilter *)ioBuffer; AddFilterToList(nf); } break; } // ioctl to free filter rule list case CLEAR_FILTER: { ClearFilterList(); break; } default: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; } break; ... } SetFilterFunction(cbFilterFunction)可能是最重要的一個程序了。具體如下: 實際上這個做法相當在系統中注冊了一個回調函數。 NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction) { NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS; UNICODE_STRING filterName; PDEVICE_OBJECT ipDeviceObject=NULL; PFILE_OBJECT ipFileObject=NULL; PF_SET_EXTENSION_HOOK_INFO filterData; KEVENT event; IO_STATUS_BLOCK ioStatus; PIRP irp; //首先獲得一個設備指針。 //first of all, we have to get a pointer to IpFilterDriver Device RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME); status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL, &ipFileObject, &ipDeviceObject); if(NT_SUCCESS(status)) { //一些初始化工作,填充filterData。 //initialize the struct with functions parameters filterData.ExtensionPointer = filterFunction; //we need initialize the event used later by the IpFilterDriver to signal us //when it finished its work KeInitializeEvent(&event, NotificationEvent, FALSE); //這個就是最重要的注冊回調函數過程。DDK中具體講述是這樣的 //IOCTL_PF_SET_EXTENSION_POINTER registers filter-hook callback functions to the IP filter driver //to inform the IP filter driver to call those filter hook callbacks for every IP packet //that is received or transmitted. Also, IOCTL_PF_SET_EXTENSION_POINTER clears filter-hook //callback functions from the IP filter driver. (看到了吧,最後一句話,注冊新的回調函 數,就將原先的清除掉了, //所以說系統中只存在一個這樣的驅動有用。) //we build the irp needed to establish fitler function這個地方僅 僅是生成這樣的IRP,並沒有注冊 irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER, ipDeviceObject, (PVOID) &filterData, sizeof(PF_SET_EXTENSION_HOOK_INFO), NULL, 0, FALSE, &event, &ioStatus); if(irp != NULL) { // we send the IRP //這個地方才是真正的注冊呀。 status = IoCallDriver(ipDeviceObject, irp); //and finally, we wait for "acknowledge" of IpDriverFilter if (status == STATUS_PENDING) { waitStatus = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); if (waitStatus != STATUS_SUCCESS ) {} } status = ioStatus.Status; if(!NT_SUCCESS(status)){} } else { //if we cant allocate the space, we return the corresponding code error status = STATUS_INSUFFICIENT_RESOURCES; } if(ipFileObject != NULL) ObDereferenceObject(ipFileObject); ipFileObject = NULL; ipDeviceObject = NULL; } else return status; } //真正的過濾函數是這個,在最早的IRPdispatch裏面傳遞的這個函數。 //這個函數就是系統傳遞了一個包頭和包內容和包長度之類的東西,你可以在裏面進行一些處理, //假如你想讓這個包通過的話,就返回PF_FORWARD,或者你不想讓包通過的話,就返回PF_D ROP就攔住了。是不是 //聽起來很簡單, PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long RecvLinkNextHop, IN unsigned long SendLinkNextHop) { IPPacket *ipp; TCPHeader *tcph; UDPHeader *udph; int countRule=0; struct filterList *aux = first; //we "extract" the ip Header ipp=(IPPacket *)PacketHeader; // dprintf("Source: %x\nDestination: %x\nProtocol: %d", ipp->ipSource, ipp->ipDestination, ipp->ipProtocol); //TCP -> protocol = 6 //we accept all packets of established connections if(ipp->ipProtocol == 6) { tcph=(TCPHeader *)Packet; // dprintf("FLAGS: %x\n", tcph->flags); //if we havent the bit SYN activate, we pass the packets if(!(tcph->flags & 0x02)) return PF_FORWARD; } //otherwise, we compare the packet with our rules while(aux != NULL) { // dprintf("Comparing with Rule %d", countRule); //if protocol is the same.... if(aux->ipf.protocol == 0 || ipp->ipProtocol == aux->ipf.protocol) { //we look in source Address if(aux->ipf.sourceIp != 0 && (ipp->ipSource & aux->ipf.sourceMask) != aux->ipf.sourceIp) { aux=aux->next; countRule++; continue; } // we look in destination address if(aux->ipf.destinationIp != 0 && (ipp->ipDestination & aux->ipf.destinationMask) != aux->ipf.destinationIp) { aux=aux->next; countRule++; continue; } //if we have a tcp packet, we look in ports //tcp, protocol = 6 if(ipp->ipProtocol == 6) { if(aux->ipf.sourcePort == 0 || tcph->sourcePort == aux->ipf.sourcePort) { if(aux->ipf.destinationPort == 0 || tcph->destinationPort == aux->ipf.destinationPort) //puerto tcp destino { //now we decided what to do with the packet if(aux->ipf.drop) return PF_DROP; else return PF_FORWARD; } } } //udp, protocol = 17 else if(ipp->ipProtocol == 17) { udph=(UDPHeader *)Packet; if(aux->ipf.sourcePort == 0 || udph->sourcePort == aux->ipf.sourcePort) { if(aux->ipf.destinationPort == 0 || udph->destinationPort == aux->ipf.destinationPort) { //now we decided what to do with the packet if(aux->ipf.drop) return PF_DROP; else return PF_FORWARD; } } } else { //for other packet we dont look more and .... //now we decided what to do with the packet if(aux->ipf.drop) return PF_DROP; else return PF_FORWARD; } } //compare with the next rule countRule++; aux=aux->next; } //we accept all not registered return PF_FORWARD; } winpcap也是用的NDIS,將自己注冊爲一個協議處理驅動。(在原代碼的driverentry裏面能看到) 又:上面這個drvipflt這個代碼的過濾部分不知道大家是不是看起來很熟悉,是的,是抄的那個nu mege的驅動開發包裏面的一個包過濾程序裏的,看來老外也是喜歡到處抄的。 ruike: 讀研的時候專門搞過nids,因此對winpcap可以說是情有獨鍾,這個東東確實好用,但也確實很煩 人,它有一個致命的缺陷就是只適用于共享式以太網絡,對于交換式網絡下的數據則無能爲力,我 專門做過測試,在使用交換機連接的局域網下,只能監聽到本網段內的數據,而對于來自其他網段 的數據則無法監聽,除非你把probe接到交換機之前或者接到交換機的console口上,不過那樣的 弊端是顯而易見的。 所以,winpcap的應用還是很有局限性的! kingzai: 實現交換網絡的嗅探也有不少方法的 1.將你的抓包程序放在網關或代理服務器上,這樣抓到整個局域網的包。 2.對交換機實行端口映射,將該端口的數據包全部映射到某個監控機器上。 3.在交換機和路由器之間連接一個HUB,這樣數據將以廣播的方式發送。 4.實行ARP欺騙,即在你的機器上實現整個包的轉發,不過會降低整個局域網的效率。 warton: 嗅探對策: 光說嗅探了,我說說反嗅探吧:) 1.檢查網內的主機上是否將網卡設置爲混合模式(有很多工具可以做到,AntiSniff,Promiscan,S entinel等) 2.對EtterCap這樣的交換網絡嗅探器(進行ARP欺騙),可以采用防止ARP欺騙的方法來對待 3.SSH加密通道 4.SSL 5.VPN 6.PGP等 目前這用利用網卡混合模式來進行sniffer的軟件看來作用不太大了,所以應該多考慮交換網絡的可 行辦法: MAC Flooding,MAC Duplicating,ARP欺騙等等 這些方法實現起來就不怎麽容易了,歡迎有興趣的朋友提供相關的資料,呵呵! netsys: 難道沒人用過RAW SOCKET 嗎? 雖然WINPCP功能很大,但RAW SOCKET可以讓你直接了SOCKET的原生機制。 實際上我提的那兩個問題是很容易解決的。。 netsys2: 對于一些混合模式的SNIFFER,大多采用發送特殊ARP包的方式,正確的網卡不會響應,而處于 混合模式的網卡則會響應。 當然,ARP與IP處于同層,因此你不能用RAW SOCKET完成,你需WinPcap支持工作。 下面是部分代碼 AnsiString msgStatus; extern TArpFuncParam wParams; int BuildARPPacket(PArpPacket ArpPacket, unsigned char *dst_etheraddr, unsigned char *src_etheraddr, int ar_op, unsigned char *ar_sha, unsigned char *ar_sip, unsigned char *ar_tha, unsigned char *ar_tip,unsigned short int ar_hw) { memcpy(&(ArpPacket->eth_dst_addr), dst_etheraddr, ETH_ADD_LEN); memcpy(&(ArpPacket->eth_src_addr), src_etheraddr, ETH_ADD_LEN); ArpPacket->eth_type = htons(ETH_TYPE_ARP); ArpPacket->ar_hrd = htons(ar_hw); ArpPacket->ar_pro = htons(ARP_PRO_IP); ArpPacket->ar_hln = ARP_ETH_ADD_SPACE; ArpPacket->ar_pln = ARP_IP_ADD_SPACE; ArpPacket->ar_op = htons(ar_op); memcpy(&(ArpPacket->ar_sha), ar_sha, ARP_ETH_ADD_SPACE); memcpy(&(ArpPacket->ar_spa), ar_sip, ARP_IP_ADD_SPACE); memcpy(&(ArpPacket->ar_tha), ar_tha, ARP_ETH_ADD_SPACE); memcpy(&(ArpPacket->ar_tpa), ar_tip, ARP_IP_ADD_SPACE); memset(ArpPacket->eth_pad, 32, ETH_PADDING_ARP); return(EXIT_SUCCESS); } int OpenAdapter(LPADAPTER *lpAdapter) { *lpAdapter = PacketOpenAdapter(wParams.AdapterList[wParams.SelectedAdapter]); if(!(*lpAdapter) || ((*lpAdapter)->hFile == INVALID_HANDLE_VALUE)) { msgStatus = "Error : unable to open the driver."; SHOWSTAT(msgStatus); return(EXIT_FAILURE); } return(EXIT_SUCCESS); } void CloseAdapter(LPADAPTER lpAdapter) { PacketCloseAdapter(lpAdapter); } void GetLocalMAC(LPADAPTER lpAdapter, unsigned char *ether_addr) { ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA) + sizeof(ULONG) - 1); PPACKET_OID_DATA OidData; OidData = (struct _PACKET_OID_DATA *)malloc(IoCtlBufferLength); OidData->Oid = OID_802_3_CURRENT_ADDRESS; OidData->Length = 6; if(PacketRequest(lpAdapter, FALSE, OidData) == FALSE) memcpy(ether_addr, 0, 6); else memcpy(ether_addr, OidData->Data, 6); free(OidData); } int GetARPReply(LPPACKET lpPacket, unsigned char *iptarget, unsigned char *result) { unsigned short int ether_type; unsigned char ipsender[4]; unsigned int off=0; unsigned int tlen; struct bpf_hdr *hdr; char *pChar; char *buf; buf = (char *)lpPacket->Buffer; hdr = (struct bpf_hdr *)(buf + off); tlen = hdr->bh_caplen; off += hdr->bh_hdrlen; pChar = (char*)(buf + off); off = Packet_WORDALIGN(off + tlen); memcpy(&ether_type, pChar + 12, 2); ether_type = ntohs(ether_type); if(ether_type == ETH_TYPE_ARP) { memcpy(ipsender, pChar + 28, 4); if((iptarget[0] == ipsender[0])&&(iptarget[1] == ipsender[1])&& (iptarget[2] == ipsender[2])&&(iptarget[3] == ipsender[3])) memcpy(result, pChar + 22, 6); else return(EXIT_FAILURE); } else return(EXIT_FAILURE); return(EXIT_SUCCESS); } int CheckPROMode(LPADAPTER lpAdapter, unsigned char *iptarget, unsigned char *remotemac) { LPPACKET lpPacketRequest; LPPACKET lpPacketReply; char buffer[256000]; TArpPacket ArpPacket; unsigned char magicpack[ETH_ADD_LEN]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFE}; unsigned char mactarget[ARP_ETH_ADD_SPACE]; DWORD timestamp = 0; int numPacks = 0; /* Init fields */ memset(mactarget, 0, 6); /* Allocate PACKET structure for ARP Request packet */ if((lpPacketRequest = PacketAllocatePacket()) == NULL) { msgStatus = "Error : failed to allocate the LPPACKET structure.."; SHOWSTAT(msgStatus); return(EXIT_FAILURE); } /* Init packet structure */ memset(&ArpPacket, 0, sizeof(TArpPacket)); /* Build ARP Request packet */ BuildARPPacket(&ArpPacket, magicpack, wParams.srcMAC, ARP_OP_REQUEST, wParams.srcMAC, wParams.srcIPAdd, mactarget, iptarget,wParams.ar_hw); /* Init ARP Request packet */ PacketInitPacket(lpPacketRequest, &ArpPacket, sizeof(ArpPacket)); /* Set number of ARP Request packets to send */ if(PacketSetNumWrites(lpAdapter, 1) == FALSE) { msgStatus = "Warning : unable to send more than one packet in a single write.."; SHOWSTAT(msgStatus); } /* Set hardware filter to directed mode */ if(PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED) == FALSE) { msgStatus ="Warning: unable to set directed mode.."; SHOWSTAT(msgStatus); } /* Set a 512K buffer in the driver */ if(PacketSetBuff(lpAdapter, 512000) == FALSE) { msgStatus = "Error: unable to set the kernel buffer.."; SHOWSTAT(msgStatus); PacketFreePacket(lpPacketRequest); return(EXIT_FAILURE); } /* Set a 1 second read timeout */ if(PacketSetReadTimeout(lpAdapter, -1) == FALSE) { msgStatus = "Warning: unable to set the read tiemout.."; SHOWSTAT(msgStatus); } /* Allocate PACKET structure for ARP Reply packet */ if((lpPacketReply = PacketAllocatePacket()) == NULL) { msgStatus = "Error: failed to allocate the LPPACKET structure.."; SHOWSTAT(msgStatus); PacketFreePacket(lpPacketRequest); return(EXIT_FAILURE); } /* Init ARP Reply packet */ PacketInitPacket(lpPacketReply, (char*)buffer, 256000); /* Allocate memory for remote MAC address */ timestamp = GetTickCount(); /* Main capture loop */ for(;;) { if(numPacks < wParams.numPacks) { /* Send packet */ if(PacketSendPacket(lpAdapter, lpPacketRequest, TRUE) == FALSE) { msgStatus ="Error : unable to send the packets.."; SHOWSTAT(msgStatus); PacketFreePacket(lpPacketRequest); PacketFreePacket(lpPacketReply); return(EXIT_FAILURE); } /* Free packet */ PacketFreePacket(lpPacketRequest); numPacks += 1; } /* Capture the packets */ if(PacketReceivePacket(lpAdapter, lpPacketReply, TRUE) == FALSE) { msgStatus = "Error: PacketReceivePacket failed.."; SHOWSTAT(msgStatus); PacketFreePacket(lpPacketReply); return(EXIT_FAILURE); } if(lpPacketReply->ulBytesReceived > 0) if(GetARPReply(lpPacketReply, iptarget, remotemac) == EXIT_SUCCESS) break; if((GetTickCount() - timestamp) > wParams.delay) { PacketFreePacket(lpPacketReply); return(EXIT_FAILURE); } } /* Free packet */ PacketFreePacket(lpPacketReply); return(EXIT_SUCCESS); } sunxufei: 哦,交換機是以MAC地址進行交換的,不是IP那一層的,要IP已經路由器了 現在交換機便宜了,因此以後你想用sniffer抓密碼概率不大了,不過還能多公司仍然是交換機和H UB一起用的,這樣小範圍內是有效地,至于[url=http://www.pcdog.com/network/special/s2.htm]ADSL[/url] CABLE FTTB,我的FTTB是用華爲設計的設備 ,呵呵,不僅僅工網IP,只有我和交換機兩個MAC(這次中國人幹的不錯),沒希望找到第三者,很安全,但 不都這樣安全,很多人的網絡還是很糟糕的. 很多加密協議可以用來提高安全性,但老的POP3,SMTP,HTTP,FTP這種協議應用廣泛,不可能在短 時間內完全取代,而且加密也是有待價的,所以對于要求較高的場合,才會加密. 不過sniffer不是給大家偷密碼用的,我當初用來學習網絡,看看包的樣子,後來就用來當作網管工具, 分析網絡的健康與否,其實這樣的話,你知道,很有可能sniffer就是接在我需要探測的網絡上,聽診器 嗎,到處都聽聽,呵呵,因此即使用了交換機,sniffer仍然是有用處的,但不是抓密碼!! Wincap很簡單,大3的學生不要怕,去他的網站看看,有例子的,VC6編譯,BCB也行的,把lib的格式轉 換一下,不過寫這種程序,你最好先熟悉協議,很多協議在linux裏有現成的源代碼,主要是一些struct 吧,移植時注意VC可不是gcc,有些c的高級語法,編譯選項要注意,否則差一個byte你就得不到正確的 結果. 如果你搞不到sniffer,Win2000 Server也有網絡包查看器的,不比sniffer強大,但簡單的東西入手 也快. 反嗅探和嗅探技術其實很old了,呵呵,不過CSDN經常old的. 注意不要幹壞事,有矛必有盾
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 
 熱帖排行
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有