(no title)
tylerflint | 9 months ago
We do this by scanning every version of Go that is released to find offsets in the standard library that won't change. Then when we detect a new Go process, we use an ELF scanner to find some function offsets and hook into those with uprobes. Using both of these, we have all the information we need to see Go pre-encryption content as well as attribute it to connections and processes.
chatmasta|9 months ago
Are these offsets consistent across compilation targets, and they vary only by version of the Go binary? Or do you need to do this scan for every architecture?
tylerflint|9 months ago
The long answer is that the offsets are the byte alignment offsets for the go structs containing the pointers to the file descriptor and buffers. Fortunately we only have to calculate these for each version where the TLS structs within go actually change, so not even for every version. For instance, if a field is added, removed, or changes type then the location in memory where those pointers will be found changes. We can then calculate the actual offset at runtime where we know which architecture (amd64, arm64, etc) with a simple calculation. Within the eBPF probe, when the function is called, it uses pointer arithmetic to extract the location of the file descriptor and buffer directly.
lelanthran|9 months ago
ISTR, at some point in the far past, using LD_PRELOAD with my own shims to capture TLS traffic before encryption/after decryption. I might have it lying around somewhere here.
bbkane|9 months ago