0x01 通杀okhttp-ssl-pinning思路 所谓通杀:就是不管有没有混淆,都可以将对应的类识别出来。。。
本质上还是hook对应的类,对应的方法。但是这些方法和类都是做了混淆处理的,怎么在所有类中识别出来特定的类和方法是通杀的关键。。。
第一次校验:X509TrustManager OKHttpClient.Builder builder = new OKHttpClient.Builder(); builder.sslSocketFactory(factory, (X509TrustManager) trustManagers[0])
X509TrustManager是TrustManager接口的一个实现类,主要校验是通过TrustManager接口下的checkServerTrusted函数。
X509TrustManager是通过对checkServerTrusted函数进行重新实现SSLPinning。
上节课的hook思路为:只要是实现了TrustManager接口的类,都hook里面的checkServerTrusted方法。
本节课换思路:Hook掉sslSocketFactory方法,将里面的factory替换我们自己的factory
factory是证书信任工厂
可以自定义factory,让其信任所有
第二次校验:certificatePinner CertificatePinner.Builder cerBuilder = new CertificatePinner.Builder(); //下面4条,对应 ".taobao.com 域名的公钥 cerBuilder.add("*.taobao.com",CertificatePinner.pin(cerBuilder)) cerBuilder.add("*.taobao.com", "sha256/IfXz1a0gWBA5oH+zasmRutUiyoZN3I8wLxHNQxk3NVo=") cerBuilder.add("*.taobao.com", "sha256/IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4=") cerBuilder.add("*.taobao.com", "sha256/K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q=") builder.cerBuilderPinner(cerBuilder.builder())
上节课思路:Hook掉CertificatePinner.Builder类的add方法,将其置空
本节课思路:同上,Hook掉cerBuilderPinner方法,将其参数cerBuilder.builder()置空
第三次校验:hostnameVerify builder.hostnameVerifier(new HostnameVerify){ @Override public boolean verify(String hostname, SSLSession session){ //传入两个参数,hostname:服务器域名 session:会话信息,里面会包含证书相关内容 if (hostname.equals('www.baidu.com')){ //首先判断hostname是否为www.baidu.com(这块随便写的) try{ Certificate[] peerCertificates = session.getPeerCertificates(); //从session获取到服务器端证书相关信息 if(peerCertificates[0].getPublicKey().equals(myCertificate.getPublicKey())){ //判断服务器端证书公钥是否和本地证书公钥一样 return true; //若匹配成功则校验通过,校验失败,也就意味抓不到包 }else{ return false; } }catch(SSLPeerUnverifiedException e){ e.printStackTrace(); return false; } } return false; } }
本节课思路:Hook掉hostnameVerifier方法,将里面的参数HostnameVerify替换为我们自己的
0x02 X509TrustManager实现 OKHttpClient.Builder builder = new OKHttpClient.Builder(); builder.sslSocketFactory(factory, (X509TrustManager) trustManagers[0])
本节课换思路:Hook掉sslSocketFactory方法,将里面的factory替换我们自己的factory
1、builder是OKHttpClient的一个内部类,正常情况下直接Java.use("OKHttp3.OKHttpClient$builder")即可
2、针对有混淆的情况,如何定位到OKHttpClient这个类呢???
原理:可以通过这类实现了哪些接口,这个类对应的方法有什么几个参数等等。如OKHttpClient这个类是一个public类,没有static和final;包名为OKHttp3只有一层等等
本质:我们通过这个类的相关特征,来对他进行识别!
var classNames = new Array ();var OkhttpClinetClassName = "" var CertificatePinnerClassName = "" var perfix = "" function loadClasses ( ){ Java .perform (function ( ){ Java .enumerateClassLoaders ({ onMatch :function (clasName,handle ){ classNames.push (clasName) }, onComplete :function ( ){ console .log ("Search classes complete!" ) } }) }) } function findOkHttpClass ( ){ Java .perform (function ( ){ var Modifier = Java .use ("java.lang.reflect.Modifier" ) function isOkhttpClient (clasName ){ if (clasName.split ('.' ).length != 2 ){ return false ; } try { var clas = Java .use (clasName); var interfaces = clas.class .getInterfaces (); var count = interfaces.length ; if (count < 2 ){ return false ; } var flag = false ; for (var i = 0 ; i < count; i++){ var interface_ = interfaces[i]; var interface_Name = interface_.getName (); if (interface_Name.indexOf ("Cloneable" ) > 0 ){ flag = true ; }else { if (interface_Name.indexOf ("$" ) <= 0 ){ return false } } } if (!flag){ return false ; } if (clas.class .getDeclaringClass ().length = 0 ){ return false ; } if (clas.class .getSuperclass ().getName ().indexOf ("java.lang.Object" ) < 0 ){ return false ; } }catch (e){ return false ; } return true ; } function isCertificatePinner (clasName,perfix ){ if (!clasName.startsWith (perfix)){ return false ; } if (clasName.indexOf ('$' ) > 0 ){ return false ; } if (clasName.split ('.' .length != 2 )){ return false ; } var cls = Java .use (clasName); if (cls.class .isInterface ()){ return false ; } if (cls.class .getInterfaces ().length > 0 ){ return false ; } if (cls.class .getDeclaringClass ().length = 0 ){ return false ; } if (cls.class .getSuperclass ().getName () != "java.lang.Object" ){ return false ; } if (!Modifier .isFinal (cls.class .getModifiers ())){ return false ; } var flag=false var methods = cls.class .getDeclaredMethods (); for (var i = 0 ; i < methods.length ; i++){ var method = methods[i]; if (method.getParameterCount () < 1 ){ couninue; } if (method.getParameterTypes ()[0 ].getName () != "java.security.cert.Certificate" ){ flag = true ; break ; } } if (!flag){ return false ; } flag=false var filed = cls.class .getDeclaredFields (); for (var i = 0 ; i < filed.length ; i++){ var field = filed[i]; if (field.getType ().getName () == "java.util.set" ){ flag = true ; break ; } } if (!flag){ return false ; } return true ; } for (var i = 0 ; i < classNames.length ; i++){ if (isOkhttpClient (classNames[i])){ OkhttpClinetClassName = classNames[i] console .log ("Find OkhttpClinetClassName: " + OkhttpClinetClassName ) perfix = OkhttpClinetClassName .split ('.' )[0 ] + "." } } for (var i = 0 ; i < classNames.length ; i++){ if (isCertificatePinner (classNames[i],perfix)){ CertificatePinnerClassName = classNames[i] } } console .error ("Found class: " + classNames.length ); console .error ("OkHttp's package prefix: " + perfix); console .error ("Find OkhttpClinetClassName: " + OkhttpClinetClassName ); console .error ("Find CertificatePinnerClassName: " + CertificatePinnerClassName ); if (OkhttpClinetClassName == "" || CertificatePinnerClassName == "" || perfix == "" ){ console .error ("Can't find OkhttpClinetClassName or CertificatePinnerClassName" ); return false } return true }) } function main ( ){ loadClasses (); if (findOkHttpClass ()){ } } setImmediate (main)
尝试在加载的类中查找OkHttpClient 和CertificatePinner 这两个类,运行这个脚本,发现通过上面脚本可以成功找到这两个类:
0x03 完整代码&详解 var classesNames = new Array ()var OkhttpClientClassName = "" var CertificatePinnerClassName = "" var prefix = "" function initConsole ( ){ var Color = {RESET : "\x1b[39;49;00m" , Black : "0;01" , Blue : "4;01" , Cyan : "6;01" , Gray : "7;11" , "Green" : "2;01" , Purple : "5;01" , Yellow : "3;01" , Red : "1;01" } var LightColor = {RESET : "\x1b[39;49;00m" , Black : "0;11" , Blue : "4;11" , Cyan : "6;11" , Gray : "7;01" , "Green" : "2;11" , Purple : "5;11" , Red : "1;11" , Yellow : "3;11" } var colorPrefix = '\x1b[3' var colorSuffix = 'm' Object .keys (Color ).forEach (function (c ){ if (c == "RESET" ) return console [c] = function (message ){ console .log (colorPrefix + Color [c] + colorSuffix + message + Color .RESET ) } console ["Light" + c] = function (message ){ console .log (colorPrefix + LightColor [c] + colorSuffix + message + Color .RESET ) } }) } function loadOkhttpClient ( ){ Java .perform (function ( ){ try { Java .use ("okhttp3.OkHttpClient" ) }catch (e){ } }) } function loadClasses ( ){ Java .perform (function ( ){ Java .enumerateLoadedClasses ({ onMatch : function (clsName, handle ){ classesNames.push (clsName) }, onComplete : function ( ){ console .Green ("Search Class Completed!" ) } }) }) } function findOkhttpClass ( ){ Java .perform (function ( ){ var Modifier = Java .use ("java.lang.reflect.Modifier" ) function isOkhttpClient (clsName ){ if (clsName.split ('.' ).length != 2 ){ return false ; } try { var cls = Java .use (clsName) var interfaces = cls.class .getInterfaces () const count = interfaces.length if (count < 2 ){ return false } var flag = false for (var i = 0 ; i < count; i++){ var interface_ = interfaces[i] var interface_name = interface_.getName () if (interface_name.indexOf ("Cloneable" ) > 0 ){ flag = true }else { if (interface_name.indexOf ("$" ) <= 0 ){ return false } } } if (!flag) return false ; if (cls.class .getDeclaredClasses ().length < 1 ){ return false } if (cls.class .getSuperclass ().getName () != 'java.lang.Object' ){ return false } }catch (e){ return false } return true ; } function isCertificatePinner (clsName,prefix ){ if (!clsName.startsWith (prefix)){ return false } if (clsName.indexOf ("$" ) > 0 ){ return false } if (clsName.split ('.' ).length != 2 ){ return false ; } var cls = Java .use (clsName) if (cls.class .isInterface ()){ return false } if (cls.class .getInterfaces ().length > 0 ){ return false } if (cls.class .getDeclaredClasses ().length < 1 ){ return false } if (cls.class .getSuperclass ().getName () != "java.lang.Object" ){ return false } if (!Modifier .isFinal (cls.class .getModifiers ())){ return false } var flag = false var methods = cls.class .getDeclaredMethods () for (var i = 0 ; i < methods.length ; i++){ var method = methods[i] if (method.getParameterCount () < 1 ){ continue } if (method.getParameterTypes ()[0 ].getName () == "java.security.cert.Certificate" ){ flag = true break } } if (!flag) return false flag = false var fields = cls.class .getDeclaredFields () for (var k = 0 ; k < fields.length ; k++){ var field = fields[k]; if (field.getType ().getName () == "java.util.Set" ){ flag = true break } } if (!flag) return false return true } for (var i = 0 ; i < classesNames.length ; i++){ if (isOkhttpClient (classesNames[i])){ OkhttpClientClassName = classesNames[i] var prefix = classesNames[i].split ('.' )[0 ]+'.' } } for (var i = 0 ; i < classesNames.length ; i++){ if (isCertificatePinner (classesNames[i],prefix)){ CertificatePinnerClassName = classesNames[i] } } var printOut if (OkhttpClientClassName == "" || CertificatePinnerClassName == "" || prefix == "" ){ printOut = console .Red printOut ("Can't find the okhttp class" ) }else { printOut = console .Green } printOut ("Found Class: " +classesNames.length ) printOut ("Okhttp's package prefix: " +prefix) printOut ("Found the OkhttpClient: " +OkhttpClientClassName ) printOut ("Found the OkhttpCertificatePinner: " +CertificatePinnerClassName ) }) } function hook ( ){ Java .perform (function ( ){ var Modifier = Java .use ("java.lang.reflect.Modifier" ) var TrustAllManagerClass = Java .registerClass ({ name : "TrustAllManager" , implements :[Java .use ("javax.net.ssl.X509TrustManager" )], methods : { checkClientTrusted (chain, authType ) { console .Cyan ("checkClientTrusted Called!!" ) }, checkServerTrusted (chain, authType ) { console .Cyan ("checkServerTrusted Called!!" ) }, getAcceptedIssuers ( ) { return []; }, } }) var trustAllManagerHandle = TrustAllManagerClass .$new() var sslContext = Java .use ("javax.net.ssl.SSLContext" ).getInstance ("TLS" ) sslContext.init (null ,Java .array ("Ljavax.net.ssl.X509TrustManager;" ,[trustAllManagerHandle]),null ) var sslSocketFactory = sslContext.getSocketFactory () var MyHostnameVerify = Java .registerClass ({ name : "MyHostnameVerify" , implements :[Java .use ("javax.net.ssl.HostnameVerifier" )], methods : { verify (hostname, session ){ console .log (hostname) return true } } }) var myHostnameVerifyHandle = MyHostnameVerify .$new() var internalOkhttpClientClasses = Java .use (OkhttpClientClassName ).class .getDeclaredClasses () internalOkhttpClientClasses.forEach (function (internalClass ) { var methods = internalClass.getDeclaredMethods () methods.forEach (function (method ) { if (method.getParameterCount () < 1 ){ return } var firstParameterTypeName = method.getParameterTypes ()[0 ].getName () if (firstParameterTypeName == "javax.net.ssl.SSLSocketFactory" ){ var Builder = Java .use (internalClass.getName ()) var sslSocketFacotryMethodName = method.getName () Builder [sslSocketFacotryMethodName].overloads .forEach (function (overload ){ overload.implementation = function (SSLSocketFactory ){ arguments [0 ] = sslSocketFactory return this [sslSocketFacotryMethodName].apply (this ,arguments ) } console .Blue (sslSocketFacotryMethodName+" Hooked!" ) }); } if (firstParameterTypeName == "javax.net.ssl.HostnameVerifier" ){ var Builder = Java .use (internalClass.getName ()) var hostnameVerifierMethodName = method.getName () Builder [hostnameVerifierMethodName].overloads .forEach (function (overload ){ overload.implementation = function (hostnameVerifier ){ arguments [0 ] = myHostnameVerifyHandle return this [hostnameVerifierMethodName].apply (this ,arguments ) } console .Yellow (hostnameVerifierMethodName+" Hooked!" ) }); } if (firstParameterTypeName == CertificatePinnerClassName ){ var Builder = Java .use (internalClass.getName ()) var certificatePinnerMethodName = method.getName () Builder [certificatePinnerMethodName].overloads .forEach (function (overload ){ overload.implementation = function (certificatePinner ){ return Java .retain (this ) } console .Purple (certificatePinnerMethodName+" Hooked!" ) }); } }) }); var CertificatePinnerClass = Java .use (CertificatePinnerClassName ) var methods = CertificatePinnerClass .class .getDeclaredMethods () methods.forEach (function (method ){ if (method.getReturnType ().getName () == 'void' ){ var methodName = method.getName () console .Cyan (methodName+" Hooked!" ) CertificatePinnerClass [methodName].overloads .forEach (function (overload ){ if (overload.returnType .name == 'V' ){ overload.implementation = function ( ){ console .Cyan ("certificatePinner check called!" ) } } }) } }) }) } function main ( ){ initConsole () loadOkhttpClient () loadClasses () findOkhttpClass () hook () } setImmediate (main)
initConsole()-可选 function initConsole ( ){ var Color = {RESET : "\x1b[39;49;00m" , Black : "0;01" , Blue : "4;01" , Cyan : "6;01" , Gray : "7;11" , "Green" : "2;01" , Purple : "5;01" , Yellow : "3;01" , Red : "1;01" } var LightColor = {RESET : "\x1b[39;49;00m" , Black : "0;11" , Blue : "4;11" , Cyan : "6;11" , Gray : "7;01" , "Green" : "2;11" , Purple : "5;11" , Red : "1;11" , Yellow : "3;11" } var colorPrefix = '\x1b[3' var colorSuffix = 'm' Object .keys (Color ).forEach (function (c ){ if (c == "RESET" ) return console [c] = function (message ){ console .log (colorPrefix + Color [c] + colorSuffix + message + Color .RESET ) } console ["Light" + c] = function (message ){ console .log (colorPrefix + LightColor [c] + colorSuffix + message + Color .RESET ) } }) }
这个函数initConsole的作用是扩展JavaScript的console对象,使得能够在控制台中输出带有颜色的文本 。它通过定义一个Color对象和一个LightColor对象来包含ANSI转义代码,这些代码用于设置终端中的文本颜色和样式。
具体来说,这个函数做了以下几件事情:
定义了一个Color对象,包含了默认的前景色(文本颜色)和背景色,以及一些基本的文本颜色代码,如黑、蓝、绿等。
定义了一个LightColor对象,包含了与Color相同的颜色,但是这些颜色是亮色的版本。
定义了colorPrefix和colorSuffix变量,这两个变量用于构造ANSI转义代码,用于在终端中设置文本颜色。
使用Object.keys(Color)获取Color对象的所有键(颜色名),然后使用forEach遍历这些键。
对于每个颜色名(除了”RESET”),这个函数会为console对象添加两个新方法:一个用于普通颜色,一个用于亮色。例如,如果颜色名是”Red”,则添加console.Red和console.LightRed两个方法。
当这些新方法被调用时,它们会使用相应的ANSI转义代码来设置文本颜色,然后打印传入的消息,最后将颜色重置为默认。
通过调用initConsole(),你可以在控制台中使用如console.Red(“Error message”)的方式来输出红色文本,或者使用console.LightGreen(“Info message”)来输出亮绿色文本。这有助于在日志输出中区分不同的信息级别或类型。
loadOkhttpClient() function loadOkhttpClient ( ){ Java .perform (function ( ){ try { Java .use ("Okhttps.OkhttpClient" ) }catch (e){ console .error (e) } }) }
loadOKhttpClient()函数的主要作用是在开始Hook前,就加载”Okhttps.OkhttpClient”。
防止通过spawn方法加载脚本的时候,没有完全加载进去所有的类,导致脚本报错。
Java.use("Okhttps.OkhttpClient") 里面的参数,根据下面findOkhttpClass()函数的实际情况进行修改。
loadClasses() var classNames = new Array ();function loadClasses ( ){ Java .perform (function ( ){ Java .enumerateClassLoaders ({ onMatch :function (clasName,handle ){ classNames.push (clasName) }, onComplete :function ( ){ console .log ("Search classes complete!" ) } }) }) }
作用:调用frida 的 API "Java.enumerateClassLoaders" 遍历内存中所有的类,并将这些类放到数组中方便后面调用。
findOkhttpClass()-关键 找到内存中的 “OkhttpClient “ 和 “CertificatePinner “ 类。
var OkhttpClinetClassName = "" var CertificatePinnerClassName = "" var perfix = "" function findOkhttpClass ( ){ Java .perform (function ( ){ var Modifier = Java .use ("java.lang.reflect.Modifier" ) function isOkhttpClient (clsName ){ if (clsName.split ('.' ).length != 2 ){ return false ; } try { var cls = Java .use (clsName) var interfaces = cls.class .getInterfaces () const count = interfaces.length if (count < 2 ){ return false } var flag = false for (var i = 0 ; i < count; i++){ var interface_ = interfaces[i] var interface_name = interface_.getName () if (interface_name.indexOf ("Cloneable" ) > 0 ){ flag = true }else { if (interface_name.indexOf ("$" ) <= 0 ){ return false } } } if (!flag) return false ; if (cls.class .getDeclaredClasses ().length < 1 ){ return false } if (cls.class .getSuperclass ().getName () != 'java.lang.Object' ){ return false } }catch (e){ return false } return true ; } function isCertificatePinner (clsName,prefix ){ if (!clsName.startsWith (prefix)){ return false } if (clsName.indexOf ("$" ) > 0 ){ return false } if (clsName.split ('.' ).length != 2 ){ return false ; } var cls = Java .use (clsName) if (cls.class .isInterface ()){ return false } if (cls.class .getInterfaces ().length > 0 ){ return false } if (cls.class .getDeclaredClasses ().length = 0 ){ return false } if (cls.class .getSuperclass ().getName () != "java.lang.Object" ){ return false } if (!Modifier .isFinal (cls.class .getModifiers ())){ return false } var flag = false var methods = cls.class .getDeclaredMethods () for (var i = 0 ; i < methods.length ; i++){ var method = methods[i] if (method.getParameterCount () < 1 ){ continue } if (method.getParameterTypes ()[0 ].getName () == "java.security.cert.Certificate" ){ flag = true break } } if (!flag) return false flag = false var fields = cls.class .getDeclaredFields () for (var k = 0 ; k < fields.length ; k++){ var field = fields[k]; if (field.getType ().getName () == "java.util.Set" ){ flag = true break } } if (!flag) return false return true } for (var i = 0 ; i < classesNames.length ; i++){ if (isOkhttpClient (classesNames[i])){ OkhttpClientClassName = classesNames[i] var prefix = classesNames[i].split ('.' )[0 ]+'.' } } for (var i = 0 ; i < classesNames.length ; i++){ if (isCertificatePinner (classesNames[i],prefix)){ CertificatePinnerClassName = classesNames[i] } } var printOut if (OkhttpClientClassName == "" || CertificatePinnerClassName == "" || prefix == "" ){ printOut = console .Red printOut ("Can't find the okhttp class" ) }else { printOut = console .Green } printOut ("Found Class: " +classesNames.length ) printOut ("Okhttp's package prefix: " +prefix) printOut ("Found the OkhttpClient: " +OkhttpClientClassName ) printOut ("Found the OkhttpCertificatePinner: " +CertificatePinnerClassName ) }) }
1、首先,定义了一个 反射类Modifier,该类是反射框架提供的一个类,可以判断当前这个类的一些属性,如final、static等
2、定义了一个函数isOkhttpClient,传入参数为类名clsName,作用是获取到经过混淆后的OkhttpClient类名
要求类名长度必须为2(正常的OkHttpClient全名为okhttp3.OkHttpClient)
要求实现的接口数量大于等于2(默认OkHttpClient实现了2个接口)
public class OkHttpClient implements Cloneable , Call.Factory { }
Cloneable: 这个接口来自 Java 标准库,表明 OkHttpClient 类可以被克隆。
Call.Factory: 这个接口是 OkHttp 库的一部分,它定义了创建 Call 实例的方法。Call 对象用于发起 HTTP 请求。
for 循环遍历所有接口,检查是否包含 Cloneable 接口,并且确保其他接口是内部类接口(通过接口名中包含 $ 符号来判断)
检查OkHttpClient 类是否至少包含一个内部类。如果没有返回false
因为 OkHttpClient 是一个顶层类,其父类应该是 Object。
如果上述条件都满足,就可以认为这个类是 OkhttpClient 类。
3、定义了一个函数isCertificatePinner,用来获取经过混淆后的CertificatePinner类
检查包名是否以prefix为前缀,若不是返回false,因为CertificatePinner和OkhttpClient都属于Okhttp3这个包名下的。
判断当前类是否是内部类,CertificatePinner不是一个内部类
判断当前类以”.”分割后,长度是否为2,如果不是返回false
判断当前类是否是接口,如果是返回false
判断当前类是否有接口,如果有返回false
判断当前类中内部类的个数,如果没有返回false
判断当前类是否继承了Object类,如果没有返回false,因为CertificatePinner是顶级类
判断当前类是否是final修饰的,如果是返回false
获取当前类中的所有方法,如果有方法参数为Certificate类型,那么就认为是okhttp3.CertificatePinner类。
hook() 这块对前面讲的三种Hook思路进行实现。
function hook ( ){ Java .perform (function ( ){ var Modifier = Java .use ("java.lang.reflect.Modifier" ) var TrustAllManagerClass = Java .registerClass ({ name : "TrustAllManager" , implements :[Java .use ("javax.net.ssl.X509TrustManager" )], methods : { checkClientTrusted (chain, authType ) { console .Cyan ("checkClientTrusted Called!!" ) }, checkServerTrusted (chain, authType ) { console .Cyan ("checkServerTrusted Called!!" ) }, getAcceptedIssuers ( ) { return []; }, } }) var trustAllManagerHandle = TrustAllManagerClass .$new() var sslContext = Java .use ("javax.net.ssl.SSLContext" ).getInstance ("TLS" ) sslContext.init (null ,Java .array ("Ljavax.net.ssl.X509TrustManager;" ,[trustAllManagerHandle]),null ) var sslSocketFactory = sslContext.getSocketFactory () var MyHostnameVerify = Java .registerClass ({ name : "MyHostnameVerify" , implements :[Java .use ("javax.net.ssl.HostnameVerifier" )], methods : { verify (hostname, session ){ console .log (hostname) return true } } }) var myHostnameVerifyHandle = MyHostnameVerify .$new() var internalOkhttpClientClasses = Java .use (OkhttpClientClassName ).class .getDeclaredClasses () internalOkhttpClientClasses.forEach (function (internalClass ) { var methods = internalClass.getDeclaredMethods () methods.forEach (function (method ) { if (method.getParameterCount () < 1 ){ return } var firstParameterTypeName = method.getParameterTypes ()[0 ].getName () if (firstParameterTypeName == "javax.net.ssl.SSLSocketFactory" ){ var Builder = Java .use (internalClass.getName ()) var sslSocketFacotryMethodName = method.getName () Builder [sslSocketFacotryMethodName].overloads .forEach (function (overload ){ overload.implementation = function (SSLSocketFactory ){ arguments [0 ] = sslSocketFactory return this [sslSocketFacotryMethodName].apply (this ,arguments ) } console .Blue (sslSocketFacotryMethodName+" Hooked!" ) }); } if (firstParameterTypeName == "javax.net.ssl.HostnameVerifier" ){ var Builder = Java .use (internalClass.getName ()) var hostnameVerifierMethodName = method.getName () Builder [hostnameVerifierMethodName].overloads .forEach (function (overload ){ overload.implementation = function (hostnameVerifier ){ arguments [0 ] = myHostnameVerifyHandle return this [hostnameVerifierMethodName].apply (this ,arguments ) } console .Yellow (hostnameVerifierMethodName+" Hooked!" ) }); } if (firstParameterTypeName == CertificatePinnerClassName ){ var Builder = Java .use (internalClass.getName ()) var certificatePinnerMethodName = method.getName () Builder [certificatePinnerMethodName].overloads .forEach (function (overload ){ overload.implementation = function (certificatePinner ){ return Java .retain (this ) } console .Purple (certificatePinnerMethodName+" Hooked!" ) }); } }) }); var CertificatePinnerClass = Java .use (CertificatePinnerClassName ) var methods = CertificatePinnerClass .class .getDeclaredMethods () methods.forEach (function (method ){ if (method.getReturnType ().getName () == 'void' ){ var methodName = method.getName () console .Cyan (methodName+" Hooked!" ) CertificatePinnerClass [methodName].overloads .forEach (function (overload ){ if (overload.returnType .name == 'V' ){ overload.implementation = function ( ){ console .Cyan ("certificatePinner check called!" ) } } }) } }) }) }