2016-05-27 8 views
1

Discalaimer, я новичок в Golang, как я использовал следующую статью в качестве основы для этого https://blog.gopheracademy.com/advent-2015/libc-hooking-go-shared-libraries/Golang LD_PRELOAD зацепить SSL_read и SSL_write

Я пытаюсь написать библиотеку LD_PRELOAD, которая будет перехватывать вызовы на SSL_read и SSL_write библиотеки OpenSSL.

Это код, который я придумал до сих пор:

package main 

import (
    "C" 

    "log" 
    "fmt" 

    "github.com/rainycape/dl" 
) 


// main is required to build a shared library, but does nothing 
func main() {} 

//export SSL_read 
func SSL_read(s C.int, b []byte, i C.int) C.int{ 

    lib, err := dl.Open("libssl", 0) 
    if err != nil { 
     log.Fatalln(err) 
    } 
    defer lib.Close() 

    var oldSSL_read func(s C.int, b []byte, i C.int) C.int 
    lib.Sym("SSL_read", &oldSSL_read) 

    res := oldSSL_read(s, b, i) 

    //buf := *(*[]byte)(b) 

    //fmt.Println(i) 

    return res 
} 

/* 
//export SSL_write 
func SSL_write(){ 

} 
*/ 

Я компиляции кода таким образом:

>$ go build -buildmode=c-shared -o preload.so golang_preload.g 

И тестирования с OpenSSL s_client:

LD_PRELOAD=./preload.so openssl s_client -host www.google.com -port 443 

Это, однако, ошибки, которые он вызывает:

fatal error: unexpected signal during runtime execution 
[signal 0xb code=0x1 addr=0x4 pc=0x7f1d91bdeee9] 

runtime stack: 
runtime.throw(0x7f1d92964580, 0x2a) 
    /usr/lib/go/src/runtime/panic.go:530 +0x92 
runtime.sigpanic() 
    /usr/lib/go/src/runtime/sigpanic_unix.go:12 +0x5e 

goroutine 17 [syscall, locked to thread]: 
runtime.cgocall(0x7f1d926d4f30, 0xc82003e930, 0xc800000000) 
    /usr/lib/go/src/runtime/cgocall.go:123 +0x121 fp=0xc82003e8e0 sp=0xc82003e8b0 
github.com/rainycape/dl._Cfunc_call(0x7f1d9231e970, 0xc82008c160, 0xc8200762a0, 0x3, 0xc82008a038, 0xc800000000) 
    github.com/rainycape/dl/_obj/_cgo_gotypes.go:83 +0x43 fp=0xc82003e930 sp=0xc82003e8e0 
github.com/rainycape/dl.makeTrampoline.func1(0xc82008e280, 0x3, 0x3, 0x0, 0x0, 0x0) 
    /home/asm/gocode/src/github.com/rainycape/dl/trampoline.go:124 +0x8b6 fp=0xc82003ebf8 sp=0xc82003e930 
reflect.callReflect(0xc82008c120, 0xc82003edf0) 
    /usr/lib/go/src/reflect/value.go:508 +0x2cd fp=0xc82003edd8 sp=0xc82003ebf8 
reflect.makeFuncStub(0xc8025cec30, 0x4, 0x25c5b70, 0x25c3b60, 0xc8025c3b60, 0x0, 0x0, 0xc820076260, 0xc82008a030, 0x0, ...) 
    /usr/lib/go/src/reflect/asm_amd64.s:17 +0x38 fp=0xc82003edf0 sp=0xc82003edd8 
main.SSL_read(0x25cec30, 0x4, 0x25c5b70, 0x25c3b60, 0x7f1d025c3b60, 0xc800000000) 
    /tmp/golang_preload.go:44 +0x1e5 fp=0xc82003ee88 sp=0xc82003edf0 
main._cgoexpwrap_24df11e45e4b_SSL_read(0x25cec30, 0x4, 0x25c5b70, 0x25c3b60, 0x25c3b60, 0x25c3b60) 
    command-line-arguments/_obj/_cgo_gotypes.go:68 +0x47 fp=0xc82003eec0 sp=0xc82003ee88 
runtime.call64(0x0, 0x7fffb5954988, 0x7fffb5954a10, 0x30) 
    /usr/lib/go/src/runtime/asm_amd64.s:473 +0x40 fp=0xc82003ef08 sp=0xc82003eec0 
runtime.cgocallbackg1() 
    /usr/lib/go/src/runtime/cgocall.go:267 +0x110 fp=0xc82003ef40 sp=0xc82003ef08 
runtime.cgocallbackg() 
    /usr/lib/go/src/runtime/cgocall.go:180 +0xd9 fp=0xc82003efa0 sp=0xc82003ef40 
runtime.cgocallback_gofunc(0x0, 0x0, 0x0) 
    /usr/lib/go/src/runtime/asm_amd64.s:716 +0x5d fp=0xc82003efb0 sp=0xc82003efa0 
runtime.goexit() 
    /usr/lib/go/src/runtime/asm_amd64.s:1998 +0x1 fp=0xc82003efb8 sp=0xc82003efb0 

goroutine 34 [syscall, locked to thread]: 
runtime.goexit() 
    /usr/lib/go/src/runtime/asm_amd64.s:1998 +0x1 

Каков правильный способ доступа к буферу в функции SSL_read, я попытался использовать unsafe.Pointer, но у меня нет привязки типа к ошибке значения.

обновление:

Протокол SSL структура определяется в openssl.h. Добавление этого импорта приводит к конфликту с функцией SSL_read.

В чистом коде C, используя простой void* указатель будет достаточно, заменив его unsafe.Pointer для SSL и буфера приводит к следующей ошибке:

panic: can't bind value of type unsafe.Pointer 

goroutine 17 [running, locked to thread]: 
panic(0x7f0a8e933400, 0xc820096060) 
    /usr/lib/go/src/runtime/panic.go:464 +0x3ea 
github.com/rainycape/dl.makeTrampoline.func1(0xc8200980f0, 0x3, 0x3, 0x0, 0x0, 0x0) 
    /home/asm/gocode/src/github.com/rainycape/dl/trampoline.go:116 +0x186e 
reflect.callReflect(0xc82009c040, 0xc82004be10) 
    /usr/lib/go/src/reflect/value.go:508 +0x2cd 
reflect.makeFuncStub(0xa12bd0, 0xa07b00, 0x400, 0x7f0a8e907800, 0xc82009a000, 0x0, 0x0, 0xc820096000, 0xc82009a000, 0x0, ...) 
    /usr/lib/go/src/reflect/asm_amd64.s:17 +0x38 
main.SSL_read(0xa12bd0, 0xa07b00, 0xc800000400, 0x7f0a00000000) 
    /tmp/preload.go:26 +0x1cd 
main._cgoexpwrap_613180a44973_SSL_read(0xa12bd0, 0xa07b00, 0x400, 0xa07b00) 
    command-line-arguments/_obj/_cgo_gotypes.go:50 +0x35 
+0

Вы пытались использовать 'uintptr'? – JimB

ответ

2

[]byte является ломтик Go, который вы не можете использовать в C. сигнатура SSL_read является:

SSL_read(SSL *ssl, void *buf, int num) 

Приказываю для вызова на работу, вы должны соответствовать подписи и использовать эквивалентные типы в определении функции.

func SSL_read(ssl *C.SSL, buf unsafe.Pointer, num C.int) 
+0

спасибо, C.ssl, однако, не определен. Я попытался добавить // #include , но он до сих пор не распознает его. –

+0

Извините, прочитайте декларацию C назад, это 'C.SSL' – JimB