@@ -28,14 +28,15 @@ import (
28
28
)
29
29
30
30
const (
31
- // 46EE50 - 46EDB0
32
- //
33
- GoTlsReadFunc = "crypto/tls.(*Conn).Read"
34
-
31
+ GoTlsReadFunc = "crypto/tls.(*Conn).Read"
35
32
GoTlsWriteFunc = "crypto/tls.(*Conn).writeRecordLocked"
36
33
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
39
40
)
40
41
41
42
var (
@@ -88,7 +89,7 @@ type GoTLSConfig struct {
88
89
PcapFilter string `json:"pcapFilter"` // pcap filter
89
90
goElfArch string //
90
91
goElf * elf.File //
91
- buildinfo * buildinfo.BuildInfo
92
+ Buildinfo * buildinfo.BuildInfo
92
93
ReadTlsAddrs []int
93
94
GoTlsWriteAddr uint64
94
95
GoTlsMasterSecretAddr uint64
@@ -119,7 +120,7 @@ func (gc *GoTLSConfig) Check() error {
119
120
}
120
121
121
122
// Read the build information of the Go application
122
- gc .buildinfo , err = buildinfo .ReadFile (gc .Path )
123
+ gc .Buildinfo , err = buildinfo .ReadFile (gc .Path )
123
124
if err != nil {
124
125
return err
125
126
}
@@ -154,7 +155,7 @@ func (gc *GoTLSConfig) Check() error {
154
155
gc .goElf = goElf
155
156
// If built with PIE and stripped, gopclntab is
156
157
// unlabeled and nested under .data.rel.ro.
157
- for _ , bs := range gc .buildinfo .Settings {
158
+ for _ , bs := range gc .Buildinfo .Settings {
158
159
if bs .Key == "-buildmode" {
159
160
if bs .Value == "pie" {
160
161
gc .IsPieBuildMode = true
@@ -167,16 +168,21 @@ func (gc *GoTLSConfig) Check() error {
167
168
if err != nil {
168
169
return err
169
170
}
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 ())
173
175
}
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 ())
177
180
}
181
+ gc .GoTlsMasterSecretAddr = addr
182
+
178
183
gc .ReadTlsAddrs , err = gc .findRetOffsetsPie (GoTlsReadFunc )
179
184
if err != nil {
185
+ panic (err )
180
186
return err
181
187
}
182
188
} else {
@@ -188,20 +194,6 @@ func (gc *GoTLSConfig) Check() error {
188
194
return err
189
195
}
190
196
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
-
205
197
// FindRetOffsets searches for the addresses of all RET instructions within
206
198
// the instruction set associated with the specified symbol in an ELF program.
207
199
// It is used for mounting uretprobe programs for Golang programs,
@@ -214,7 +206,6 @@ func (gc *GoTLSConfig) findRetOffsets(symbolName string) ([]int, error) {
214
206
if len (goSymbs ) > 0 {
215
207
allSymbs = append (allSymbs , goSymbs ... )
216
208
}
217
-
218
209
goDynamicSymbs , _ := gc .goElf .DynamicSymbols ()
219
210
if len (goDynamicSymbs ) > 0 {
220
211
allSymbs = append (allSymbs , goDynamicSymbs ... )
@@ -256,6 +247,23 @@ func (gc *GoTLSConfig) findRetOffsets(symbolName string) ([]int, error) {
256
247
if len (offsets ) == 0 {
257
248
return offsets , ErrorNoRetFound
258
249
}
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
+ }
259
267
return offsets , nil
260
268
}
261
269
@@ -278,29 +286,33 @@ func (gc *GoTLSConfig) checkModel() (string, error) {
278
286
}
279
287
280
288
func (gc * GoTLSConfig ) ReadTable () (* gosym.Table , error ) {
281
- sectionLabel := ".data.rel.ro "
289
+ sectionLabel := ".gopclntab "
282
290
section := gc .goElf .Section (sectionLabel )
283
291
if section == nil {
284
292
// binary may be built with -pie
285
- sectionLabel = ".gopclntab"
293
+ sectionLabel = ".data.rel.ro. gopclntab"
286
294
section = gc .goElf .Section (sectionLabel )
287
295
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
+ }
289
301
}
290
302
}
291
303
tableData , err := section .Data ()
292
304
if err != nil {
293
305
return nil , fmt .Errorf ("found section but could not read %s from %s " , sectionLabel , gc .Path )
294
306
}
295
-
296
307
// Find .gopclntab by magic number even if there is no section label
297
- magic := magicNumber (gc .buildinfo .GoVersion )
308
+ magic := magicNumber (gc .Buildinfo .GoVersion )
298
309
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)
300
311
if pclntabIndex < 0 {
301
312
return nil , fmt .Errorf ("could not find magic number in %s " , gc .Path )
302
313
}
303
314
tableData = tableData [pclntabIndex :]
315
+
304
316
addr := gc .goElf .Section (".text" ).Addr
305
317
lineTable := gosym .NewLineTable (tableData , addr )
306
318
symTable , err := gosym .NewTable ([]byte {}, lineTable )
@@ -310,38 +322,60 @@ func (gc *GoTLSConfig) ReadTable() (*gosym.Table, error) {
310
322
return symTable , nil
311
323
}
312
324
313
- func (gc * GoTLSConfig ) findFuncOffsetBySymfun ( f * gosym. Func , elfF * elf. File ) ([]int , error ) {
325
+ func (gc * GoTLSConfig ) findRetOffsetsPie ( lfunc string ) ([]int , error ) {
314
326
var offsets []int
327
+ var address uint64
315
328
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
+ }
316
355
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 {
318
364
if prog .Type != elf .PT_LOAD || (prog .Flags & elf .PF_X ) == 0 {
319
365
continue
320
366
}
321
367
// 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
327
369
if prog .Vaddr <= f .Value && f .Value < (prog .Vaddr + prog .Memsz ) {
328
370
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 )
330
371
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 ))
332
374
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 )
342
376
}
343
- return offsets , nil
377
+ return address , nil
344
378
}
345
379
}
346
- return offsets , ErrorNoRetFoundFromSymTabFun
380
+ return 0 , ErrorNoRetFoundFromSymTabFun
347
381
}
0 commit comments