Ask Your Question

Revision history [back]

Unable to trace HTTP2 stream when decrypting tls in tls traffic

target:

Hi, everyone. I'm trying to decrypt Trojan traffic using wireshark, Trojan's encryption is two layers of TLS,i.e. TLS in TLS

trouble:

Unable to trace HTTP2 stream Here is an example of a traffic package for accessing Google using Trojan proxy. Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 0 image-1

Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 1is empty, but according to the parse tree in the figure below, it can parse normal traffic. Does this indicate that the decryption was normal, but the stream information was lost? image-2

code implementation

general idea: image-3

The following is the key implementation process, ignoring some code. For detailed implementation, please refer to https://github.com/SIGPET-SEU/Wireshark-CPlugin/tree/main/trojan

  1. proto_register_trojan()
    void proto_register_trojan(void)
    {
            proto_trojan = proto_register_protocol(
                "Trojan Protocol", /* name        */
                "Trojan",          /* short_name  */
                "trojan"           /* filter_name */
            );
            trojan_handle = register_dissector("trojan", dissect_trojan, proto_trojan);
    }
  1. proto_reg_handoff_trojan() Disconnect the first layer of tls from HTTP2, so that wireshark can call the trojan dissector after the first layer of tls is decrypted. (dissector_add_string("tls.alpn", "h2", trojan_handle))
void proto_reg_handoff_trojan(void)
{
    dissector_add_uint("tls.port", TROJAN_TLS_PORT, trojan_handle);

    // Disconnect the first layer of tls from HTTP2, so that wireshark can call the trojan dissector after the first layer of tls is decrypted
    dissector_add_string("tls.alpn", "h2", trojan_handle); 

    heur_dissector_add("tls", dissect_trojan_heur_tls, "Trojan Over Tls", "trojan_over_tls", proto_trojan, HEURISTIC_ENABLE);
}
  1. dissect_trojan() The following code first checks whether the TLS packet header matches the content of the current TVB. If it matches, then the current content is TLS content and a second TLS decryption is performed.
  2. Before call_tls_ handle, because the two tls decryption keys are different, a new tls session needs to be created to force Wireshark to use the new key. Wireshark uses quintuples (src_ip, src_port, dst_ip, dst_port, pinfo ->ptype) internally to find previous session information, so the port type is forcibly changed here to force Wireshark to establish a new session. (pinfo->ptype = PT_NONE)
  3. Another important thing is that we cut off the connection between TLS and HTTP2 when registering the Trojan protocol, so Wireshark will enter Trojan dissector instead of HTTP2 after decrypting the first layer TLS. But after decrypting the second layer TLS, HTTP2 is still needed for parsing, so we will reconstruct the connection here. (dissector_add_string("tls.alpn", "h2", h2_handle))
  4. The tls code implements a data reassembly mechanism, so we do not consider data reassembly here
bool is_trojan_response(tvbuff_t* tvb) {
    // Match the information of tls header
    return tvb_find_TLS_signature(tvb) == 0 ? true : false;
}
static int
dissect_trojan(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree _U_, void* data _U_) {
    if (is_trojan_response(tvb))
    {
        // save pinfo
        save_port_type = pinfo->ptype;
        save_can_desegment = pinfo->can_desegment;
        pinfo->ptype = PT_NONE;
        pinfo->can_desegment = pinfo->saved_can_desegment;

        col_set_str(pinfo->cinfo, COL_INFO, "Trojan Response");
        ti = proto_tree_add_item(tree, proto_trojan, tvb, 0, -1, ENC_NA);
        trojan_tree = proto_item_add_subtree(ti, ett_trojan);
        proto_tree_add_item(trojan_tree, hf_trojan_tunnel_data, tvb, 0, tvb_reported_length(tvb), ENC_BIG_ENDIAN);

        next_tvb = tvb_new_subset_remaining(tvb, 0);

        dissector_add_string("tls.alpn", "h2", h2_handle);

        ret = call_dissector_with_data(tls_handle, next_tvb, pinfo, tree, data);

        dissector_delete_string("tls.alpn", "h2", h2_handle);

        // restore information
        pinfo->ptype = save_port_type;
        pinfo->can_desegment = save_can_desegment;
    }

}

After performing the above operations, our trojan can decrypt http2 data normally, but some bugs have appeared: trouble: Unable to trace HTTP2 stream Here is an example of a traffic package for accessing Google using Trojan proxy. Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 0

Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 1is empty, but according to the parse tree in the figure below, it can parse normal traffic. Does this indicate that the decryption was normal, but the stream information was lost?

In the trojan dissector implementation code, in order to decrypt the second layer TLS, we forcibly changed the port type to generate a new session. This may have affected the judgment of HTTP2 stream, so we also attempted to modify the code of packet-http2. c to restore the port type to normal before parsing http2. (The above operations are somewhat useful, but not all). What am I doing wrong? We provide open-source trojan traffic data and code implementation for your easy replication. Thank for your help!!!

Unable to trace HTTP2 stream when decrypting tls in tls traffic

