Using keylog_callback with LD_PRELOAD

Kevin Grigorenko kevin at myplaceonline.com
Fri Jun 11 20:48:50 UTC 2021


Hi, I want to use keylog_callback with LD_PRELOAD (i.e. without modifying
 the program to call 
SSL_CTX_set_keylog_callback). For testing, I'm using curl compiled with
 openssl. First, let's confirm curl is using 
SSL_CTX_set_keylog_callback only if there's an SSLKEYLOGFILE by using
 ltrace. With the envar, 
SSL_CTX_set_keylog_callback is called:

$ SSLKEYLOGFILE=/tmp/tls.log ltrace -e SSL_CTX_set_keylog_callback curl
 https://www.openssl.org/robots.txt
libcurl.so.4->SSL_CTX_set_keylog_callback(0x55afd55bc0c0, 0x7f497df43fa0, 0,
 0) = 1
User-agent: *
Disallow: /source/old
Disallow: err404.html
+++ exited (status 0) +++

This prints data to /tmp/tls.log as expected. Without the envar,
 SSL_CTX_set_keylog_callback isn't called as expected:

$ ltrace -e SSL_CTX_set_keylog_callback curl
 https://www.openssl.org/robots.txt
User-agent: *
Disallow: /source/old
Disallow: err404.html
+++ exited (status 0) +++

Next, I downloaded openssl and compiled it locally and wrote the following
 program that hooks into SSL_CTX_new to 
directly set keylog_callback before calling the real SSL_CTX_new. The
 callback function simply writes the data to stderr:

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <ssl/ssl_local.h>

static void keylog_callback(const SSL *ssl, const char *line) {
   fprintf(stderr, "%s\n", line);
}

SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) {
   SSL_CTX* (*real_SSL_CTX_new)(const SSL_METHOD *meth) = dlsym(RTLD_NEXT,
 "SSL_CTX_new");
   if (!real_SSL_CTX_new) {
     fprintf(stderr, "Could not find real SSL_CTX_new\n");
     exit(1);
   }
   #ifdef DEBUG
   fprintf(stderr, "Calling real SSL_CTX_new\n");
   #endif
   SSL_CTX *ctx = real_SSL_CTX_new(meth);
   if (ctx != NULL) {
     ctx->keylog_callback = keylog_callback;
     fprintf(stderr, "[%s:%d:%s] Set custom keylog_callback to %p\n",
 __FILE__, __LINE__, __func__, ctx->keylog_callback);
   }
   #ifdef DEBUG
   fprintf(stderr, "Return ctx %p\n", ctx);
   #endif
   return ctx;
}

Compile the shared library:

gcc -g -Wall -o openssl_keylogfile.so -shared -fPIC keylogfile.c -lcrypto
 -lssl -I/usr/local/src/openssl 
-I/usr/local/src/openssl/include -DDEBUG

Finally, run curl again with this shared library (and obviously without
 SSLKEYLOGFILE so that curl doesn't call 
SSL_CTX_set_keylog_callback and override the above function pointer). It
 prints that it has set keylog_callback but 
keylog_callback is never called:

$ LD_PRELOAD=/work/openssl/openssl_sslkeylogfile/openssl_keylogfile.so curl
 https://www.openssl.org/robots.txt
Calling real SSL_CTX_new
[keylogfile.c:23:SSL_CTX_new] Set custom keylog_callback to 0x7fd1aa7bf139
Return ctx 0x55809c1310c0
User-agent: *
Disallow: /source/old
Disallow: err404.html

Any ideas?

Thanks,

-- 
Kevin Grigorenko



More information about the openssl-users mailing list