Skip to content

Commit

Permalink
kern: support openssl 3.2.x , change ssl_st to ssl_connection_st, upd…
Browse files Browse the repository at this point in the history
…ate more OFFSETS.

Signed-off-by: CFC4N <cfc4n.cs@gmail.com>
  • Loading branch information
cfc4n committed Jan 27, 2024
1 parent ff9b71c commit 1362476
Show file tree
Hide file tree
Showing 5 changed files with 510 additions and 1 deletion.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ AUTOGENCMD ?=
TAG_COMMIT := $(shell git rev-list --abbrev-commit --tags --max-count=1)
TAG := $(shell git describe --abbrev=0 --tags ${TAG_COMMIT} 2>/dev/null || true)
COMMIT := $(shell git rev-parse --short HEAD)
DATE := $(shell git log -1 --format=%cd --date=format:"%Y%m%d")
#DATE := $(shell git log -1 --format=%cd --date=format:"%Y%m%d")
DATE := $(shell date +"%Y%m%d")
LAST_GIT_TAG := $(TAG:v%=%)-$(DATE)-$(COMMIT)
RPM_RELEASE := $(DATE).$(COMMIT)
#ifneq ($(COMMIT), $(TAG_COMMIT))
Expand Down Expand Up @@ -203,6 +204,7 @@ TARGETS += kern/openssl_1_1_1j
TARGETS += kern/openssl_1_1_0a
TARGETS += kern/openssl_1_0_2a
TARGETS += kern/openssl_3_0_0
TARGETS += kern/openssl_3_2_0
TARGETS += kern/gotls

ifeq ($(ANDROID),0)
Expand Down
71 changes: 71 additions & 0 deletions kern/openssl_3_2_0_kern.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#ifndef ECAPTURE_OPENSSL_3_2_0_KERN_H
#define ECAPTURE_OPENSSL_3_2_0_KERN_H

/* OPENSSL_VERSION_TEXT: OpenSSL 3.2.0 23 Nov 2023 */
/* OPENSSL_VERSION_NUMBER: 807403520 */

// ssl_st->type
#define SSL_ST_TYPE 0x0

// ssl_connection_st->version
#define SSL_CONNECTION_ST_VERSION 0x40

// ssl_connection_st->session
#define SSL_CONNECTION_ST_SESSION 0x880

// ssl_connection_st->s3
#define SSL_CONNECTION_ST_S3 0x118

// ssl_connection_st->rbio
#define SSL_CONNECTION_ST_RBIO 0x48

// ssl_connection_st->wbio
#define SSL_CONNECTION_ST_WBIO 0x50

// ssl_session_st->master_key
#define SSL_SESSION_ST_MASTER_KEY 0x50

// ssl_connection_st->s3.client_random
#define SSL_CONNECTION_ST_S3_CLIENT_RANDOM 0x140

// ssl_session_st->cipher
#define SSL_SESSION_ST_CIPHER 0x300

// ssl_session_st->cipher_id
#define SSL_SESSION_ST_CIPHER_ID 0x308

// ssl_cipher_st->id
#define SSL_CIPHER_ST_ID 0x18

// ssl_connection_st->handshake_secret
#define SSL_CONNECTION_ST_HANDSHAKE_SECRET 0x53c

// ssl_connection_st->handshake_traffic_hash
#define SSL_CONNECTION_ST_HANDSHAKE_TRAFFIC_HASH 0x6bc

// ssl_connection_st->client_app_traffic_secret
#define SSL_CONNECTION_ST_CLIENT_APP_TRAFFIC_SECRET 0x6fc

// ssl_connection_st->server_app_traffic_secret
#define SSL_CONNECTION_ST_SERVER_APP_TRAFFIC_SECRET 0x73c

// ssl_connection_st->exporter_master_secret
#define SSL_CONNECTION_ST_EXPORTER_MASTER_SECRET 0x77c

// bio_st->num
#define BIO_ST_NUM 0x38

// quic_conn_st->tls
#define QUIC_CONN_ST_TLS 0x40

