forked from themeldingwars/Documentation
-
Notifications
You must be signed in to change notification settings - Fork 0
netscripts
Lukas Dürrenberger edited this page Jun 1, 2019
·
1 revision
A bunch of small helper scripts for reversing the network proto.
Add require ("Path to this file.lua")
to your wiresharks init.lua file and use firefall || firefall_gss
to filter to just Firefall traffic
FirefallMatrix_Proto = Proto("Firefall","Firefall Matrix Protocol")
FirefallGSS_Proto = Proto("Firefall_GSS","Firefall GSS Protocol")
local vars =
{
gssPort = 0,
packetIds = {},
packetTypeCount = {}
}
-- Decode the matrix proto
function FirefallMatrix_Proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol = "Firefall Matrix"
local subtree = tree:add(FirefallMatrix_Proto,buffer(),"Firefall Matrix")
subtree:add(buffer(0,buffer:len()),"RawData: " .. buffer(0,buffer:len()))
local id = buffer(0, 4)
local typeStr = buffer(4, 4)
local typeStr_string = typeStr:string()
subtree:add(id,"ID: " .. id:uint())
subtree:add(typeStr,"Type: " .. typeStr_string)
if typeStr_string == "POKE" then
--local protcolVer = buffer(10, 2) ? why??
local protcolVer = buffer(8, 4)
subtree:add(protcolVer,"Protocol Version: " .. protcolVer:uint())
elseif typeStr_string == "HEHE" then
local socketID = buffer(8, 4)
subtree:add(socketID,"Socket ID: " .. socketID:uint())
elseif typeStr_string == "KISS" then
local socketID = buffer(8, 4)
subtree:add(socketID,"Socket ID: " .. socketID:uint())
local streamingProtocol = buffer(12, 2)
subtree:add(streamingProtocol,"Streaming Protcol: " .. streamingProtocol:uint())
elseif typeStr_string == "HUGG" then
local sequenceStart = buffer(8, 2)
local gameServerPort = buffer(10, 2)
subtree:add(sequenceStart,"Sequence Start: " .. sequenceStart:uint())
subtree:add(gameServerPort,"Game Server Port: " .. gameServerPort:uint())
-- Set the port that the gss info will be on
vars.gssPort = gameServerPort:uint()
udp_table = DissectorTable.get("udp.port")
udp_table:add(vars.gssPort, FirefallGSS_Proto)
end
end
udp_table = DissectorTable.get("udp.port")
udp_table:add(25000, FirefallMatrix_Proto) -- 25000 is the default matrix port for firefall
-- GSS Packet handlers
local GSS_PacketHandlers = {}
local GssPckOff = 11
-- Decode the matrix proto
function FirefallGSS_Proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol = "Firefall GSS"
local subtree = tree:add(FirefallGSS_Proto,buffer(),"Firefall GSS")
subtree:add(buffer(0,buffer:len()),"RawData: " .. buffer(0,buffer:len()))
local socketID = buffer(0, 4)
local flags = buffer(4, 1) -- Guessing
local packetID = buffer(5, 1) -- Im not sure on this any more, there seems to be way way too many
local pckIdx = buffer(6, 2) -- Ok this matchs between a message and a reply
local unknown = buffer(8, 2)
--[[if (buffer(4, 1):uint() ~= 0) then
report_failure("Packet ID padding was not 0, was: "..buffer(4, 1))
end]]
subtree:add(socketID,"Socket ID: " .. socketID:uint())
subtree:add(packetID,"Packet ID: " .. packetID:uint())
--subtree:add(buffer(5, 1),"Packet ID(byte): " .. buffer(5, 1):uint())
subtree:add(flags,"Flags: " .. flags:uint())
subtree:add(pckIdx,"Pck Idx: " .. pckIdx:uint())
subtree:add(unknown,"Unknown: " .. unknown:uint())
pinfo.cols.protocol:append(" ("..tostring(packetID:uint())..")")
-- pass off to a packet handler if we have one
local id = buffer(5, 1):uint()
if GSS_PacketHandlers[id] then
GSS_PacketHandlers[id](buffer, pinfo, subtree)
end
if not vars.packetTypeCount[id] then
table.insert(vars.packetIds, id)
end
-- stats
local count = 0
if vars.packetTypeCount[id] and vars.packetTypeCount[id].count then
count = vars.packetTypeCount[id].count
end
count = count + 1
vars.packetTypeCount[id] =
{
count = count,
size = buffer:len()
}
end
GSS_PacketHandlers[11] = function(buffer, pinfo, tree)
local subtree = tree:add(FirefallGSS_Proto, buffer(), "Connection Accepct")
local unknown = buffer(GssPckOff, 4)
subtree:add(unknown,"Unknown: " .. unknown:uint())
end
-- Tools and stuff
local function ShowPacketStats()
local splash = TextWindow.new("Firefall Packet Stats :D");
splash:set("Firefall packet stats\n")
table.sort(vars.packetIds, function( a,b ) return a < b end)
splash:append("Number of packets of type:\n")
splash:append("Total packet types: ".. #vars.packetIds .."\n")
splash:append("-------------------------\n")
splash:append("| PacketID\t | Count\t |\n")
splash:append("-------------------------\n")
for i in ipairs(vars.packetIds) do
info(tostring(vars.packetTypeCount[vars.packetIds[i]]))
local count = vars.packetTypeCount[vars.packetIds[i]].count
local size = vars.packetTypeCount[vars.packetIds[i]].size
splash:append("| ".. vars.packetIds[i] .."\t | ".. count .."\t | ".. size.."\n")
end
splash:append("-------------------------\n")
end
register_menu("Firefall Packet Stats", ShowPacketStats, MENU_TOOLS_UNSORTED)
0Trackers
This node.js script will parse your console log and create a packet flow report, may be useful to cross ref with wire shark dumps.
Add this to your ini
[Debug]
LogLevel-NetLib = "debug";
LogLevel-Network = "debug";
MatrixMessages = true;
and then run this after your play session
// read the console log and output a textfile with a list of all the packets send/revced and their timestamps
// might be handy to compare with wiresahrk dumps
// Add the following to your Firefall.ini to enable logging of these
/*
[Debug]
LogLevel-NetLib = "debug";
LogLevel-Network = "debug";
MatrixMessages = true;
*/
var AsciiTable = require('ascii-table')
var logFilePath = process.env.LOCALAPPDATA + "/Red 5 Studios/Firefall/console.log";
var lineReader = require('readline').createInterface({
input: require('fs').createReadStream(logFilePath)
});
var outFilePath = process.argv[2];
var writer = require("fs").createWriteStream(outFilePath || "Packet Flow.txt");
var RX_Line = /(\d*:\d*) RAM:(\d*)MB FPS:(\d*) (\w*) *(\w*) *(.*)/;
var RX_Matrix = /MATRIX *- *Sent *(.*)/;
var RX_Recv = /received *(.*)/;
var packetIdCounts = {
sent: {},
recv: {}
};
writer.write("-------------------------------------\r\n");
writer.write("| Time\t| Direction | ID \t|\r\n");
writer.write("-------------------------------------\r\n");
lineReader.on('line', function (line) {
var m;
if ((m = RX_Line.exec(line)) !== null) {
var category = m[5];
if (category == "NETWORK") {
var match = RX_Recv.exec(m[6]);
if (match != null) {
var msgId = match[1];
writer.write("| {0}\t| Server -> Client | {1}\t| \u2666\r\n".format(m[1] , msgId));
var count = packetIdCounts.recv[msgId]
if (count != null) {
count++;
}
else {
count = 1;
}
packetIdCounts.recv[msgId] = count
}
}
else if (category == "GAME") {
var match = RX_Matrix.exec(m[6]);
if (match != null) {
var msgId = match[1];
writer.write("| {0}\t| Client -> Server | {1}\t|\r\n".format(m[1] , msgId));
var count = packetIdCounts.sent[msgId]
if (count != null) {
count++;
}
else {
count = 1;
}
packetIdCounts.sent[msgId] = count
}
}
}
});
lineReader.on("close", function() {
writer.write("-------------------------------------\r\n\r\n\r\n");
var table = new AsciiTable('Sent');
table.setHeading('ID', 'Count');
Object.keys(packetIdCounts.sent).forEach(function(key) {
var value = packetIdCounts.sent[key];
table.addRow(key, value);
});
writer.write(table.toString()+"\r\n");
table = new AsciiTable('Recived');
table.setHeading('ID', 'Count');
Object.keys(packetIdCounts.recv).forEach(function(key) {
var value = packetIdCounts.recv[key];
table.addRow(key, value);
});
writer.write(table.toString()+"\r\n");
writer.end();
console.log("Done :>");
});
// Util
//------------------------------
// http://stackoverflow.com/a/4673436
if (!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
}