samedi 3 août 2019

Manipulating TCP Packet in libtins

I have have used this example to capture tcp packet. Now I need to change the Stream on the fly e.g changing the HTTP status code

I have already caputured the stream data but this is read only and changes to this won't apply to the client

    Stream::payload_type &client_payload = stream.client_payload();
    Stream::payload_type &server_payload = stream.server_payload();

    //Here I need to manipulate the packet for the client
    server_payload.data()[9] = '4';

    stringstream ss;

    for (char c : server_payload) {
        ss << c;
    }
    cout << on_green << "Server raw payload " << on_magenta << ss.str() << reset << endl;

    stringstream cc;
    for (char c : client_payload) {
        cc << c;
    }
    cout << on_green << "Client raw payload " << on_magenta << cc.str() << reset << endl;

This is my full code

//#define WIN32
//#define TINS_STATIC
//#define NOMINMAX
//#pragma warning(disable : 4996)
#include <string>
#include <iostream>
#include <stdexcept>
#include <boost/regex.hpp>
#include <tins/tcp_ip/stream_follower.h>
#include <tins/sniffer.h>
#include <tins/tins.h>
#include "color.h"
#include <vector>
#include <sstream>

using std::string;
using std::cout;
using std::cerr;
using std::endl;
using std::exception;
using std::vector;
using std::wcout;
using std::stringstream;

using boost::regex;
using boost::match_results;

using Tins::Packet;
using Tins::Sniffer;
using Tins::SnifferConfiguration;
using Tins::TCPIP::Stream;
using Tins::TCPIP::StreamFollower;
using Tins::NetworkInterface;


using termcolor::on_red;
using termcolor::on_green;
using termcolor::reset;
using termcolor::on_magenta;

// This example captures and follows TCP streams seen on port 80. It will
// wait until both the client and server send data and then apply a regex
// to both payloads, extrating some information and printing it.

// Don't buffer more than 3kb of data in either request/response
const size_t MAX_PAYLOAD = 3 * 1024;

void on_server_data(Stream &stream) {
    match_results<Stream::payload_type::const_iterator> client_match;
    match_results<Stream::payload_type::const_iterator> server_match;
    Stream::payload_type &client_payload = stream.client_payload();
    Stream::payload_type &server_payload = stream.server_payload();

    string string1 = "h";
    server_payload.data()[9] = '4';

    stringstream ss;

    for (char c : server_payload) {
        ss << c;
    }
    cout << on_green << "Server raw payload " << on_magenta << ss.str() << reset << endl;

    stringstream cc;
    for (char c : client_payload) {
        cc << c;
    }
    cout << on_green << "Client raw payload " << on_magenta << cc.str() << reset << endl;


    // Once we've seen the first request on this stream, ignore it
    stream.ignore_client_data();
    stream.ignore_server_data();

    // Just in case the server returns invalid data, stop at 3kb
    if (stream.server_payload().size() > MAX_PAYLOAD) {
        stream.ignore_server_data();
    }
}

void on_client_data(Stream &stream) {
    // Don't hold more than 3kb of data from the client's flow
    if (stream.client_payload().size() > MAX_PAYLOAD) {
        stream.ignore_client_data();
    }
}

void on_new_connection(Stream &stream) {
    stream.client_data_callback(&on_client_data);
    stream.server_data_callback(&on_server_data);
    // Don't automatically cleanup the stream's data, as we'll manage
    // the buffer ourselves and let it grow until we see a full request
    // and response
    stream.auto_cleanup_payloads(false);
}

int main(int argc, char *argv[]) {
    // First fetch all network interfaces
    vector<NetworkInterface> interfaces = NetworkInterface::all();
    // Now iterate them
    int i = 0;
    for (const NetworkInterface &iface : interfaces) {
        // First print the name (GUID)
        cout << i++ << ' ' << "Interface name: " << termcolor::on_red << iface.name() <<
             termcolor::on_cyan << ' ' << iface.addresses().ip_addr << termcolor::reset;

        // Now print the friendly name, a wstring that will contain something like
        // "Local Area Connection 2"
        wcout << " (" << iface.friendly_name() << ")" << endl;
    }

    try {
        // Construct the sniffer configuration object
        SnifferConfiguration config;
        // Only capture TCP traffic sent from/to port 80
        config.set_filter("tcp port 8080");
        // Construct the sniffer we'll use
        Sniffer sniffer(interfaces[1].name(), config);

        std::wstring w = interfaces[1].friendly_name();
        string s(w.begin(), w.end());

        cout << on_green << "Starting capture on interface " << s << reset << endl;

        // Now construct the stream follower
        StreamFollower follower;
//        follower.follow_streams(sniffer,)
        // We just need to specify the callback to be executed when a new
        // stream is captured. In this stream, you should define which callbacks
        // will be executed whenever new data is sent on that stream
        // (see on_new_connection)
        follower.new_stream_callback(&on_new_connection);
        // Now start capturing. Every time there's a new packet, call
        // follower.process_packet
        sniffer.sniff_loop([&](Packet &packet) {
            follower.process_packet(packet);
            return true;
        });
    }
    catch (exception &ex) {
        cerr << "Error: " << ex.what() << endl;
        return 1;
    }
}

How can I accomplish this ?!

Aucun commentaire:

Enregistrer un commentaire