#define SSL_ST_VERSION SSL_CONNECTION_ST_VERSION

#define SSL_ST_WBIO SSL_CONNECTION_ST_WBIO

#define SSL_ST_RBIO SSL_CONNECTION_ST_RBIO


#include "openssl.h"
#include "openssl_masterkey_3.2.h"

#endif
297 changes: 297 additions & 0 deletions kern/openssl_masterkey_3.2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
// Copyright 2022 CFC4N <cfc4n.cs@gmail.com>. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "ecapture.h"

// https://wiki.openssl.org/index.php/TLS1.3
// 仅openssl 1.1.1 后才支持 TLS 1.3 协议

// openssl 1.1.1.X 版本相关的常量
#define SSL3_RANDOM_SIZE 32
#define MASTER_SECRET_MAX_LEN 48
#define EVP_MAX_MD_SIZE 64

struct mastersecret_t {
// TLS 1.2 or older
s32 version;
u8 client_random[SSL3_RANDOM_SIZE];
u8 master_key[MASTER_SECRET_MAX_LEN];

// TLS 1.3
u32 cipher_id;
u8 handshake_secret[EVP_MAX_MD_SIZE];
u8 handshake_traffic_hash[EVP_MAX_MD_SIZE];
u8 client_app_traffic_secret[EVP_MAX_MD_SIZE];
u8 server_app_traffic_secret[EVP_MAX_MD_SIZE];
u8 exporter_master_secret[EVP_MAX_MD_SIZE];
};

#define TLS1_1_VERSION 0x0302
#define TLS1_2_VERSION 0x0303
#define TLS1_3_VERSION 0x0304

#define SSL_TYPE_SSL_CONNECTION 0
#define SSL_TYPE_QUIC_CONNECTION 1
#define SSL_TYPE_QUIC_XSO 2

/////////////////////////BPF MAPS ////////////////////////////////

// bpf map
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
__uint(max_entries, 1024);
} mastersecret_events SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, u64);
__type(value, struct mastersecret_t);
__uint(max_entries, 2048);
} bpf_context SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, struct mastersecret_t);
__uint(max_entries, 1);
} bpf_context_gen SEC(".maps");

/////////////////////////COMMON FUNCTIONS ////////////////////////////////
// 这个函数用来规避512字节栈空间限制,通过在堆上创建内存的方式,避开限制
static __always_inline struct mastersecret_t *make_event() {
u32 key_gen = 0;
struct mastersecret_t *bpf_ctx =
bpf_map_lookup_elem(&bpf_context_gen, &key_gen);
if (!bpf_ctx) return 0;
u64 id = bpf_get_current_pid_tgid();
bpf_map_update_elem(&bpf_context, &id, bpf_ctx, BPF_ANY);
return bpf_map_lookup_elem(&bpf_context, &id);
}