Because this is my first time using the Ask system, I don't know why images cannot be uploaded. I have uploaded this document here, you can choose to read it here

target:

Hi, everyone. I'm trying to decrypt Trojan traffic using wireshark, Trojan's encryption is two layers of TLS,i.e. TLS in TLSTLS.

trouble:

Unable to trace HTTP2 stream Here is an example of a traffic package for accessing Google using Trojan proxy. Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 0 image-1

Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 1is empty, but according to the parse tree in the figure below, it can parse normal traffic. Does this indicate that the decryption was normal, but the stream information was lost? image-2

code implementation

general idea: image-3

The following is the key implementation process, ignoring some code. For detailed implementation, please refer to https://github.com/SIGPET-SEU/Wireshark-CPlugin/tree/main/trojan

  1. proto_register_trojan()
    void proto_register_trojan(void)
    {
            proto_trojan = proto_register_protocol(
                "Trojan Protocol", /* name        */
                "Trojan",          /* short_name  */
                "trojan"           /* filter_name */
            );
            trojan_handle = register_dissector("trojan", dissect_trojan, proto_trojan);
    }
  1. proto_reg_handoff_trojan() Disconnect the first layer of tls from HTTP2, so that wireshark can call the trojan dissector after the first layer of tls is decrypted. (dissector_add_string("tls.alpn", "h2", trojan_handle))
void proto_reg_handoff_trojan(void)
{
    dissector_add_uint("tls.port", TROJAN_TLS_PORT, trojan_handle);

    // Disconnect the first layer of tls from HTTP2, so that wireshark can call the trojan dissector after the first layer of tls is decrypted
    dissector_add_string("tls.alpn", "h2", trojan_handle); 

    heur_dissector_add("tls", dissect_trojan_heur_tls, "Trojan Over Tls", "trojan_over_tls", proto_trojan, HEURISTIC_ENABLE);
}
  1. dissect_trojan() The following code first checks whether the TLS packet header matches the content of the current TVB. If it matches, then the current content is TLS content and a second TLS decryption is performed.
  2. Before call_tls_ handle, because the two tls decryption keys are different, a new tls session needs to be created to force Wireshark to use the new key. Wireshark uses quintuples (src_ip, src_port, dst_ip, dst_port, pinfo ->ptype) internally to find previous session information, so the port type is forcibly changed here to force Wireshark to establish a new session. (pinfo->ptype = PT_NONE)
  3. Another important thing is that we cut off the connection between TLS and HTTP2 when registering the Trojan protocol, so Wireshark will enter Trojan dissector instead of HTTP2 after decrypting the first layer TLS. But after decrypting the second layer TLS, HTTP2 is still needed for parsing, so we will reconstruct the connection here. (dissector_add_string("tls.alpn", "h2", h2_handle))
  4. The tls code implements a data reassembly mechanism, so we do not consider data reassembly here
bool is_trojan_response(tvbuff_t* tvb) {
    // Match the information of tls header
    return tvb_find_TLS_signature(tvb) == 0 ? true : false;
}
static int
dissect_trojan(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree _U_, void* data _U_) {
    if (is_trojan_response(tvb))
    {
        // save pinfo
        save_port_type = pinfo->ptype;
        save_can_desegment = pinfo->can_desegment;
        pinfo->ptype = PT_NONE;
        pinfo->can_desegment = pinfo->saved_can_desegment;

        col_set_str(pinfo->cinfo, COL_INFO, "Trojan Response");
        ti = proto_tree_add_item(tree, proto_trojan, tvb, 0, -1, ENC_NA);
        trojan_tree = proto_item_add_subtree(ti, ett_trojan);
        proto_tree_add_item(trojan_tree, hf_trojan_tunnel_data, tvb, 0, tvb_reported_length(tvb), ENC_BIG_ENDIAN);

        next_tvb = tvb_new_subset_remaining(tvb, 0);

        dissector_add_string("tls.alpn", "h2", h2_handle);

        ret = call_dissector_with_data(tls_handle, next_tvb, pinfo, tree, data);

        dissector_delete_string("tls.alpn", "h2", h2_handle);

        // restore information
        pinfo->ptype = save_port_type;
        pinfo->can_desegment = save_can_desegment;
    }

}

After performing the above operations, our trojan can decrypt http2 data normally, but some bugs have appeared: trouble: Unable to trace HTTP2 stream Here is an example of a traffic package for accessing Google using Trojan proxy. Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 0

Attempt to track the following stream:tcp.stream eq 31 and http2.streamid eq 1is empty, but according to the parse tree in the figure below, it can parse normal traffic. Does this indicate that the decryption was normal, but the stream information was lost?

In the trojan dissector implementation code, in order to decrypt the second layer TLS, we forcibly changed the port type to generate a new session. This may have affected the judgment of HTTP2 stream, so we also attempted to modify the code of packet-http2. c to restore the port type to normal before parsing http2. (The above operations are somewhat useful, but not all). What am I doing wrong? We provide open-source trojan traffic data and code implementation for your easy replication. Thank for your help!!!