gotls shared object not supported
Describe the bug I'm not sure if this is a bug or is not supported.
To Reproduce Steps to reproduce the behavior: ./ecapture gotls --elfpath="tls-client-x86.so" --hex
Expected behavior No TLS or HTTPS request gets intercepted while using a GO compiled .so file
Linux Server/Android (please complete the following information):
- Env: Linux
- OS: Ubuntu 22.04
- Arch: x86_64
- Kernel Version: 6.5.0-35-generic
Additional context I have the compiled GO code into .so format which I use to load through the Python environment and make the HTTPS/TLS requests, however after running the above command no traffic is captured by ecapture.
Please give more detailed error information.
I'm using tls-client lib with Python (a wrapper around GO shared object)
tls-client library link (.so file)
Python code example here link The above Python code loads the .so file compiled from the GO code into the memory and then is used to execute the requests at the GO side
what I'm doing with ecapture is:
- Start capturing using the shared object file.
./ecapture gotls --elfpath="tls-client-x86.so" --hex - Start the Python script as normal (load tls-client-x86.so in memory)
- Make TLS/HTTPS requests through the compiled .so file, commands are passed from the Python code, but requests are made at the GO side.
After all the above processes there is no traffic being intercepted by ecapture. (I'm not sure if .so also needs linking with the Python or maybe some extra stuff is also required)
eCapture can correctly analyze this dynamic link library and correctly find the offset address of the symbol crypto/tls.(*Conn).Read.
However, it did not capture this communication. I am unable to determine where the issue lies, and I also do not have the time to analyze this library. I suggest you debug it yourself to confirm whether the crypto/tls functions are not being used.
sudo bin/ecapture gotls -m text --elfpath=/home/cfc4n/project/python-test/tls-client-linux-arm64-1.7.5.so
[sudo] password for cfc4n:
2024-05-22T14:44:45Z INF AppName="eCapture(旁观者)"
2024-05-22T14:44:45Z INF HomePage=https://ecapture.cc
2024-05-22T14:44:45Z INF Repository=https://github.com/gojue/ecapture
2024-05-22T14:44:45Z INF Author="CFC4N <[email protected]>"
2024-05-22T14:44:45Z INF Description="Capturing SSL/TLS plaintext without a CA certificate using eBPF. Supported on Linux/Android kernels for amd64/arm64."
2024-05-22T14:44:45Z INF Version=linux_arm64:0.7.7-20240303-bfb4a8c:5.15.0-105-generic
2024-05-22T14:44:45Z INF listen=localhost:28256
2024-05-22T14:44:45Z INF https server starting...You can update the configuration file via the HTTP interface.
2024-05-22T14:44:45Z WRN ========== module starting. ==========
2024-05-22T14:44:45Z INF Kernel Info=5.15.148 Pid=231170
2024-05-22T14:44:45Z INF BTF bytecode mode: CORE. btfMode=0
2024-05-22T14:44:45Z INF GoTlsProbe init keylogFile= model=Text
2024-05-22T14:44:45Z INF module initialization. isReload=false moduleName=EBPFProbeGoTLS
2024-05-22T14:44:45Z INF Module.Run()
2024-05-22T14:44:45Z INF HOOK type:Golang elf GoVersion=go1.20 binrayPath=/home/cfc4n/project/python-test/tls-client-linux-arm64-1.7.5.so buildInfo=" -buildmode=c-shared -compiler=gc CGO_ENABLED=1 GOARCH=arm64 GOOS=linux vcs=git vcs.revision=a0890ed4f1cd67d5e33ffcb2985c7620c3432eb9 vcs.time=2024-05-01T17:59:26Z vcs.modified=true" isRegisterABI=true
2024-05-22T14:44:45Z INF golang uretprobe added. function=crypto/tls.(*Conn).Read offset=286848
2024-05-22T14:44:45Z INF golang uretprobe added. function=crypto/tls.(*Conn).Read offset=286870
2024-05-22T14:44:45Z INF golang uretprobe added. function=crypto/tls.(*Conn).Read offset=2868D4
2024-05-22T14:44:45Z INF golang uretprobe added. function=crypto/tls.(*Conn).Read offset=2869F0
2024-05-22T14:44:45Z INF golang uretprobe added. function=crypto/tls.(*Conn).Read offset=286A20
2024-05-22T14:44:45Z INF golang uretprobe added. function=crypto/tls.(*Conn).Read offset=286A80
2024-05-22T14:44:45Z INF golang uretprobe added. function=crypto/tls.(*Conn).Read offset=286A9C
2024-05-22T14:44:45Z INF target all process.
2024-05-22T14:44:45Z INF target all users.
2024-05-22T14:44:45Z INF BPF bytecode file is matched. bpfFileName=user/bytecode/gotls_kern_core.o
2024-05-22T14:44:45Z INF perfEventReader created mapSize(MB)=4
2024-05-22T14:44:45Z INF module started successfully. isReload=false moduleName=EBPFProbeGoTLS
Thanks for the update, I'll debug the library this weekend, can you also confirm if you tested the Python side of the code using this link or if there is any other example code you used please refer me the link. Thanks
Yes, my test code also used this link.
I did debug the library and I can confirm the crypto/tls is being used in the lib.
There are multiple methods for crypto/tls being used when we submit a request to the client, but ecapture is not able to intercept any. I'm also not sure why you marked this issue as completed and closed this but the issue is probably somewhere with ecapture not being able to capture the communication.
I think this may not be related to eCapture; if you need it, you can open it. Feel free to share your new findings.
I tied all possible ways I could have thought of, but ecapture doesn't seem to hook into the dynamic lib properly though it does find the offset addresses correctly, something doesn't seem to be right while the shared lib is loaded into the memory, and does perform all the crypto/tls operations.
I'm closing this for now because I have managed to directly hook into crypto/tls methods to fetch the SSLKEYLOGFILE from the dynamically loaded lib without ecapture, will probably open it again if I find more on this in the future.
In the source code of the library, it can be seen that it uses a custom TLS handshake packet, instead of the official implementation by golang.
https://github.com/bogdanfinn/tls-client/blob/077a497dc1047d3ed5f53f257af383b334a7a609/roundtripper.go#L154
conn := tls.UClient(rawConn, tlsConfig, rt.clientHelloId, rt.withRandomTlsExtensionOrder, rt.forceHttp1)
if err = conn.HandshakeContext(ctx); err != nil {
_ = conn.Close()
return nil, err
}
err = rt.certificatePinner.Pin(conn, host)
if err != nil {
return nil, err
}
About tls.UClient
tls.UClient used package bogdanfinn/utls , As project introduction
uTLS is a fork of "crypto/tls", which provides ClientHello fingerprinting resistance, low-level access to handshake, fake session tickets and some other features. Handshake is still performed by "crypto/tls", this library merely changes ClientHello part of it and provides low-level access.
So, this is not a flaw of eCapture; you need to study the project and find the appropriate HOOK symbol.
Solution
You can change the hook symbol crypto/tls.(*Config).writeKeyLog to github.com/bogdanfinn/utls.(*Config).writeKeyLog, which may solve your problem.
https://github.com/gojue/ecapture/blob/8e25629235c882caa6cf6825009ad660b4d9047b/user/config/config_gotls.go#L31-L35
It works.
Thanks for looking into it, this works :)