mscdex / cap

A cross-platform binding for performing packet capturing with node.js
MIT License
361 stars 45 forks source link

Trying to sniff ARP packets using cap #39

Closed dheerajreddy1 closed 6 years ago

dheerajreddy1 commented 8 years ago

Its not an issue . I know u didnt made a code to sniff ARP packets. But actually looking at your decoder file I just made some piece of code to sniff ARP packets but i didn't got output . I will attach code below. please help me if you found any errors.

// Internet Layer Protocols ====================================================
exports.ARP = function(b, offset) {
  offset || (offset = 0);   
  var origoffset = offset, i;
  var ret = {
    info: {
      hardwareAddr: undefined,
      protocol: undefined,
      hdrlen: undefined,
      protlen: undefined,
      opcode: undefined,
      senderMac: undefined,
      senderIp: undefined,
      targetMac: undefined,
      targetIp: undefined,
    },
    hdrlen: undefined,
    offset: undefined
  };
  ret.info.hardwareAddr = b.readUInt16BE(offset, true);
  offset += 2;
  ret.info.protocol = b.readUInt16BE(offset, true);
  offset += 2;
  ret.info.hdrlen = b.readUInt16BE(offset, true);
  offset += 1;
  ret.info.protlen = b.readUInt16BE(offset, true);
  offset += 1;
  ret.info.opcode = b.readUInt16BE(offset, true);
  offset += 2;
  ret.info.senderMac = b.toString('hex', offset, offset + 6);
  offset += 6;
  ret.info.senderIp = b.toString('hex', offset, offset + 4);
  offset += 4;
  ret.info.targetMac = b.toString('hex', offset, offset + 6);
  offset += 6;
  ret.info.targetIp = b.toString('hex', offset, offset + 4);
  offset += 4;
  ret.offset = offset;
  return ret;
};  
mscdex commented 8 years ago

Can you also show the code you're using that uses this function?

dheerajreddy1 commented 8 years ago
var Cap = require('cap').Cap,
    decoders = require('cap').decoders,
    PROTOCOL = decoders.PROTOCOL;
    c = new Cap(),
    device = '\\Device\\NPF_{B72765D8-CD73-45E0-8723-BD121163DC18}',
    filter = 'arp',
    bufSize = 10 * 1024 * 1024,
    buffer = new Buffer(65535);
    console.log("buffer");
    c.on('packet', function(nbytes, trunc) 
    {
        console.log('packet: length ' + nbytes + ' bytes, truncated? '
        + (trunc ? 'yes\r\n' : 'no\r\n'));

        var linkType = c.open(device, filter, bufSize, buffer);
        if (linkType === 'ETHERNET') 
        console.log('Decoding ARP ...');    
        {
            var ret = decoders.Ethernet(buffer);

            if (ret.info.type === PROTOCOL.ETHERNET.ARP)
            {
                console.log('Decoding ARP ...');

                ret = decoders.ARP(buffer, ret.offset);
                console.log("sender mac address:", ret.info.hardwareAddr);
                console.log("sender Ip Address:", ret.info.senderIp);

            }
        }
    }); 
mscdex commented 8 years ago

Your c.open() is in the wrong place. You won't get any packet events until you c.open() first, so place that outside of your packet event handler.

dheerajreddy1 commented 8 years ago

yeah... i got it thank. Is there any filter in cap module to filter certain "mac address" . can you add my code to your decoders source code so that it will be helpful to everyone . directly they will get ARP packets instead of going for some other modules.

mscdex commented 8 years ago

As far as the filter syntax goes, it's the same syntax that tcpdump uses. So to look for a particular mac address you should be able to use something like 'ether host aa:bb:cc:dd:ee:ff'.

dheerajreddy1 commented 8 years ago

actually now able to see ARP packets . I saw in wireshark, it consists of both ethernet-2 and 802.3 packets . But using cap module i am sniffing only ethernet-2 packets. Is there any way to sniff 802.3 packets also..??

mscdex commented 8 years ago

You'd have to decode the packet differently. 802.3 is fairly similar to ethernet-2 though, so you could re-use some code. See this SO answer for details.

mscdex commented 8 years ago

Are you seeing packet events for the 802.3-encapsulated packets? As far as I know the 'arp' filter should emit packets for both types, with the difference being in the decoding of the packets as I previously noted (e.g. if the type/len field is >= 1536, it's Ethernet II). The current ethernet decoder only performs simple type/length field checking and does not handle SNAP or other fields for non-Ethernet II encapsulation.

dheerajreddy1 commented 8 years ago

NO ..i am not getting 802.3 packets in any format.

dheerajreddy1 commented 8 years ago

so now what shall I add to typelen in ethernet code to decode the packets...???

dheerajreddy1 commented 8 years ago

what "linkType" does in function code. actually i have removed ethernet part in decoders and i have added IEEE8023 . but when i try to print linkType it still printing as ETHERNET. So I am not understanding where i have to change ETHERNET TO IEEE8023.

mscdex commented 8 years ago

Do you have a reliable way of duplicating these packets that I can use?

dheerajreddy1 commented 8 years ago

since I am generating packets with local board so i can't share the packets. If you want we can make webex meeting

mwittig commented 8 years ago

@mscdex I am wondering whether or not you progressed on this one. As I need an ARP decoder for my project I have rolled my own decoding function based on the snippet @dheerajreddy1 posted. My implementation is not perfect as it might not cover all cases, but it is comparable to what node-pcap has. If you like my proposal I am happy to create a pull request.

exports.ARP = function(b, offset) {
  offset || (offset = 0);
  var ret = {
    info: {
      hardwareaddr: undefined,
      protocol: undefined,
      hdrlen: undefined,
      protlen: undefined,
      opcode: undefined,
      sendermac: '',
      senderip: '',
      targetmac: '',
      targetip: ''
    },
    offset: undefined
  };
  ret.info.hardwareaddr = b.readUInt16BE(offset, true);
  offset += 2;
  ret.info.protocol = b.readUInt16BE(offset, true);
  offset += 2;
  ret.info.hdrlen = b.readInt8(offset, true);
  offset += 1;
  ret.info.protlen = b.readInt8(offset, true);
  offset += 1;
  ret.info.opcode = b.readUInt16BE(offset, true);
  offset += 2;
  if (ret.info.hdrlen == 6 && ret.info.protlen == 4) {
    for (i = 0; i < 6; ++i) {
      ret.info.sendermac += ('00' + b[offset++].toString(16)).substr(-2);
      if (i < 5)
        ret.info.sendermac += ':';
    }

    for (i = 0; i < 4; ++i) {
      ret.info.senderip += b[offset++].toString(10);
      if (i < 3)
        ret.info.senderip += '.';
    }

    for (i = 0; i < 6; ++i) {
      ret.info.targetmac += ('00' + b[offset++].toString(16)).substr(-2);
      if (i < 5)
        ret.info.targetmac += ':';
    }

    for (i = 0; i < 4; ++i) {
      ret.info.targetip += b[offset++].toString(10);
      if (i < 3)
        ret.info.targetip += '.';
    }
  }
  ret.offset = offset;
  return ret;
};
mscdex commented 8 years ago

@mwittig If you have a working decoder, feel free to open a PR.