打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
用Java来实现的Sniffer
用Java来实现的Sniffer
来自:leeight@ LEEIGHT 日期:2006-8-14 19:21:31 全文阅读:130 分类:技术专区
【摘要】
没有办法, 不得不做啊, 还得靠这个东西混学分呢。
老师给的例子是用VC写的, 说心里话, 俺对VC不感兴趣, 所以就想用Java来实现。
但是java是无法直接访问raw socket的, 所以如果要实现sniffer的功能的话, 只能通过jni调用本地的接口, 实际上还是要用VC来写。 不过从网上搜了搜, 发现已经有前人做过了,所以俺就省事儿了, 直接拿过来用吧。
看到有两个地方介绍的, 一个是

【全文】
没有办法, 不得不做啊, 还得靠这个东西混学分呢。
老师给的例子是用VC写的, 说心里话, 俺对VC不感兴趣, 所以就想用Java来实现。
但是java是无法直接访问raw socket的, 所以如果要实现sniffer的功能的话, 只能通过jni调用本地的接口, 实际上还是要用VC来写。 不过从网上搜了搜, 发现已经有前人做过了,所以俺就省事儿了, 直接拿过来用吧。
看到有两个地方介绍的, 一个是:
http://www.savarese.org/software/rocksaw/, 不过这个实现的功能有限。 而且不可以抓取数据包, 不过可以发送ICMP消息了, 这个功能在Java中是没法直接实现的。但是如果修改一下它给的c源文件, 应该就可以了。主要是它没有将网卡设置为“混杂模式”(这是我们老师这么称呼的)。
另外一个就是JPCAP了, 这个功能就强大的多了, 不过使用之前需要先安装WinPCap, 好像装其他的sniffer的时候, 也是需要这个软件的, 估计是需要它的DLL文件吧。JPCAP的下载地址是:http://www.sf.net/projects/jpcap。参照了CSDN上面yanqlv的文章,http://blog.csdn.net/yanqlv/archive/2005/12/08/547402.aspx。 俺的这个作业也就基本上做完了, 就剩下报告了 ^_^.
下面给出俺的源代码, 有兴趣的可以试着运行一下, 现在只解析出来了TCP, TDP和ARP的数据包, 其他的没有做。 实际上所有的数据都已经抓到了, 因为所有的数据是从以太网帧里面解析的。

import net.sourceforge.jpcap.capture.CaptureDeviceLookupException;
import net.sourceforge.jpcap.capture.CaptureDeviceOpenException;
import net.sourceforge.jpcap.capture.CapturePacketException;
import net.sourceforge.jpcap.capture.PacketCapture;
import net.sourceforge.jpcap.capture.RawPacketListener;
import net.sourceforge.jpcap.net.RawPacket;

public class Sniffer implements RawPacketListener {
    private PacketCapture pcap;

    public static int MAC_ADDRESS_WIDTH = 6;

    public static int PROTOCOL_TYPE_WIDTH = 2;

    public static int DEST_MAC_POS = 0;

    public static int SRC_MAC_POS = DEST_MAC_POS + MAC_ADDRESS_WIDTH;

    public static int ETH_FRAME_HEADER_LEN = MAC_ADDRESS_WIDTH * 2 + PROTOCOL_TYPE_WIDTH;

    public static int ARP = 0x0806;

    public static int IP = 0x0800;

    public static int TCP = 0x06;

    public static int UDP = 0x11;

    public static int LOOPBACK = 0x9000;

    public String INFO;

    public byte[] RAW_DATA;

    public int TCP_PACKET_COUNT;
    
    public int UDP_PACKET_COUNT;
    
    public int ARP_PACKET_COUNT;
    
    public Sniffer() {
        pcap = new PacketCapture();

        try {
            String[] devices = PacketCapture.lookupDevices();
            pcap.open(devices[4].split("\\\n")[0], true);
            pcap.addRawPacketListener(this);
            pcap.capture(-1);
        } catch (CaptureDeviceOpenException e) {
            e.printStackTrace();
        } catch (CapturePacketException e) {
            e.printStackTrace();
        } catch (CaptureDeviceLookupException e) {
            e.printStackTrace();
        }

    }

    // 解析以太网帧
    public void rawPacketArrived(RawPacket rawPacket) {
        RAW_DATA = rawPacket.getData();
        int type = getInt(RAW_DATA, MAC_ADDRESS_WIDTH * 2, PROTOCOL_TYPE_WIDTH);
        switch (type) {
        case 0x0806: // ARP
            parseARP();
            break;
        case 0x0800: // IP
            parseIP();
            break;
        }

        System.out.println(INFO);
    }

