From a723bd87d0b0bbb2176fd581c95c4e71776e2133 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Thu, 21 Jul 2022 00:23:22 +0800 Subject: [PATCH 01/18] update CHANGELOG.md Signed-off-by: CFC4N --- CHANGELOG.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a4f42919..93c7ee33a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,21 +5,19 @@ **Capture TLS master_key ,save to file. Support openssl `1.1.1.X` . `TLS 1.2` .** Quick Guide: - - use `ecapture` to capture TLS master_key, will save master secret to `ecapture_masterkey_[pid].log`. - - use `tcpdump` to capture and save packets to `xxx.pcapng` file. - - open `xxx.pcapng` file with `wireshark`. - - Setting : `Wireshark` --> `Preferences` --> `Protocols` --> `TLS` --> `(Pre)-Master-Secret log filename`, select `ecapture_masterkey_[pid].log`. - - Using : right click packet item, select `follow` -> `HTTP Stream` / `HTTP/2 Stream` +- use `ecapture` to capture TLS master_key, will save master secret to `ecapture_masterkey_[pid].log`. +- use `tcpdump` to capture and save packets to `xxx.pcapng` file. +- open `xxx.pcapng` file with `wireshark`. +- Setting : `Wireshark` --> `Preferences` --> `Protocols` --> `TLS` --> `(Pre)-Master-Secret log filename`, select `ecapture_masterkey_[pid].log`. +- Using : right click packet item, select `follow` -> `HTTP Stream` / `HTTP/2 Stream` ## What's Changed - - -## New Contributors +* all : refactor event_processor EventType. by @cfc4n in https://github.com/ehids/ecapture/pull/134 +* fixed #138 : You have an error in your yaml syntax on line 79 by @cfc4n in https://github.com/ehids/ecapture/pull/139 +* New feature: capture openssl masterkey #27 by @cfc4n in https://github.com/ehids/ecapture/pull/140 **Full Changelog**: https://github.com/ehids/ecapture/compare/v0.2.2...v0.3.0 - -
# v0.2.2 (2022-07-09) From eecf74d132899e18422b7132bd5861920a01e381 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Fri, 22 Jul 2022 23:48:09 +0800 Subject: [PATCH 02/18] user : add TLS 1.3 master secret event. Signed-off-by: CFC4N --- user/event_masterkey.go | 41 ++++++++++++++++------------ user/probe_openssl.go | 59 ++++++++++++++++++++++++++--------------- 2 files changed, 62 insertions(+), 38 deletions(-) diff --git a/user/event_masterkey.go b/user/event_masterkey.go index 99d3e9a29..01d1efd0f 100644 --- a/user/event_masterkey.go +++ b/user/event_masterkey.go @@ -12,21 +12,28 @@ import ( const ( SSL3_RANDOM_SIZE = 32 MASTER_SECRET_MAX_LEN = 48 + EVP_MAX_MD_SIZE = 64 ) /* u8 client_random[SSL3_RANDOM_SIZE]; u8 master_key[MASTER_SECRET_MAX_LEN]; */ -type MasterKeyEvent struct { - module IModule - event_type event_processor.EventType - ClientRandom [SSL3_RANDOM_SIZE]byte - MasterKey [MASTER_SECRET_MAX_LEN]byte - payload string +type MasterSecretEvent struct { + module IModule + event_type event_processor.EventType + Version int32 // TLS version + ClientRandom [SSL3_RANDOM_SIZE]byte + MasterKey [MASTER_SECRET_MAX_LEN]byte + ServerHandshakeTrafficSecret [EVP_MAX_MD_SIZE]byte + ExporterSecret [EVP_MAX_MD_SIZE]byte + ServerTrafficSecret0 [EVP_MAX_MD_SIZE]byte + ClientHandshakeTrafficSecret [EVP_MAX_MD_SIZE]byte + ClientTrafficSecret0 [EVP_MAX_MD_SIZE]byte + payload string } -func (this *MasterKeyEvent) Decode(payload []byte) (err error) { +func (this *MasterSecretEvent) Decode(payload []byte) (err error) { buf := bytes.NewBuffer(payload) if err = binary.Read(buf, binary.LittleEndian, &this.ClientRandom); err != nil { return @@ -38,43 +45,43 @@ func (this *MasterKeyEvent) Decode(payload []byte) (err error) { return nil } -func (this *MasterKeyEvent) StringHex() string { +func (this *MasterSecretEvent) StringHex() string { s := fmt.Sprintf("ClientRandom:%02x, MasterKey:%02x", this.ClientRandom, this.MasterKey) return s } -func (this *MasterKeyEvent) String() string { +func (this *MasterSecretEvent) String() string { s := fmt.Sprintf("ClientRandom:%02x, MasterKey:%02x", this.ClientRandom, this.MasterKey) return s } -func (this *MasterKeyEvent) SetModule(module IModule) { +func (this *MasterSecretEvent) SetModule(module IModule) { this.module = module } -func (this *MasterKeyEvent) Module() IModule { +func (this *MasterSecretEvent) Module() IModule { return this.module } -func (this *MasterKeyEvent) Clone() event_processor.IEventStruct { - event := new(MasterKeyEvent) +func (this *MasterSecretEvent) Clone() event_processor.IEventStruct { + event := new(MasterSecretEvent) event.module = this.module event.event_type = event_processor.EventTypeModuleData return event } -func (this *MasterKeyEvent) EventType() event_processor.EventType { +func (this *MasterSecretEvent) EventType() event_processor.EventType { return this.event_type } -func (this *MasterKeyEvent) GetUUID() string { +func (this *MasterSecretEvent) GetUUID() string { return fmt.Sprintf("%02X", this.ClientRandom) } -func (this *MasterKeyEvent) Payload() []byte { +func (this *MasterSecretEvent) Payload() []byte { return []byte(this.payload) } -func (this *MasterKeyEvent) PayloadLen() int { +func (this *MasterSecretEvent) PayloadLen() int { return len(this.payload) } diff --git a/user/probe_openssl.go b/user/probe_openssl.go index 48a8c1554..5c76d484d 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -5,20 +5,28 @@ import ( "context" "ecapture/assets" "ecapture/pkg/event_processor" - "fmt" - "log" - "math" - "os" - "errors" + "fmt" "github.com/cilium/ebpf" manager "github.com/ehids/ebpfmanager" "golang.org/x/sys/unix" + "log" + "math" + "os" ) const ( - CLIENT_RANDOM = "CLIENT_RANDOM" CONN_NOT_FOUND = "[ADDR_NOT_FOUND]" + + // tls 1.2 + CLIENT_RANDOM = "CLIENT_RANDOM" + + // tls 1.3 + SERVER_HANDSHAKE_TRAFFIC_SECRET = "SERVER_HANDSHAKE_TRAFFIC_SECRET" + EXPORTER_SECRET = "EXPORTER_SECRET" + SERVER_TRAFFIC_SECRET_0 = "SERVER_TRAFFIC_SECRET_0" + CLIENT_HANDSHAKE_TRAFFIC_SECRET = "CLIENT_HANDSHAKE_TRAFFIC_SECRET" + CLIENT_TRAFFIC_SECRET_0 = "CLIENT_TRAFFIC_SECRET_0" ) type MOpenSSLProbe struct { @@ -33,7 +41,7 @@ type MOpenSSLProbe struct { filename string file *os.File - masterKeys map[string]string + masterKeys map[string]bool } //对象初始化 @@ -44,7 +52,7 @@ func (this *MOpenSSLProbe) Init(ctx context.Context, logger *log.Logger, conf IC this.eventMaps = make([]*ebpf.Map, 0, 2) this.eventFuncMaps = make(map[*ebpf.Map]event_processor.IEventStruct) this.pidConns = make(map[uint32]map[uint32]string) - this.masterKeys = make(map[string]string) + this.masterKeys = make(map[string]bool) fd := os.Getpid() this.filename = fmt.Sprintf("ecapture_masterkey_%d.log", fd) file, err := os.OpenFile(this.filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) @@ -306,7 +314,7 @@ func (this *MOpenSSLProbe) initDecodeFun() error { return errors.New("cant found map:masterkey_events") } this.eventMaps = append(this.eventMaps, MasterkeyEventsMap) - masterkeyEvent := &MasterKeyEvent{} + masterkeyEvent := &MasterSecretEvent{} masterkeyEvent.SetModule(this) this.eventFuncMaps[MasterkeyEventsMap] = masterkeyEvent return nil @@ -369,33 +377,42 @@ func (this *MOpenSSLProbe) GetConn(pid, fd uint32) string { return addr } -func (this *MOpenSSLProbe) saveMasterKey(client_random [32]byte, master_key [48]byte) { - var k = fmt.Sprintf("%02x", client_random) - var v = fmt.Sprintf("%02x", master_key) +func (this *MOpenSSLProbe) saveMasterSecret(event *MasterSecretEvent) { + + var k = fmt.Sprintf("%02x", event.ClientRandom) - v, f := this.masterKeys[k] + _, f := this.masterKeys[k] if f { + // 已存在该随机数的masterSecret,不需要重复写入 return } - this.masterKeys[k] = v + this.masterKeys[k] = true // save to file - var b = fmt.Sprintf("%s %02x %02x\n", CLIENT_RANDOM, client_random, master_key) - l, e := this.file.WriteString(b) + var b *bytes.Buffer + switch event.Version { + case TLS1_2_VERSION: + b = bytes.NewBufferString(fmt.Sprintf("%s %02x %02x\n", CLIENT_RANDOM, event.ClientRandom, event.MasterKey)) + case TLS1_3_VERSION: + // TODO fixme + b = bytes.NewBufferString(fmt.Sprintf("%s %02x %02x\n", SERVER_HANDSHAKE_TRAFFIC_SECRET, event.ClientRandom, event.MasterKey)) + } + v := tls_version{version: event.Version} + l, e := this.file.WriteString(b.String()) if e != nil { - this.logger.Fatalf("save CLIENT_RANDOM to file error:%s", e.Error()) + this.logger.Fatalf("%s: save CLIENT_RANDOM to file error:%s", e.Error()) return } - this.logger.Printf("save CLIENT_RANDOM %02x to file success, %d bytes", client_random, l) + this.logger.Printf("%s: save CLIENT_RANDOM %02x to file success, %d bytes", v.String(), event.ClientRandom, l) } func (this *MOpenSSLProbe) Dispatcher(event event_processor.IEventStruct) { - // detect event type TODO + // detect event type switch event.(type) { case *ConnDataEvent: this.AddConn(event.(*ConnDataEvent).Pid, event.(*ConnDataEvent).Fd, event.(*ConnDataEvent).Addr) - case *MasterKeyEvent: - this.saveMasterKey(event.(*MasterKeyEvent).ClientRandom, event.(*MasterKeyEvent).MasterKey) + case *MasterSecretEvent: + this.saveMasterSecret(event.(*MasterSecretEvent)) } //this.logger.Println(event) } From eda0c3887fd53dedbb7b51d566a72a709f8a8e7f Mon Sep 17 00:00:00 2001 From: CFC4N Date: Sat, 23 Jul 2022 23:10:22 +0800 Subject: [PATCH 03/18] improve TLS 1.3 master secret. Signed-off-by: CFC4N --- kern/masterkey_kern.h | 178 ++++++++++++++++++++++++++++++++++------ user/event_masterkey.go | 2 +- user/probe_openssl.go | 6 +- 3 files changed, 155 insertions(+), 31 deletions(-) diff --git a/kern/masterkey_kern.h b/kern/masterkey_kern.h index 7bc4f5b87..3bbff1ec9 100644 --- a/kern/masterkey_kern.h +++ b/kern/masterkey_kern.h @@ -1,29 +1,91 @@ #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 -// openssl 1.1.1.X 版本相关的偏移量 +/* + * openssl 1.1.1.X 版本相关的常量 + * 参考:https://wiki.openssl.org/index.php/TLS1.3 + */ + +////////// TLS 1.2 or older ///////// +// ssl->session 在 ssl_st 结构中的偏移量 #define SSL_SESSION_OFFSET 0x510 -#define MASTER_SECRET_OFFSET 80 + +// session->ssl_session_st 在 SSL_SESSION 中的偏移量 +#define MASTER_KEY_OFFSET 80 + +// ssl->s3 在 ssl_st中的偏移量 #define SSL_S3_OFFSET 0xA8 + +// s3->client_random 在 ssl3_state_st 中的偏移量 #define SSL_S3_CLIENT_RANDOM_OFFSET 0xD8 -struct masterkey_t { + + + +////////// TLS 1.3 ///////// + +/* + // openssl 1.1.1J repo: https://github.com/openssl/openssl/tree/OpenSSL_1_1_1j + // ssl/ssl_local.h line 1143 + * The TLS1.3 secrets. + unsigned char early_secret[EVP_MAX_MD_SIZE]; + unsigned char handshake_secret[EVP_MAX_MD_SIZE]; // 【NEED】 + unsigned char master_secret[EVP_MAX_MD_SIZE]; // 【NEED】 + unsigned char resumption_master_secret[EVP_MAX_MD_SIZE]; + unsigned char client_finished_secret[EVP_MAX_MD_SIZE]; + unsigned char server_finished_secret[EVP_MAX_MD_SIZE]; + unsigned char server_finished_hash[EVP_MAX_MD_SIZE]; //【NEED】 + unsigned char handshake_traffic_hash[EVP_MAX_MD_SIZE]; //【NEED】 + unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE]; + unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE]; + unsigned char exporter_master_secret[EVP_MAX_MD_SIZE]; //【NEED】 + unsigned char early_exporter_master_secret[EVP_MAX_MD_SIZE]; +*/ + +// session->cipher 在 SSL_SESSION 中的偏移量 +#define CIPHER_OFFSET 0xEC + +// ssl_cipher_st-> id 在 ssl_cipher_st 中的偏移量 +#define CIPHER_ID_OFFSET 0x18 + +// ssl->handshake_secret 在 ssl_st 中的偏移量 +#define HANDSHAKE_SECRET_OFFSET 0x13C // 316 + +// ssl->master_secret 在 ssl_st 中的偏移量 +#define MASTER_SECRET_OFFSET 0x17C //380 + +// ssl->server_finished_hash 在 ssl_st 中的偏移量 +#define SERVER_FINISHED_HASH_OFFSET 0x27C // 636 + +// ssl->handshake_traffic_hash 在 ssl_st 中的偏移量 +#define HANDSHAKE_TRAFFIC_HASH_OFFSET 0x2BC // 700 + +// ssl->exporter_master_secret 在 ssl_st 中的偏移量 +#define EXPORTER_MASTER_SECRET_OFFSET 0x37C // 892 + + +struct mastersecret_t { + // TLS 1.2 or older + s32 version; u8 client_random[SSL3_RANDOM_SIZE]; u8 master_key[MASTER_SECRET_MAX_LEN]; -}; -// bpf map -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -// __uint(type, BPF_MAP_TYPE_HASH); -// __type(key, u32); -// __type(value, struct masterkey_t); -// __uint(max_entries, 1024); -} masterkey_events SEC(".maps"); + // TLS 1.3 + u32 cipher_id; + u8 handshake_secret[EVP_MAX_MD_SIZE]; + u8 master_secret[EVP_MAX_MD_SIZE]; + u8 server_finished_hash[EVP_MAX_MD_SIZE]; + u8 handshake_traffic_hash[EVP_MAX_MD_SIZE]; + u8 exporter_master_secret[EVP_MAX_MD_SIZE]; +}; // ssl/ssl_local.h 1556行 struct ssl3_state_st { @@ -36,6 +98,43 @@ struct ssl3_state_st { unsigned char client_random[SSL3_RANDOM_SIZE]; }; +#define TLS1_3_VERSION 0x0304 + +/////////////////////////BPF MAPS //////////////////////////////// + +// bpf map +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); +} 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(); @@ -54,18 +153,29 @@ int probe_ssl_master_key(struct pt_regs *ctx) { #endif debug_bpf_printk("openssl uprobe/SSL_write masterKey PID :%d\n", pid); - // masterkey_t sent to userspace - struct masterkey_t masterkey; - __builtin_memset(&masterkey, 0, sizeof(masterkey)); + // 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; + } // Get a ssl_session_st pointer u64 *ssl_session_st_ptr = (u64 *)(ssl_st_ptr + SSL_SESSION_OFFSET); u64 *ssl_s3_st_ptr = (u64 *)(ssl_st_ptr + SSL_S3_OFFSET); + int version; + int ret = bpf_probe_read_user(&version, sizeof(version), (void *)ssl_st_ptr); + if (ret) { + debug_bpf_printk( + "bpf_probe_read tls_version failed, ret :%d\n", ret); + return 0; + } + debug_bpf_printk("tls_version: %d\n", version); + u64 address; - int ret = + ret = bpf_probe_read_user(&address, sizeof(address), ssl_session_st_ptr); if (ret) { debug_bpf_printk( @@ -74,16 +184,16 @@ int probe_ssl_master_key(struct pt_regs *ctx) { } // Access the TLS 1.2 master secret - void *ms_ptr = (void *)(address + MASTER_SECRET_OFFSET); - ret = bpf_probe_read_user(&masterkey.master_key, - sizeof(masterkey.master_key), ms_ptr); + void *ms_ptr = (void *)(address + MASTER_KEY_OFFSET); + ret = bpf_probe_read_user(&mastersecret->master_key, + sizeof(mastersecret->master_key), ms_ptr); if (ret) { debug_bpf_printk( - "bpf_probe_read MASTER_SECRET_OFFSET failed, ret :%d\n", ret); + "bpf_probe_read MASTER_KEY_OFFSET failed, ret :%d\n", ret); return 0; } - debug_bpf_printk("master_key: %x %x %x\n",masterkey.master_key[0],masterkey.master_key[1],masterkey.master_key[2]); + debug_bpf_printk("master_key: %x %x %x\n",mastersecret->master_key[0],mastersecret->master_key[1],mastersecret->master_key[2]); // Get ssl3_state_st pointer @@ -102,17 +212,31 @@ int probe_ssl_master_key(struct pt_regs *ctx) { return 0; } debug_bpf_printk("client_random: %x %x %x\n",ssl3_stat.client_random[0],ssl3_stat.client_random[1],ssl3_stat.client_random[2]); - ret = bpf_probe_read_kernel(&masterkey.client_random, - sizeof(masterkey.client_random), + ret = bpf_probe_read_kernel(&mastersecret->client_random, + sizeof(mastersecret->client_random), (void *)&ssl3_stat.client_random); if (ret) { debug_bpf_printk( "bpf_probe_read_kernel ssl3_stat.client_random failed, ret :%d\n", ret); return 0; } - debug_bpf_printk("copy : %x %x %x\n",masterkey.client_random[0],masterkey.client_random[1],masterkey.client_random[2]); - bpf_perf_event_output(ctx, &masterkey_events, BPF_F_CURRENT_CPU, &masterkey, - sizeof(struct masterkey_t)); + bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, mastersecret, + sizeof(struct mastersecret_t)); + + // check tls version eq to TLS 1.3 + if (version != TLS1_3_VERSION) { + return 0; + } + // TLS 1.3 master secret + void *ms_ptr_tls13 = (void *)(ssl_st_ptr + MASTER_SECRET_OFFSET); + unsigned char master_secret[EVP_MAX_MD_SIZE]; + ret = bpf_probe_read_user(&master_secret, sizeof(master_secret), (void *)ms_ptr_tls13); + if (ret) { + debug_bpf_printk( + "bpf_probe_read MASTER_SECRET_OFFSET failed, ret :%d\n", ret); + return 0; + } + debug_bpf_printk("*****master_secret*****: %x %x %x\n",master_secret[0],master_secret[1],master_secret[2]); return 0; } \ No newline at end of file diff --git a/user/event_masterkey.go b/user/event_masterkey.go index 01d1efd0f..f06d949b8 100644 --- a/user/event_masterkey.go +++ b/user/event_masterkey.go @@ -7,7 +7,7 @@ import ( "fmt" ) -// openssl_masterkey_events +// openssl_mastersecret_events const ( SSL3_RANDOM_SIZE = 32 diff --git a/user/probe_openssl.go b/user/probe_openssl.go index 5c76d484d..3d178ca56 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -248,7 +248,7 @@ func (this *MOpenSSLProbe) setupManagers() error { Name: "connect_events", }, { - Name: "masterkey_events", + Name: "mastersecret_events", }, }, } @@ -306,12 +306,12 @@ func (this *MOpenSSLProbe) initDecodeFun() error { connEvent.SetModule(this) this.eventFuncMaps[ConnEventsMap] = connEvent - MasterkeyEventsMap, found, err := this.bpfManager.GetMap("masterkey_events") + MasterkeyEventsMap, found, err := this.bpfManager.GetMap("mastersecret_events") if err != nil { return err } if !found { - return errors.New("cant found map:masterkey_events") + return errors.New("cant found map:mastersecret_events") } this.eventMaps = append(this.eventMaps, MasterkeyEventsMap) masterkeyEvent := &MasterSecretEvent{} From 3c971ebc7b2fc759cd073292a45c321f3c37608e Mon Sep 17 00:00:00 2001 From: CFC4N Date: Sat, 23 Jul 2022 23:59:11 +0800 Subject: [PATCH 04/18] improve: get SESSION_CIPHER->cipher->id for tls 1.3 Signed-off-by: CFC4N --- kern/masterkey_kern.h | 43 ++++++++++++++++++++++++++++++++++++----- user/event_masterkey.go | 3 +++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/kern/masterkey_kern.h b/kern/masterkey_kern.h index 3bbff1ec9..3e7cb3b6a 100644 --- a/kern/masterkey_kern.h +++ b/kern/masterkey_kern.h @@ -18,7 +18,7 @@ // ssl->session 在 ssl_st 结构中的偏移量 #define SSL_SESSION_OFFSET 0x510 -// session->ssl_session_st 在 SSL_SESSION 中的偏移量 +// session->master_key 在 SSL_SESSION 中的偏移量 #define MASTER_KEY_OFFSET 80 // ssl->s3 在 ssl_st中的偏移量 @@ -27,6 +27,11 @@ // s3->client_random 在 ssl3_state_st 中的偏移量 #define SSL_S3_CLIENT_RANDOM_OFFSET 0xD8 +// session->cipher 在 SSL_SESSION 中的偏移量 +#define SESSION_CIPHER_OFFSET 496 // 已计算 char *psk_identity_hint; + char *psk_identity; + +// session->cipher->id 在 ssl_cipher_st 中的偏移量 +#define SESSION_CIPHER_ID_OFFSET 24 @@ -172,8 +177,11 @@ int probe_ssl_master_key(struct pt_regs *ctx) { "bpf_probe_read tls_version failed, ret :%d\n", ret); return 0; } - debug_bpf_printk("tls_version: %d\n", version); + mastersecret->version = version; + debug_bpf_printk("tls_version: %d\n", mastersecret->version); + + // Get SSL_SESSION_t pointer u64 address; ret = bpf_probe_read_user(&address, sizeof(address), ssl_session_st_ptr); @@ -183,7 +191,10 @@ int probe_ssl_master_key(struct pt_regs *ctx) { return 0; } - // Access the TLS 1.2 master secret + // Get SSL_SESSION->cipher pointer + u64 *ssl_cipher_st_ptr = (u64 *)(address + SESSION_CIPHER_OFFSET); + + ///////////////////////// get TLS 1.2 master secret //////////////////// void *ms_ptr = (void *)(address + MASTER_KEY_OFFSET); ret = bpf_probe_read_user(&mastersecret->master_key, sizeof(mastersecret->master_key), ms_ptr); @@ -224,11 +235,33 @@ int probe_ssl_master_key(struct pt_regs *ctx) { bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, mastersecret, sizeof(struct mastersecret_t)); - // check tls version eq to TLS 1.3 + + //////////////////// check tls version eq to TLS 1.3 //////////////////////// if (version != TLS1_3_VERSION) { return 0; } - // TLS 1.3 master secret + + // 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) { + debug_bpf_printk( + "bpf_probe_read ssl_cipher_st_ptr failed, ret :%d\n", ret); + return 0; + } + + void *cipher_id_ptr = (void *)(address + SESSION_CIPHER_ID_OFFSET); + ret = bpf_probe_read_user(&mastersecret->cipher_id, + sizeof(mastersecret->cipher_id), cipher_id_ptr); + if (ret) { + debug_bpf_printk( + "bpf_probe_read SESSION_CIPHER_ID_OFFSET failed, ret :%d\n", ret); + return 0; + } + + //////////////////// TLS 1.3 master secret //////////////////////// + debug_bpf_printk("cipher_id: %d\n", mastersecret->cipher_id); + void *ms_ptr_tls13 = (void *)(ssl_st_ptr + MASTER_SECRET_OFFSET); unsigned char master_secret[EVP_MAX_MD_SIZE]; ret = bpf_probe_read_user(&master_secret, sizeof(master_secret), (void *)ms_ptr_tls13); diff --git a/user/event_masterkey.go b/user/event_masterkey.go index f06d949b8..0d709e7ac 100644 --- a/user/event_masterkey.go +++ b/user/event_masterkey.go @@ -35,6 +35,9 @@ type MasterSecretEvent struct { func (this *MasterSecretEvent) Decode(payload []byte) (err error) { buf := bytes.NewBuffer(payload) + if err = binary.Read(buf, binary.LittleEndian, &this.Version); err != nil { + return + } if err = binary.Read(buf, binary.LittleEndian, &this.ClientRandom); err != nil { return } From e4dfc8453d42e58301eea8cb0844e63d43e37e59 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Sun, 24 Jul 2022 00:19:45 +0800 Subject: [PATCH 05/18] get all master_secrets of tls 1.3 ,sent to userspace by ebpf map. Signed-off-by: CFC4N --- kern/masterkey_kern.h | 47 +++++++++++++++++++++++++++++------ user/event_masterkey.go | 55 +++++++++++++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/kern/masterkey_kern.h b/kern/masterkey_kern.h index 3e7cb3b6a..64b074918 100644 --- a/kern/masterkey_kern.h +++ b/kern/masterkey_kern.h @@ -232,12 +232,10 @@ int probe_ssl_master_key(struct pt_regs *ctx) { return 0; } - bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, mastersecret, - sizeof(struct mastersecret_t)); - - //////////////////// check tls version eq to TLS 1.3 //////////////////////// if (version != TLS1_3_VERSION) { + bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, mastersecret, + sizeof(struct mastersecret_t)); return 0; } @@ -258,18 +256,51 @@ int probe_ssl_master_key(struct pt_regs *ctx) { "bpf_probe_read SESSION_CIPHER_ID_OFFSET failed, ret :%d\n", ret); return 0; } + debug_bpf_printk("cipher_id: %d\n", mastersecret->cipher_id); //////////////////// TLS 1.3 master secret //////////////////////// - debug_bpf_printk("cipher_id: %d\n", mastersecret->cipher_id); + + void *hs_ptr_tls13 = (void *)(ssl_st_ptr + HANDSHAKE_SECRET_OFFSET); + ret = bpf_probe_read_user(&mastersecret->handshake_secret, sizeof(mastersecret->handshake_secret), (void *)hs_ptr_tls13); + if (ret) { + debug_bpf_printk( + "bpf_probe_read HANDSHAKE_SECRET_OFFSET failed, ret :%d\n", ret); + return 0; + } void *ms_ptr_tls13 = (void *)(ssl_st_ptr + MASTER_SECRET_OFFSET); - unsigned char master_secret[EVP_MAX_MD_SIZE]; - ret = bpf_probe_read_user(&master_secret, sizeof(master_secret), (void *)ms_ptr_tls13); + ret = bpf_probe_read_user(&mastersecret->master_secret, sizeof(mastersecret->master_secret), (void *)ms_ptr_tls13); if (ret) { debug_bpf_printk( "bpf_probe_read MASTER_SECRET_OFFSET failed, ret :%d\n", ret); return 0; } - debug_bpf_printk("*****master_secret*****: %x %x %x\n",master_secret[0],master_secret[1],master_secret[2]); + + void *sf_ptr_tls13 = (void *)(ssl_st_ptr + SERVER_FINISHED_HASH_OFFSET); + ret = bpf_probe_read_user(&mastersecret->server_finished_hash, sizeof(mastersecret->server_finished_hash), (void *)sf_ptr_tls13); + if (ret) { + debug_bpf_printk( + "bpf_probe_read SERVER_FINISHED_HASH_OFFSET failed, ret :%d\n", ret); + return 0; + } + + void *hth_ptr_tls13 = (void *)(ssl_st_ptr + HANDSHAKE_TRAFFIC_HASH_OFFSET); + 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 HANDSHAKE_TRAFFIC_HASH_OFFSET failed, ret :%d\n", ret); + return 0; + } + + void *ems_ptr_tls13 = (void *)(ssl_st_ptr + EXPORTER_MASTER_SECRET_OFFSET); + 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 EXPORTER_MASTER_SECRET_OFFSET failed, ret :%d\n", ret); + return 0; + } + debug_bpf_printk("*****master_secret*****: %x %x %x\n",mastersecret->master_secret[0],mastersecret->master_secret[1],mastersecret->master_secret[2]); + bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, mastersecret, + sizeof(struct mastersecret_t)); return 0; } \ No newline at end of file diff --git a/user/event_masterkey.go b/user/event_masterkey.go index 0d709e7ac..e62077fc4 100644 --- a/user/event_masterkey.go +++ b/user/event_masterkey.go @@ -20,17 +20,22 @@ const ( u8 master_key[MASTER_SECRET_MAX_LEN]; */ type MasterSecretEvent struct { - module IModule - event_type event_processor.EventType - Version int32 // TLS version - ClientRandom [SSL3_RANDOM_SIZE]byte - MasterKey [MASTER_SECRET_MAX_LEN]byte - ServerHandshakeTrafficSecret [EVP_MAX_MD_SIZE]byte - ExporterSecret [EVP_MAX_MD_SIZE]byte - ServerTrafficSecret0 [EVP_MAX_MD_SIZE]byte - ClientHandshakeTrafficSecret [EVP_MAX_MD_SIZE]byte - ClientTrafficSecret0 [EVP_MAX_MD_SIZE]byte - payload string + module IModule + event_type event_processor.EventType + Version int32 // TLS version + + // TLS 1.2 or older + ClientRandom [SSL3_RANDOM_SIZE]byte + MasterKey [MASTER_SECRET_MAX_LEN]byte + + // TLS 1.3 + CipherId uint32 + HandshakeSecret [EVP_MAX_MD_SIZE]byte + MasterSecret [EVP_MAX_MD_SIZE]byte + ServerFinishedHash [EVP_MAX_MD_SIZE]byte + HandshakeTrafficHash [EVP_MAX_MD_SIZE]byte + ExporterMasterSecret [EVP_MAX_MD_SIZE]byte + payload string } func (this *MasterSecretEvent) Decode(payload []byte) (err error) { @@ -44,17 +49,41 @@ func (this *MasterSecretEvent) Decode(payload []byte) (err error) { if err = binary.Read(buf, binary.LittleEndian, &this.MasterKey); err != nil { return } + if err = binary.Read(buf, binary.LittleEndian, &this.CipherId); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.HandshakeSecret); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.MasterSecret); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.ServerFinishedHash); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.HandshakeTrafficHash); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.ExporterMasterSecret); err != nil { + return + } this.payload = fmt.Sprintf("CLIENT_RANDOM %02x %02x", this.ClientRandom, this.MasterKey) return nil } func (this *MasterSecretEvent) StringHex() string { - s := fmt.Sprintf("ClientRandom:%02x, MasterKey:%02x", this.ClientRandom, this.MasterKey) + v := tls_version{ + version: this.Version, + } + s := fmt.Sprintf("TLS Version:%s, ClientRandom:%02x", v.String(), this.ClientRandom) return s } func (this *MasterSecretEvent) String() string { - s := fmt.Sprintf("ClientRandom:%02x, MasterKey:%02x", this.ClientRandom, this.MasterKey) + v := tls_version{ + version: this.Version, + } + s := fmt.Sprintf("TLS Version:%s, ClientRandom:%02x", v.String(), this.ClientRandom) return s } From fab8669bfab4c2135530f3b58f7811f47205ce76 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Thu, 28 Jul 2022 22:07:43 +0800 Subject: [PATCH 06/18] cli : change write-file command flag to log-file . and change short name -w to -l of global flags. Signed-off-by: CFC4N --- cli/cmd/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 41ead1267..e1b525787 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -80,5 +80,5 @@ func init() { rootCmd.PersistentFlags().BoolVar(&globalFlags.NoSearch, "nosearch", false, "no lib search") rootCmd.PersistentFlags().Uint64VarP(&globalFlags.Pid, "pid", "p", defaultPid, "if pid is 0 then we target all pids") rootCmd.PersistentFlags().Uint64VarP(&globalFlags.Uid, "uid", "u", defaultUid, "if uid is 0 then we target all users") - rootCmd.PersistentFlags().StringVarP(&globalFlags.loggerFile, "write-file", "w", "", "-w file Write the packets to file") + rootCmd.PersistentFlags().StringVarP(&globalFlags.loggerFile, "log-file", "l", "", "-l save the packets to file") } From 541685c835e195c546b208f1dddaaff00f47a711 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Thu, 28 Jul 2022 22:59:03 +0800 Subject: [PATCH 07/18] cli : add -w, -i flags into tls module. longflag: write, ifname. Signed-off-by: CFC4N --- cli/cmd/global.go | 2 +- cli/cmd/tls.go | 2 + user/config_openssl.go | 2 + user/probe_openssl.go | 91 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 94 insertions(+), 3 deletions(-) diff --git a/cli/cmd/global.go b/cli/cmd/global.go index 1c0c440dd..abf1a27ba 100644 --- a/cli/cmd/global.go +++ b/cli/cmd/global.go @@ -45,7 +45,7 @@ func getGlobalConf(command *cobra.Command) (conf GlobalFlags, err error) { return } - conf.loggerFile, err = command.Flags().GetString("write-file") + conf.loggerFile, err = command.Flags().GetString("log-file") if err != nil { return } diff --git a/cli/cmd/tls.go b/cli/cmd/tls.go index a5bdbc3a8..0527db8f5 100644 --- a/cli/cmd/tls.go +++ b/cli/cmd/tls.go @@ -40,6 +40,8 @@ func init() { opensslCmd.PersistentFlags().StringVar(&nc.Nsprpath, "nspr", "", "libnspr44.so file path, will automatically find it from curl default.") opensslCmd.PersistentFlags().StringVar(&oc.Pthread, "pthread", "", "libpthread.so file path, use to hook connect to capture socket FD.will automatically find it from curl.") opensslCmd.PersistentFlags().StringVar(&goc.Path, "gobin", "", "path to binary built with Go toolchain.") + opensslCmd.PersistentFlags().StringVarP(&oc.Write, "write", "w", "", "write the raw packets to file as pcapng format.") + opensslCmd.PersistentFlags().StringVarP(&oc.Ifname, "ifname", "i", "", "(TC Classifier) Interface name on which the probe will be attached.") rootCmd.AddCommand(opensslCmd) } diff --git a/user/config_openssl.go b/user/config_openssl.go index 4c8dcb5f8..62be8e7a1 100644 --- a/user/config_openssl.go +++ b/user/config_openssl.go @@ -10,6 +10,8 @@ type OpensslConfig struct { Curlpath string `json:"curlpath"` //curl的文件路径 Openssl string `json:"openssl"` Pthread string `json:"pthread"` // /lib/x86_64-linux-gnu/libpthread.so.0 + Write string `json:"write"` // Write the raw packets to file rather than parsing and printing them out. + Ifname string `json:"ifname"` // (TC Classifier) Interface name on which the probe will be attached. elfType uint8 // } diff --git a/user/probe_openssl.go b/user/probe_openssl.go index 38d3c1537..8e0ce7411 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -90,8 +90,17 @@ func (this *MOpenSSLProbe) start() error { return fmt.Errorf("couldn't find asset %v .", err) } + if len(this.conf.(*OpensslConfig).Write) > 0 { + // TC PROBE + this.logger.Printf("%s\tTC MODEL\n", this.Name()) + err = this.setupManagersTC() + } else { + // UPROBE + this.logger.Printf("%s\tUPROBE MODEL\n", this.Name()) + err = this.setupManagersUprobe() + } // setup the managers - err = this.setupManagers() + if err != nil { return fmt.Errorf("tls module couldn't find binPath %v .", err) } @@ -151,7 +160,85 @@ func (this *MOpenSSLProbe) constantEditor() []manager.ConstantEditor { return editor } -func (this *MOpenSSLProbe) setupManagers() error { +func (this *MOpenSSLProbe) setupManagersTC() error { + var writeFile, ifname, binaryPath string + + writeFile = this.conf.(*OpensslConfig).Write + ifname = this.conf.(*OpensslConfig).Ifname + + _, err := os.Stat(writeFile) + if err != nil { + return err + } + + switch this.conf.(*OpensslConfig).elfType { + case ELF_TYPE_BIN: + binaryPath = this.conf.(*OpensslConfig).Curlpath + case ELF_TYPE_SO: + binaryPath = this.conf.(*OpensslConfig).Openssl + default: + //如果没找到 + binaryPath = "/lib/x86_64-linux-gnu/libssl.so.1.1" + } + + this.logger.Printf("%s\teBPF Program type TC, interface:%s, save pcapng file:%s\n", ifname, writeFile) + + this.bpfManager = &manager.Manager{ + Probes: []*manager.Probe{ + { + Section: "classifier/egress", + EbpfFuncName: "egress_cls_func", + Ifname: ifname, + NetworkDirection: manager.Egress, + }, + { + Section: "classifier/ingress", + EbpfFuncName: "ingress_cls_func", + Ifname: ifname, + NetworkDirection: manager.Ingress, + }, + // -------------------------------------------------- + + // openssl masterkey + { + Section: "uprobe/SSL_write_key", + EbpfFuncName: "probe_ssl_master_key", + AttachToFuncName: "SSL_write", + BinaryPath: binaryPath, + UID: "uprobe_ssl_master_key", + }, + }, + + Maps: []*manager.Map{ + { + Name: "mastersecret_events", + }, + }, + } + + this.bpfManagerOptions = manager.Options{ + DefaultKProbeMaxActive: 512, + + VerifierOptions: ebpf.CollectionOptions{ + Programs: ebpf.ProgramOptions{ + LogSize: 2097152, + }, + }, + + RLimit: &unix.Rlimit{ + Cur: math.MaxUint64, + Max: math.MaxUint64, + }, + } + + if this.conf.EnableGlobalVar() { + // 填充 RewriteContants 对应map + this.bpfManagerOptions.ConstantEditors = this.constantEditor() + } + return nil +} + +func (this *MOpenSSLProbe) setupManagersUprobe() error { var binaryPath, libPthread string switch this.conf.(*OpensslConfig).elfType { case ELF_TYPE_BIN: From 238785447aa837ed58537ded6d2b48cd135fffc5 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Thu, 28 Jul 2022 23:17:29 +0800 Subject: [PATCH 08/18] user : disable gossl module when gobin not setting. Signed-off-by: CFC4N --- cli/cmd/tls.go | 23 ++++++++++++++++------- user/config_gossl.go | 6 +++++- user/probe_openssl.go | 4 ++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/cli/cmd/tls.go b/cli/cmd/tls.go index 0527db8f5..8e9dfafe7 100644 --- a/cli/cmd/tls.go +++ b/cli/cmd/tls.go @@ -7,6 +7,7 @@ package cmd import ( "context" "ecapture/user" + "errors" "log" "os" "os/signal" @@ -55,9 +56,9 @@ func openSSLCommandFunc(command *cobra.Command, args []string) { logger := log.New(os.Stdout, "tls_", log.LstdFlags) // save global config - gConf, e := getGlobalConf(command) - if e != nil { - logger.Fatal(e) + gConf, err := getGlobalConf(command) + if err != nil { + logger.Fatal(err) } if gConf.loggerFile != "" { f, e := os.Create(gConf.loggerFile) @@ -103,14 +104,22 @@ func openSSLCommandFunc(command *cobra.Command, args []string) { conf.SetHex(gConf.IsHex) conf.SetNoSearch(gConf.NoSearch) - logger.Printf("%s\tmodule initialization", mod.Name()) - if e := conf.Check(); e != nil { - logger.Printf("%s\tmodule initialization failed. [skip it]. error:%+v", mod.Name(), e) + err := conf.Check() + + if err != nil { + // ErrorGoBINNotFound is a special error, we should not print it. + if errors.Is(err, user.ErrorGoBINNotFound) { + continue + } + + logger.Printf("%s\tmodule initialization failed. [skip it]. error:%+v", mod.Name(), err) continue } + logger.Printf("%s\tmodule initialization", mod.Name()) + //初始化 - err := mod.Init(ctx, logger, conf) + err = mod.Init(ctx, logger, conf) if err != nil { logger.Printf("%s\tmodule initialization failed, [skip it]. error:%+v", mod.Name(), err) continue diff --git a/user/config_gossl.go b/user/config_gossl.go index 829065487..8e862ef0d 100644 --- a/user/config_gossl.go +++ b/user/config_gossl.go @@ -6,6 +6,10 @@ import ( "os" ) +var ( + ErrorGoBINNotFound = errors.New("GO binary not found") +) + // GoSSLConfig represents configuration for Go SSL probe type GoSSLConfig struct { eConfig @@ -19,7 +23,7 @@ func NewGoSSLConfig() *GoSSLConfig { func (c *GoSSLConfig) Check() error { if c.Path == "" { - return errors.New("go binary not found") + return ErrorGoBINNotFound } _, err := os.Stat(c.Path) return err diff --git a/user/probe_openssl.go b/user/probe_openssl.go index 8e0ce7411..c60a418e9 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -71,7 +71,7 @@ func (this *MOpenSSLProbe) Init(ctx context.Context, logger *log.Logger, conf IC return err } this.file = file - this.logger.Printf("master key file: %s\n", this.filename) + this.logger.Printf("%s\tmaster key file: %s\n", this.Name(), this.filename) return nil } @@ -87,7 +87,7 @@ func (this *MOpenSSLProbe) start() error { // fetch ebpf assets byteBuf, err := assets.Asset("user/bytecode/openssl_kern.o") if err != nil { - return fmt.Errorf("couldn't find asset %v .", err) + return fmt.Errorf("%s\tcouldn't find asset %v .", this.Name(), err) } if len(this.conf.(*OpensslConfig).Write) > 0 { From 270ef13e63899fd9abb1701ba194171a0061f88c Mon Sep 17 00:00:00 2001 From: CFC4N Date: Thu, 28 Jul 2022 23:21:09 +0800 Subject: [PATCH 09/18] cli : rename constant name ErrorGoBINNotFound to ErrorGoBINNotSET. Signed-off-by: CFC4N --- cli/cmd/tls.go | 5 +++-- user/config_gossl.go | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cli/cmd/tls.go b/cli/cmd/tls.go index 8e9dfafe7..facb3d96a 100644 --- a/cli/cmd/tls.go +++ b/cli/cmd/tls.go @@ -107,8 +107,9 @@ func openSSLCommandFunc(command *cobra.Command, args []string) { err := conf.Check() if err != nil { - // ErrorGoBINNotFound is a special error, we should not print it. - if errors.Is(err, user.ErrorGoBINNotFound) { + // ErrorGoBINNotSET is a special error, we should not print it. + if errors.Is(err, user.ErrorGoBINNotSET) { + logger.Printf("%s\tmodule [disabled].", mod.Name()) continue } diff --git a/user/config_gossl.go b/user/config_gossl.go index 8e862ef0d..5e7e36de7 100644 --- a/user/config_gossl.go +++ b/user/config_gossl.go @@ -7,7 +7,7 @@ import ( ) var ( - ErrorGoBINNotFound = errors.New("GO binary not found") + ErrorGoBINNotSET = errors.New("GO binary not set") ) // GoSSLConfig represents configuration for Go SSL probe @@ -23,7 +23,7 @@ func NewGoSSLConfig() *GoSSLConfig { func (c *GoSSLConfig) Check() error { if c.Path == "" { - return ErrorGoBINNotFound + return ErrorGoBINNotSET } _, err := os.Stat(c.Path) return err From d13fec952d9374e9cfd0939e3336381886cb6776 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Fri, 29 Jul 2022 00:00:12 +0800 Subject: [PATCH 10/18] kern : add openssl_tc submodule. Signed-off-by: CFC4N --- kern/common.h | 4 ++ kern/openssl_kern.c | 1 + kern/openssl_tc.h | 14 +++++ user/common.go | 8 +-- user/probe_openssl.go | 133 +++++++++++---------------------------- user/probe_openssl_tc.go | 80 +++++++++++++++++++++++ 6 files changed, 141 insertions(+), 99 deletions(-) create mode 100644 kern/openssl_tc.h create mode 100644 user/probe_openssl_tc.go diff --git a/kern/common.h b/kern/common.h index a69703fd3..b3aca107a 100644 --- a/kern/common.h +++ b/kern/common.h @@ -26,6 +26,10 @@ #define SA_DATA_LEN 14 #define BASH_ERRNO_DEFAULT 128 +///////// for TC & XDP ebpf programs in openssl_tc.h +#define TC_ACT_OK 0 + + // Optional Target PID // .rodata section bug via : https://github.com/ehids/ecapture/issues/39 #ifndef KERNEL_LESS_5_2 diff --git a/kern/openssl_kern.c b/kern/openssl_kern.c index 1659d1cef..854398e25 100644 --- a/kern/openssl_kern.c +++ b/kern/openssl_kern.c @@ -1,5 +1,6 @@ #include "ecapture.h" #include "masterkey_kern.h" +#include "openssl_tc.h" enum ssl_data_event_type { kSSLRead, kSSLWrite }; const u32 invalidFD = 0; diff --git a/kern/openssl_tc.h b/kern/openssl_tc.h new file mode 100644 index 000000000..cebefd84f --- /dev/null +++ b/kern/openssl_tc.h @@ -0,0 +1,14 @@ + +SEC("classifier/egress") +int egress_cls_func(struct __sk_buff *skb) +{ + debug_bpf_printk("new packet captured on egress (TC)\n"); + return TC_ACT_OK; +}; + +SEC("classifier/ingress") +int ingress_cls_func(struct __sk_buff *skb) +{ + debug_bpf_printk("new packet captured on ingress (TC)\n"); + return TC_ACT_OK; +}; \ No newline at end of file diff --git a/user/common.go b/user/common.go index a9d05d6e3..ebce4b085 100644 --- a/user/common.go +++ b/user/common.go @@ -84,12 +84,12 @@ func ParseDynLibConf(pattern string) (dirs []string, err error) { } } if len(dirs) <= 0 { - err = errors.New(fmt.Sprintf("read file :%s error .", pattern)) + err = errors.New(fmt.Sprintf("read keylogger :%s error .", pattern)) } return dirs, err } -// getDynsFromElf get shared objects from ELF file +// getDynsFromElf get shared objects from ELF keylogger func getDynsFromElf(file string) ([]string, error) { f, e := elf.Open(file) if e != nil { @@ -121,7 +121,7 @@ func getDynPathByElf(elfName, soName string) (string, error) { func recurseDynStrings(dynSym []string, searchPath []string, soName string) string { var realSoName string for _, el := range dynSym { - // check file path here for library if it doesnot exists panic + // check keylogger path here for library if it doesnot exists panic var fd *os.File for _, entry := range searchPath { path := filepath.Join(entry, el) @@ -129,7 +129,7 @@ func recurseDynStrings(dynSym []string, searchPath []string, soName string) stri fd, err = os.OpenFile(path, os.O_RDONLY, 0644) if err != nil { //log.Fatal(err) - fmt.Printf("open file:%s error:%v\n", path, err) + fmt.Printf("open keylogger:%s error:%v\n", path, err) continue } else { // found diff --git a/user/probe_openssl.go b/user/probe_openssl.go index c60a418e9..a60455b5a 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -16,6 +16,7 @@ import ( "log" "math" "os" + "path/filepath" ) const ( @@ -40,6 +41,13 @@ type Tls13MasterSecret struct { ClientTrafficSecret0 []byte } +type EBPFPROGRAMTYPE uint8 + +const ( + EBPFPROGRAMTYPE_OPENSSL_TC EBPFPROGRAMTYPE = iota + EBPFPROGRAMTYPE_OPENSSL_UPROBE +) + type MOpenSSLProbe struct { Module bpfManager *manager.Manager @@ -50,9 +58,11 @@ type MOpenSSLProbe struct { // pid[fd:Addr] pidConns map[uint32]map[uint32]string - filename string - file *os.File - masterKeys map[string]bool + keyloggerFilename string + keylogger *os.File + masterKeys map[string]bool + eBPFProgramType EBPFPROGRAMTYPE + pcapngFilename string } //对象初始化 @@ -65,21 +75,30 @@ func (this *MOpenSSLProbe) Init(ctx context.Context, logger *log.Logger, conf IC this.pidConns = make(map[uint32]map[uint32]string) this.masterKeys = make(map[string]bool) fd := os.Getpid() - this.filename = fmt.Sprintf("ecapture_masterkey_%d.log", fd) - file, err := os.OpenFile(this.filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + this.keyloggerFilename = fmt.Sprintf("ecapture_masterkey_%d.log", fd) + file, err := os.OpenFile(this.keyloggerFilename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) if err != nil { return err } - this.file = file - this.logger.Printf("%s\tmaster key file: %s\n", this.Name(), this.filename) + this.keylogger = file + var writeFile = this.conf.(*OpensslConfig).Write + if len(writeFile) > 0 { + this.eBPFProgramType = EBPFPROGRAMTYPE_OPENSSL_TC + fileInfo, err := filepath.Abs(writeFile) + if err != nil { + return err + } + this.pcapngFilename = fileInfo + } else { + this.eBPFProgramType = EBPFPROGRAMTYPE_OPENSSL_UPROBE + this.logger.Printf("%s\tmaster key keylogger: %s\n", this.Name(), this.keyloggerFilename) + } + return nil } func (this *MOpenSSLProbe) Start() error { - if err := this.start(); err != nil { - return err - } - return nil + return this.start() } func (this *MOpenSSLProbe) start() error { @@ -90,16 +109,18 @@ func (this *MOpenSSLProbe) start() error { return fmt.Errorf("%s\tcouldn't find asset %v .", this.Name(), err) } - if len(this.conf.(*OpensslConfig).Write) > 0 { - // TC PROBE + // setup the managers + switch this.eBPFProgramType { + case EBPFPROGRAMTYPE_OPENSSL_TC: this.logger.Printf("%s\tTC MODEL\n", this.Name()) err = this.setupManagersTC() - } else { - // UPROBE + case EBPFPROGRAMTYPE_OPENSSL_UPROBE: + this.logger.Printf("%s\tUPROBE MODEL\n", this.Name()) + err = this.setupManagersUprobe() + default: this.logger.Printf("%s\tUPROBE MODEL\n", this.Name()) err = this.setupManagersUprobe() } - // setup the managers if err != nil { return fmt.Errorf("tls module couldn't find binPath %v .", err) @@ -160,84 +181,6 @@ func (this *MOpenSSLProbe) constantEditor() []manager.ConstantEditor { return editor } -func (this *MOpenSSLProbe) setupManagersTC() error { - var writeFile, ifname, binaryPath string - - writeFile = this.conf.(*OpensslConfig).Write - ifname = this.conf.(*OpensslConfig).Ifname - - _, err := os.Stat(writeFile) - if err != nil { - return err - } - - switch this.conf.(*OpensslConfig).elfType { - case ELF_TYPE_BIN: - binaryPath = this.conf.(*OpensslConfig).Curlpath - case ELF_TYPE_SO: - binaryPath = this.conf.(*OpensslConfig).Openssl - default: - //如果没找到 - binaryPath = "/lib/x86_64-linux-gnu/libssl.so.1.1" - } - - this.logger.Printf("%s\teBPF Program type TC, interface:%s, save pcapng file:%s\n", ifname, writeFile) - - this.bpfManager = &manager.Manager{ - Probes: []*manager.Probe{ - { - Section: "classifier/egress", - EbpfFuncName: "egress_cls_func", - Ifname: ifname, - NetworkDirection: manager.Egress, - }, - { - Section: "classifier/ingress", - EbpfFuncName: "ingress_cls_func", - Ifname: ifname, - NetworkDirection: manager.Ingress, - }, - // -------------------------------------------------- - - // openssl masterkey - { - Section: "uprobe/SSL_write_key", - EbpfFuncName: "probe_ssl_master_key", - AttachToFuncName: "SSL_write", - BinaryPath: binaryPath, - UID: "uprobe_ssl_master_key", - }, - }, - - Maps: []*manager.Map{ - { - Name: "mastersecret_events", - }, - }, - } - - this.bpfManagerOptions = manager.Options{ - DefaultKProbeMaxActive: 512, - - VerifierOptions: ebpf.CollectionOptions{ - Programs: ebpf.ProgramOptions{ - LogSize: 2097152, - }, - }, - - RLimit: &unix.Rlimit{ - Cur: math.MaxUint64, - Max: math.MaxUint64, - }, - } - - if this.conf.EnableGlobalVar() { - // 填充 RewriteContants 对应map - this.bpfManagerOptions.ConstantEditors = this.constantEditor() - } - return nil -} - func (this *MOpenSSLProbe) setupManagersUprobe() error { var binaryPath, libPthread string switch this.conf.(*OpensslConfig).elfType { @@ -527,7 +470,7 @@ func (this *MOpenSSLProbe) saveMasterSecret(event *MasterSecretEvent) { b = bytes.NewBufferString(fmt.Sprintf("%s %02x %02x\n", CLIENT_RANDOM, event.ClientRandom, event.MasterKey)) } v := tls_version{version: event.Version} - l, e := this.file.WriteString(b.String()) + l, e := this.keylogger.WriteString(b.String()) if e != nil { this.logger.Fatalf("%s: save CLIENT_RANDOM to file error:%s", v.String(), e.Error()) return diff --git a/user/probe_openssl_tc.go b/user/probe_openssl_tc.go new file mode 100644 index 000000000..8dd099f89 --- /dev/null +++ b/user/probe_openssl_tc.go @@ -0,0 +1,80 @@ +package user + +import ( + "github.com/cilium/ebpf" + manager "github.com/ehids/ebpfmanager" + "golang.org/x/sys/unix" + "math" +) + +func (this *MOpenSSLProbe) setupManagersTC() error { + var ifname, binaryPath string + + ifname = this.conf.(*OpensslConfig).Ifname + + switch this.conf.(*OpensslConfig).elfType { + case ELF_TYPE_BIN: + binaryPath = this.conf.(*OpensslConfig).Curlpath + case ELF_TYPE_SO: + binaryPath = this.conf.(*OpensslConfig).Openssl + default: + //如果没找到 + binaryPath = "/lib/x86_64-linux-gnu/libssl.so.1.1" + } + + this.logger.Printf("%s\tInterface:%s, Pcapng filepath:%s\n", this.Name(), ifname, this.pcapngFilename) + + this.bpfManager = &manager.Manager{ + Probes: []*manager.Probe{ + { + Section: "classifier/egress", + EbpfFuncName: "egress_cls_func", + Ifname: ifname, + NetworkDirection: manager.Egress, + }, + { + Section: "classifier/ingress", + EbpfFuncName: "ingress_cls_func", + Ifname: ifname, + NetworkDirection: manager.Ingress, + }, + // -------------------------------------------------- + + // openssl masterkey + { + Section: "uprobe/SSL_write_key", + EbpfFuncName: "probe_ssl_master_key", + AttachToFuncName: "SSL_write", + BinaryPath: binaryPath, + UID: "uprobe_ssl_master_key", + }, + }, + + Maps: []*manager.Map{ + { + Name: "mastersecret_events", + }, + }, + } + + this.bpfManagerOptions = manager.Options{ + DefaultKProbeMaxActive: 512, + + VerifierOptions: ebpf.CollectionOptions{ + Programs: ebpf.ProgramOptions{ + LogSize: 2097152, + }, + }, + + RLimit: &unix.Rlimit{ + Cur: math.MaxUint64, + Max: math.MaxUint64, + }, + } + + if this.conf.EnableGlobalVar() { + // 填充 RewriteContants 对应map + this.bpfManagerOptions.ConstantEditors = this.constantEditor() + } + return nil +} From 9b88333deafcf7f671204ef92ba29eea8f1e20ce Mon Sep 17 00:00:00 2001 From: CFC4N Date: Sat, 30 Jul 2022 19:58:10 +0800 Subject: [PATCH 11/18] kern : capture rawpacket from TC eBPF program. Signed-off-by: CFC4N --- Makefile | 1 + kern/common.h | 5 +- kern/ecapture.h | 7 +++ kern/masterkey_kern.h | 124 +++++++++++++++++++++------------------ kern/openssl_tc.h | 90 +++++++++++++++++++++++++--- user/event_openssl_tc.go | 71 ++++++++++++++++++++++ user/probe_openssl.go | 11 +++- user/probe_openssl_tc.go | 40 +++++++++++++ 8 files changed, 283 insertions(+), 66 deletions(-) create mode 100644 user/event_openssl_tc.go diff --git a/Makefile b/Makefile index 08228f918..f39718e21 100644 --- a/Makefile +++ b/Makefile @@ -353,6 +353,7 @@ format: @clang-format -i -style=$(STYLE) kern/*.c @clang-format -i -style=$(STYLE) kern/common.h @clang-format -i -style=$(STYLE) kern/masterkey_kern.h + @clang-format -i -style=$(STYLE) kern/openssl_tc.h autogen: .checkver_$(CMD_BPFTOOL) $(AUTOGENCMD) diff --git a/kern/common.h b/kern/common.h index b3aca107a..e58aad7d3 100644 --- a/kern/common.h +++ b/kern/common.h @@ -27,8 +27,9 @@ #define BASH_ERRNO_DEFAULT 128 ///////// for TC & XDP ebpf programs in openssl_tc.h -#define TC_ACT_OK 0 - +#define TC_ACT_OK 0 +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#define SKB_MAX_DATA_SIZE 2048 // Optional Target PID // .rodata section bug via : https://github.com/ehids/ecapture/issues/39 diff --git a/kern/ecapture.h b/kern/ecapture.h index 8d698ea0a..7f5c94446 100644 --- a/kern/ecapture.h +++ b/kern/ecapture.h @@ -7,6 +7,7 @@ #include "bpf/bpf_core_read.h" #include "bpf/bpf_helpers.h" #include "bpf/bpf_tracing.h" +#include "bpf/bpf_endian.h" #else #include @@ -15,6 +16,12 @@ #include #include #include +#include +#include +#include +#include +#include + #endif #include "common.h" diff --git a/kern/masterkey_kern.h b/kern/masterkey_kern.h index 64b074918..a78e69870 100644 --- a/kern/masterkey_kern.h +++ b/kern/masterkey_kern.h @@ -1,6 +1,5 @@ #include "ecapture.h" - // https://wiki.openssl.org/index.php/TLS1.3 // 仅openssl 1.1.1 后才支持 TLS 1.3 协议 @@ -28,17 +27,16 @@ #define SSL_S3_CLIENT_RANDOM_OFFSET 0xD8 // session->cipher 在 SSL_SESSION 中的偏移量 -#define SESSION_CIPHER_OFFSET 496 // 已计算 char *psk_identity_hint; + char *psk_identity; +#define SESSION_CIPHER_OFFSET 496 // session->cipher->id 在 ssl_cipher_st 中的偏移量 #define SESSION_CIPHER_ID_OFFSET 24 - - ////////// TLS 1.3 ///////// /* - // openssl 1.1.1J repo: https://github.com/openssl/openssl/tree/OpenSSL_1_1_1j + // openssl 1.1.1J repo: + https://github.com/openssl/openssl/tree/OpenSSL_1_1_1j // ssl/ssl_local.h line 1143 * The TLS1.3 secrets. unsigned char early_secret[EVP_MAX_MD_SIZE]; @@ -62,20 +60,19 @@ #define CIPHER_ID_OFFSET 0x18 // ssl->handshake_secret 在 ssl_st 中的偏移量 -#define HANDSHAKE_SECRET_OFFSET 0x13C // 316 +#define HANDSHAKE_SECRET_OFFSET 0x13C // 316 // ssl->master_secret 在 ssl_st 中的偏移量 -#define MASTER_SECRET_OFFSET 0x17C //380 +#define MASTER_SECRET_OFFSET 0x17C // 380 // ssl->server_finished_hash 在 ssl_st 中的偏移量 -#define SERVER_FINISHED_HASH_OFFSET 0x27C // 636 +#define SERVER_FINISHED_HASH_OFFSET 0x27C // 636 // ssl->handshake_traffic_hash 在 ssl_st 中的偏移量 -#define HANDSHAKE_TRAFFIC_HASH_OFFSET 0x2BC // 700 +#define HANDSHAKE_TRAFFIC_HASH_OFFSET 0x2BC // 700 // ssl->exporter_master_secret 在 ssl_st 中的偏移量 -#define EXPORTER_MASTER_SECRET_OFFSET 0x37C // 892 - +#define EXPORTER_MASTER_SECRET_OFFSET 0x37C // 892 struct mastersecret_t { // TLS 1.2 or older @@ -103,7 +100,7 @@ struct ssl3_state_st { unsigned char client_random[SSL3_RANDOM_SIZE]; }; -#define TLS1_3_VERSION 0x0304 +#define TLS1_3_VERSION 0x0304 /////////////////////////BPF MAPS //////////////////////////////// @@ -113,32 +110,31 @@ struct { } mastersecret_events SEC(".maps"); struct { - __uint(type, BPF_MAP_TYPE_LRU_HASH); - __type(key, u64); - __type(value, struct mastersecret_t); - __uint(max_entries, 2048); + __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); + __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; + 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) { @@ -171,23 +167,21 @@ int probe_ssl_master_key(struct pt_regs *ctx) { u64 *ssl_s3_st_ptr = (u64 *)(ssl_st_ptr + SSL_S3_OFFSET); int version; - int ret = bpf_probe_read_user(&version, sizeof(version), (void *)ssl_st_ptr); + int ret = + bpf_probe_read_user(&version, sizeof(version), (void *)ssl_st_ptr); if (ret) { - debug_bpf_printk( - "bpf_probe_read tls_version failed, ret :%d\n", ret); + debug_bpf_printk("bpf_probe_read tls_version failed, ret :%d\n", ret); return 0; } mastersecret->version = version; debug_bpf_printk("tls_version: %d\n", mastersecret->version); - // Get SSL_SESSION_t pointer u64 address; - ret = - bpf_probe_read_user(&address, sizeof(address), ssl_session_st_ptr); + ret = bpf_probe_read_user(&address, sizeof(address), ssl_session_st_ptr); if (ret) { - debug_bpf_printk( - "bpf_probe_read ssl_session_st_ptr failed, ret :%d\n", ret); + debug_bpf_printk("bpf_probe_read ssl_session_st_ptr failed, ret :%d\n", + ret); return 0; } @@ -199,13 +193,13 @@ int probe_ssl_master_key(struct pt_regs *ctx) { 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, ret :%d\n", ret); + debug_bpf_printk("bpf_probe_read MASTER_KEY_OFFSET failed, ret :%d\n", + ret); return 0; } - debug_bpf_printk("master_key: %x %x %x\n",mastersecret->master_key[0],mastersecret->master_key[1],mastersecret->master_key[2]); - + debug_bpf_printk("master_key: %x %x %x\n", mastersecret->master_key[0], + mastersecret->master_key[1], mastersecret->master_key[2]); // Get ssl3_state_st pointer ret = bpf_probe_read_user(&address, sizeof(address), ssl_s3_st_ptr); @@ -222,20 +216,23 @@ int probe_ssl_master_key(struct pt_regs *ctx) { "bpf_probe_read ssl3_state_st struct failed, ret :%d\n", ret); return 0; } - debug_bpf_printk("client_random: %x %x %x\n",ssl3_stat.client_random[0],ssl3_stat.client_random[1],ssl3_stat.client_random[2]); + debug_bpf_printk("client_random: %x %x %x\n", ssl3_stat.client_random[0], + ssl3_stat.client_random[1], ssl3_stat.client_random[2]); ret = bpf_probe_read_kernel(&mastersecret->client_random, - sizeof(mastersecret->client_random), - (void *)&ssl3_stat.client_random); + sizeof(mastersecret->client_random), + (void *)&ssl3_stat.client_random); if (ret) { debug_bpf_printk( - "bpf_probe_read_kernel ssl3_stat.client_random failed, ret :%d\n", ret); + "bpf_probe_read_kernel ssl3_stat.client_random failed, ret :%d\n", + ret); return 0; } - //////////////////// check tls version eq to TLS 1.3 //////////////////////// + //////////////////// check tls version eq to TLS 1.3 + /////////////////////////// if (version != TLS1_3_VERSION) { - bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, mastersecret, - sizeof(struct mastersecret_t)); + bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, + mastersecret, sizeof(struct mastersecret_t)); return 0; } @@ -243,8 +240,8 @@ int probe_ssl_master_key(struct pt_regs *ctx) { 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) { - debug_bpf_printk( - "bpf_probe_read ssl_cipher_st_ptr failed, ret :%d\n", ret); + debug_bpf_printk("bpf_probe_read ssl_cipher_st_ptr failed, ret :%d\n", + ret); return 0; } @@ -261,7 +258,9 @@ int probe_ssl_master_key(struct pt_regs *ctx) { //////////////////// TLS 1.3 master secret //////////////////////// void *hs_ptr_tls13 = (void *)(ssl_st_ptr + HANDSHAKE_SECRET_OFFSET); - ret = bpf_probe_read_user(&mastersecret->handshake_secret, sizeof(mastersecret->handshake_secret), (void *)hs_ptr_tls13); + ret = bpf_probe_read_user(&mastersecret->handshake_secret, + sizeof(mastersecret->handshake_secret), + (void *)hs_ptr_tls13); if (ret) { debug_bpf_printk( "bpf_probe_read HANDSHAKE_SECRET_OFFSET failed, ret :%d\n", ret); @@ -269,7 +268,9 @@ int probe_ssl_master_key(struct pt_regs *ctx) { } void *ms_ptr_tls13 = (void *)(ssl_st_ptr + MASTER_SECRET_OFFSET); - ret = bpf_probe_read_user(&mastersecret->master_secret, sizeof(mastersecret->master_secret), (void *)ms_ptr_tls13); + ret = bpf_probe_read_user(&mastersecret->master_secret, + sizeof(mastersecret->master_secret), + (void *)ms_ptr_tls13); if (ret) { debug_bpf_printk( "bpf_probe_read MASTER_SECRET_OFFSET failed, ret :%d\n", ret); @@ -277,30 +278,41 @@ int probe_ssl_master_key(struct pt_regs *ctx) { } void *sf_ptr_tls13 = (void *)(ssl_st_ptr + SERVER_FINISHED_HASH_OFFSET); - ret = bpf_probe_read_user(&mastersecret->server_finished_hash, sizeof(mastersecret->server_finished_hash), (void *)sf_ptr_tls13); + ret = bpf_probe_read_user(&mastersecret->server_finished_hash, + sizeof(mastersecret->server_finished_hash), + (void *)sf_ptr_tls13); if (ret) { debug_bpf_printk( - "bpf_probe_read SERVER_FINISHED_HASH_OFFSET failed, ret :%d\n", ret); + "bpf_probe_read SERVER_FINISHED_HASH_OFFSET failed, ret :%d\n", + ret); return 0; } void *hth_ptr_tls13 = (void *)(ssl_st_ptr + HANDSHAKE_TRAFFIC_HASH_OFFSET); - ret = bpf_probe_read_user(&mastersecret->handshake_traffic_hash, sizeof(mastersecret->handshake_traffic_hash), (void *)hth_ptr_tls13); + 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 HANDSHAKE_TRAFFIC_HASH_OFFSET failed, ret :%d\n", ret); + "bpf_probe_read HANDSHAKE_TRAFFIC_HASH_OFFSET failed, ret :%d\n", + ret); return 0; } void *ems_ptr_tls13 = (void *)(ssl_st_ptr + EXPORTER_MASTER_SECRET_OFFSET); - ret = bpf_probe_read_user(&mastersecret->exporter_master_secret, sizeof(mastersecret->exporter_master_secret), (void *)ems_ptr_tls13); + 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 EXPORTER_MASTER_SECRET_OFFSET failed, ret :%d\n", ret); + "bpf_probe_read EXPORTER_MASTER_SECRET_OFFSET failed, ret :%d\n", + ret); return 0; } - debug_bpf_printk("*****master_secret*****: %x %x %x\n",mastersecret->master_secret[0],mastersecret->master_secret[1],mastersecret->master_secret[2]); - bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, mastersecret, - sizeof(struct mastersecret_t)); + debug_bpf_printk( + "*****master_secret*****: %x %x %x\n", mastersecret->master_secret[0], + mastersecret->master_secret[1], mastersecret->master_secret[2]); + bpf_perf_event_output(ctx, &mastersecret_events, BPF_F_CURRENT_CPU, + mastersecret, sizeof(struct mastersecret_t)); return 0; } \ No newline at end of file diff --git a/kern/openssl_tc.h b/kern/openssl_tc.h index cebefd84f..3b3a1e58a 100644 --- a/kern/openssl_tc.h +++ b/kern/openssl_tc.h @@ -1,14 +1,90 @@ -SEC("classifier/egress") -int egress_cls_func(struct __sk_buff *skb) -{ - debug_bpf_printk("new packet captured on egress (TC)\n"); +struct skb_data_event_t { + u32 data_len; + char data[SKB_MAX_DATA_SIZE]; +}; + +////////////////////// ebpf maps ////////////////////// +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(max_entries, 1024); +} skb_events SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __type(key, u32); + __type(value, struct skb_data_event_t); + __uint(max_entries, 1); +} skb_data_buffer_heap SEC(".maps"); + +////////////////////// General helper functions ////////////////////// +static __inline struct skb_data_event_t* make_skb_data_event() { + u32 kZero = 0; + struct skb_data_event_t* event = + bpf_map_lookup_elem(&skb_data_buffer_heap, &kZero); + if (event == NULL) { + return NULL; + } + return event; +} + +///////////////////// ebpf functions ////////////////////// +int capture_packets(struct __sk_buff *skb) { + + // packet data + unsigned char *data_start = (void *)(long)skb->data; + unsigned char *data_end = (void *)(long)skb->data_end; + u32 data_len = (u32)skb->len; + + if (data_len < 70) { + return TC_ACT_OK; + } + // Ethernet headers + struct ethhdr *eth = (struct ethhdr *)data_start; + // IP headers + struct iphdr *iph = (struct iphdr *)(data_start + sizeof(struct ethhdr)); + + // Simple length check + if ((data_start + sizeof(struct ethhdr) + sizeof(struct iphdr)) > + data_end) { + return TC_ACT_OK; + } + + // filter out non-IP packets + // TODO support IPv6 + if (eth->h_proto != bpf_htons(ETH_P_IP)) { + return TC_ACT_OK; + } + + // filter out non-TCP packets + if (iph->protocol != IPPROTO_TCP) { + return TC_ACT_OK; + } + + struct skb_data_event_t* event = make_skb_data_event(); + if (event == NULL) { + return 0; + } + // make sure data_len is not negative + event->data_len = data_len; + + bpf_probe_read_kernel(event->data, sizeof(event->data), &data_start); + + bpf_perf_event_output(skb, &skb_events, BPF_F_CURRENT_CPU, event, + sizeof(struct skb_data_event_t)); + debug_bpf_printk("new packet captured on egress/ingress (TC), length:%d\n", data_len); return TC_ACT_OK; +} + +// egress_cls_func is called for packets that are going out of the network +SEC("classifier/egress") +int egress_cls_func(struct __sk_buff *skb) { + return capture_packets(skb); }; +// ingress_cls_func is called for packets that are coming into the network SEC("classifier/ingress") -int ingress_cls_func(struct __sk_buff *skb) -{ - debug_bpf_printk("new packet captured on ingress (TC)\n"); +int ingress_cls_func(struct __sk_buff *skb) { return TC_ACT_OK; + return capture_packets(skb); }; \ No newline at end of file diff --git a/user/event_openssl_tc.go b/user/event_openssl_tc.go new file mode 100644 index 000000000..bbaac294e --- /dev/null +++ b/user/event_openssl_tc.go @@ -0,0 +1,71 @@ +package user + +import ( + "bytes" + "ecapture/pkg/event_processor" + "encoding/binary" +) + +const ( + SKB_MAX_DATA_SIZE = 2048 +) + +type TcSkbEvent struct { + module IModule + event_type event_processor.EventType + + DataLen uint32 + Data [SKB_MAX_DATA_SIZE]byte + + payload string +} + +func (this *TcSkbEvent) Decode(payload []byte) (err error) { + buf := bytes.NewBuffer(payload) + if err = binary.Read(buf, binary.LittleEndian, &this.DataLen); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.Data); err != nil { + return + } + return nil +} + +func (this *TcSkbEvent) StringHex() string { + return "[internal data]" +} + +func (this *TcSkbEvent) String() string { + return "[internal data]" +} + +func (this *TcSkbEvent) SetModule(module IModule) { + this.module = module +} + +func (this *TcSkbEvent) Module() IModule { + return this.module +} + +func (this *TcSkbEvent) Clone() event_processor.IEventStruct { + event := new(TcSkbEvent) + event.module = this.module + event.event_type = event_processor.EventTypeModuleData + return event +} + +func (this *TcSkbEvent) EventType() event_processor.EventType { + return this.event_type +} + +func (this *TcSkbEvent) GetUUID() string { + return "[internal data]" +} + +func (this *TcSkbEvent) Payload() []byte { + return []byte(this.payload) +} + +func (this *TcSkbEvent) PayloadLen() int { + return len(this.payload) +} diff --git a/user/probe_openssl.go b/user/probe_openssl.go index a60455b5a..0c83f147c 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -137,7 +137,14 @@ func (this *MOpenSSLProbe) start() error { } // 加载map信息,map对应events decode表。 - err = this.initDecodeFun() + switch this.eBPFProgramType { + case EBPFPROGRAMTYPE_OPENSSL_TC: + err = this.initDecodeFunTC() + case EBPFPROGRAMTYPE_OPENSSL_UPROBE: + err = this.initDecodeFun() + default: + err = this.initDecodeFun() + } if err != nil { return err } @@ -485,6 +492,8 @@ func (this *MOpenSSLProbe) Dispatcher(event event_processor.IEventStruct) { this.AddConn(event.(*ConnDataEvent).Pid, event.(*ConnDataEvent).Fd, event.(*ConnDataEvent).Addr) case *MasterSecretEvent: this.saveMasterSecret(event.(*MasterSecretEvent)) + case *TcSkbEvent: + this.dumpTcSkb(event.(*TcSkbEvent)) } //this.logger.Println(event) } diff --git a/user/probe_openssl_tc.go b/user/probe_openssl_tc.go index 8dd099f89..3303467dd 100644 --- a/user/probe_openssl_tc.go +++ b/user/probe_openssl_tc.go @@ -1,6 +1,7 @@ package user import ( + "errors" "github.com/cilium/ebpf" manager "github.com/ehids/ebpfmanager" "golang.org/x/sys/unix" @@ -26,6 +27,9 @@ func (this *MOpenSSLProbe) setupManagersTC() error { this.bpfManager = &manager.Manager{ Probes: []*manager.Probe{ + // customize deleteed TC filter + // tc filter del dev eth0 ingress + // tc filter del dev eth0 egress { Section: "classifier/egress", EbpfFuncName: "egress_cls_func", @@ -54,6 +58,9 @@ func (this *MOpenSSLProbe) setupManagersTC() error { { Name: "mastersecret_events", }, + { + Name: "skb_events", + }, }, } @@ -78,3 +85,36 @@ func (this *MOpenSSLProbe) setupManagersTC() error { } return nil } + +func (this *MOpenSSLProbe) initDecodeFunTC() error { + //SSLDumpEventsMap 与解码函数映射 + SkbEventsMap, found, err := this.bpfManager.GetMap("skb_events") + if err != nil { + return err + } + if !found { + return errors.New("cant found map:skb_events") + } + this.eventMaps = append(this.eventMaps, SkbEventsMap) + sslEvent := &TcSkbEvent{} + sslEvent.SetModule(this) + this.eventFuncMaps[SkbEventsMap] = sslEvent + + MasterkeyEventsMap, found, err := this.bpfManager.GetMap("mastersecret_events") + if err != nil { + return err + } + if !found { + return errors.New("cant found map:mastersecret_events") + } + this.eventMaps = append(this.eventMaps, MasterkeyEventsMap) + masterkeyEvent := &MasterSecretEvent{} + masterkeyEvent.SetModule(this) + this.eventFuncMaps[MasterkeyEventsMap] = masterkeyEvent + return nil +} + +func (this *MOpenSSLProbe) dumpTcSkb(event *TcSkbEvent) { + this.logger.Printf("%s\t%s, length:%d\n", this.Name(), event.String(), event.DataLen) + return +} From 03dbfe42c5a8381f9469f09c64df122a6b0026bc Mon Sep 17 00:00:00 2001 From: CFC4N Date: Tue, 2 Aug 2022 20:56:27 +0800 Subject: [PATCH 12/18] kern : add port filter for TC probe. Signed-off-by: CFC4N --- kern/openssl_tc.h | 71 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/kern/openssl_tc.h b/kern/openssl_tc.h index 3b3a1e58a..b96987fe4 100644 --- a/kern/openssl_tc.h +++ b/kern/openssl_tc.h @@ -4,6 +4,17 @@ struct skb_data_event_t { char data[SKB_MAX_DATA_SIZE]; }; +typedef struct net_id { + struct in6_addr address; + u16 port; + u16 protocol; +} net_id_t; + +typedef struct net_ctx { + u32 host_tid; + char comm[TASK_COMM_LEN]; +} net_ctx_t; + ////////////////////// ebpf maps ////////////////////// struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); @@ -17,6 +28,15 @@ struct { __uint(max_entries, 1); } skb_data_buffer_heap SEC(".maps"); +/* +struct { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __type(key, struct net_id_t); + __type(value, struct net_ctx_t); + __uint(max_entries, 10240); +} network_map SEC(".maps"); +*/ + ////////////////////// General helper functions ////////////////////// static __inline struct skb_data_event_t* make_skb_data_event() { u32 kZero = 0; @@ -28,25 +48,42 @@ static __inline struct skb_data_event_t* make_skb_data_event() { return event; } +static __always_inline bool +skb_revalidate_data(struct __sk_buff *skb, uint8_t **head, uint8_t **tail, const u32 offset) +{ + if (*head + offset > *tail) { + if (bpf_skb_pull_data(skb, offset) < 0) { + return false; + } + + *head = (uint8_t *) (long) skb->data; + *tail = (uint8_t *) (long) skb->data_end; + + if (*head + offset > *tail) { + return false; + } + } + + return true; +} + ///////////////////// ebpf functions ////////////////////// -int capture_packets(struct __sk_buff *skb) { +int capture_packets(struct __sk_buff *skb, bool is_ingress) { + // packet data unsigned char *data_start = (void *)(long)skb->data; unsigned char *data_end = (void *)(long)skb->data_end; u32 data_len = (u32)skb->len; + uint32_t l4_hdr_off; - if (data_len < 70) { - return TC_ACT_OK; - } // Ethernet headers struct ethhdr *eth = (struct ethhdr *)data_start; // IP headers struct iphdr *iph = (struct iphdr *)(data_start + sizeof(struct ethhdr)); // Simple length check - if ((data_start + sizeof(struct ethhdr) + sizeof(struct iphdr)) > - data_end) { + if ((data_start + sizeof(struct ethhdr) + sizeof(struct iphdr)) > data_end) { return TC_ACT_OK; } @@ -55,13 +92,31 @@ int capture_packets(struct __sk_buff *skb) { if (eth->h_proto != bpf_htons(ETH_P_IP)) { return TC_ACT_OK; } + l4_hdr_off = sizeof(struct ethhdr) + sizeof(struct iphdr); + if (!skb_revalidate_data(skb, &data_start, &data_end, l4_hdr_off)) + { + return TC_ACT_OK; + } // filter out non-TCP packets if (iph->protocol != IPPROTO_TCP) { return TC_ACT_OK; } + if (!skb_revalidate_data(skb, &data_start, &data_end, l4_hdr_off + sizeof(struct tcphdr))) + { + return TC_ACT_UNSPEC; + } + struct tcphdr *tcp = (struct tcphdr *) (data_start + l4_hdr_off); + if (tcp->source != bpf_htons(443) && tcp->dest != bpf_htons(443)) { + return TC_ACT_OK; + } + + debug_bpf_printk("capture_packets port : %d, dest port :%d\n", bpf_ntohs(tcp->source), bpf_ntohs(tcp->dest)); + // get the skb data event + net_id_t connect_id = {0}; struct skb_data_event_t* event = make_skb_data_event(); + if (event == NULL) { return 0; } @@ -79,12 +134,12 @@ int capture_packets(struct __sk_buff *skb) { // egress_cls_func is called for packets that are going out of the network SEC("classifier/egress") int egress_cls_func(struct __sk_buff *skb) { - return capture_packets(skb); + return capture_packets(skb, false); }; // ingress_cls_func is called for packets that are coming into the network SEC("classifier/ingress") int ingress_cls_func(struct __sk_buff *skb) { return TC_ACT_OK; - return capture_packets(skb); + return capture_packets(skb, true); }; \ No newline at end of file From 283dbaf1022c12e3a489ae4d50b33104e5c193bd Mon Sep 17 00:00:00 2001 From: CFC4N Date: Tue, 2 Aug 2022 20:58:35 +0800 Subject: [PATCH 13/18] user : add pcap writer. Signed-off-by: CFC4N --- go.mod | 3 +- go.sum | 15 ++++-- user/probe_openssl.go | 14 ++++- user/probe_openssl_tc.go | 114 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 136 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 1017e068a..8c7dc5c99 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,10 @@ go 1.17 require ( github.com/cilium/ebpf v0.9.0 github.com/ehids/ebpfmanager v0.3.0 + github.com/google/gopacket v1.1.19 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa golang.org/x/sys v0.0.0-20211210111614-af8b64212486 ) @@ -24,6 +26,5 @@ require ( github.com/stretchr/testify v1.7.0 // indirect github.com/vishvananda/netlink v1.1.0 // indirect github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect ) diff --git a/go.sum b/go.sum index ba8cf214b..dd0f608dc 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -70,7 +72,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shuLhan/go-bindata v4.0.0+incompatible h1:xD8LkuVZLV5OOn/IEuFdt6EEAW7deWiqgwaaSGhjAJc= github.com/shuLhan/go-bindata v4.0.0+incompatible/go.mod h1:pkcPAATLBDD2+SpAPnX5vEM90F7fcwHCvvLCMXcmw3g= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= @@ -87,11 +88,15 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -101,10 +106,10 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -126,6 +131,7 @@ golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -134,6 +140,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -141,6 +149,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/user/probe_openssl.go b/user/probe_openssl.go index 0c83f147c..fee20d454 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -11,6 +11,7 @@ import ( "fmt" "github.com/cilium/ebpf" manager "github.com/ehids/ebpfmanager" + "github.com/google/gopacket/pcapgo" "golang.org/x/sys/unix" "hash" "log" @@ -63,6 +64,9 @@ type MOpenSSLProbe struct { masterKeys map[string]bool eBPFProgramType EBPFPROGRAMTYPE pcapngFilename string + ifIdex int + ifName string + pcapWriter *pcapgo.NgWriter } //对象初始化 @@ -153,10 +157,18 @@ func (this *MOpenSSLProbe) start() error { } func (this *MOpenSSLProbe) Close() error { + if this.eBPFProgramType == EBPFPROGRAMTYPE_OPENSSL_TC { + this.logger.Printf("saving pcapng file %s\n", this.pcapngFilename) + err := this.savePcapng() + if err != nil { + return err + } + } + if err := this.bpfManager.Stop(manager.CleanAll); err != nil { return fmt.Errorf("couldn't stop manager %v .", err) } - return nil + return this.Module.Close() } // 通过elf的常量替换方式传递数据 diff --git a/user/probe_openssl_tc.go b/user/probe_openssl_tc.go index 3303467dd..49bbb8873 100644 --- a/user/probe_openssl_tc.go +++ b/user/probe_openssl_tc.go @@ -2,16 +2,49 @@ package user import ( "errors" + "fmt" "github.com/cilium/ebpf" manager "github.com/ehids/ebpfmanager" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcapgo" "golang.org/x/sys/unix" "math" + "net" + "os" + "time" ) +type netPcap struct { + FileObj os.File + Writer pcapgo.NgWriter +} + +type NetCaptureData struct { + PacketLength uint32 `json:"pktLen"` + ConfigIfaceIndex uint32 `json:"ifIndex"` +} + +func (NetCaptureData) GetSizeBytes() uint32 { + return 8 +} + +type NetEventMetadata struct { + TimeStamp uint64 `json:"timeStamp"` + HostTid uint32 `json:"hostTid"` + ProcessName [16]byte `json:"processName"` +} + func (this *MOpenSSLProbe) setupManagersTC() error { var ifname, binaryPath string ifname = this.conf.(*OpensslConfig).Ifname + this.ifName = ifname + interf, err := net.InterfaceByName(this.conf.(*OpensslConfig).Ifname) + if err != nil { + return err + } + this.ifIdex = interf.Index switch this.conf.(*OpensslConfig).elfType { case ELF_TYPE_BIN: @@ -25,21 +58,33 @@ func (this *MOpenSSLProbe) setupManagersTC() error { this.logger.Printf("%s\tInterface:%s, Pcapng filepath:%s\n", this.Name(), ifname, this.pcapngFilename) + // create pcapng writer + err = this.createPcapng() + if err != nil { + return err + } + this.bpfManager = &manager.Manager{ Probes: []*manager.Probe{ // customize deleteed TC filter // tc filter del dev eth0 ingress // tc filter del dev eth0 egress + // loopback devices are special, some tc probes should be skipped + // TODO: detect loopback devices via aquasecrity/tracee/pkg/ebpf/probes/probe.go line 322 + // isNetIfaceLo := netIface.Flags&net.FlagLoopback == net.FlagLoopback + // if isNetIfaceLo && p.skipLoopback { + // return nil + // } { Section: "classifier/egress", EbpfFuncName: "egress_cls_func", - Ifname: ifname, + Ifname: this.ifName, NetworkDirection: manager.Egress, }, { Section: "classifier/ingress", EbpfFuncName: "ingress_cls_func", - Ifname: ifname, + Ifname: this.ifName, NetworkDirection: manager.Ingress, }, // -------------------------------------------------- @@ -114,7 +159,68 @@ func (this *MOpenSSLProbe) initDecodeFunTC() error { return nil } -func (this *MOpenSSLProbe) dumpTcSkb(event *TcSkbEvent) { +func (this *MOpenSSLProbe) dumpTcSkb(event *TcSkbEvent) error { + this.logger.Printf("%s\t%s, length:%d\n", this.Name(), event.String(), event.DataLen) - return + var netEventMetadata *NetEventMetadata = &NetEventMetadata{} + netEventMetadata.TimeStamp = uint64(time.Now().UnixNano()) + + packetBytes := make([]byte, event.DataLen) + packetBytes = event.Data[:event.DataLen] + if err := this.writePacket(event.DataLen, this.ifIdex, time.Unix(0, int64(netEventMetadata.TimeStamp)), packetBytes); err != nil { + return err + } + return nil +} + +// save pcapng file ,merge master key into pcapng file TODO +func (this *MOpenSSLProbe) savePcapng() error { + return this.pcapWriter.Flush() +} + +func (this *MOpenSSLProbe) createPcapng() error { + + pcapFile, err := os.OpenFile(this.pcapngFilename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + return fmt.Errorf("error creating pcap file: %v", err) + } + + ngIface := pcapgo.NgInterface{ + Name: this.conf.(*OpensslConfig).Ifname, + Comment: "eCapture TC capture", + Filter: "", + LinkType: layers.LinkTypeEthernet, + SnapLength: uint32(math.MaxUint16), + } + + pcapWriter, err := pcapgo.NewNgWriterInterface(pcapFile, ngIface, pcapgo.NgWriterOptions{}) + if err != nil { + return err + } + + // Flush the header + err = pcapWriter.Flush() + if err != nil { + return err + } + + // TODO 保存数据包所属进程ID信息,以LRU Cache方式存储。 + this.pcapWriter = pcapWriter + return nil +} + +func (this *MOpenSSLProbe) writePacket(dataLen uint32, ifaceIdx int, timeStamp time.Time, packetBytes []byte) error { + info := gopacket.CaptureInfo{ + Timestamp: timeStamp, + CaptureLength: int(dataLen), + Length: int(dataLen), + InterfaceIndex: ifaceIdx, + } + + // TODO 按照进程PID方式,划分独立的Writer + err := this.pcapWriter.WritePacket(info, packetBytes) + if err != nil { + return err + } + return nil } From def9373e2339864fc0f7df68a49ab515be4d7330 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Tue, 2 Aug 2022 21:10:14 +0800 Subject: [PATCH 14/18] go.sum : revert go-bindata package add go-bindata to go.sum for Makefile script. Signed-off-by: CFC4N --- go.sum | 1 + main.go | 1 + 2 files changed, 2 insertions(+) diff --git a/go.sum b/go.sum index dd0f608dc..8be1400a1 100644 --- a/go.sum +++ b/go.sum @@ -72,6 +72,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shuLhan/go-bindata v4.0.0+incompatible h1:xD8LkuVZLV5OOn/IEuFdt6EEAW7deWiqgwaaSGhjAJc= github.com/shuLhan/go-bindata v4.0.0+incompatible/go.mod h1:pkcPAATLBDD2+SpAPnX5vEM90F7fcwHCvvLCMXcmw3g= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= diff --git a/main.go b/main.go index 5b40f1d2a..028d9d63e 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "ecapture/cli" "ecapture/pkg/util/ebpf" "ecapture/pkg/util/kernel" + _ "github.com/shuLhan/go-bindata" // add for bindata in Makefile "log" ) From c90747c4e42df934e587c3239e0137ada5ea8567 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Tue, 2 Aug 2022 21:10:46 +0800 Subject: [PATCH 15/18] cli/cmd : fix variable name. Signed-off-by: CFC4N --- cli/cmd/tls.go | 6 +++--- kern/openssl_tc.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/cmd/tls.go b/cli/cmd/tls.go index b26bc179c..a16b2f884 100644 --- a/cli/cmd/tls.go +++ b/cli/cmd/tls.go @@ -152,9 +152,9 @@ func openSSLCommandFunc(command *cobra.Command, args []string) { // clean up for _, mod := range runModules { - e = mod.Close() - if e != nil { - logger.Fatalf("%s\tmodule close failed. error:%+v", mod.Name(), e) + err = mod.Close() + if err != nil { + logger.Fatalf("%s\tmodule close failed. error:%+v", mod.Name(), err) } wg.Done() } diff --git a/kern/openssl_tc.h b/kern/openssl_tc.h index b96987fe4..bce3637a9 100644 --- a/kern/openssl_tc.h +++ b/kern/openssl_tc.h @@ -104,7 +104,7 @@ int capture_packets(struct __sk_buff *skb, bool is_ingress) { } if (!skb_revalidate_data(skb, &data_start, &data_end, l4_hdr_off + sizeof(struct tcphdr))) { - return TC_ACT_UNSPEC; + return TC_ACT_OK; } struct tcphdr *tcp = (struct tcphdr *) (data_start + l4_hdr_off); From e6dfa38a4ae321535d4b57c84e3b3857b04630df Mon Sep 17 00:00:00 2001 From: CFC4N Date: Tue, 2 Aug 2022 21:14:42 +0800 Subject: [PATCH 16/18] user : remove return value. Signed-off-by: CFC4N --- user/probe_openssl_tc.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user/probe_openssl_tc.go b/user/probe_openssl_tc.go index 49bbb8873..15eacacf5 100644 --- a/user/probe_openssl_tc.go +++ b/user/probe_openssl_tc.go @@ -159,7 +159,7 @@ func (this *MOpenSSLProbe) initDecodeFunTC() error { return nil } -func (this *MOpenSSLProbe) dumpTcSkb(event *TcSkbEvent) error { +func (this *MOpenSSLProbe) dumpTcSkb(event *TcSkbEvent) { this.logger.Printf("%s\t%s, length:%d\n", this.Name(), event.String(), event.DataLen) var netEventMetadata *NetEventMetadata = &NetEventMetadata{} @@ -168,9 +168,9 @@ func (this *MOpenSSLProbe) dumpTcSkb(event *TcSkbEvent) error { packetBytes := make([]byte, event.DataLen) packetBytes = event.Data[:event.DataLen] if err := this.writePacket(event.DataLen, this.ifIdex, time.Unix(0, int64(netEventMetadata.TimeStamp)), packetBytes); err != nil { - return err + this.logger.Printf("%s\t save packet error %s .\n", this.Name(), err.Error()) } - return nil + return } // save pcapng file ,merge master key into pcapng file TODO From 1cf4ba59a1fd2d632dd130e55925ac7178c9f87a Mon Sep 17 00:00:00 2001 From: CFC4N Date: Wed, 3 Aug 2022 20:52:13 +0800 Subject: [PATCH 17/18] user : improve TCP packet captured. Signed-off-by: CFC4N --- kern/openssl_tc.h | 38 +++++++++++++++++++++------------ user/event_openssl_tc.go | 46 +++++++++++++++++++++++++++++----------- user/probe_openssl.go | 12 +++++++++++ user/probe_openssl_tc.go | 37 ++++++++++++++++++++++++-------- 4 files changed, 98 insertions(+), 35 deletions(-) diff --git a/kern/openssl_tc.h b/kern/openssl_tc.h index bce3637a9..d415cde27 100644 --- a/kern/openssl_tc.h +++ b/kern/openssl_tc.h @@ -1,7 +1,11 @@ +#define TC_PACKET_MIN_SIZE 36 struct skb_data_event_t { - u32 data_len; - char data[SKB_MAX_DATA_SIZE]; + uint64_t ts; + u32 pid; + char comm[TASK_COMM_LEN]; + u32 len; + u32 ifindex; }; typedef struct net_id { @@ -70,7 +74,6 @@ skb_revalidate_data(struct __sk_buff *skb, uint8_t **head, uint8_t **tail, const ///////////////////// ebpf functions ////////////////////// int capture_packets(struct __sk_buff *skb, bool is_ingress) { - // packet data unsigned char *data_start = (void *)(long)skb->data; unsigned char *data_end = (void *)(long)skb->data_end; @@ -115,18 +118,25 @@ int capture_packets(struct __sk_buff *skb, bool is_ingress) { debug_bpf_printk("capture_packets port : %d, dest port :%d\n", bpf_ntohs(tcp->source), bpf_ntohs(tcp->dest)); // get the skb data event net_id_t connect_id = {0}; - struct skb_data_event_t* event = make_skb_data_event(); - - if (event == NULL) { - return 0; - } - // make sure data_len is not negative - event->data_len = data_len; - - bpf_probe_read_kernel(event->data, sizeof(event->data), &data_start); + // new packet event + struct skb_data_event_t event = {0}; + event.ts = bpf_ktime_get_ns(); + event.len = skb->len; + event.ifindex = skb->ifindex; + + u64 flags = BPF_F_CURRENT_CPU; + flags |= (u64) skb->len << 32; + + // via aquasecurity/tracee tracee.bpf.c tc_probe + // if net_packet event not chosen, send minimal data only: + // timestamp (u64) 8 bytes + // pid (u32) 4 bytes + // comm (char[]) 16 bytes + // packet len (u32) 4 bytes + // ifindex (u32) 4 bytes + size_t pkt_size = TC_PACKET_MIN_SIZE; + bpf_perf_event_output(skb, &skb_events, flags, &event, pkt_size); - bpf_perf_event_output(skb, &skb_events, BPF_F_CURRENT_CPU, event, - sizeof(struct skb_data_event_t)); debug_bpf_printk("new packet captured on egress/ingress (TC), length:%d\n", data_len); return TC_ACT_OK; } diff --git a/user/event_openssl_tc.go b/user/event_openssl_tc.go index bbaac294e..502e1f9df 100644 --- a/user/event_openssl_tc.go +++ b/user/event_openssl_tc.go @@ -4,39 +4,61 @@ import ( "bytes" "ecapture/pkg/event_processor" "encoding/binary" + "fmt" ) const ( SKB_MAX_DATA_SIZE = 2048 + TASK_COMM_LEN = 16 ) type TcSkbEvent struct { module IModule event_type event_processor.EventType - - DataLen uint32 - Data [SKB_MAX_DATA_SIZE]byte - - payload string + Ts uint64 + Pid uint32 + Comm [TASK_COMM_LEN]byte + Len uint32 + Ifindex uint32 + payload []byte } func (this *TcSkbEvent) Decode(payload []byte) (err error) { buf := bytes.NewBuffer(payload) - if err = binary.Read(buf, binary.LittleEndian, &this.DataLen); err != nil { + if err = binary.Read(buf, binary.LittleEndian, &this.Ts); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.Pid); err != nil { + return + } + if err = binary.Read(buf, binary.LittleEndian, &this.Comm); err != nil { return } - if err = binary.Read(buf, binary.LittleEndian, &this.Data); err != nil { + if err = binary.Read(buf, binary.LittleEndian, &this.Len); err != nil { return } + if err = binary.Read(buf, binary.LittleEndian, &this.Ifindex); err != nil { + return + } + tmpData := make([]byte, this.Len) + if err = binary.Read(buf, binary.LittleEndian, &tmpData); err != nil { + return + } + this.payload = tmpData return nil } func (this *TcSkbEvent) StringHex() string { - return "[internal data]" + b := dumpByteSlice(this.payload, COLORGREEN) + b.WriteString(COLORRESET) + s := fmt.Sprintf("Pid:%d, Comm:%s, Length:%d, Ifindex:%d, Payload:%s", this.Pid, this.Comm, this.Len, this.Ifindex, b.String()) + return s } func (this *TcSkbEvent) String() string { - return "[internal data]" + + s := fmt.Sprintf("Pid:%d, Comm:%s, Length:%d, Ifindex:%d, Payload:[internal data]", this.Pid, this.Comm, this.Len, this.Ifindex) + return s } func (this *TcSkbEvent) SetModule(module IModule) { @@ -59,13 +81,13 @@ func (this *TcSkbEvent) EventType() event_processor.EventType { } func (this *TcSkbEvent) GetUUID() string { - return "[internal data]" + return fmt.Sprintf("%d-%d-%s", this.Pid, this.Ifindex, this.Comm) } func (this *TcSkbEvent) Payload() []byte { - return []byte(this.payload) + return this.payload } func (this *TcSkbEvent) PayloadLen() int { - return len(this.payload) + return int(this.Len) } diff --git a/user/probe_openssl.go b/user/probe_openssl.go index 3c69e0174..8543bd189 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -18,6 +18,7 @@ import ( "math" "os" "path/filepath" + "time" ) const ( @@ -67,6 +68,8 @@ type MOpenSSLProbe struct { ifIdex int ifName string pcapWriter *pcapgo.NgWriter + startTime uint64 + bootTime uint64 } //对象初始化 @@ -98,6 +101,15 @@ func (this *MOpenSSLProbe) Init(ctx context.Context, logger *log.Logger, conf IC this.logger.Printf("%s\tmaster key keylogger: %s\n", this.Name(), this.keyloggerFilename) } + var ts unix.Timespec + unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts) + startTime := ts.Nano() + // Calculate the boot time using the monotonic time (since this is the clock we're using as a timestamp) + // Note: this is NOT the real boot time, as the monotonic clock doesn't take into account system sleeps. + bootTime := time.Now().UnixNano() - startTime + + this.startTime = uint64(startTime) + this.bootTime = uint64(bootTime) return nil } diff --git a/user/probe_openssl_tc.go b/user/probe_openssl_tc.go index 15eacacf5..cbafce4da 100644 --- a/user/probe_openssl_tc.go +++ b/user/probe_openssl_tc.go @@ -59,7 +59,12 @@ func (this *MOpenSSLProbe) setupManagersTC() error { this.logger.Printf("%s\tInterface:%s, Pcapng filepath:%s\n", this.Name(), ifname, this.pcapngFilename) // create pcapng writer - err = this.createPcapng() + netIfs, err := net.Interfaces() + if err != nil { + return err + } + + err = this.createPcapng(netIfs[1:]) if err != nil { return err } @@ -161,13 +166,13 @@ func (this *MOpenSSLProbe) initDecodeFunTC() error { func (this *MOpenSSLProbe) dumpTcSkb(event *TcSkbEvent) { - this.logger.Printf("%s\t%s, length:%d\n", this.Name(), event.String(), event.DataLen) + this.logger.Printf("%s\t%s\n", this.Name(), event.String()) var netEventMetadata *NetEventMetadata = &NetEventMetadata{} - netEventMetadata.TimeStamp = uint64(time.Now().UnixNano()) + // timeStamp is nanoseconds since system boot time + // To get the monotonic time since tracee was started, we have to subtract the start time from the timestamp. + netEventMetadata.TimeStamp += this.bootTime - packetBytes := make([]byte, event.DataLen) - packetBytes = event.Data[:event.DataLen] - if err := this.writePacket(event.DataLen, this.ifIdex, time.Unix(0, int64(netEventMetadata.TimeStamp)), packetBytes); err != nil { + if err := this.writePacket(event.Len, this.ifIdex, time.Unix(0, int64(netEventMetadata.TimeStamp)), event.Payload()); err != nil { this.logger.Printf("%s\t save packet error %s .\n", this.Name(), err.Error()) } return @@ -178,8 +183,7 @@ func (this *MOpenSSLProbe) savePcapng() error { return this.pcapWriter.Flush() } -func (this *MOpenSSLProbe) createPcapng() error { - +func (this *MOpenSSLProbe) createPcapng(netIfs []net.Interface) error { pcapFile, err := os.OpenFile(this.pcapngFilename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return fmt.Errorf("error creating pcap file: %v", err) @@ -187,7 +191,7 @@ func (this *MOpenSSLProbe) createPcapng() error { ngIface := pcapgo.NgInterface{ Name: this.conf.(*OpensslConfig).Ifname, - Comment: "eCapture TC capture", + Comment: "eCapture (旁观者): github.com/ehids/ecapture", Filter: "", LinkType: layers.LinkTypeEthernet, SnapLength: uint32(math.MaxUint16), @@ -198,6 +202,21 @@ func (this *MOpenSSLProbe) createPcapng() error { return err } + // insert other interfaces into pcapng file + for _, iface := range netIfs { + ngIface = pcapgo.NgInterface{ + Name: iface.Name, + Comment: "eCapture (旁观者): github.com/ehids/ecapture", + Filter: "", + LinkType: layers.LinkTypeEthernet, + SnapLength: uint32(math.MaxUint16), + } + + _, err := pcapWriter.AddInterface(ngIface) + if err != nil { + return err + } + } // Flush the header err = pcapWriter.Flush() if err != nil { From c31a460496d936be024baef799e6775c878bf1c0 Mon Sep 17 00:00:00 2001 From: CFC4N Date: Wed, 3 Aug 2022 20:57:22 +0800 Subject: [PATCH 18/18] user : check error, return value of `unix.ClockGettime`. Signed-off-by: CFC4N --- user/probe_openssl.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/user/probe_openssl.go b/user/probe_openssl.go index 8543bd189..e263802c2 100644 --- a/user/probe_openssl.go +++ b/user/probe_openssl.go @@ -102,7 +102,10 @@ func (this *MOpenSSLProbe) Init(ctx context.Context, logger *log.Logger, conf IC } var ts unix.Timespec - unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts) + err = unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts) + if err != nil { + return err + } startTime := ts.Nano() // Calculate the boot time using the monotonic time (since this is the clock we're using as a timestamp) // Note: this is NOT the real boot time, as the monotonic clock doesn't take into account system sleeps.