diff --git a/ios/ios-connect-hook.js b/ios/ios-connect-hook.js index 8459df6..8349b2e 100644 --- a/ios/ios-connect-hook.js +++ b/ios/ios-connect-hook.js @@ -20,12 +20,13 @@ // This is the method we're going to patch: // https://developer.apple.com/documentation/network/2976677-nw_connection_create (iOS 12+) -const nw_connection_create = Module.findExportByName('libnetwork.dylib', 'nw_connection_create'); +const libnetwork = Process.getModuleByName('libnetwork.dylib'); +const nw_connection_create = libnetwork.getExportByName('nw_connection_create'); // This is the method to make a new endpoint to connect to: // https://developer.apple.com/documentation/network/2976720-nw_endpoint_create_host (iOS 12+) const nw_endpoint_create_host = new NativeFunction( - Module.findExportByName('libnetwork.dylib', 'nw_endpoint_create_host'), + libnetwork.findExportByName('nw_endpoint_create_host'), 'pointer', ['pointer', 'pointer'] ); diff --git a/native-connect-hook.js b/native-connect-hook.js index 20e3b5a..96c8e52 100644 --- a/native-connect-hook.js +++ b/native-connect-hook.js @@ -21,11 +21,15 @@ const PROXY_HOST_IPv4_BYTES = PROXY_HOST.split('.').map(part => parseInt(part, 1 const IPv6_MAPPING_PREFIX_BYTES = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff]; const PROXY_HOST_IPv6_BYTES = IPv6_MAPPING_PREFIX_BYTES.concat(PROXY_HOST_IPv4_BYTES); -const connectFn = ( - Module.findExportByName('libc.so', 'connect') ?? // Android - Module.findExportByName('libc.so.6', 'connect') ?? // Linux - Module.findExportByName('libsystem_kernel.dylib', 'connect') // iOS -); +let connectFn = null; +try { + connectFn = + Process.findModuleByName('libc.so')?.findExportByName('connect') ?? // Android + Process.findModuleByName('libc.so.6')?.findExportByName('connect') ?? // Linux + Process.findModuleByName('libsystem_kernel.dylib')?.findExportByName('connect'); // iOS +} catch (e) { + console.error("Failed to find 'connect' export:", e); +} if (!connectFn) { // Should always be set, but just in case console.warn('Could not find libc connect() function to hook raw traffic'); diff --git a/native-tls-hook.js b/native-tls-hook.js index 24d2b38..b21883d 100644 --- a/native-tls-hook.js +++ b/native-tls-hook.js @@ -40,8 +40,8 @@ const TARGET_LIBS = [ ]; TARGET_LIBS.forEach((targetLib) => { - waitForModule(targetLib.name, (moduleName) => { - patchTargetLib(moduleName); + waitForModule(targetLib.name, (targetModule) => { + patchTargetLib(targetModule, targetLib.name); targetLib.hooked = true; }); @@ -56,36 +56,36 @@ TARGET_LIBS.forEach((targetLib) => { } }); -function patchTargetLib(targetLib) { +function patchTargetLib(targetModule, targetName) { // Get the peer certificates from an SSL pointer. Returns a pointer to a STACK_OF(CRYPTO_BUFFER) // which requires use of the next few methods below to actually access. // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_get0_peer_certificates const SSL_get0_peer_certificates = new NativeFunction( - Module.findExportByName(targetLib, 'SSL_get0_peer_certificates'), + targetModule.getExportByName('SSL_get0_peer_certificates'), 'pointer', ['pointer'] ); // Stack methods: // https://commondatastorage.googleapis.com/chromium-boringssl-docs/stack.h.html const sk_num = new NativeFunction( - Module.findExportByName(targetLib, 'sk_num'), + targetModule.getExportByName('sk_num'), 'size_t', ['pointer'] ); const sk_value = new NativeFunction( - Module.findExportByName(targetLib, 'sk_value'), + targetModule.getExportByName('sk_value'), 'pointer', ['pointer', 'int'] ); // Crypto buffer methods: // https://commondatastorage.googleapis.com/chromium-boringssl-docs/pool.h.html const crypto_buffer_len = new NativeFunction( - Module.findExportByName(targetLib, 'CRYPTO_BUFFER_len'), + targetModule.getExportByName('CRYPTO_BUFFER_len'), 'size_t', ['pointer'] ); const crypto_buffer_data = new NativeFunction( - Module.findExportByName(targetLib, 'CRYPTO_BUFFER_data'), + targetModule.getExportByName('CRYPTO_BUFFER_data'), 'pointer', ['pointer'] ); @@ -118,7 +118,7 @@ function patchTargetLib(targetLib) { } pendingCheckThreads.add(threadId); - if (targetLib !== 'libboringssl.dylib') { + if (targetName !== 'libboringssl.dylib') { // Cronet assumes its callback is always called, and crashes if not. iOS's BoringSSL // meanwhile seems to use some negative checks in its callback, and rejects the // connection independently of the return value here if it's called with a bad cert. @@ -171,8 +171,8 @@ function patchTargetLib(targetLib) { }; const customVerifyAddrs = [ - Module.findExportByName(targetLib, "SSL_set_custom_verify"), - Module.findExportByName(targetLib, "SSL_CTX_set_custom_verify") + targetModule.findExportByName("SSL_set_custom_verify"), + targetModule.findExportByName("SSL_CTX_set_custom_verify") ].filter(Boolean); customVerifyAddrs.forEach((set_custom_verify_addr) => { @@ -190,14 +190,14 @@ function patchTargetLib(targetLib) { if (customVerifyAddrs.length) { if (DEBUG_MODE) { - console.log(`[+] Patched ${customVerifyAddrs.length} ${targetLib} verification methods`); + console.log(`[+] Patched ${customVerifyAddrs.length} ${targetName} verification methods`); } - console.log(`== Hooked native TLS lib ${targetLib} ==`); + console.log(`== Hooked native TLS lib ${targetName} ==`); } else { - console.log(`\n !!! Hooking native TLS lib ${targetLib} failed - no verification methods found`); + console.log(`\n !!! Hooking native TLS lib ${targetName} failed - no verification methods found`); } - const get_psk_identity_addr = Module.findExportByName(targetLib, "SSL_get_psk_identity"); + const get_psk_identity_addr = targetModule.findExportByName("SSL_get_psk_identity"); if (get_psk_identity_addr) { // Hooking this is apparently required for some verification paths which check the // result is not 0x0. Any return value should work fine though.