I'm able to log all windows traffic by Wireshark and Chrome Inspector thru Network->WS.
Unfortunately I'm writing a web bot to interact with some websites automatically. I really need to go thru the data in websocket, not by HTML and some other methods that I have used before.
Chrome (and most probably Firefox) cannot save data in realtime. Chrome can save .har file with all the traffic, but even if I automate that, the file grows with every new packet, so it will result in performance issue very soon.
Wireshark can do that and even decrypt TLS (https) in realtime. It also supports saving file on every x packets or x seconds. But for some (maybe security) reason it saves encrypted pcap file. I don't know how to decrypt it.
On other hand I'm able to capture traffic with PcapDotNet. I'm also able to log IPs, ports and sequence and rebuild whole TLS frame from 2-3 separate TCP packets.
Till the moment in C# I tried logging the packets and try some decryption without any success:
int index = -1;
foreach (IpV4Datagram IPpack in IPPackets)
{
index += 1;
string src = IPpack.Source.ToString();
string dest = IPpack.Destination.ToString();
string destPort = IPpack.Tcp.DestinationPort.ToString();
string controlBits = IPpack.Tcp.ControlBits.ToString();
int p1 = 0;
if ((controlBits == "Acknowledgment")|(controlBits == "Push, Acknowledgment"))
{
//Add
p1 = TCPCPackets.FindIndex(x => (x.SourceIP == src) & (x.DestinationIP == dest) & (x.DestinationPort == destPort));
if (p1 < 0)
{
TCPCombinedPacket newCP = new TCPCombinedPacket();
newCP.SourceIP = src;
newCP.DestinationIP = dest;
newCP.DestinationPort = destPort;
TCPCPackets.Add(newCP);
p1 = TCPCPackets.Count() - 1;
}
TCPCPackets[p1].Counter += 1;
int totcount = packets[index].Count();
int start = totcount - IPpack.Tcp.PayloadLength;
if (start < totcount)
{
for (int o = start; o < totcount; o++)
{
TCPCPackets[p1].bytedata.Add(packets[index][o]);
}
}
}
if (controlBits == "Push, Acknowledgment")
{
//Finish
TCPWPackets.Add(TCPCPackets[p1]);
TCPCPackets.RemoveAt(p1);
}
}
But I'm not able to find any single TLS decryption function. I tried with the integrated .net decryptor but with no success:
public string DecryptString(byte[] key, byte[] buffer)
{
byte[] iv = new byte[16];
//byte[] buffer = Convert.FromBase64String(cipherText);
using (Aes aes = Aes.Create())
{
aes.Key = key;//Encoding.UTF8.GetBytes(key);
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(buffer))
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader((Stream)cryptoStream))
{
return streamReader.ReadToEnd();
}
}
}
}
}
It seems TLS uses many types of encryptions and it's generally not exposed to C#, much more likely to driver level. I'm not able to find any TLS decryption code anywhere.
I have many CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET in the ssl.log file from the web browser as I already set SSLKEYLOGFILE environment variable. My idea was to try with some decrypt function until I find working key and store the key per IP and port. Sorting this "try" list of keys by success rate, while outdated will go last. But obviously with packets in my variable but no TLS decryption function I can do nothing...
The last thing I tried is to run inspector over inspector and run the following Java scrypt. But it seems it's no longer supported. Also I found 1-2 third party extensions to capture WinSocket traffic for Chrome that are no longer available (and I even cannot find them, only history pages). Here is the JS code which I tried on older version chrome with no success (which returns errors, and actually I don't see the used sub-objects - maybe no longer supported):
// https://bgrins.github.io/devtools-snippets/#console-save
(function(console){
console.save = function(data, filename){
if(!data) {
console.error('Console.save: No data')
return;
}
if(!filename) filename = 'console.json'
if(typeof data === "object"){
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
})(console)
// Frame/Socket message counter + filename
var iter = 0;
// This replaces the browser's `webSocketFrameReceived` code with the original code
// and adds two lines, one to save the socket message and one to increment the counter.
SDK.NetworkDispatcher.prototype.webSocketFrameReceived = function (requestId, time, response) {
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest) return;
console.save(JSON.parse(response.payloadData), iter + ".json")
iter++;
networkRequest.addFrame(response, time, false);
networkRequest.responseReceivedTime = time;
this._updateNetworkRequest(networkRequest);
}
The link is this one: How to save websocket frames in Chrome
Any idea how I can capture TLS encrypted WebSocket traffic in realtime with max delay of 1 second?