/////////////////////////BPF FUNCTIONS ////////////////////////////////
SEC("uprobe/SSL_write_key")
int probe_ssl_master_key(struct pt_regs *ctx) {
u64 current_pid_tgid = bpf_get_current_pid_tgid();
u32 pid = current_pid_tgid >> 32;
u64 current_uid_gid = bpf_get_current_uid_gid();
u32 uid = current_uid_gid;

#ifndef KERNEL_LESS_5_2
// if target_ppid is 0 then we target all pids
if (target_pid != 0 && target_pid != pid) {
return 0;
}
if (target_uid != 0 && target_uid != uid) {
return 0;
}
#endif
debug_bpf_printk("openssl uprobe/SSL_write masterKey PID :%d\n", pid);

// mastersecret_t sent to userspace
struct mastersecret_t *mastersecret = make_event();
// Get a ssl_st pointer
void *ssl_st_ptr = (void *)PT_REGS_PARM1(ctx);
if (!mastersecret) {
debug_bpf_printk("mastersecret is null\n");
return 0;
}
// TODO 检查 ssl->type, 参考 ssl/ssl_local.h的 SSL_CONNECTION_FROM_SSL_int 宏
int type;
if (type == SSL_TYPE_QUIC_CONNECTION) {
// 重新获取 ssl->tls 的地址作为 SSL_CONNECTION的地址
// Reget the address of the ssl->tls as the address of the SSL_CONNECTION
// ssl_st_ptr =
}

// Get SSL->version pointer
u64 *ssl_version_ptr = (u64 *)(ssl_st_ptr + SSL_CONNECTION_ST_VERSION);
int version;
u64 address;
int ret =
bpf_probe_read_user(&version, sizeof(version), (void *)ssl_version_ptr);
if (ret) {
debug_bpf_printk("bpf_probe_read tls_version failed, ret :%d\n", ret);
return 0;
}
mastersecret->version = version; // int version;
debug_bpf_printk("TLS version :%d\n", mastersecret->version);

u64 *ssl_client_random_ptr = (u64 *)(ssl_st_ptr + SSL_CONNECTION_ST_S3_CLIENT_RANDOM);
// get SSL_CONNECTION_ST_S3_CLIENT_RANDOM
unsigned char client_random[SSL3_RANDOM_SIZE];
ret = bpf_probe_read_user(&client_random, sizeof(client_random),
(void *)ssl_client_random_ptr);
if (ret) {
debug_bpf_printk(
"bpf_probe_read ssl3_ssl_client_random_ptr_st failed, ret :%d\n",
ret);
return 0;
}
debug_bpf_printk("client_random: %x %x %x\n", client_random[0],
client_random[1], client_random[2]);
ret = bpf_probe_read_kernel(&mastersecret->client_random,
sizeof(mastersecret->client_random),
(void *)&client_random);
if (ret) {
debug_bpf_printk(
"bpf_probe_read_kernel ssl3_stat.client_random failed, ret :%d\n",
ret);
return 0;
}

// Get ssl_session_st pointer
u64 *ssl_session_st_ptr;
u64 ssl_session_st_addr;

ssl_session_st_ptr = (u64 *)(ssl_st_ptr + SSL_CONNECTION_ST_SESSION);
ret = bpf_probe_read_user(&ssl_session_st_addr, sizeof(ssl_session_st_addr),
ssl_session_st_ptr);
if (ret) {
debug_bpf_printk(
"(OPENSSL) bpf_probe_read ssl_session_st_ptr failed, ret :%d\n",
ret);
return 0;
}

///////////////////////// get TLS 1.2 master secret ////////////////////
if (mastersecret->version != TLS1_3_VERSION) {
void *ms_ptr =
(void *)(ssl_session_st_addr + SSL_SESSION_ST_MASTER_KEY);
ret = bpf_probe_read_user(&mastersecret->master_key,
sizeof(mastersecret->master_key), ms_ptr);
if (ret) {
debug_bpf_printk(
"bpf_probe_read MASTER_KEY_OFFSET failed, ms_ptr:%llx, ret "
":%d\n",
ms_ptr, ret);
return 0;
}

debug_bpf_printk("master_key: %x %x %x\n", mastersecret->master_key[0],
mastersecret->master_key[1],
mastersecret->master_key[2]);

bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU,
mastersecret, sizeof(struct mastersecret_t));
return 0;
}

///////////////////////// get TLS 1.3 master secret ////////////////////
// Get SSL_SESSION->cipher pointer
u64 *ssl_cipher_st_ptr =
(u64 *)(ssl_session_st_addr + SSL_SESSION_ST_CIPHER);

