From a8143e50357d796b4f59b58a6add97e2b0c319b1 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 20 Nov 2019 18:26:19 +0000 Subject: sslkeylog: add macOS support Tested with macOS 10.15.1 (Catalina). Works with python3 3.7.5 (requests library) and openssl 1.1.1d (s_client) from Homebrew. Does not work with curl 7.64.1 in /usr/bin/curl because it is signed and does not allow DYLD environment variables to be passed when SIP is enabled. --- src/Makefile | 20 +++++++++++++++++--- src/sslkeylog.c | 19 +++++++++++++++++-- src/sslkeylog.sh | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/Makefile b/src/Makefile index ea8e7b6..34120ac 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,20 @@ -libsslkeylog.so: sslkeylog.c - $(CC) $(CFLAGS) sslkeylog.c -shared -o $@ -fPIC -ldl +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) + LIBNAME := libsslkeylog.dylib + # Assumes default Homebrew installation prefix. + OPENSSL_PREFIX ?= /usr/local/opt/openssl@1.1 +ifneq ($(OPENSSL_PREFIX),) + CPPFLAGS ?= -I$(OPENSSL_PREFIX)/include + # Link to library to avoid having to set LD_LIBRARY_PATH at runtime. + LDFLAGS ?= -L$(OPENSSL_PREFIX)/lib -lssl +endif +else + LIBNAME := libsslkeylog.so +endif + +$(LIBNAME): sslkeylog.c + $(CC) $(CPPFLAGS) $(CFLAGS) sslkeylog.c -shared -o $@ -fPIC -ldl $(LDFLAGS) clean: - $(RM) libsslkeylog.so + $(RM) $(LIBNAME) diff --git a/src/sslkeylog.c b/src/sslkeylog.c index 3706689..9d176c9 100644 --- a/src/sslkeylog.c +++ b/src/sslkeylog.c @@ -9,6 +9,13 @@ * Usage: * cc sslkeylog.c -shared -o libsslkeylog.so -fPIC -ldl * SSLKEYLOGFILE=premaster.txt LD_PRELOAD=./libsslkeylog.so openssl ... + * + * Usage for macOS: + * cc sslkeylog.c -shared -o libsslkeylog.dylib -fPIC -ldl \ + * -I/usr/local/opt/openssl@1.1/include \ + * -L/usr/local/opt/openssl@1.1/lib -lssl + * DYLD_INSERT_LIBRARIES=./libsslkeylog.dylib DYLD_FORCE_FLAT_NAMESPACE=1 \ + * SSLKEYLOGFILE=premaster.txt /usr/local/opt/openssl@1.1/bin/openssl ... */ /* @@ -39,9 +46,17 @@ #include #ifndef OPENSSL_SONAME -/* fallback library if OpenSSL is not already loaded. Other values to try: - * libssl.so.0.9.8 libssl.so.1.0.0 libssl.so.1.1 */ +/* fallback library if OpenSSL is not already loaded. */ +# ifdef __APPLE__ +/* libssl.dylib is a symlink, Homebrew installs: + * OpenSSL 1.0.2 /usr/local/opt/openssl/lib/libssl.1.0.0.dylib + * OpenSSL 1.1.1 /usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib + */ +# define OPENSSL_SONAME "libssl.dylib" +# else +/* Other values to try: libssl.so.0.9.8 libssl.so.1.0.0 libssl.so.1.1 */ # define OPENSSL_SONAME "libssl.so" +# endif #endif #define FIRSTLINE "# SSL key logfile generated by sslkeylog.c\n" diff --git a/src/sslkeylog.sh b/src/sslkeylog.sh index 0197302..38036f5 100755 --- a/src/sslkeylog.sh +++ b/src/sslkeylog.sh @@ -15,9 +15,54 @@ gdb() { "$@" } -LD_PRELOAD=$(readlink -f "${BASH_SOURCE[0]%/*}")/libsslkeylog.so -SSLKEYLOGFILE=${SSLKEYLOGFILE:-/dev/stderr} -export LD_PRELOAD SSLKEYLOGFILE +case "$OSTYPE" in +darwin*) + # Unfortunately not all executables can be injected (e.g. /usr/bin/curl). + # See also man dyld + # + # "Note: If System Integrity Protection is enabled, these environment + # variables are ignored when executing binaries protected by System + # Integrity Protection." + # + # Note that DYLD_* env vars are *not* propagated though system binaries such + # as bash. To set an environment variable, use 'env' as in: + # + # ./sslkeylog.sh env DYLD_PRINT_OPTS=1 python3 + # + # If the variable is picked up, it should show something like: + # + # opt[0] = "python3" + # + # If not visible, then interception is not possible until SIP is disabled. + + export DYLD_INSERT_LIBRARIES=$(cd "${BASH_SOURCE[0]%/*}" && pwd)/libsslkeylog.dylib + export DYLD_FORCE_FLAT_NAMESPACE=1 + # Expected output: dyld: loaded: <1A23FBC9-68C9-3808-88A5-C2D3A18C7DE1> .../wireshark-notes/src/libsslkeylog.dylib + #export DYLD_PRINT_LIBRARIES=1 + # Expected output: dyld: lazy bind: openssl:0x105B21CE0 = libsslkeylog.dylib:_SSL_new, *0x105B21CE0 = 0x105B59660 + #export DYLD_PRINT_BINDINGS + + # Since DYLD is not propagated when using 'env', simulate it here. + # This is safer than using 'eval'. + if [[ ${BASH_SOURCE[0]} == $0 ]] && [[ "$1" == env ]]; then + shift + while [ $# -gt 0 ]; do + case "$1" in + *=*) + export "$1" + shift + ;; + *) + break + esac + done + fi + ;; +*) + export LD_PRELOAD=$(readlink -f "${BASH_SOURCE[0]%/*}")/libsslkeylog.so + ;; +esac +export SSLKEYLOGFILE=${SSLKEYLOGFILE:-/dev/stderr} # Run the command (if not sourced) [[ ${BASH_SOURCE[0]} != $0 ]] || \ -- cgit v1.2.1