Now that we’ve gotten the SSL library identified in IDA (see last post), it’s time to change the certificate validation mode. This is useful when you want to use a cert that isn’t inside the certificate store, like a self-signed localhost cert.

First we start by finding where SSL_CTX_get_verify_callback is used. We can search for the function then right-click -> Jump to xref to operand. You can also place your caret on the function name and use the shortcut X.

It only had one use in my case:

Disassembly

Assembly view

mov rcx, [rbx+8]
call SSL_CTX_get_verify_callback
mov r8, rax
mov edx, 1
mov rcx, [rbx+8]
call SSL_CTX_set_verify

C view

verify_callback = SSL_CTX_get_verify_callback(*(_QWORD *)(v13 + 8));
SSL_CTX_set_verify(*(_QWORD *)(v13 + 8), 1, verify_callback);

Function signatures

int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int, X509_STORE_CTX *);
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));

Let’s take this one line at a time. Compared to x86 assembly, instead of pushing arguments to the stack the compiler sets registers instead. The arguments are set in reverse order.

x86_64 Assembly C Description
mov rcx, [rbx+8] verify_callback = SSL_CTX_get_verify_callback(*(_QWORD *)(v13 + 8)) Set the parameter for SSL_CTX_get_verify_callback to the value in [rbx+8].
call SSL_CTX_get_verify_callback verify_callback = SSL_CTX_get_verify_callback(*(_QWORD *)(v13 + 8)) Call the function, the result will be stored in rAX.
mov r8, rax SSL_CTX_set_verify(*(_QWORD *)(v13 + 8), 1, verify_callback) Set the 3rd parameter for SSL_CTX_set_verify, which is the callback.
mov edx, 1 SSL_CTX_set_verify(*(_QWORD *)(v13 + 8), 1, verify_callback) Set the 2nd parameter for SSL_CTX_set_verify, which is the mode.
mov rcx, [rbx+8] SSL_CTX_set_verify(*(_QWORD *)(v13 + 8), 1, verify_callback) Set the 1st parameter for SSL_CTX_set_verify, which is the context.
call SSL_ctx_set_verify SSL_CTX_set_verify(*(_QWORD *)(v13 + 8), 1, verify_callback) Call the function to set the verify callback/mode in the context.

We want to change set_verify’s 2nd argument to use SSL_VERIFY_NONE (0) instead of SSL_VERIFY_PEER (1).

Patching

We understand what we’re looking for now – we want to replace the instruction mov edx, 1 to mov edx, 0.

The hex here shows BA 01 00 00 00. BA is the opcode for mov eDX. Its operand is a 32-bit immediate value. We’ll simply want to change this to BA 00 00 00 00!

You can hex edit the executable directly or write a script to do it, or save a binary diff patch. Either way – that’s all folks.

References

  • https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_get_verify_callback.html
  • https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html
  • https://stackoverflow.com/a/11130969