    public void parseIP() {
        StringBuffer sb = new StringBuffer();
        byte b1 = RAW_DATA[ETH_FRAME_HEADER_LEN];
        byte dsf = RAW_DATA[ETH_FRAME_HEADER_LEN + 1];
        String totalLength = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 2, 2);
        String identification = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 4, 2);
        String flags = byte2HexString(RAW_DATA[ETH_FRAME_HEADER_LEN + 6]);
        String frameOffset = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 6, 2);
        String ttl = byte2HexString(RAW_DATA[ETH_FRAME_HEADER_LEN + 8]);
        byte ptype = RAW_DATA[ETH_FRAME_HEADER_LEN + 9];
        String cksum = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 10, 2);
        String SOURCE = getIPAddress(RAW_DATA, ETH_FRAME_HEADER_LEN + 12);
        String DESTINATION = getIPAddress(RAW_DATA, ETH_FRAME_HEADER_LEN + 16);
        
        
        
        sb.append("IP Version:" + (b1 >> 4));
        sb.append(",Header Length:" + (b1 & 0x0F) * 4 + " bytes");
        sb.append(",DSF: " + byte2HexString(dsf));
        sb.append(",Total Length: 0x" + totalLength);
        sb.append(",Identification 0x: " + identification);
        sb.append(",Flags: 0x" + flags);
        sb.append(",Frame Offset: 0x" + frameOffset);
        sb.append(",TTL: 0x" + ttl);
        sb.append(",Protocol Type: 0x" + byte2HexString(ptype));
        sb.append(",Header Check Sum: 0x" + cksum);
        sb.append(",Source:" + SOURCE);
        sb.append(",Destination:" + DESTINATION);
        sb.append("\n\t");
        
        if(ptype == 0x06){    // TCP PACKET
            TCP_PACKET_COUNT ++;
            
            String sport = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 20, 2);
            String dport = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 22, 2);
            String seqNum  = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 24, 4);
            String ackNum  = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 28, 4);
            String headerLen = byte2HexString(RAW_DATA[ETH_FRAME_HEADER_LEN + 32]);
            String tcpFlags = byte2HexString(RAW_DATA[ETH_FRAME_HEADER_LEN + 33]);
            String windowSize = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 34, 2);
            String tcpCkSum = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 36, 2);
            String data = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 40, RAW_DATA.length - ETH_FRAME_HEADER_LEN - 40);
            
            sb.append("[TCP Segmentaion]Source Port: 0x" + sport);
            sb.append(",Destination Port: 0x" + dport);
            sb.append(",Sequence number: 0x" + seqNum);
            sb.append(",Acknowledgment number: 0x" + ackNum);
            sb.append(",Header length: 0x" + (headerLen));
            sb.append(",Flags: 0x" + (tcpFlags));
            sb.append(",Window size: 0x" + windowSize);
            sb.append(",Check sum: 0x" + tcpCkSum);
            sb.append(",Data: 0x" + data);
            
        }else if(ptype == 0x11){    // UDP PACKET
            UDP_PACKET_COUNT ++;
            
            String sport = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 20, 2);
            String dport = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 22, 2);
            String len   = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 24, 2);
            String udpCkSum = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 26, 2);
            String data = byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 28, RAW_DATA.length - ETH_FRAME_HEADER_LEN - 28);
            
            sb.append("[UDP Segmentaion]Source Port: 0x" + sport);
            sb.append(",Destination Port: 0x" + dport);
            sb.append(",Length: 0x" + len);
            sb.append(",Check sum: 0x" + udpCkSum);
            sb.append(",Data: 0x" + data);
        }
        
        INFO = sb.toString();
    }

    public void parseARP() {
        ARP_PACKET_COUNT ++;
        
//        if (getInt(RAW_DATA, 0, 3) == 0x00FFFFFF && getInt(RAW_DATA, 3, 3) == 0x00FFFFFF)
//            DESTINATION = "Broadcast";

        StringBuffer sb = new StringBuffer();
        sb.append("Hardware Type:");
        sb.append(byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN, 2));
        sb.append(",Protocol Type:");
        sb.append(byte2HexString(RAW_DATA, ETH_FRAME_HEADER_LEN + 2, 2));
        sb.append(",Hardware Size:");
        sb.append(getInt(RAW_DATA, ETH_FRAME_HEADER_LEN + 4, 1));
        sb.append(",Protocol Size:");
        sb.append(getInt(RAW_DATA, ETH_FRAME_HEADER_LEN + 5, 1));
        sb.append(",Operation Code:");
        int opcode = getInt(RAW_DATA, ETH_FRAME_HEADER_LEN + 6, 2);
        sb.append(opcode == 0x0001 ? "[Request]0x0001" : "[Response]0x0002");
        sb.append(",Sender MAC:");
        sb.append(getMACAddress(RAW_DATA, ETH_FRAME_HEADER_LEN + 8));
        sb.append(",Sender IP:");
        sb.append(getIPAddress(RAW_DATA, ETH_FRAME_HEADER_LEN + 14));
        sb.append(",Target MAC:");
        sb.append(getMACAddress(RAW_DATA, ETH_FRAME_HEADER_LEN + 18));
        sb.append(",Target IP:");
        sb.append(getIPAddress(RAW_DATA, ETH_FRAME_HEADER_LEN + 24));

        INFO = sb.toString();
    }

    public String getFactoryName(int id) {
        String name = null;
        switch (id) {
        case 0x00096B:
            name = "Ibm";
            break;
        case 0x000B5F:
            name = "Cisco";
            break;
        case 0x0015E9:
            name = "D-Link";
            break;
        default:
            byte b1 = (byte) (id >> 16);
            byte b2 = (byte) (id >> 8);
            byte b3 = (byte) id;
            name = byte2HexString(b1) + ":" + byte2HexString(b2) + ":"
                    + byte2HexString(b3);
            break;
        }
        return name;
    }

    public int getInt(byte[] bs, int pos, int len) {
        int value = 0;
        for (int i = 0; i < len; i++)
            value |= (bs[pos + len - i - 1] << 8 * i);
        return value;
    }

    public String byte2HexString(byte b) {
        return "" + byte2Char((byte) (b >> 4)) + byte2Char(b);
    }

    public String byte2HexString(byte[] b, int pos, int len) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < len; i++)
            sb.append(byte2HexString(b[pos + i]));
        return sb.toString();
    }

    public char byte2Char(byte b) {
        char c = (char) (b & 0xf); // mask low nibble
        return (c > 9 ? (char) (c - 10 + ‘A‘) : (char) (c + ‘0‘));
    }

    public String getMACAddress(byte[] b, int pos) {
        return getFactoryName(getInt(b, pos, 3)) + "_"
                + byte2HexString(b[pos + 3]) + ":" + byte2HexString(b[pos + 4])
                + ":" + byte2HexString(b[pos + 5]);
    }

    public String getIPAddress(byte[] b, int pos) {
        int WIDTH = 4;
        int address = getInt(b, pos, WIDTH);
        StringBuffer sa = new StringBuffer();
        for (int i = 0; i < WIDTH; i++) {
            sa.append(0xff & address >> 24);
            address <<= 8;
            if (i != WIDTH - 1)
                sa.append(‘.‘);
        }
        return sa.toString();
    }

    public static void main(String args[]) {
        new Sniffer();
    }
}
注意:pcap.open(devices[4].split("\\\n")[0], true);这一行, 是用来选择网卡的, 如果你不清楚是那一个, 请将所有的devices输出来, 然后选择一个。
运行的时候, 需要net.sourceforge.jpcap-0.01.16.jar和jpcap.dll,
在和源文件的同一级目录下面建立一个lib文件夹, 然后将上面两个文件拷贝进去。
javac  -cp lib\net.sourceforge.jpcap-0.01.16.jar Sniffer.java
java -Djava.library.path=lib -cp=lib\net.sourceforge.jpcap-0.01.16.jar Sniffer
正常情况下, 应该有类似如下的输出的:
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.169.63
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.255.140
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.133.20.83
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.232.100
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:FF:FF:E9_07:84:21,Sender IP:255.255.255.250,Target MAC:Cisco_B5:27:00,Target IP:202.117.21.1
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.229.49
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.244.42
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.217.59
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:222.51.121.73
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.255.162
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.255.162
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:59.34.116.34
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:59.34.116.34
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:58.50.48.47
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.255.213
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.255.226
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:59.41.41.17
IP Version:4,Header Length:20 bytes,DSF: 00,Total Length: 0x004C,Identification 0x: A4EA,Flags: 0x00,Frame Offset: 0x0000,TTL: 0x80,Protocol Type: 0x11,Header Check Sum: 0xB5F6,Source:202.117.21.75,Destination:255.255.255.255
    [UDP Segmentaion]Source Port: 0x09B1,Destination Port: 0x1394,Length: 0x0038,Check sum: 0xAFF4,Data: 0x30004B5600000000000103000100000001003000F604AD8500000000000000000000000000000000000001001D5DE044
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:Ibm_12:E2:15,Sender IP:255.255.255.197,Target MAC:00:00:00_00:00:00,Target IP:255.255.255.189
Hardware Type:0001,Protocol Type:0800,Hardware Size:6,Protocol Size:4,Operation Code:[Request]0x0001,Sender MAC:FF:FF:E9_07:84:21,Sender IP:255.255.255.250,Target MAC:Cisco_B5:27:00,Target IP:202.117.21.1
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C# 进制之间的转换
Android MD5加密
Python3中bytes和HexStr之间的转换
Redis批量导入数据的方法
General Network Engineer Interview Questions ...
EtherPeek NX在网络维护中的应用
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服