How to Gracefully Capture HTTPS Traffic on Android

Follow us on WeChat public account 「Wonderful Linux World
Set as 「Starred」, bringing you daily Linux fun!
How to Gracefully Capture HTTPS Traffic on Android

Introduction

Is it becoming increasingly difficult to capture HTTPS traffic on the Android system? In high versions, you cannot add CA certificates, and packet capture software relies too much on VPN modes or HOOK programs, which can be detected by the app. The cost of countermeasures is rising. Is there a universal tool?

Yes, eCapture for Android[1] is here. From now on, capturing HTTPS communication packets on Android no longer requires installing CA certificates, downloading a bunch of Python dependencies, repackaging SSL libraries, or changing many phone parameters. One-click activation, simple and clear.

eCapture Overview

eCapture is software that can capture HTTPS plaintext without CA certificates. It supports pcapng format, and can be viewed directly with Wireshark. Based on eBPF technology, it only requires root privileges to capture packets with one click. eCapture’s Chinese name is ‘Observer’, meaning that the observer has a clearer perspective than the person involved.

In early 2022, during the Shanghai pandemic, the author began to write and open-source[2] it. After half a year, it has already received 4200 stars on GitHub.

eCapture is a packet capture software based on eBPF technology, depending on whether the system kernel supports eBPF. Currently, it supports operating systems with Linux kernel versions above 4.18 for X86_64 and ARM64, and Android (Linux) kernel versions above 5.4. The latest version, v0.4.3, was released on September 9, 2022.

How to Gracefully Capture HTTPS Traffic on Android

Demo Video

After downloading, start with one command, clean and efficient. ./ecapture tls -w ecapture.pcapng

First, watch the demo video, the demo environment is Ubuntu 21.04, Android 5.4 (Pixel 6).

The following video is from Sunmao Jianghu

Module Functions

eCapture supports information extraction and capture for modules like tls, bash, mysqld, postgres, etc. This article only discusses the tls module for capturing HTTPS/TLS plaintext.

Plaintext Capture of Encrypted Communication — tls Module

The tls module supports various libraries such as openssl, gnutls, nspr/nss, and boringssl for encrypted communication. However, on Android, pcapng mode only supports boringssl, while text mode supports all.

How to Use eCapture

Environment Dependencies

  1. Operating system Linux kernel 4.18 or later, Android kernel 5.4 or later.
  2. Support BPF, optional support for BTF (varies by eCapture version)
  3. Root privileges

Version Selection

BPF CO-RE[3] feature is a universal format for BTF, used for cross-kernel version compatibility. Some Android phones do not enable BTF. You can check the system configuration to confirm; CONFIG_DEBUG_INFO_BTF=y means enabled; CONFIG_DEBUG_INFO_BTF=n means disabled; others do not support BPF and cannot use eCapture.

cfc4n@vm-server:~$# cat /boot/config-`uname -r` | grep CONFIG_DEBUG_INFO_BTF
CONFIG_DEBUG_INFO_BTF=y

On Android, the config is gzip compressed, and the configuration file directory has changed. You can use the zcat /proc/config.gz command instead.

eCapture is released with an ELF program that supports CO-RE by default. The Android version will release a version that does not support BTF (i.e., without CO-RE) for kernel 5.4. After downloading, you can confirm with ./ecapture -v. The version information for non-CO-RE versions includes the kernel version at compile time.

# no CO-RE
eCapture version:  linux_aarch64:0.4.2-20220906-fb34467:5.4.0-104-generic
# CO-RE
eCapture version:  linux_aarch64:0.4.2-20220906-fb34467:[CORE]

If the version does not meet your needs, you can compile it yourself; see the end of this article for steps.

Global Parameters Introduction

Focus on the following global parameters

root@vm-server:/home/cfc4n/# ecapture -h
      --hex[=false]  print byte strings as hex encoded strings
  -l, --log-file=""  -l save the packets to file
  -p, --pid=0   if pid is 0 then we target all pids
  -u, --uid=0   if uid is 0 then we target all users
  1. --hex is used for stdout output scenarios, displaying results in hexadecimal, which is particularly necessary for viewing non-ASCII characters in encrypted and encoded content.
  2. -l, --log-file= saves the result to a file path.
  3. -p, --pid=0 targets the process to capture; default is 0, capturing all processes.
  4. -u, --uid=0 targets the user to capture; default is 0, capturing all users, which is very needed for Android.

Module Parameters

root@vm-server:/home/cfc4n/project/ssldump# bin/ecapture tls -h
OPTIONS:
      --curl=""  curl or wget file path, use to detect openssl.so path, default:/usr/bin/curl
      --firefox="" firefox file path, default: /usr/lib/firefox/firefox.
      --gnutls="" libgnutls.so file path, will automatically find it from curl default.
      --gobin="" path to binary built with Go toolchain.
  -h, --help[=false] help for tls
  -i, --ifname="" (TC Classifier) Interface name on which the probe will be attached.
      --libssl="" libssl.so file path, will automatically find it from curl default.
      --nspr=""  libnspr44.so file path, will automatically find it from curl default.
      --port=443 port number to capture, default:443.
      --pthread="" libpthread.so file path, use to hook connect to capture socket FD.will automatically find it from curl.
      --wget=""  wget file path, default: /usr/bin/wget.
  -w, --write="" write the raw packets to file as pcapng format.

-i Parameter

The -i parameter is the name of the network card; on Linux, it defaults to eth0, and on Android, it defaults to wlan0. You can specify it with this parameter.

Output Modes

