added addon stubs
This commit is contained in:
parent
5eacc49a62
commit
739a6b7e06
12 changed files with 368 additions and 167 deletions
|
@ -12,19 +12,6 @@ set(CMAKE_AUTORCC ON)
|
|||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
|
||||
# Check http://doc.qt.io/qt-5/deployment-android.html for more information.
|
||||
# They need to be set before the find_package(Qt5 ...) call.
|
||||
|
||||
#if(ANDROID)
|
||||
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
|
||||
# if (ANDROID_ABI STREQUAL "armeabi-v7a")
|
||||
# set(ANDROID_EXTRA_LIBS
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
|
||||
# endif()
|
||||
#endif()
|
||||
|
||||
find_package(Qt5 COMPONENTS Widgets REQUIRED)
|
||||
find_package(cppzmq REQUIRED)
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
|
@ -39,6 +26,7 @@ add_executable(littlesnitch
|
|||
httpflow.cpp
|
||||
historymodel.cpp
|
||||
editandresend.cpp
|
||||
addonhandler.cpp
|
||||
mainwindow.h
|
||||
httpflow.h
|
||||
networkthread.h
|
||||
|
@ -46,6 +34,8 @@ add_executable(littlesnitch
|
|||
includes.h
|
||||
historymodel.h
|
||||
editandresend.h
|
||||
addonhandler.h
|
||||
include/api.h
|
||||
mainwindow.ui
|
||||
editandresend.ui
|
||||
)
|
||||
|
@ -61,6 +51,11 @@ add_executable(littlesnitch_tests
|
|||
target_include_directories(littlesnitch_tests PRIVATE /usr/local/include)
|
||||
target_link_libraries(littlesnitch_tests PRIVATE Qt5::Widgets cppzmq sqlite3 Catch2::Catch2)
|
||||
|
||||
file(GLOB_RECURSE addonfiles addons/CMakeLists.txt)
|
||||
foreach(loopvar IN ITEMS ${addonfiles})
|
||||
include(${loopvar})
|
||||
endforeach(loopvar)
|
||||
|
||||
include(CTest)
|
||||
include(Catch)
|
||||
catch_discover_tests(littlesnitch_tests)
|
||||
|
|
66
addonhandler.cpp
Normal file
66
addonhandler.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "addonhandler.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
AddonHandler::AddonHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::optional<std::string> AddonHandler::load(std::filesystem::path path)
|
||||
{
|
||||
// load library
|
||||
void* lib = dlopen(path.c_str(), RTLD_LAZY);
|
||||
if(!lib) {
|
||||
qDebug() << "addon " << path.c_str() << " not loaded!";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto get_name = reinterpret_cast<const char*(*)()>(dlsym(lib, "get_name"));
|
||||
std::string name;
|
||||
try {
|
||||
get_name();
|
||||
} catch (...) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto initialize = reinterpret_cast<const char*(*)()>(dlsym(lib, "initialize"));
|
||||
try {
|
||||
if(initialize) {
|
||||
initialize();
|
||||
}
|
||||
} catch (...) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
on_request.append(name, dlsym(lib, "on_request"));
|
||||
on_response.append(name, dlsym(lib, "on_response"));
|
||||
|
||||
loaded_addon_paths.insert(std::make_pair(name, path));
|
||||
loaded_addon_libs.insert(std::make_pair(name, lib));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void AddonHandler::unload(std::string name)
|
||||
{
|
||||
on_request.remove(name);
|
||||
on_response.remove(name);
|
||||
void* lib = loaded_addon_libs.find(name)->second;
|
||||
auto deinitialize = reinterpret_cast<const char*(*)()>(dlsym(lib, "initialize"));
|
||||
try {
|
||||
if(deinitialize) {
|
||||
deinitialize();
|
||||
}
|
||||
} catch (...) {
|
||||
qDebug() << "deinitialize failed";
|
||||
}
|
||||
}
|
||||
|
||||
bool AddonHandler::isLoaded(std::string name)
|
||||
{
|
||||
return loaded_addon_libs.count(name);
|
||||
}
|
||||
|
||||
std::map<std::string, std::filesystem::path> AddonHandler::loadedAddons()
|
||||
{
|
||||
return std::map<std::string, std::filesystem::path>();
|
||||
}
|
61
addonhandler.h
Normal file
61
addonhandler.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
#include <includes.h>
|
||||
#include <dlfcn.h>
|
||||
#include <functional>
|
||||
|
||||
template <typename T>
|
||||
class DLWrapper {
|
||||
private:
|
||||
std::map<std::string, void*> funcs;
|
||||
public:
|
||||
void append(std::string name, void* ptr) {
|
||||
if(ptr) {
|
||||
funcs.insert({name, ptr});
|
||||
}
|
||||
}
|
||||
|
||||
void remove(std::string name) {
|
||||
for(auto it = funcs.begin(); it != funcs.end(); ) {
|
||||
if(it->first == name) {
|
||||
it = funcs.erase(it);
|
||||
return;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
void operator()(Args... args) const {
|
||||
for(auto fun : funcs) {
|
||||
(T)(fun)(args...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
the addon handler loads addon shared library objects and calls
|
||||
in every loaded addon the implemented events, when they're implemented.
|
||||
*/
|
||||
class AddonHandler
|
||||
{
|
||||
private:
|
||||
//list of loaded addons with library pointer
|
||||
std::map<std::string, std::filesystem::path> loaded_addon_paths;
|
||||
std::map<std::string, void*> loaded_addon_libs;
|
||||
public:
|
||||
AddonHandler();
|
||||
// loads an addon and returns it's name, if successfully loaded
|
||||
std::optional<std::string> load(std::filesystem::path path);
|
||||
// unload an addon
|
||||
void unload(std::string name);
|
||||
// returns whether an addon with name is loaded
|
||||
bool isLoaded(std::string name);
|
||||
// returns the list of loaded addons (name, path)
|
||||
std::map<std::string, std::filesystem::path> loadedAddons();
|
||||
|
||||
DLWrapper<void(*)(int)> on_request;
|
||||
DLWrapper<void(*)(int)> on_response;
|
||||
};
|
||||
|
9
addons/yararules/CMakeLists.txt
Normal file
9
addons/yararules/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
project(yararules VERSION 1.0.0 DESCRIPTION "addon for tagging using yara rules")
|
||||
|
||||
add_library(yararules SHARED ${CMAKE_CURRENT_LIST_DIR}/yararules.cpp)
|
||||
set_target_properties(yararules PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION 1)
|
||||
target_include_directories(yararules PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include/)
|
5
addons/yararules/yararules.cpp
Normal file
5
addons/yararules/yararules.cpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
extern "C" const char* get_name() {
|
||||
return "yararules";
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef EDITANDRESEND_H
|
||||
#define EDITANDRESEND_H
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
|
@ -18,5 +17,3 @@ public:
|
|||
private:
|
||||
Ui::EditAndResend *ui;
|
||||
};
|
||||
|
||||
#endif // EDITANDRESEND_H
|
||||
|
|
148
editandresend.ui
148
editandresend.ui
|
@ -6,13 +6,157 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>459</width>
|
||||
<height>354</height>
|
||||
<width>897</width>
|
||||
<height>570</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>9</y>
|
||||
<width>871</width>
|
||||
<height>100</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Minimum">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>730</x>
|
||||
<y>20</y>
|
||||
<width>80</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>640</x>
|
||||
<y>20</y>
|
||||
<width>80</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>120</y>
|
||||
<width>781</width>
|
||||
<height>404</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit"/>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit_3"/>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit_2"/>
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit_4"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
@ -5,26 +5,6 @@
|
|||
#include <QSortFilterProxyModel>
|
||||
#include <mutex>
|
||||
|
||||
struct HistoryItem {
|
||||
int id = -1;
|
||||
double timestamp = 0;
|
||||
std::string method;
|
||||
std::string scheme;
|
||||
std::string host;
|
||||
unsigned short port = 0;
|
||||
std::string path;
|
||||
int status_code = 0;
|
||||
std::string reason;
|
||||
double rtt = 0.0;
|
||||
size_t size = 0;
|
||||
std::string request_http_version;
|
||||
std::map<std::string, std::string> request_headers;
|
||||
std::string request_content;
|
||||
std::string response_http_version;
|
||||
std::map<std::string, std::string> response_headers;
|
||||
std::string response_content;
|
||||
};
|
||||
|
||||
class HistoryModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
127
httpflow.h
127
httpflow.h
|
@ -2,135 +2,8 @@
|
|||
|
||||
#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_ip_address;
|
||||
|
||||
bool tls;
|
||||
std::string content;
|
||||
std::string scheme;
|
||||
std::string method;
|
||||
std::string host;
|
||||
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 {
|
||||
int status_code;
|
||||
std::string http_version;
|
||||
std::string reason;
|
||||
std::string content;
|
||||
double timestamp_start;
|
||||
double timestamp_end;
|
||||
std::vector<std::tuple<std::string,std::string>> headers;
|
||||
};
|
||||
|
||||
struct Flow {
|
||||
std::string uid;
|
||||
Request request;
|
||||
Response response;
|
||||
};
|
||||
|
||||
inline void to_json(json& j, const Flow& flow) {}
|
||||
|
||||
inline void from_json(const json& j, Flow& flow) {
|
||||
|
|
68
include/api.h
Normal file
68
include/api.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
struct HistoryItem {
|
||||
int id = -1;
|
||||
double timestamp = 0;
|
||||
std::string method;
|
||||
std::string scheme;
|
||||
std::string host;
|
||||
unsigned short port = 0;
|
||||
std::string path;
|
||||
int status_code = 0;
|
||||
std::string reason;
|
||||
double rtt = 0.0;
|
||||
size_t size = 0;
|
||||
std::string request_http_version;
|
||||
std::map<std::string, std::string> request_headers;
|
||||
std::string request_content;
|
||||
std::string response_http_version;
|
||||
std::map<std::string, std::string> response_headers;
|
||||
std::string response_content;
|
||||
};
|
||||
|
||||
namespace http {
|
||||
|
||||
struct Request
|
||||
{
|
||||
std::string server_ip_address;
|
||||
|
||||
bool tls;
|
||||
std::string content;
|
||||
std::string scheme;
|
||||
std::string method;
|
||||
std::string host;
|
||||
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 {
|
||||
int status_code;
|
||||
std::string http_version;
|
||||
std::string reason;
|
||||
std::string content;
|
||||
double timestamp_start;
|
||||
double timestamp_end;
|
||||
std::vector<std::tuple<std::string,std::string>> headers;
|
||||
};
|
||||
|
||||
struct Flow {
|
||||
std::string uid;
|
||||
Request request;
|
||||
Response response;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <include/api.h>
|
||||
#include <zmq.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sqlite3.h>
|
||||
|
@ -12,7 +13,7 @@
|
|||
using json = nlohmann::json;
|
||||
|
||||
//major minor patch
|
||||
#define LITTLESNITCH_VERSION 010
|
||||
#define LITTLESNITCH_VERSION 100
|
||||
|
||||
template<typename T, typename K>
|
||||
bool json_get(json j, T& value, K key) noexcept {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <session.h>
|
||||
#include <includes.h>
|
||||
#include <httpflow.h>
|
||||
#include <editandresend.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class MainWindow; }
|
||||
|
@ -16,6 +17,7 @@ class MainWindow : public QMainWindow
|
|||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
Ui::EditAndResend *ui_editandresend;
|
||||
QThread* thread;
|
||||
Session* current_session;
|
||||
HistoryModel history_model;
|
||||
|
|
Loading…
Reference in a new issue