Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Gotls master secrets module. #329

Merged
merged 8 commits into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions kern/boringssl_masterkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ static __always_inline struct mastersecret_bssl_t *make_event() {

// in boringssl, the master secret is stored in src/ssl/handshake.cc 581
// const SSL_SESSION *ssl_handshake_session(const SSL_HANDSHAKE *hs) {
static __always_inline u64 get_session_addr(void *ssl_st_ptr, u64 s3_address, u64 ssl_hs_st_ptr) {
static __always_inline u64 get_session_addr(void *ssl_st_ptr, u64 s3_address,
u64 ssl_hs_st_ptr) {
u64 tmp_address;
int ret;

Expand Down Expand Up @@ -220,7 +221,8 @@ int probe_ssl_master_key(struct pt_regs *ctx) {
ret = bpf_probe_read_user(&ssl_hs_st_addr, sizeof(ssl_hs_st_addr),
ssl_hs_st_ptr);
if (ret || ssl_hs_st_addr == 0) {
// debug_bpf_printk("bpf_probe_read ssl_hs_st_ptr failed, ret :%d\n", ret);
// debug_bpf_printk("bpf_probe_read ssl_hs_st_ptr failed, ret
// :%d\n", ret);
return 0;
}

Expand All @@ -241,7 +243,7 @@ int probe_ssl_master_key(struct pt_regs *ctx) {
(u64 *)(ssl_hs_st_addr + BSSL__SSL_HANDSHAKE_CLIENT_VERSION);
ret = bpf_probe_read_user(&client_version, sizeof(client_version),
ssl_hs_cv_ptr);
// if (ret || client_version == 0) {
// if (ret || client_version == 0) {
if (ret) {
debug_bpf_printk(
"bpf_probe_read ssl_hs_st_ptr failed, ret :%d, client_version:%d\n",
Expand All @@ -261,15 +263,17 @@ int probe_ssl_master_key(struct pt_regs *ctx) {

// ssl_client_hs_state_t::ssl3_hs_state=5
// tls13_server_hs_state_t::state13_read_second_client_flight
// if (ssl3_hs_state.state == 5 && ssl3_hs_state.tls13_state < 8) {
// return 0;
// }
// if (ssl3_hs_state.state == 5 && ssl3_hs_state.tls13_state < 8) {
// return 0;
// }
///////////// debug info /////////

debug_bpf_printk("client_version:%d, state:%d, tls13_state:%d\n", client_version, ssl3_hs_state.state,
debug_bpf_printk("client_version:%d, state:%d, tls13_state:%d\n",
client_version, ssl3_hs_state.state,
ssl3_hs_state.tls13_state);
// debug_bpf_printk("openssl uprobe/SSL_write masterKey PID :%d\n", pid);
debug_bpf_printk("TLS version :%d, hash_len:%d, \n", mastersecret->version, hash_len);
debug_bpf_printk("TLS version :%d, hash_len:%d, \n", mastersecret->version,
hash_len);
// 判断当前tls链接状态
// handshake->handshake_finalized = hs_st_addr + BSSL__SSL_HANDSHAKE_HINTS +
s32 all_bool;
Expand All @@ -289,15 +293,16 @@ int probe_ssl_master_key(struct pt_regs *ctx) {
if (mastersecret->version != TLS1_3_VERSION) {
// state12_finish_server_handshake
// state12_done
if (ssl3_hs_state.state < 20) {
if (ssl3_hs_state.state < 20) {
// not finished yet.
return 0;
}
// Get ssl_session_st pointer
u64 ssl_session_st_addr;
ssl_session_st_addr = get_session_addr(ssl_st_ptr, s3_address, ssl_hs_st_addr);
ssl_session_st_addr =
get_session_addr(ssl_st_ptr, s3_address, ssl_hs_st_addr);
if (ssl_session_st_addr == 0) {
// debug_bpf_printk("ssl_session_st_addr is null\n");
// debug_bpf_printk("ssl_session_st_addr is null\n");
return 0;
}
debug_bpf_printk("s3_address:%llx, ssl_session_st_addr addr :%llx\n",
Expand Down
4 changes: 2 additions & 2 deletions kern/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@
#define SA_DATA_LEN 14
#define BASH_ERRNO_DEFAULT 128

///////// for TC & XDP ebpf programs in openssl_tc.h
///////// for TC & XDP ebpf programs in tc.h
#define TC_ACT_OK 0
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define SKB_MAX_DATA_SIZE 2048

// .rodata section bug via : https://github.com/gojue/ecapture/issues/39
#ifndef KERNEL_LESS_5_2
// alawyse, we used it in openssl_tc.h
// alawyse, we used it in tc.h
const volatile u64 target_port = 443;

// Optional Target PID and UID
Expand Down
4 changes: 0 additions & 4 deletions kern/gotls.h → kern/go_argument.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
// false: newer
//volatile const bool is_register_abi;

// // TLS record types in golang tls package
#define recordTypeApplicationData 23


// golang register-based ABI via https://tip.golang.org/src/cmd/compile/abi-internal
#ifndef NOCORE

Expand Down
157 changes: 139 additions & 18 deletions kern/gotls_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@

/* Copyright © 2022 Hengqi Chen */
#include "ecapture.h"
#include "gotls.h"
#include "go_argument.h"
#include "tc.h"

#define GOTLS_RANDOM_SIZE 32

// max length is "CLIENT_HANDSHAKE_TRAFFIC_SECRET"=31
#define MASTER_SECRET_KEY_LEN 32
#define EVP_MAX_MD_SIZE 64

// // TLS record types in golang tls package
#define recordTypeApplicationData 23

struct go_tls_event {
u64 ts_ns;
Expand All @@ -25,6 +35,22 @@ struct go_tls_event {
char data[MAX_DATA_SIZE_OPENSSL];
};

struct mastersecret_gotls_t {
u8 label[MASTER_SECRET_KEY_LEN];
u8 labellen;
u8 client_random[EVP_MAX_MD_SIZE];
u8 client_random_len;
u8 secret_[EVP_MAX_MD_SIZE];
u8 secret_len;
};

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

// bpf map
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
} mastersecret_go_events SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
} events SEC(".maps");
Expand Down Expand Up @@ -57,13 +83,15 @@ static __always_inline struct go_tls_event *get_gotls_event() {
return bpf_map_lookup_elem(&gte_context, &id);
}

static __always_inline int gotls_text(struct pt_regs *ctx, bool is_register_abi) {
static __always_inline int gotls_text(struct pt_regs *ctx,
bool is_register_abi) {
s32 record_type, len;
const char *str;
void * record_type_ptr;
void * len_ptr;
void *record_type_ptr;
void *len_ptr;
record_type_ptr = (void *)go_get_argument(ctx, is_register_abi, 2);
bpf_probe_read_kernel(&record_type, sizeof(record_type), (void *)&record_type_ptr);
bpf_probe_read_kernel(&record_type, sizeof(record_type),
(void *)&record_type_ptr);
str = (void *)go_get_argument(ctx, is_register_abi, 3);
len_ptr = (void *)go_get_argument(ctx, is_register_abi, 4);
bpf_probe_read_kernel(&len, sizeof(len), (void *)&len_ptr);
Expand All @@ -79,7 +107,8 @@ static __always_inline int gotls_text(struct pt_regs *ctx, bool is_register_abi)
}

event->data_len = len;
int ret = bpf_probe_read_user(&event->data, sizeof(event->data), (void*)str);
int ret =
bpf_probe_read_user(&event->data, sizeof(event->data), (void *)str);
if (ret < 0) {
debug_bpf_printk(
"gotls_text bpf_probe_read_user_str failed, ret:%d, str:%d\n", ret,
Expand All @@ -91,18 +120,110 @@ static __always_inline int gotls_text(struct pt_regs *ctx, bool is_register_abi)
return 0;
}

// capture golang tls plaintext, supported golang stack-based ABI (go version >= 1.17)
// type recordType uint8
// writeRecordLocked(typ recordType, data []byte)
// capture golang tls plaintext, supported golang stack-based ABI (go version
// >= 1.17) type recordType uint8 writeRecordLocked(typ recordType, data []byte)
SEC("uprobe/gotls_text_register")
int gotls_text_register(struct pt_regs *ctx) {
return gotls_text(ctx, true);
}
int gotls_text_register(struct pt_regs *ctx) { return gotls_text(ctx, true); }

// capture golang tls plaintext, supported golang stack-based ABI (go version < 1.17)
// type recordType uint8
// writeRecordLocked(typ recordType, data []byte)
// capture golang tls plaintext, supported golang stack-based ABI (go version
// < 1.17) type recordType uint8 writeRecordLocked(typ recordType, data []byte)
SEC("uprobe/gotls_text_stack")
int gotls_text_stack(struct pt_regs *ctx) {
return gotls_text(ctx, false);
}
int gotls_text_stack(struct pt_regs *ctx) { return gotls_text(ctx, false); }

/*
* crypto/tls/common.go
* func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error
*/
static __always_inline int gotls_mastersecret(struct pt_regs *ctx,
bool is_register_abi) {
// const char *label, *clientrandom, *secret;
void *lab_ptr, *cr_ptr, *secret_ptr;
void *lab_len_ptr, *cr_len_ptr, *secret_len_ptr;
s32 lab_len, cr_len, secret_len;

/*
*
* in golang struct, slice header like this
* type slice struct {
* array unsafe.Pointer
* len int
* cap int
* }
* so, arument index are in the order one by one
*
*/
lab_ptr = (void *)go_get_argument(ctx, is_register_abi, 2);
lab_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 3);
cr_ptr = (void *)go_get_argument(ctx, is_register_abi, 4);
cr_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 5);
secret_ptr = (void *)go_get_argument(ctx, is_register_abi, 7);
secret_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 8);

bpf_probe_read_kernel(&lab_len, sizeof(lab_len), (void *)&lab_len_ptr);
bpf_probe_read_kernel(&cr_len, sizeof(lab_len), (void *)&cr_len_ptr);
bpf_probe_read_kernel(&secret_len, sizeof(lab_len),
(void *)&secret_len_ptr);

if (lab_len <= 0 || cr_len <= 0 || secret_len <= 0) {
return 0;
}

debug_bpf_printk(
"gotls_mastersecret read params length success, lab_len:%d, cr_len:%d, "
"secret_len:%d\n",
lab_len, cr_len, secret_len);

struct mastersecret_gotls_t mastersecret_gotls = {};
mastersecret_gotls.labellen = lab_len;
mastersecret_gotls.client_random_len = cr_len;
mastersecret_gotls.secret_len = secret_len;
int ret = bpf_probe_read_user_str(&mastersecret_gotls.label,
sizeof(mastersecret_gotls.label),
(void *)lab_ptr);
if (ret < 0) {
debug_bpf_printk(
"gotls_mastersecret read mastersecret label failed, ret:%d, "
"lab_ptr:%p\n",
ret, lab_ptr);
return 0;
}

debug_bpf_printk("gotls_mastersecret read mastersecret label%s\n",
mastersecret_gotls.label);
ret = bpf_probe_read_user_str(&mastersecret_gotls.client_random,
sizeof(mastersecret_gotls.client_random),
(void *)cr_ptr);
if (ret < 0) {
debug_bpf_printk(
"gotls_mastersecret read mastersecret client_random failed, "
"ret:%d, cr_ptr:%p\n",
ret, cr_ptr);
return 0;
}

ret = bpf_probe_read_user_str(&mastersecret_gotls.secret_,
sizeof(mastersecret_gotls.secret_),
(void *)secret_ptr);
if (ret < 0) {
debug_bpf_printk(
"gotls_mastersecret read mastersecret secret_ failed, ret:%d, "
"secret_ptr:%p\n",
ret, secret_ptr);
return 0;
}

bpf_perf_event_output(ctx, &mastersecret_go_events, BPF_F_CURRENT_CPU,
&mastersecret_gotls,
sizeof(struct mastersecret_gotls_t));
return 0;
}

SEC("uprobe/gotls_mastersecret_register")
int gotls_mastersecret_register(struct pt_regs *ctx) {
return gotls_mastersecret(ctx, true);
}

SEC("uprobe/gotls_mastersecret_stack")
int gotls_mastersecret_stack(struct pt_regs *ctx) {
return gotls_mastersecret(ctx, false);
}
2 changes: 1 addition & 1 deletion kern/openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

#include "ecapture.h"
#include "openssl_tc.h"
#include "tc.h"

enum ssl_data_event_type { kSSLRead, kSSLWrite };
const u32 invalidFD = 0;
Expand Down
File renamed without changes.
Loading