Skip to content

Commit 5121f36

Browse files
committed
support symbols in sections .data.rel.ro.gopclntab and .data.rel.ro.
see PR #512 for more info . Signed-off-by: CFC4N <cfc4n.cs@gmail.com>
1 parent cb9e205 commit 5121f36

File tree

5 files changed

+116
-60
lines changed

5 files changed

+116
-60
lines changed

kern/gotls_kern.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ static __always_inline int gotls_mastersecret(struct pt_regs *ctx,
251251
return 0;
252252
}
253253

254-
debug_bpf_printk("gotls_mastersecret read mastersecret label%s\n",
254+
debug_bpf_printk("gotls_mastersecret read mastersecret label:%s\n",
255255
mastersecret_gotls.label);
256256
ret = bpf_probe_read_user_str(&mastersecret_gotls.client_random,
257257
sizeof(mastersecret_gotls.client_random),

user/config/config_gotls.go

Lines changed: 90 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ import (
2828
)
2929

3030
const (
31-
// 46EE50 - 46EDB0
32-
//
33-
GoTlsReadFunc = "crypto/tls.(*Conn).Read"
34-
31+
GoTlsReadFunc = "crypto/tls.(*Conn).Read"
3532
GoTlsWriteFunc = "crypto/tls.(*Conn).writeRecordLocked"
3633
GoTlsMasterSecretFunc = "crypto/tls.(*Config).writeKeyLog"
37-
// crypto_tls._ptr_Conn.Read
38-
GoTlsReadFuncArm64 = "crypto_tls._ptr_Conn.Read"
34+
35+
/*
36+
我是通过IDA静态分析符号发现`crypto/tls.(*Conn).Read`的地址是`46EE50`。用程序计算出来的总是比这个数字少了`0x120` ,通过分析其他多个编译的程序,发现差值总是`0x120`。
37+
所以,我定义了一个常量,增加到程序计算的地址上。但是我不知道原因,如果你知道,请告诉我。更多信息见:https://github.com/gojue/ecapture/pull/512
38+
*/
39+
IdaProOffset = 0x120
3940
)
4041

4142
var (
@@ -88,7 +89,7 @@ type GoTLSConfig struct {
8889
PcapFilter string `json:"pcapFilter"` // pcap filter
8990
goElfArch string //
9091
goElf *elf.File //
91-
buildinfo *buildinfo.BuildInfo
92+
Buildinfo *buildinfo.BuildInfo
9293
ReadTlsAddrs []int
9394
GoTlsWriteAddr uint64
9495
GoTlsMasterSecretAddr uint64
@@ -119,7 +120,7 @@ func (gc *GoTLSConfig) Check() error {
119120
}
120121

121122
// Read the build information of the Go application
122-
gc.buildinfo, err = buildinfo.ReadFile(gc.Path)
123+
gc.Buildinfo, err = buildinfo.ReadFile(gc.Path)
123124
if err != nil {
124125
return err
125126
}
@@ -154,7 +155,7 @@ func (gc *GoTLSConfig) Check() error {
154155
gc.goElf = goElf
155156
// If built with PIE and stripped, gopclntab is
156157
// unlabeled and nested under .data.rel.ro.
157-
for _, bs := range gc.buildinfo.Settings {
158+
for _, bs := range gc.Buildinfo.Settings {
158159
if bs.Key == "-buildmode" {
159160
if bs.Value == "pie" {
160161
gc.IsPieBuildMode = true
@@ -167,16 +168,21 @@ func (gc *GoTLSConfig) Check() error {
167168
if err != nil {
168169
return err
169170
}
170-
fun := gc.goSymTab.LookupFunc(GoTlsWriteFunc)
171-
if fun != nil {
172-
gc.GoTlsWriteAddr = fun.Entry
171+
var addr uint64
172+
addr, err = gc.findPieSymbolAddr(GoTlsWriteFunc)
173+
if err != nil {
174+
return fmt.Errorf("%s symbol address error:%s", GoTlsWriteFunc, err.Error())
173175
}
174-
fun = gc.goSymTab.LookupFunc(GoTlsMasterSecretFunc)
175-
if fun != nil {
176-
gc.GoTlsMasterSecretAddr = fun.Entry
176+
gc.GoTlsWriteAddr = addr
177+
addr, err = gc.findPieSymbolAddr(GoTlsMasterSecretFunc)
178+
if err != nil {
179+
return fmt.Errorf("%s symbol address error:%s", GoTlsMasterSecretFunc, err.Error())
177180
}
181+
gc.GoTlsMasterSecretAddr = addr
182+
178183
gc.ReadTlsAddrs, err = gc.findRetOffsetsPie(GoTlsReadFunc)
179184
if err != nil {
185+
panic(err)
180186
return err
181187
}
182188
} else {
@@ -188,20 +194,6 @@ func (gc *GoTLSConfig) Check() error {
188194
return err
189195
}
190196

191-
func (gc *GoTLSConfig) findRetOffsetsPie(symbolName string) ([]int, error) {
192-
var offsets []int
193-
var err error
194-
195-
fun := gc.goSymTab.LookupFunc(symbolName)
196-
if fun == nil {
197-
return nil, ErrorSymbolNotFoundFromTable
198-
}
199-
200-
//fmt.Printf("found in %s, entry:%x, end:%x , end-entry:%x\n", fun.Name, fun.Entry, fun.End, fun.End-fun.Entry)
201-
offsets, err = gc.findFuncOffsetBySymfun(fun, gc.goElf)
202-
return offsets, err
203-
}
204-
205197
// FindRetOffsets searches for the addresses of all RET instructions within
206198
// the instruction set associated with the specified symbol in an ELF program.
207199
// It is used for mounting uretprobe programs for Golang programs,
@@ -214,7 +206,6 @@ func (gc *GoTLSConfig) findRetOffsets(symbolName string) ([]int, error) {
214206
if len(goSymbs) > 0 {
215207
allSymbs = append(allSymbs, goSymbs...)
216208
}
217-
218209
goDynamicSymbs, _ := gc.goElf.DynamicSymbols()
219210
if len(goDynamicSymbs) > 0 {
220211
allSymbs = append(allSymbs, goDynamicSymbs...)
@@ -256,6 +247,23 @@ func (gc *GoTLSConfig) findRetOffsets(symbolName string) ([]int, error) {
256247
if len(offsets) == 0 {
257248
return offsets, ErrorNoRetFound
258249
}
250+
251+
address := symbol.Value
252+
for _, prog := range gc.goElf.Progs {
253+
// Skip uninteresting segments.
254+
if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 {
255+
continue
256+
}
257+
258+
if prog.Vaddr <= symbol.Value && symbol.Value < (prog.Vaddr+prog.Memsz) {
259+
// stackoverflow.com/a/40249502
260+
address = symbol.Value - prog.Vaddr + prog.Off
261+
break
262+
}
263+
}
264+
for i, offset := range offsets {
265+
offsets[i] = int(address) + offset
266+
}
259267
return offsets, nil
260268
}
261269

@@ -278,29 +286,33 @@ func (gc *GoTLSConfig) checkModel() (string, error) {
278286
}
279287

280288
func (gc *GoTLSConfig) ReadTable() (*gosym.Table, error) {
281-
sectionLabel := ".data.rel.ro"
289+
sectionLabel := ".gopclntab"
282290
section := gc.goElf.Section(sectionLabel)
283291
if section == nil {
284292
// binary may be built with -pie
285-
sectionLabel = ".gopclntab"
293+
sectionLabel = ".data.rel.ro.gopclntab"
286294
section = gc.goElf.Section(sectionLabel)
287295
if section == nil {
288-
return nil, fmt.Errorf("could not read section %s from %s ", sectionLabel, gc.Path)
296+
sectionLabel = ".data.rel.ro"
297+
section = gc.goElf.Section(sectionLabel)
298+
if section == nil {
299+
return nil, fmt.Errorf("could not read section %s from %s ", sectionLabel, gc.Path)
300+
}
289301
}
290302
}
291303
tableData, err := section.Data()
292304
if err != nil {
293305
return nil, fmt.Errorf("found section but could not read %s from %s ", sectionLabel, gc.Path)
294306
}
295-
296307
// Find .gopclntab by magic number even if there is no section label
297-
magic := magicNumber(gc.buildinfo.GoVersion)
308+
magic := magicNumber(gc.Buildinfo.GoVersion)
298309
pclntabIndex := bytes.Index(tableData, magic)
299-
//fmt.Printf("buildinfo :%v, magic:%x, pclntabIndex:%d offset:%x , section:%v \n", gc.buildinfo, magic, pclntabIndex, section.Offset, section)
310+
//fmt.Printf("Buildinfo :%v, magic:%x, pclntabIndex:%d offset:%x , section:%v \n", gc.Buildinfo, magic, pclntabIndex, section.Offset, section)
300311
if pclntabIndex < 0 {
301312
return nil, fmt.Errorf("could not find magic number in %s ", gc.Path)
302313
}
303314
tableData = tableData[pclntabIndex:]
315+
304316
addr := gc.goElf.Section(".text").Addr
305317
lineTable := gosym.NewLineTable(tableData, addr)
306318
symTable, err := gosym.NewTable([]byte{}, lineTable)
@@ -310,38 +322,60 @@ func (gc *GoTLSConfig) ReadTable() (*gosym.Table, error) {
310322
return symTable, nil
311323
}
312324

313-
func (gc *GoTLSConfig) findFuncOffsetBySymfun(f *gosym.Func, elfF *elf.File) ([]int, error) {
325+
func (gc *GoTLSConfig) findRetOffsetsPie(lfunc string) ([]int, error) {
314326
var offsets []int
327+
var address uint64
315328
var err error
329+
address, err = gc.findPieSymbolAddr(lfunc)
330+
if err != nil {
331+
return offsets, err
332+
}
333+
f := gc.goSymTab.LookupFunc(lfunc)
334+
funcLen := f.End - f.Entry
335+
for _, prog := range gc.goElf.Progs {
336+
if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 {
337+
continue
338+
}
339+
data := make([]byte, funcLen)
340+
_, err = prog.ReadAt(data, int64(address))
341+
if err != nil {
342+
return offsets, fmt.Errorf("finding function return: %w", err)
343+
}
344+
offsets, err = gc.decodeInstruction(data)
345+
if err != nil {
346+
return offsets, fmt.Errorf("finding function return: %w", err)
347+
}
348+
for i, offset := range offsets {
349+
offsets[i] = int(address) + offset
350+
}
351+
return offsets, nil
352+
}
353+
return offsets, errors.New("cant found gotls symbol offsets.")
354+
}
316355

317-
for _, prog := range elfF.Progs {
356+
func (gc *GoTLSConfig) findPieSymbolAddr(lfunc string) (uint64, error) {
357+
f := gc.goSymTab.LookupFunc(lfunc)
358+
if f == nil {
359+
return 0, errors.New("Cant found symbol address on pie model.")
360+
}
361+
var err error
362+
var address uint64
363+
for _, prog := range gc.goElf.Progs {
318364
if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 {
319365
continue
320366
}
321367
// For more info on this calculation: stackoverflow.com/a/40249502
322-
/*
323-
ida : start : 46EE50, end : 46F258 , len :0x408
324-
elf info: start : 46ed30, end : , len: 0x3B0, 0x58
325-
326-
*/
368+
address = f.Value
327369
if prog.Vaddr <= f.Value && f.Value < (prog.Vaddr+prog.Memsz) {
328370
funcLen := f.End - f.Entry
329-
fmt.Printf("name :%s, f.Value:%x, f.Entry:%x, f.End:%x, funcLen:%X \n ", f.Name, f.Value, f.Entry, f.End, funcLen)
330371
data := make([]byte, funcLen)
331-
_, err = prog.ReadAt(data, int64(f.Value-prog.Vaddr))
372+
address = f.Value - prog.Vaddr + prog.Off + IdaProOffset
373+
_, err = prog.ReadAt(data, int64(address))
332374
if err != nil {
333-
return offsets, fmt.Errorf("finding function return: %w", err)
334-
}
335-
336-
offsets, err = gc.decodeInstruction(data)
337-
if err != nil {
338-
return offsets, fmt.Errorf("finding function return: %w", err)
339-
}
340-
for i, offset := range offsets {
341-
offsets[i] = int(f.Entry) + offset
375+
return 0, fmt.Errorf("search function return: %w", err)
342376
}
343-
return offsets, nil
377+
return address, nil
344378
}
345379
}
346-
return offsets, ErrorNoRetFoundFromSymTabFun
380+
return 0, ErrorNoRetFoundFromSymTabFun
347381
}

user/event/event_gotls.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ func (ge *GoTLSEvent) Decode(payload []byte) error {
3232
if err = binary.Read(r, binary.LittleEndian, &ge.Data); err != nil {
3333
return err
3434
}
35+
} else {
36+
ge.Len = 0
3537
}
3638
decodedKtime, err := DecodeKtime(int64(ge.TimestampNS), true)
3739
if err == nil {

user/module/probe_gotls_keylog.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,28 @@ import (
2222
manager "github.com/gojue/ebpfmanager"
2323
"golang.org/x/sys/unix"
2424
"math"
25+
"strings"
2526
)
2627

2728
func (g *GoTLSProbe) setupManagersKeylog() error {
28-
29-
g.logger.Printf("%s\tHOOK type:golang elf, binrayPath:%s\n", g.Name(), g.path)
30-
g.logger.Printf("%s\tHook masterKey function:%s, Address:%x \n", g.Name(), config.GoTlsMasterSecretFunc, g.conf.(*config.GoTLSConfig).GoTlsMasterSecretAddr)
29+
var gotlsConf = g.conf.(*config.GoTLSConfig)
30+
var buildInfo = new(strings.Builder)
31+
for _, setting := range gotlsConf.Buildinfo.Settings {
32+
if setting.Value == "" {
33+
continue
34+
}
35+
buildInfo.WriteString(" ")
36+
buildInfo.WriteString(setting.Key)
37+
buildInfo.WriteString("=")
38+
buildInfo.WriteString(setting.Value)
39+
}
40+
g.logger.Printf("%s\tHOOK type:Golang elf, binrayPath:%s\n", g.Name(), g.path)
41+
g.logger.Printf("%s\tGolang buildInfo version:%s, Params: %s\n", g.Name(), gotlsConf.Buildinfo.GoVersion, buildInfo.String())
42+
if gotlsConf.IsPieBuildMode {
43+
// buildmode pie is enabled.
44+
g.logger.Printf("%s\tGolang elf buildmode with pie\n", g.Name())
45+
}
46+
g.logger.Printf("%s\tHook masterKey function:%s, Address:%x \n", g.Name(), config.GoTlsMasterSecretFunc, gotlsConf.GoTlsMasterSecretAddr)
3147

3248
var (
3349
sec string

user/module/probe_gotls_text.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ func (g *GoTLSProbe) setupManagersText() error {
4343
readFn = "gotls_read_stack"
4444
}
4545
g.logger.Printf("%s\teBPF Function Name:%s, isRegisterABI:%t\n", g.Name(), fn, g.isRegisterABI)
46+
if g.conf.(*config.GoTLSConfig).IsPieBuildMode {
47+
// buildmode pie is enabled.
48+
g.logger.Printf("%s\tGolang elf buildmode with pie\n", g.Name())
49+
}
4650
g.bpfManager = &manager.Manager{
4751
Probes: []*manager.Probe{
4852
{

0 commit comments

Comments
 (0)