Output format supports two formats: text and pcapng file. There are three parameters:

  1. Default, global parameters, outputs text results to stdout.
  2. -l global parameter, saves text results to a file path.
  3. -w only tls module parameter, saves pcapng results to a file path.

Library Paths

Linux supports various libraries, and the paths for different libraries vary.

Library Parameter Path Default Value
openssl/boringssl –libssl Linux automatically finds it, Android is /apex/com.android.conscrypt/lib64/libssl.so
gnutls –gnutls Linux automatically finds it, Android pcapng mode not yet supported
nspr/nss –nspr Linux automatically finds it, Android pcapng mode not yet supported

Text Mode

-l or no -w parameter will enable this mode.

Supports various TLS encryption libraries such as openssl, boringssl, gnutls, nspr/nss. Supports all versions of encryption protocols from DTLS, TLS 1.0 to TLS 1.3. Supports all global filtering parameters like -p, -u.

Pcapng Mode

The -w parameter enables this mode, and you can select the network card name with -i; on Linux, it defaults to eth0, and on Android, it defaults to wlan0.

Only supports data capture from openssl and boringssl libraries. TLS 1.3 protocol is currently not supported.

How to Gracefully Capture HTTPS Traffic on Android

Library and Parameter Support

On Linux systems, most libraries and parameters are supported. However, on Android systems, due to kernel and ARM architecture, there are certain differences in supported parameters.

Parameter Support for Different Modes

Both -p and -u global parameters support text mode but do not support pcapng mode. This is because pcapng mode is implemented using eBPF TC technology.

Mode -p -u –libssl –port
Text
Pcapng

Library Support by Protocol for Different Modes

Mode openssl (Library) boringssl (Library) TLS 1.0/1.1/1.2 (Protocol) TLS 1.3 (Protocol)
Text
Pcapng

Pcapng mode currently does not support TLS 1.3, TLS 1.3 key capture functionality[4] has been developed but is encountering some bugs that are still being resolved. The author is not an expert in openssl and is not very familiar with the TLS protocol. It is necessary to supplement knowledge in these two areas, which increases the cost of resolution. Friends who are proficient in this area are welcome to collaborate.

Using with tcpdump

eCapture is based on eBPF TC, which captures traffic and saves it to pcapng files. It uses eBPF Uprobe to capture the TLS Master Secret. Based on Wireshark’s Decryption Secrets Block (DSB)[5] standard, it implements the gopacket’s DSB function[6], merging network packets with keys and saving them to pcapng.

eCapture is not as powerful as tcpdump in network packet capture and does not support rich parameters. You can use eCapture to capture master secrets, use tcpdump to capture network packets, and then use Wireshark to customize the key file settings for combined use.

Network Packet Capture

The regular usage of tcpdump will not be repeated here.

Key Capture

When enabling ecapture, either text or pcapng mode can be selected, and both will save the TLS master secrets key data to ecapture_masterkey.log.

Network Packet Viewing

Open the network packet file with Wireshark, set this master key file, and then you can see the decrypted plaintext of TLS.

Configuration path: Wireshark –> Preferences –> Protocols –> TLS –> (Pre)-Master-Secret log filenameHow to Gracefully Capture HTTPS Traffic on Android

Parameters

Specify Path

Default Path

On Android, Google uses the boringssl library, which is a C++ language wrapper based on libssl. By default, it will use the path /apex/com.android.conscrypt/lib64/libssl.so.

APP Library Confirmation

You can use lsof -p {APP PID}|grep libssl to confirm. If it is not the default path, you can specify it using the --libssl parameter.

Advanced Usage

If the APP you need to view uses a custom SSL library, you can modify eCapture yourself to achieve this.

Custom Function Names and Offsets

First, you need to determine the function name or symbol table address of the HOOK function.

No Source Code

If you do not have the source code of the target library, you can determine the SSL Write address offset through static analysis and dynamic debugging with software like IDA. Fill in the configuration in the user/module/probe_openssl.go file, corresponding to the probe configuration section.

{
    Section:          "uprobe/SSL_write",
    EbpfFuncName:     "probe_entry_SSL_write",
    AttachToFuncName: "SSL_write",
    UprobeOffset:       0xFFFF00, // TODO
    BinaryPath:       binaryPath,
},

Automatic Offset Calculation

If you have the source code, you can read the source code to determine the function name or symbol table address. For reading member properties of a structure, you can use the offsetof macro to automatically calculate. Read the content through offsets.

//  g++ -I include/ -I src/ ./src/offset.c -o off
#include <stdio.h>
#include <stddef.h>
#include <ssl/internal.h>
#include <openssl/base.h>
#include <openssl/crypto.h>

#define SSL_STRUCT_OFFSETS               \
    X(ssl_st, session)              \
    X(ssl_st, s3)              \
    X(ssl_session_st, secret)        \
    X(ssl_session_st, secret_length)  \
    X(bssl::SSL3_STATE, client_random) \
    X(bssl::SSL_HANDSHAKE, new_session) \
    X(bssl::SSL_HANDSHAKE, early_session) \
    X(bssl::SSL3_STATE, hs) \
    X(bssl::SSL3_STATE, established_session) \
    X(bssl::SSL_HANDSHAKE, expected_client_finished_)    

struct offset_test
{
    /* data */
    int t1;
    bssl::UniquePtr<SSL_SESSION> session;
};

int main() {
    printf("typedef struct ssl_offsets { // DEF \n");
#define X(struct_name, field_name) \
    printf("   int " #struct_name "_

Leave a Comment

×