// get cipher_suite_st pointer
debug_bpf_printk("cipher_suite_st pointer: %x\n", ssl_cipher_st_ptr);
ret = bpf_probe_read_user(&address, sizeof(address), ssl_cipher_st_ptr);
if (ret || address == 0) {
debug_bpf_printk(
"bpf_probe_read ssl_cipher_st_ptr failed, ret :%d, address:%x\n",
ret, address);
// return 0;
void *cipher_id_ptr =
(void *)(ssl_session_st_addr + SSL_SESSION_ST_CIPHER_ID);
ret =
bpf_probe_read_user(&mastersecret->cipher_id,
sizeof(mastersecret->cipher_id), cipher_id_ptr);
if (ret) {
debug_bpf_printk(
"bpf_probe_read SSL_SESSION_ST_CIPHER_ID failed from "
"SSL_SESSION->cipher_id, ret :%d\n",
ret);
return 0;
}
} else {
debug_bpf_printk("cipher_suite_st value: %x\n", address);
void *cipher_id_ptr = (void *)(address + SSL_CIPHER_ST_ID);
ret =
bpf_probe_read_user(&mastersecret->cipher_id,
sizeof(mastersecret->cipher_id), cipher_id_ptr);
if (ret) {
debug_bpf_printk(
"bpf_probe_read SSL_CIPHER_ST_ID failed from "
"ssl_cipher_st->id, ret :%d\n",
ret);
return 0;
}
}

debug_bpf_printk("cipher_id: %d\n", mastersecret->cipher_id);

//////////////////// TLS 1.3 master secret ////////////////////////

void *hs_ptr_tls13 = (void *)(ssl_st_ptr + SSL_CONNECTION_ST_HANDSHAKE_SECRET);
ret = bpf_probe_read_user(&mastersecret->handshake_secret,
sizeof(mastersecret->handshake_secret),
(void *)hs_ptr_tls13);
if (ret) {
debug_bpf_printk(
"bpf_probe_read SSL_CONNECTION_ST_HANDSHAKE_SECRET failed, ret :%d\n", ret);
return 0;
}

void *hth_ptr_tls13 = (void *)(ssl_st_ptr + SSL_CONNECTION_ST_HANDSHAKE_TRAFFIC_HASH);
ret = bpf_probe_read_user(&mastersecret->handshake_traffic_hash,
sizeof(mastersecret->handshake_traffic_hash),
(void *)hth_ptr_tls13);
if (ret) {
debug_bpf_printk(
"bpf_probe_read SSL_CONNECTION_ST_HANDSHAKE_TRAFFIC_HASH failed, ret :%d\n",
ret);
return 0;
}

void *cats_ptr_tls13 =
(void *)(ssl_st_ptr + SSL_CONNECTION_ST_CLIENT_APP_TRAFFIC_SECRET);
ret = bpf_probe_read_user(&mastersecret->client_app_traffic_secret,
sizeof(mastersecret->client_app_traffic_secret),
(void *)cats_ptr_tls13);
if (ret) {
debug_bpf_printk(
"bpf_probe_read SSL_CONNECTION_ST_CLIENT_APP_TRAFFIC_SECRET failed, ret :%d\n",
ret);
return 0;
}

void *sats_ptr_tls13 =
(void *)(ssl_st_ptr + SSL_CONNECTION_ST_SERVER_APP_TRAFFIC_SECRET);
ret = bpf_probe_read_user(&mastersecret->server_app_traffic_secret,
sizeof(mastersecret->server_app_traffic_secret),
(void *)sats_ptr_tls13);
if (ret) {
debug_bpf_printk(
"bpf_probe_read SSL_CONNECTION_ST_SERVER_APP_TRAFFIC_SECRET failed, ret :%d\n",
ret);
return 0;
}

void *ems_ptr_tls13 = (void *)(ssl_st_ptr + SSL_CONNECTION_ST_EXPORTER_MASTER_SECRET);
ret = bpf_probe_read_user(&mastersecret->exporter_master_secret,
sizeof(mastersecret->exporter_master_secret),
(void *)ems_ptr_tls13);
if (ret) {
debug_bpf_printk(
"bpf_probe_read SSL_CONNECTION_ST_EXPORTER_MASTER_SECRET failed, ret :%d\n",
ret);
return 0;
}
debug_bpf_printk("*****master_secret*****: %x %x %x\n",
mastersecret->master_key[0], mastersecret->master_key[1],
mastersecret->master_key[2]);
bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU,
mastersecret, sizeof(struct mastersecret_t));
return 0;
}
Loading

0 comments on commit 1362476

Please sign in to comment.