yolo
This commit is contained in:
		
							parent
							
								
									f91da7a47c
								
							
						
					
					
						commit
						d8b52dcb44
					
				
					 12 changed files with 278 additions and 119 deletions
				
			
		| 
						 | 
					@ -34,11 +34,13 @@ add_executable(littlesnitch
 | 
				
			||||||
    mainwindow.cpp
 | 
					    mainwindow.cpp
 | 
				
			||||||
    networkthread.cpp
 | 
					    networkthread.cpp
 | 
				
			||||||
    session.cpp
 | 
					    session.cpp
 | 
				
			||||||
    mainwindow.ui
 | 
					    httpflow.cpp
 | 
				
			||||||
    mainwindow.h
 | 
					    mainwindow.h
 | 
				
			||||||
 | 
					    httpflow.h
 | 
				
			||||||
    networkthread.h
 | 
					    networkthread.h
 | 
				
			||||||
    session.h
 | 
					    session.h
 | 
				
			||||||
    includes.h
 | 
					    includes.h
 | 
				
			||||||
 | 
					    mainwindow.ui
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(littlesnitch PRIVATE Qt5::Widgets cppzmq sqlite3)
 | 
					target_link_libraries(littlesnitch PRIVATE Qt5::Widgets cppzmq sqlite3)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								httpflow.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								httpflow.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					#include "httpflow.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										153
									
								
								httpflow.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								httpflow.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,153 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <includes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    "flow": {
 | 
				
			||||||
 | 
					    "client_conn": {
 | 
				
			||||||
 | 
					        "address": [
 | 
				
			||||||
 | 
					        "::1",
 | 
				
			||||||
 | 
					        37570,
 | 
				
			||||||
 | 
					        0,
 | 
				
			||||||
 | 
					        0
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "alpn_proto_negotiated": "http/1.1",
 | 
				
			||||||
 | 
					        "cipher_name": "TLS_AES_256_GCM_SHA384",
 | 
				
			||||||
 | 
					        "clientcert": null,
 | 
				
			||||||
 | 
					        "id": "a1e82917-2d58-4b99-be9e-2b962bc499b2",
 | 
				
			||||||
 | 
					        "mitmcert": "mitmcertstring",
 | 
				
			||||||
 | 
					        "sni": "yolo.jetzt",
 | 
				
			||||||
 | 
					        "timestamp_end": null,
 | 
				
			||||||
 | 
					        "timestamp_start": 1597284668.6260498,
 | 
				
			||||||
 | 
					        "timestamp_tls_setup": 1597284669.8449724,
 | 
				
			||||||
 | 
					        "tls_established": true,
 | 
				
			||||||
 | 
					        "tls_extensions": [...],
 | 
				
			||||||
 | 
					        "tls_version": "TLSv1.3"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "error": null,
 | 
				
			||||||
 | 
					    "id": "a6aa4e6e-ca31-4f58-bf47-2da7bfcf0000",
 | 
				
			||||||
 | 
					    "intercepted": false,
 | 
				
			||||||
 | 
					    "marked": false,
 | 
				
			||||||
 | 
					    "metadata": {},
 | 
				
			||||||
 | 
					    "mode": "transparent",
 | 
				
			||||||
 | 
					    "request": {
 | 
				
			||||||
 | 
					        "content": "",
 | 
				
			||||||
 | 
					        "first_line_format": "relative",
 | 
				
			||||||
 | 
					        "headers": [
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            "Host",
 | 
				
			||||||
 | 
					            "yolo.jetzt"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            "User-Agent",
 | 
				
			||||||
 | 
					            "curl/7.68.0"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					            "Accept",
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "host": "yolo.jetzt",
 | 
				
			||||||
 | 
					        "http_version": "HTTP/1.1",
 | 
				
			||||||
 | 
					        "is_replay": false,
 | 
				
			||||||
 | 
					        "method": "GET",
 | 
				
			||||||
 | 
					        "path": "/",
 | 
				
			||||||
 | 
					        "port": 443,
 | 
				
			||||||
 | 
					        "scheme": "https",
 | 
				
			||||||
 | 
					        "timestamp_end": 1597284669.92817,
 | 
				
			||||||
 | 
					        "timestamp_start": 1597284669.8761458
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "response": null,
 | 
				
			||||||
 | 
					    "server_conn": {
 | 
				
			||||||
 | 
					        "address": [
 | 
				
			||||||
 | 
					        "yolo.jetzt",
 | 
				
			||||||
 | 
					        443
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "alpn_proto_negotiated": "http/1.1",
 | 
				
			||||||
 | 
					        "cert": "certstring",
 | 
				
			||||||
 | 
					        "id": "50a3b79d-2912-45f3-991b-c03406a1018f",
 | 
				
			||||||
 | 
					        "ip_address": [
 | 
				
			||||||
 | 
					        "95.156.226.69",
 | 
				
			||||||
 | 
					        443
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "sni": "yolo.jetzt",
 | 
				
			||||||
 | 
					        "source_address": [
 | 
				
			||||||
 | 
					        "192.168.42.102",
 | 
				
			||||||
 | 
					        44949
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "timestamp_end": null,
 | 
				
			||||||
 | 
					        "timestamp_start": 1597284669.2133315,
 | 
				
			||||||
 | 
					        "timestamp_tcp_setup": 1597284669.2892282,
 | 
				
			||||||
 | 
					        "timestamp_tls_setup": 1597284669.584602,
 | 
				
			||||||
 | 
					        "tls_established": true,
 | 
				
			||||||
 | 
					        "tls_version": "TLSv1.2",
 | 
				
			||||||
 | 
					        "via": null
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "type": "http",
 | 
				
			||||||
 | 
					    "version": 7
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "msg": "request"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace http {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Request
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::string server_conn_id;
 | 
				
			||||||
 | 
					    std::string server_ip_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool tls;
 | 
				
			||||||
 | 
					    std::string content;
 | 
				
			||||||
 | 
					    std::string scheme;
 | 
				
			||||||
 | 
					    std::string method;
 | 
				
			||||||
 | 
					    std::string host;
 | 
				
			||||||
 | 
					    std::string address;
 | 
				
			||||||
 | 
					    unsigned short port;
 | 
				
			||||||
 | 
					    std::string http_version;
 | 
				
			||||||
 | 
					    std::string path;
 | 
				
			||||||
 | 
					    double timestamp_start;
 | 
				
			||||||
 | 
					    double timestamp_end;
 | 
				
			||||||
 | 
					    std::vector<std::tuple<std::string,std::string>> headers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Response {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Flow {
 | 
				
			||||||
 | 
					    Request request;
 | 
				
			||||||
 | 
					    Response response;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void to_json(json& j, const Flow& flow) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void from_json(const json& j, Flow& flow) {
 | 
				
			||||||
 | 
					    std::cout << std::setw(4) << j << "\n\n";
 | 
				
			||||||
 | 
					    if(!j.contains("flow")) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(j.at("flow").contains("server_conn")) {
 | 
				
			||||||
 | 
					        j.at("flow").at("server_conn").at("id").get_to(flow.request.server_conn_id);
 | 
				
			||||||
 | 
					        j.at("flow").at("server_conn").at("tls_established").get_to(flow.request.tls);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(j.at("flow").contains("request")) {
 | 
				
			||||||
 | 
					        j.at("flow").at("request").at("port").get_to(flow.request.port);
 | 
				
			||||||
 | 
					        j.at("flow").at("request").at("host").get_to(flow.request.host);
 | 
				
			||||||
 | 
					        j.at("flow").at("request").at("scheme").get_to(flow.request.scheme);
 | 
				
			||||||
 | 
					        j.at("flow").at("request").at("path").get_to(flow.request.path);
 | 
				
			||||||
 | 
					        j.at("flow").at("request").at("content").get_to(flow.request.content);
 | 
				
			||||||
 | 
					        j.at("flow").at("request").at("method").get_to(flow.request.method);
 | 
				
			||||||
 | 
					        j.at("flow").at("request").at("http_version").get_to(flow.request.http_version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //j.at("server_conn").at("address").get_to(flow.server_conn_address);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Q_DECLARE_METATYPE(http::Flow)
 | 
				
			||||||
| 
						 | 
					@ -5,5 +5,6 @@
 | 
				
			||||||
#include <sqlite3.h>
 | 
					#include <sqlite3.h>
 | 
				
			||||||
#include <filesystem>
 | 
					#include <filesystem>
 | 
				
			||||||
#include <QDebug>
 | 
					#include <QDebug>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using json = nlohmann::json;
 | 
					using json = nlohmann::json;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ MainWindow::MainWindow(QWidget *parent)
 | 
				
			||||||
    : QMainWindow(parent),
 | 
					    : QMainWindow(parent),
 | 
				
			||||||
      ui(new Ui::MainWindow)
 | 
					      ui(new Ui::MainWindow)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    int metatype_id = qRegisterMetaType<http::Flow>("httpflow");
 | 
				
			||||||
    current_session = new Session();
 | 
					    current_session = new Session();
 | 
				
			||||||
    current_session->load("/tmp/littlesnitch.session");
 | 
					    current_session->load("/tmp/littlesnitch.session");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,8 +17,8 @@ MainWindow::MainWindow(QWidget *parent)
 | 
				
			||||||
    worker->moveToThread(thread);
 | 
					    worker->moveToThread(thread);
 | 
				
			||||||
    connect(thread, SIGNAL (started()), worker, SLOT (process()));
 | 
					    connect(thread, SIGNAL (started()), worker, SLOT (process()));
 | 
				
			||||||
    //connect(worker, SIGNAL (error(QString)), this, SLOT (errorString(QString)));
 | 
					    //connect(worker, SIGNAL (error(QString)), this, SLOT (errorString(QString)));
 | 
				
			||||||
    connect(worker, SIGNAL (httpMessage(json)), current_session, SLOT (saveRequest(json)));
 | 
					    connect(worker, SIGNAL (httpMessage(http::Flow)), current_session, SLOT (saveRequest(http::Flow)), Qt::QueuedConnection);
 | 
				
			||||||
    connect(worker, SIGNAL (httpMessage(json)), this, SLOT (updateHistory(json)));
 | 
					    connect(worker, SIGNAL (httpMessage(http::Flow)), this, SLOT (updateHistory(http::Flow)), Qt::QueuedConnection);
 | 
				
			||||||
    thread->start();
 | 
					    thread->start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ui->setupUi(this);
 | 
					    ui->setupUi(this);
 | 
				
			||||||
| 
						 | 
					@ -40,10 +41,10 @@ MainWindow::~MainWindow()
 | 
				
			||||||
    delete ui;
 | 
					    delete ui;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::updateHistory(json data) {
 | 
					void MainWindow::updateHistory(http::Flow flow) {
 | 
				
			||||||
    ui->historyHTTPTable->setItem(0,0,new QTableWidgetItem(QString::fromStdString(data["id"])));
 | 
					    ui->historyHTTPTable->setItem(0,0,new QTableWidgetItem(QString::fromStdString(flow.request.server_conn_id)));
 | 
				
			||||||
//    ui->historyHTTPTable->setItem(0,1,new QTableWidgetItem(QString::fromStdString(data.method)));
 | 
					    ui->historyHTTPTable->setItem(0,1,new QTableWidgetItem(QString::fromStdString(flow.request.method)));
 | 
				
			||||||
//    ui->historyHTTPTable->setItem(0,2,new QTableWidgetItem(QString::fromStdString(data.url)));
 | 
					    ui->historyHTTPTable->setItem(0,2,new QTableWidgetItem(QString::fromStdString(flow.request.host)));
 | 
				
			||||||
    //ui->historyHTTPTable->setItem(0,3,new QTableWidgetItem(QString::number(data.ttl)));
 | 
					    //ui->historyHTTPTable->setItem(0,3,new QTableWidgetItem(QString::number(data.ttl)));
 | 
				
			||||||
    ui->historyHTTPTable->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
 | 
					    ui->historyHTTPTable->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <session.h>
 | 
					#include <session.h>
 | 
				
			||||||
#include <includes.h>
 | 
					#include <includes.h>
 | 
				
			||||||
 | 
					#include <httpflow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QT_BEGIN_NAMESPACE
 | 
					QT_BEGIN_NAMESPACE
 | 
				
			||||||
namespace Ui { class MainWindow; }
 | 
					namespace Ui { class MainWindow; }
 | 
				
			||||||
| 
						 | 
					@ -21,5 +22,5 @@ public:
 | 
				
			||||||
    MainWindow(QWidget *parent = nullptr);
 | 
					    MainWindow(QWidget *parent = nullptr);
 | 
				
			||||||
    ~MainWindow();
 | 
					    ~MainWindow();
 | 
				
			||||||
public slots:
 | 
					public slots:
 | 
				
			||||||
    void updateHistory(json data);
 | 
					    void updateHistory(http::Flow flow);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,18 +8,6 @@ import zmq
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
from enum import Enum
 | 
					from enum import Enum
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
NO_MSG = {"msg": None}
 | 
					 | 
				
			||||||
INIT_MSG = {"msg": "init"}
 | 
					 | 
				
			||||||
ACK_MSG = {"msg": "ack"}
 | 
					 | 
				
			||||||
PING_MSG = {"msg": "ping"}
 | 
					 | 
				
			||||||
PONG_MSG = {"msg": "pong"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NetworkState(Enum):
 | 
					 | 
				
			||||||
        DISCONNECTED = auto()
 | 
					 | 
				
			||||||
        CONNECTED = auto()
 | 
					 | 
				
			||||||
        PING = auto()
 | 
					 | 
				
			||||||
        SENDING = auto()
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
def convert_to_strings(obj):
 | 
					def convert_to_strings(obj):
 | 
				
			||||||
        if isinstance(obj, dict):
 | 
					        if isinstance(obj, dict):
 | 
				
			||||||
            return {convert_to_strings(key): convert_to_strings(value)
 | 
					            return {convert_to_strings(key): convert_to_strings(value)
 | 
				
			||||||
| 
						 | 
					@ -38,87 +26,57 @@ class NetworkThread(threading.Thread):
 | 
				
			||||||
                self.context = zmq.Context()
 | 
					                self.context = zmq.Context()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def run(self):
 | 
					        def run(self):
 | 
				
			||||||
 | 
					                print("thread started")
 | 
				
			||||||
                self.connect()
 | 
					                self.connect()
 | 
				
			||||||
                msg = self.send_msg_and_expect()
 | 
					                while True:
 | 
				
			||||||
 | 
					                        timer = time.monotonic()
 | 
				
			||||||
 | 
					                        a = None
 | 
				
			||||||
 | 
					                        if not a:
 | 
				
			||||||
 | 
					                                try:
 | 
				
			||||||
 | 
					                                        a = self.q.get(block=False)
 | 
				
			||||||
 | 
					                                except Empty:
 | 
				
			||||||
 | 
					                                        pass
 | 
				
			||||||
 | 
					                        if a:
 | 
				
			||||||
 | 
					                                self.send_msg_and_ack(a)
 | 
				
			||||||
 | 
					                                timer = time.monotonic()
 | 
				
			||||||
 | 
					                        if timer - time.monotonic() < -5:
 | 
				
			||||||
 | 
					                                self.send_msg_and_ack({"msg": "ping"})
 | 
				
			||||||
                                        
 | 
					                                        
 | 
				
			||||||
        def disconnect(self):
 | 
					        def disconnect(self):
 | 
				
			||||||
                self.socket.setsockopt(zmq.LINGER,0)
 | 
					                self.socket.setsockopt(zmq.LINGER,0)
 | 
				
			||||||
                self.socket.close()
 | 
					                self.socket.close()
 | 
				
			||||||
 | 
					                print("disconnected")
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
        def reconnect(self):
 | 
					        def reconnect(self):
 | 
				
			||||||
                self.disconnect()
 | 
					                self.disconnect()
 | 
				
			||||||
 | 
					                time.sleep(1)
 | 
				
			||||||
                self.connect()
 | 
					                self.connect()
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        def connect(self):
 | 
					        def connect(self):
 | 
				
			||||||
                self.socket = self.context.socket(zmq.PAIR)
 | 
					                self.socket = self.context.socket(zmq.PAIR)
 | 
				
			||||||
                self.socket.connect("tcp://127.0.0.1:12345")
 | 
					                self.socket.connect("tcp://127.0.0.1:12345")
 | 
				
			||||||
 | 
					                self.send_msg_and_ack({"msg": "ping"})
 | 
				
			||||||
 | 
					                print("successfully connected")
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        def send_msg_and_expect(this, msg, expect, timeout=5, retries=3):
 | 
					        def send_msg_and_ack(self, msg):
 | 
				
			||||||
                while retries:
 | 
					                while True:
 | 
				
			||||||
                        a = convert_to_strings(msg)
 | 
					                        a = convert_to_strings(msg)
 | 
				
			||||||
                        self.socket.send(str.encode(json.dumps(a)))
 | 
					                        self.socket.send(str.encode(json.dumps(a)))
 | 
				
			||||||
                        if (client.poll(REQUEST_TIMEOUT) & zmq.POLLIN) != 0:
 | 
					                        if (self.socket.poll(5) & zmq.POLLIN) != 0:
 | 
				
			||||||
                                msg = self.socket.recv()
 | 
					                                msg = self.socket.recv()
 | 
				
			||||||
                                try:
 | 
					                                try:
 | 
				
			||||||
                                        if msg:
 | 
					                                        if msg:
 | 
				
			||||||
                                                result = json.loads(msg)
 | 
					                                                result = json.loads(msg)
 | 
				
			||||||
                                                if result["msg"] in expect:
 | 
					                                                if result["msg"] == "ack":
 | 
				
			||||||
                                                        return result
 | 
					                                                        return result
 | 
				
			||||||
                                                else:
 | 
					                                                else:
 | 
				
			||||||
                                                        print("got unexpected message {result}")
 | 
					                                                        print("got unexpected message {result}")
 | 
				
			||||||
                                        
 | 
					                                        
 | 
				
			||||||
                                except json.JSONDecodeError:
 | 
					                                except json.JSONDecodeError:
 | 
				
			||||||
                                        print(f"malformed message received {msg}")
 | 
					                                        print(f"malformed message received {msg}")
 | 
				
			||||||
                        retries -= 1
 | 
					                        print("no ack received, reconnecting...")
 | 
				
			||||||
                        self.reconnect()
 | 
					                        self.reconnect()
 | 
				
			||||||
                return NO_MSG
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
def networking(q):
 | 
					 | 
				
			||||||
        print("starting thread")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        state = NetworkState.DISCONNECTED
 | 
					 | 
				
			||||||
        a = None
 | 
					 | 
				
			||||||
        while state == NetworkState.DISCONNECTED:
 | 
					 | 
				
			||||||
                socket = context.socket(zmq.PAIR)
 | 
					 | 
				
			||||||
                socket.connect("tcp://127.0.0.1:12345")
 | 
					 | 
				
			||||||
                msg = get_msg(socket)
 | 
					 | 
				
			||||||
                if msg["msg"] == "init":
 | 
					 | 
				
			||||||
                        send_msg(ACK_MSG, socket)
 | 
					 | 
				
			||||||
                        state = NetworkState.CONNECTED
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                timer = time.monotonic()
 | 
					 | 
				
			||||||
                while state != NetworkState.DISCONNECTED:
 | 
					 | 
				
			||||||
                        if state == NetworkState.CONNECTED and timer - time.monotonic() >= 5:
 | 
					 | 
				
			||||||
                                timer = time.monotonic()
 | 
					 | 
				
			||||||
                                send_msg(PING_MSG,socket)
 | 
					 | 
				
			||||||
                                msg = get_msg(socket)
 | 
					 | 
				
			||||||
                                if msg["msg"] != "pong":
 | 
					 | 
				
			||||||
                                        state = NetworkState.
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        msg = get_msg(socket)
 | 
					 | 
				
			||||||
                        if msg['msg'] == "ping":
 | 
					 | 
				
			||||||
                                send_msg(PONG_MSG, socket)
 | 
					 | 
				
			||||||
                                timer = time.monotonic()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if not a:
 | 
					 | 
				
			||||||
                                try:
 | 
					 | 
				
			||||||
                                        a = q.get(block=False)
 | 
					 | 
				
			||||||
                                except Empty:
 | 
					 | 
				
			||||||
                                        pass
 | 
					 | 
				
			||||||
                        if a:
 | 
					 | 
				
			||||||
                                send_msg(a, socket)
 | 
					 | 
				
			||||||
                                msg = get_msg(socket)
 | 
					 | 
				
			||||||
                                if msg["msg"] == "ack":
 | 
					 | 
				
			||||||
                                        timer = time.monotonic()
 | 
					 | 
				
			||||||
                                        a = None
 | 
					 | 
				
			||||||
                                        self.q.task_done()
 | 
					 | 
				
			||||||
                                else:
 | 
					 | 
				
			||||||
                                        connected = False
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
class LittleSnitchBridge:
 | 
					class LittleSnitchBridge:
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        self.q = Queue()
 | 
					        self.q = Queue()
 | 
				
			||||||
| 
						 | 
					@ -127,11 +85,9 @@ class LittleSnitchBridge:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def request(self, flow):
 | 
					    def request(self, flow):
 | 
				
			||||||
        self.q.put({'msg': 'request', 'flow': flow.get_state()})
 | 
					        self.q.put({'msg': 'request', 'flow': flow.get_state()})
 | 
				
			||||||
        self.q.join()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def response(self, flow):
 | 
					    def response(self, flow):
 | 
				
			||||||
        self.q.put({'msg': 'response', 'flow': flow.get_state()})
 | 
					        self.q.put({'msg': 'response', 'flow': flow.get_state()})
 | 
				
			||||||
        self.q.join()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
addons = [
 | 
					addons = [
 | 
				
			||||||
        LittleSnitchBridge()
 | 
					        LittleSnitchBridge()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,40 +1,70 @@
 | 
				
			||||||
#include "networkthread.h"
 | 
					#include "networkthread.h"
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NetworkThread::NetworkThread(QObject *parent) : QObject(parent)
 | 
					NetworkThread::NetworkThread(QObject *parent) :
 | 
				
			||||||
 | 
					        QObject(parent),
 | 
				
			||||||
 | 
					        context(1)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetworkThread::process() {
 | 
					void NetworkThread::connect() {
 | 
				
			||||||
	zmq::context_t ctx(1);
 | 
					    socket = new zmq::socket_t(context, zmq::socket_type::pair);
 | 
				
			||||||
	zmq::socket_t sock(ctx, zmq::socket_type::pair);
 | 
					    int linger = 0;
 | 
				
			||||||
 | 
					    socket->setsockopt(ZMQ_LINGER, &linger, sizeof (linger));
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
		sock.bind("tcp://127.0.0.1:12345");
 | 
					        socket->bind("tcp://127.0.0.1:12345");
 | 
				
			||||||
    } catch (zmq::error_t err) {
 | 
					    } catch (zmq::error_t err) {
 | 
				
			||||||
        qDebug() << "failed binding socket" << err.what();
 | 
					        qDebug() << "failed binding socket" << err.what();
 | 
				
			||||||
        emit error(err.what());
 | 
					        emit error(err.what());
 | 
				
			||||||
		return;
 | 
					        throw;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					    qDebug() << "connected";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NetworkThread::disconnect() {
 | 
				
			||||||
 | 
					    delete socket;
 | 
				
			||||||
 | 
					    qDebug() << "disconnected";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NetworkThread::reconnect() {
 | 
				
			||||||
 | 
					    this->disconnect();
 | 
				
			||||||
 | 
					    this->connect();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NetworkThread::process() {
 | 
				
			||||||
 | 
					    connect();
 | 
				
			||||||
    while(true) {
 | 
					    while(true) {
 | 
				
			||||||
		bool connected = false;
 | 
					        zmq::message_t response;
 | 
				
			||||||
        while(!connected) {
 | 
					        const auto ret = socket->recv(response, zmq::recv_flags::dontwait);
 | 
				
			||||||
            sock.send(zmq::buffer(INIT_MSG_STR.c_str(), INIT_MSG_STR.length()), zmq::send_flags::dontwait);
 | 
					 | 
				
			||||||
			zmq::message_t msg;
 | 
					 | 
				
			||||||
			const auto ret = sock.recv(msg, zmq::recv_flags::dontwait);
 | 
					 | 
				
			||||||
        if(ret) {
 | 
					        if(ret) {
 | 
				
			||||||
                if(msg.to_string() == ACK_MSG_STR) {
 | 
					            auto j = json::parse(response.to_string());
 | 
				
			||||||
					connected = true;
 | 
					            //std::cout << std::setw(4) << j << "\n\n";
 | 
				
			||||||
 | 
					            if(j.contains("msg") && j["msg"].is_string()) {
 | 
				
			||||||
 | 
					                std::string msg_type;
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    j["msg"].get_to(msg_type);
 | 
				
			||||||
 | 
					                } catch (nlohmann::detail::type_error& err) {
 | 
				
			||||||
 | 
					                    qDebug() << "json type error, message type not a string: " << response.to_string().c_str();
 | 
				
			||||||
 | 
					                    emit error("no message type");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                if(msg_type == "request") {
 | 
				
			||||||
 | 
					                } else if (msg_type == "response") {
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        emit httpMessage(j);
 | 
				
			||||||
 | 
					                    } catch (nlohmann::detail::type_error& err) {
 | 
				
			||||||
 | 
					                        qDebug() << "error reading HTTP Flow";
 | 
				
			||||||
 | 
					                        emit error("error converting to flow");
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                } else if(msg_type == "ping") {
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    qDebug() << "unknown or broken message type received: " << msg_type.c_str();
 | 
				
			||||||
 | 
					                    emit error("unknown message");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
		while(connected) {
 | 
					                std::string m = "{\"msg\": \"ack\"}";
 | 
				
			||||||
            zmq::message_t msg;
 | 
					                socket->send(zmq::buffer(m.c_str(), m.length()), zmq::send_flags::dontwait);
 | 
				
			||||||
            const auto ret = sock.recv(msg, zmq::recv_flags::dontwait);
 | 
					            } else {
 | 
				
			||||||
			if(ret) {
 | 
					                qDebug() << "broken message, but correct json: " << response.to_string().c_str();
 | 
				
			||||||
                qDebug() << msg.to_string().c_str();
 | 
					 | 
				
			||||||
                emit httpMessage(json(msg.to_string()));
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,15 +2,17 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QObject>
 | 
					#include <QObject>
 | 
				
			||||||
#include <includes.h>
 | 
					#include <includes.h>
 | 
				
			||||||
 | 
					#include <httpflow.h>
 | 
				
			||||||
const std::string INIT_MSG_STR = R"({"msg": "init"})";
 | 
					 | 
				
			||||||
const std::string ACK_MSG_STR = R"({"msg": "ack"})";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NetworkThread : public QObject
 | 
					class NetworkThread : public QObject
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Q_OBJECT
 | 
					    Q_OBJECT
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    // add your variables here
 | 
					    zmq::context_t context;
 | 
				
			||||||
 | 
					    zmq::socket_t *socket;
 | 
				
			||||||
 | 
					    void connect();
 | 
				
			||||||
 | 
					    void disconnect();
 | 
				
			||||||
 | 
					    void reconnect();
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit NetworkThread(QObject *parent = nullptr);
 | 
					    explicit NetworkThread(QObject *parent = nullptr);
 | 
				
			||||||
public slots:
 | 
					public slots:
 | 
				
			||||||
| 
						 | 
					@ -18,5 +20,5 @@ public slots:
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
    void finished();
 | 
					    void finished();
 | 
				
			||||||
    void error(QString err);
 | 
					    void error(QString err);
 | 
				
			||||||
    void httpMessage(json data);
 | 
					    void httpMessage(http::Flow flow);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,6 @@ void Session::unload() {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Session::saveRequest(json data) {
 | 
					void Session::saveRequest(http::Flow flow) {
 | 
				
			||||||
    // todo
 | 
					    // todo
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QObject>
 | 
					#include <QObject>
 | 
				
			||||||
#include <includes.h>
 | 
					#include <includes.h>
 | 
				
			||||||
 | 
					#include <httpflow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  static int callback(void *NotUsed, int argc, char **argv, char **azColName){
 | 
					//  static int callback(void *NotUsed, int argc, char **argv, char **azColName){
 | 
				
			||||||
//    int i;
 | 
					//    int i;
 | 
				
			||||||
| 
						 | 
					@ -51,7 +52,7 @@ public:
 | 
				
			||||||
    void unload();
 | 
					    void unload();
 | 
				
			||||||
    bool isLoaded();
 | 
					    bool isLoaded();
 | 
				
			||||||
public slots:
 | 
					public slots:
 | 
				
			||||||
    void saveRequest(json data);
 | 
					    void saveRequest(http::Flow flow);
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								test.sh
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								test.sh
									
										
									
									
									
								
							| 
						 | 
					@ -4,5 +4,15 @@ mitmdump -k -p 8080 -s mitmaddon/littlesnitch.py &
 | 
				
			||||||
./build/littlesnitch &
 | 
					./build/littlesnitch &
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sleep 1
 | 
					sleep 1
 | 
				
			||||||
curl -x http://localhost:8080 -k https://yolo.jetzt
 | 
					curl -x http://localhost:8080 -k https://get.yolo.jetzt
 | 
				
			||||||
 | 
					sleep 1
 | 
				
			||||||
 | 
					curl -x http://localhost:8080 -k https://get.yolo.jetzt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					killall mitmdump
 | 
				
			||||||
 | 
					sleep 1
 | 
				
			||||||
 | 
					killall mitmdump
 | 
				
			||||||
 | 
					sleep 2
 | 
				
			||||||
 | 
					killall mitmdump
 | 
				
			||||||
 | 
					sleep 3
 | 
				
			||||||
 | 
					killall mitmdump
 | 
				
			||||||
 | 
					killall mitmdump
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue