Skip to content

Instantly share code, notes, and snippets.

@yurydelendik
Created February 3, 2014 16:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurydelendik/8787043 to your computer and use it in GitHub Desktop.
Save yurydelendik/8787043 to your computer and use it in GitHub Desktop.
Parse network monitor cap file
var sourceAddress = [192,168,1,2];
var targetAddress = [192,168,1,1];
function readCapFile() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'test.cap');
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
var file = new Uint8Array(xhr.response);
if (file[0] !== 0x47 || file[1] !== 0x4D) throw new Error('invalid cap file');
findCapFrames(file);
};
xhr.send();
}
function findCapFrames(file) {
// http://msdn.microsoft.com/en-us/library/windows/desktop/ee817717%28v=vs.85%29.aspx
var frameTableOffset = file[0x18] | (file[0x19] << 8) | (file[0x1A] << 16) | (file[0x1B] << 24);
var frameTableLength = file[0x1C] | (file[0x1D] << 8) | (file[0x1E] << 16) | (file[0x1F] << 24);
var pos = frameTableOffset, count = frameTableLength >> 2;
var framesOffsets = [];
for (var i = 0; i < count; i++, pos += 4) {
framesOffsets.push(file[pos] | (file[pos + 1] << 8) | (file[pos + 2] << 16) | (file[pos + 3] << 24));
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/ee831821%28v=vs.85%29.aspx
var frames = [];
for (var i = 0; i < count; i++) {
pos = framesOffsets[i];
var timestamp = (file[pos] | (file[pos + 1] << 8) | (file[pos + 2] << 16)) +
((file[pos + 3] | (file[pos + 4] << 8) | (file[pos + 5] << 16)) * 16777216) +
(file[pos + 6] | (file[pos + 7] << 8)) * 281474976710656;
var length = file[pos + 8] | (file[pos + 9] << 8) | (file[pos + 10] << 16) | (file[pos + 11] << 24);
var available = file[pos + 12] | (file[pos + 13] << 8) | (file[pos + 14] << 16) | (file[pos + 15] << 24);
pos += 16;
frames.push({timestamp: timestamp * 1e-6, available: available, macFrame: file.subarray(pos, pos + length)});
}
// parse
var lastSeq = {'in': 0, 'out': 0};
for (var i = 0; i < count; i++) {
// guessing ip, http://en.wikipedia.org/wiki/IPv4
var frame = frames[i];
var macFrame = frame.macFrame;
var tcpPos, direction = null;
for (var j = 0; j < macFrame.length; j++) {
if (macFrame[j] === 0x45 && // Ipv4 with IHL=5
macFrame[j + 6] === 0x40 && macFrame[j + 7] === 0x00 && // don't frag
macFrame[j + 9] === 0x06) { // TCP
if (macFrame[j + 12] === sourceAddress[0] && macFrame[j + 13] === sourceAddress[1] &&
macFrame[j + 14] === sourceAddress[2] && macFrame[j + 15] === sourceAddress[3] &&
macFrame[j + 16] === targetAddress[0] && macFrame[j + 17] === targetAddress[1] &&
macFrame[j + 18] === targetAddress[2] && macFrame[j + 19] === targetAddress[3]) {
direction = 'out'; tcpPos = j + 20; break;
}
if (macFrame[j + 16] === sourceAddress[0] && macFrame[j + 17] === sourceAddress[1] &&
macFrame[j + 18] === sourceAddress[2] && macFrame[j + 19] === sourceAddress[3] &&
macFrame[j + 12] === targetAddress[0] && macFrame[j + 13] === targetAddress[1] &&
macFrame[j + 14] === targetAddress[2] && macFrame[j + 15] === targetAddress[3]) {
direction = 'in'; tcpPos = j + 20; break;
}
}
}
if (!direction) continue;
frame.direction = direction;
frame.srcPort = (macFrame[tcpPos] << 8) | macFrame[tcpPos + 1];
frame.destPort = (macFrame[tcpPos + 2] << 8) | macFrame[tcpPos + 3];
var seq = ((macFrame[tcpPos + 4] << 24) | (macFrame[tcpPos + 5] << 16) | (macFrame[tcpPos + 6] << 8) | macFrame[tcpPos + 7]) >>> 0;
var ack = ((macFrame[tcpPos + 8] << 24) | (macFrame[tcpPos + 9] << 16) | (macFrame[tcpPos + 10] << 8) | macFrame[tcpPos + 11]) >>> 0;
if (ack === 0) {
lastSeq = {'in': 0, 'out': 0};
}
if (lastSeq[direction] > seq) {
// console.log('retransmit');
continue;
}
lastSeq[direction] = seq;
var dataPos = tcpPos + 4 * (macFrame[tcpPos + 12] >> 4);
if (dataPos < macFrame.length) {
frame.data = macFrame.subarray(dataPos);
}
}
frames = frames.filter(function (f) { return f.data; });
processFrames(frames);
}
function processFrames0(frames) {
frames.forEach(function (f) {
var el = document.createElement('div');
el.textContent = f.direction + '(' + f.srcPort + '->' + f.destPort + '): ' +
f.timestamp.toFixed(3) + ' ' + f.data.length;
/*
Array.prototype.map.call(f.data,
function (i) { return (i + 256).toString(16).substr(1); }).join(' ') + ' :: ' +
String.fromCharCode.apply(String, f.data);*/
document.body.appendChild(el);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment