Skip to content

Instantly share code, notes, and snippets.

@NathanFrench
Last active March 20, 2022 07:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NathanFrench/d38ab24b98a3d5c9536e8993e7964997 to your computer and use it in GitHub Desktop.
Save NathanFrench/d38ab24b98a3d5c9536e8993e7964997 to your computer and use it in GitHub Desktop.
gobpf SSL snooper.
pid:28357 (openssl)
--------
00000000 48 54 54 50 2f 31 2e 31 20 34 30 30 20 42 61 64 |HTTP/1.1 400 Bad|
00000010 20 52 65 71 75 65 73 74 0d 0a 53 65 72 76 65 72 | Request..Server|
00000020 3a 20 63 6c 6f 75 64 66 6c 61 72 65 2d 6e 67 69 |: cloudflare-ngi|
00000030 6e 78 0d 0a 44 61 74 65 3a 20 54 75 65 2c 20 30 |nx..Date: Tue, 0|
00000040 32 20 4a 61 6e 20 32 30 31 38 20 32 33 3a 30 37 |2 Jan 2018 23:07|
00000050 3a 30 37 20 47 4d 54 0d 0a 43 6f 6e 74 65 6e 74 |:07 GMT..Content|
00000060 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74 6d 6c |-Type: text/html|
00000070 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 |..Content-Length|
00000080 3a 20 31 37 37 0d 0a 43 6f 6e 6e 65 63 74 69 6f |: 177..Connectio|
00000090 6e 3a 20 63 6c 6f 73 65 0d 0a 43 46 2d 52 41 59 |n: close..CF-RAY|
000000a0 3a 20 2d 0d 0a 0d 0a 3c 68 74 6d 6c 3e 0d 0a 3c |: -....<html>..<|
000000b0 68 65 61 64 3e 3c 74 69 74 6c 65 3e 34 30 30 20 |head><title>400 |
000000c0 42 61 64 20 52 65 71 75 65 73 74 3c 2f 74 69 74 |Bad Request</tit|
000000d0 6c 65 3e 3c 2f 68 65 61 64 3e 0d 0a 3c 62 6f 64 |le></head>..<bod|
000000e0 79 20 62 67 63 6f 6c 6f 72 3d 22 77 68 69 74 65 |y bgcolor="white|
000000f0 22 3e 0d 0a 3c 63 65 6e 74 65 72 3e 3c 68 31 3e |">..<center><h1>|
00000100 34 30 30 20 42 61 64 20 52 65 71 75 65 73 74 3c |400 Bad Request<|
00000110 2f 68 31 3e 3c 2f 63 65 6e 74 65 72 3e 0d 0a 3c |/h1></center>..<|
00000120 68 72 3e 3c 63 65 6e 74 65 72 3e 63 6c 6f 75 64 |hr><center>cloud|
00000130 66 6c 61 72 65 2d 6e 67 69 6e 78 3c 2f 63 65 6e |flare-nginx</cen|
00000140 74 65 72 3e 0d 0a 3c 2f 62 6f 64 79 3e 0d 0a 3c |ter>..</body>..<|
00000150 2f 68 74 6d 6c 3e 0d 0a |/html>..|
#include <linux/ptrace.h>
struct ssl_probe_data {
u64 timestamp_ns;
u32 pid;
u32 len;
char comm[16];
char payload[400];
} __attribute__((packed));
BPF_PERF_OUTPUT(perf_SSL_read);
BPF_HASH(bufs, u32, u64);
int probe_SSL_read_enter(struct pt_regs * ctx, void * ssl, void * buf, int num) {
u32 pid = bpf_get_current_pid_tgid();
bufs.update(&pid, (u64 *)&buf);
return 0;
}
int probe_SSL_read_exit(struct pt_regs * ctx, void * ssl, void * buf, int num) {
struct ssl_probe_data event = { 0 };
u32 pid = bpf_get_current_pid_tgid();
u64 * bufp = bufs.lookup(&pid);
if (bufp == 0) {
return 0;
}
if (PT_REGS_RC(ctx) == 0) {
return 0;
}
event.timestamp_ns = bpf_ktime_get_ns();
event.pid = pid;
event.len = PT_REGS_RC(ctx);
bpf_get_current_comm(&event.comm,
sizeof(event.comm));
if (bufp != 0) {
bpf_probe_read(&event.payload,
sizeof(event.payload),
(char *)*bufp);
}
bufs.delete(&pid);
perf_SSL_read.perf_submit(ctx,
&event,
sizeof(event));
return 0;
}
package main
import (
"C"
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"io/ioutil"
"log"
"os"
"os/signal"
bpf "github.com/iovisor/gobpf/bcc"
)
// CFile he source BPF file
const CFile string = "./ssl-snoop.c"
// ProbeEnter the UProbe function name
const ProbeEnter string = "probe_SSL_read_enter"
// ProbeExit the URETprobe function name
const ProbeExit string = "probe_SSL_read_exit"
// LibSSLPath the path of the library for our UProbe
const LibSSLPath string = "ssl"
// LibSSLSymb the symbol to probe from LibSSLPath
const LibSSLSymb string = "SSL_read"
// perfTblName is the bpf table to read events from
const perfTblName string = "perf_SSL_read"
type sslDataEvent struct {
TimeStamp uint64 `json:"TimeStamp"`
Pid uint32 `json:"Pid"`
Len uint32 `json:"DataLen"`
Comm [16]byte `json:"Comm"`
Data [400]byte `json:"SSLData"`
}
func main() {
content, err := ioutil.ReadFile(CFile)
if err != nil {
log.Fatal(err)
}
source := string(content)
mod := bpf.NewModule(source, []string{})
defer mod.Close()
uEnterProbe, _ := mod.LoadUprobe(ProbeEnter)
uExitProbe, _ := mod.LoadUprobe(ProbeExit)
fmt.Printf("%d %d\n", uExitProbe, uEnterProbe)
mod.AttachUprobe(
LibSSLPath,
LibSSLSymb,
uEnterProbe, -1)
err = mod.AttachUretprobe(
LibSSLPath,
LibSSLSymb,
uExitProbe, -1)
if err != nil {
log.Fatal(err)
}
table := bpf.NewTable(mod.TableId(perfTblName), mod)
bpfch := make(chan []byte)
signl := make(chan os.Signal, 1)
prmap, _ := bpf.InitPerfMap(table, bpfch)
signal.Notify(signl, os.Interrupt, os.Kill)
go func() {
var event sslDataEvent
for {
data := <-bpfch
if err := binary.Read(bytes.NewBuffer(data),
binary.LittleEndian, &event); err != nil {
log.Printf("error: %s\n", err)
continue
}
var realLen = event.Len
if realLen > 400 {
event.Len = 400
}
fmt.Printf("\npid:%d (%s)\n--------\n%s",
event.Pid,
event.Comm,
hex.Dump(event.Data[:event.Len]))
}
}()
prmap.Start()
<-signl
prmap.Stop()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment