计算机网络的课程要求我们做一个HTTP服务器或者STMP邮件发送代理.
这两个都是基于TCP协议的,在Java下使用Socket连接,应该是很简单的,所以我直接丢给组内其它同学做了.
而我下面做的,是一个Sniffer和Packet Sender的结合工具.使用WinPcap.
由于WinPcap已经做了大部分的事情,所以Sniffer的实现就没什么特殊之处,唯一一点,就是可以把数据包存储到文件里面.
而Packet Sender也是很简单的,就是把磁盘上指定的文件作为Packet,发送出去而已.测试的时候,我自己制作了一个IP攻击的Packet,以广播方式发送出去,类式网络执法官那样的功能.最后的测试是成功了的.
下面这个是我测试IP攻击的ARP数据包.攻击的IP是192.168.0.2.
为了防治别人查看的记录,所以,里面的发送段MAC地址,我是乱写的.
下面这个是ARP包的图解说明
下面就是程序代码.
/*
eth tool source code
author: tangl_99
update: 2005/5/27
*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include "Include/packet32.h"
#include "Include/ntddndis.h"
// #define _MY_DEBUG
#define MAX_NUM_ADAPTER 10
#define MAX_LEN_ADAPTER_NAME 1024
char SelectedAdapterName[MAX_LEN_ADAPTER_NAME];
LPADAPTER lpAdapter = 0; //define a pointer to an ADAPTER structure
// Prototypes
int SelectAdapter();
int OpenAndInitAdapter();
int SniffAndSaveToFile(const char *filename,int Hex);
int SniffAndPrintOut();
int SendPacketsFromFile(const char *filename,int count);
void PrintUsage();
void PrintPackets(LPPACKET lpPacket);
void PrintGetStatus();
int WritePacketsInHex(LPPACKET lpPacket,FILE *fp);
int WritePacketsInBin(LPPACKET lpPacket,FILE *fp);
int SendPacket(char* buf, ULONG bufsize);
void CloseAdapter();
int main(int argc,char *argv[])
{
#ifdef _MY_DEBUG
char *default_argv[] = {
"eth","-send",
"ipshock.pak", "90000",
};
argv = default_argv;
argc = 4;
#endif
if(argc < 2)
{
PrintUsage();
return 0;
}
// select networking adapter
SelectAdapter();
// initialize the adapter
OpenAndInitAdapter();
if(strcmp(argv[1],"-sniff") == 0) // sniffing packets
{
if(argc == 2) // print packet data on screen
SniffAndPrintOut();
else // save packet data in file
{
int hex; // hex or bin
if(argc == 3) hex = 1; // hex
else
hex = strcmp(argv[3],"bin") == 0 ? 0:1;
SniffAndSaveToFile(argv[2],hex);
}
}
else if(strcmp(argv[1],"-send") == 0) // sending packets
{
int count = 1; // count for sending
if(argc < 3)
{
PrintUsage();
return 0;
}
if(argc == 4)
count = atoi(argv[3]);
else
count = 1;
SendPacketsFromFile(argv[2],count);
}
else // otherwise
{
PrintUsage();
return 0;
}
//print the capture statistics
PrintGetStatus();
// close the adapter and exit
CloseAdapter();
return (0);
}
void PrintUsage()
{
printf("/nUsage:/n");
printf("1.sniffing: eth -sniff [filename] [hex | bin] /n");
printf("2.send: eth -send packefilename [count]/n");
printf("tangl_99/n");
}
// this function prints the content of a block of packets received from the driver
void PrintPackets(LPPACKET lpPacket)
{
ULONG i, j, ulLines, ulen, ulBytesReceived;
char *pChar, *pLine, *base;
char *buf;
u_int off=0;
u_int tlen,tlen1;
struct bpf_hdr *hdr;
ulBytesReceived = lpPacket->ulBytesReceived;
buf = lpPacket->Buffer;
off=0;
while(off<ulBytesReceived){
if(kbhit())return;
hdr=(struct bpf_hdr *)(buf+off);
tlen1=hdr->bh_datalen;
tlen=hdr->bh_caplen;
printf("Packet length, captured portion: %ld, %ld/n", tlen1, tlen);
off+=hdr->bh_hdrlen;
ulLines = (tlen + 15) / 16;
pChar =(char*)(buf+off);
base=pChar;
off=Packet_WORDALIGN(off+tlen);
for ( i=0; i<ulLines; i++ )
{
pLine =pChar;
printf( "%08lx : ", pChar-base );
ulen=tlen;
ulen = ( ulen > 16 ) ? 16 : ulen;
tlen -= ulen;
for ( j=0; j<ulen; j++ )
printf( "%02x ", *(BYTE *)pChar++ );
if ( ulen < 16 )
printf( "%*s", (16-ulen)*3, " " );
pChar = pLine;
for ( j=0; j<ulen; j++, pChar++ )
{
if((unsigned)(*pChar) <= 255)
printf( "%c", isprint( *pChar ) ? *pChar : '.' );
else
printf( ".");
}
printf( "/n" );
}
printf( "/n" );
}
}
int SelectAdapter()
{
char AdapterList[MAX_NUM_ADAPTER][MAX_LEN_ADAPTER_NAME];
DWORD dwVersion;
DWORD dwWindowsMajorVersion;
//unicode strings (winnt)
WCHAR AdapterName[8192]; // string that contains a list of the network adapters
WCHAR *temp,*temp1;
//ascii strings (win95)
char AdapterNamea[8192]; // string that contains a list of the network adapters
char *tempa,*temp1a;
int i;
int AdapterNum=0;
int Open;
ULONG AdapterLength;
//
// Obtain the name of the adapters installed on this machine
//
printf("Adapters installed:/n");
i=0;
memset(AdapterList,0,MAX_NUM_ADAPTER*MAX_LEN_ADAPTER_NAME);
// the data returned by PacketGetAdapterNames is different in Win95 and in WinNT.
// We have to check the os on which we are running
dwVersion=GetVersion();
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4))
{
// Windows NT
AdapterLength = sizeof(AdapterName);
if(PacketGetAdapterNames((PTSTR)AdapterName,&AdapterLength)==FALSE){
printf("Unable to retrieve the list of the adapters!/n");
return -1;
}
temp=AdapterName;
temp1=AdapterName;
while ((*temp!='/0')||(*(temp-1)!='/0'))
{
if (*temp=='/0')
{
memcpy(AdapterList[i],temp1,(temp-temp1)*2);
temp1=temp+1;
i++;
}
temp++;
}
AdapterNum=i;
for (i=0;i<AdapterNum;i++)
wprintf(L"/n%d- %s/n",i+1,AdapterList[i]);
printf("/n");
}
else //windows 95
{
AdapterLength = sizeof(AdapterNamea);
if(PacketGetAdapterNames(AdapterNamea,&AdapterLength)==FALSE){
printf("Unable to retrieve the list of the adapters!/n");
return -1;
}
tempa=AdapterNamea;
temp1a=AdapterNamea;
while ((*tempa!='/0')||(*(tempa-1)!='/0'))
{
if (*tempa=='/0')
{
memcpy(AdapterList[i],temp1a,tempa-temp1a);
temp1a=tempa+1;
i++;
}
tempa++;
}
AdapterNum=i;
for (i=0;i<AdapterNum;i++)
printf("/n%d- %s/n",i+1,AdapterList[i]);
printf("/n");
}
do
{
printf("Select the number of the adapter to open : ");
scanf("%d",&Open);
if (Open>AdapterNum) printf("/nThe number must be smaller than %d",AdapterNum);
}while (Open>AdapterNum);
memcpy(SelectedAdapterName,AdapterList[Open-1],MAX_LEN_ADAPTER_NAME);
lpAdapter = PacketOpenAdapter(AdapterList[Open-1]);
return 0;
}
int OpenAndInitAdapter()
{
DWORD dwErrorCode;
lpAdapter = PacketOpenAdapter(SelectedAdapterName);
if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE))
{
dwErrorCode=GetLastError();
printf("Unable to open the adapter, Error Code : %lx/n",dwErrorCode);
return -1;
}
// set the network adapter in promiscuous mode
if(PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_PROMISCUOUS)==FALSE){
printf("Warning: unable to set promiscuous mode!/n");
}
// set a 512K buffer in the driver
if(PacketSetBuff(lpAdapter,512000)==FALSE){
printf("Unable to set the kernel buffer!/n");
return -1;
}
// set a 1 second read timeout
if(PacketSetReadTimeout(lpAdapter,1000)==FALSE){
printf("Warning: unable to set the read tiemout!/n");
}
return 0;
}
int SniffAndSaveToFile(const char *filename,int Hex)
{
//define a pointer to a PACKET structure
LPPACKET lpPacket;
char buffer[256000]; // buffer to hold the data coming from the driver
FILE *fp;
fp = fopen(filename,"wb");
if(fp == NULL)
{
printf("Cannot open the file!/n");
return -1;
}
//allocate and initialize a packet structure that will be used to
//receive the packets.
if((lpPacket = PacketAllocatePacket())==NULL){
printf("/nError: failed to allocate the LPPACKET structure.");
fclose(fp);
return -1;
}
PacketInitPacket(lpPacket,(char*)buffer,256000);
//main capture loop
while(!kbhit())
{
// capture the packets
if(PacketReceivePacket(lpAdapter,lpPacket,TRUE)==FALSE){
printf("Error: PacketReceivePacket failed");
fclose(fp);
return -1;
}
if(Hex)
WritePacketsInHex(lpPacket,fp);
else
WritePacketsInBin(lpPacket,fp);
PrintGetStatus();
}
PacketFreePacket(lpPacket);
fclose(fp);
return 0;
}
int SniffAndPrintOut()
{
//define a pointer to a PACKET structure
LPPACKET lpPacket;
char buffer[256000]; // buffer to hold the data coming from the driver
//allocate and initialize a packet structure that will be used to
//receive the packets.
if((lpPacket = PacketAllocatePacket())==NULL){
printf("/nError: failed to allocate the LPPACKET structure.");
return -1;
}
PacketInitPacket(lpPacket,(char*)buffer,256000);
//main capture loop
while(!kbhit())
{
// capture the packets
if(PacketReceivePacket(lpAdapter,lpPacket,TRUE)==FALSE){
printf("Error: PacketReceivePacket failed");
return -1;
}
PrintPackets(lpPacket);
}
PacketFreePacket(lpPacket);
return 0;
}
int WritePacketsInHex(LPPACKET lpPacket,FILE *fp)
{
ULONG i, j, ulLines, ulen, ulBytesReceived;
char *pChar, *pLine, *base;
char *buf;
u_int off=0;
u_int tlen,tlen1;
struct bpf_hdr *hdr;
ulBytesReceived = lpPacket->ulBytesReceived;
buf = lpPacket->Buffer;
off=0;
while(off<ulBytesReceived){
hdr=(struct bpf_hdr *)(buf+off);
tlen1=hdr->bh_datalen;
tlen=hdr->bh_caplen;
fprintf(fp,"Packet length, captured portion: %ld, %ld /r/n", tlen1, tlen);
off+=hdr->bh_hdrlen;
ulLines = (tlen + 15) / 16;
pChar =(char*)(buf+off);
base=pChar;
off=Packet_WORDALIGN(off+tlen);
for ( i=0; i<ulLines; i++ )
{
pLine =pChar;
fprintf(fp, "%08lx : ", pChar-base );
ulen=tlen;
ulen = ( ulen > 16 ) ? 16 : ulen;
tlen -= ulen;
for ( j=0; j<ulen; j++ )
fprintf(fp,"%02x ", *(BYTE *)pChar++ );
if ( ulen < 16 )
fprintf(fp, "%*s", (16-ulen)*3, " " );
pChar = pLine;
for ( j=0; j<ulen; j++, pChar++ )
{
if((unsigned)(*pChar) <= 255)
fprintf(fp,"%c", isprint( *pChar ) ? *pChar : '.' );
else
fprintf(fp, ".");
}
fprintf(fp, "/r/n" );
}
fprintf(fp, "/r/n" );
}
return 0;
}
int WritePacketsInBin(LPPACKET lpPacket,FILE *fp)
{
ULONG ulBytesReceived;
char *buf;
ulBytesReceived = lpPacket->ulBytesReceived;
buf = lpPacket->Buffer;
fwrite(buf, ulBytesReceived, 1, fp);
return 0;
}
void PrintGetStatus()
{
struct bpf_stat stat;
if(PacketGetStats(lpAdapter,&stat)==FALSE){
printf("Warning: unable to get stats from the kernel!/n");
}
else
printf("/n/n%d packets received./n%d Packets lost",stat.bs_recv,stat.bs_drop);
}
int SendPacketsFromFile(const char *filename,int count)
{
FILE *fp;
char *buf;
int filelength;
fp = fopen(filename,"rb");
fseek(fp,0L,SEEK_END);
filelength = ftell(fp);
fseek(fp,0L,SEEK_SET);
buf = (char*)malloc(filelength);
fread(buf,filelength,1,fp);
fclose(fp);
while(count--)
{
if(SendPacket(buf,filelength) == -1)
return -1;
}
free(buf);
return 0;
}
int SendPacket(char* buf, ULONG bufsize)
{
LPPACKET lpPacket = 0;
lpPacket = PacketAllocatePacket();
PacketInitPacket(lpPacket,buf,bufsize);
if(PacketSendPacket(lpAdapter,lpPacket,TRUE)==FALSE)
{
printf("PacketSendPacket in getmine Error: %d/n",GetLastError());
return -1;
}
PacketFreePacket(lpPacket);
return 0;
}
void CloseAdapter()
{
PacketCloseAdapter(lpAdapter);
}