우회해야하는 pinning request 목록은 아래와 같다.
1. UNPINNED REQUEST
2. CONFIG FINNED REQUEST
3. OKHTTP PINNED REQUEST
4. VOLLEY PINNED REQUEST
5. TRUSTKT PINNED REQUEST
6. MANUALLY PINNED REQUEST
Java.perform(function(){
console.log('');
console.log('======');
console.log('[#] Android Network Security Config bypass [#]');
console.log('======');
var array_list = Java.use("java.util.ArrayList");
var ApiClient1 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
var ApiClient2 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
var ApiClient3 = Java.use('okhttp3.CertificatePinner');
var ApiClient4 = Java.use('okhttp3.CertificatePinner');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
const TrustManager = Java.registerClass({
// Implement a custom TrustManager
name: 'dev.asd.test.TrustManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function (chain, authType) { },
checkServerTrusted: function (chain, authType) { },
getAcceptedIssuers: function () { return []; }
}
});
const TrustManagers = [TrustManager.$new()];
const SSLContext_init = SSLContext.init.overload(
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom'
);
SSLContext_init.implementation = function (keyManager, trustManager, secureRandom) {
console.log(' --> Bypassing Trustmanager (Android < 7) request');
SSLContext_init.call(this, keyManager, TrustManagers, secureRandom);
};
ApiClient1.checkTrustedRecursive.implementation = function(a1, a2, a3, a4, a5, a6, a7, a8){
console.log('Bypassing SSL Pinning');
var trusted = array_list.$new();
return trusted;
//return;
};
ApiClient2.verifyChain.implementation = function(a1, a2, a3, a4, a5, a6, a7, a8){
console.log('Bypassing SSL Pinning');
var trusted = array_list.$new();
return trusted;
//return;
};
ApiClient3.check.implementation = function(a1, a2, a3){
console.log('Bypassing SSL Pinning');
var trusted = array_list.$new();
return trusted;
//return;
};
ApiClient4.check$okhttp.implementation = function(a1, a2, a3){
console.log('Bypassing SSL Pinning');
var trusted = array_list.$new();
return trusted;
//return;
};
});
위의 frida script를 통해 아래 캡처 사진에서 보이는 것처럼 1, 2, 4, 5번의 pinning request를 우회할 수 있다.
UNPINNED REQUEST, CONFIG PINNED REQUEST, VOLLEY PINNED REQUEST는 교안에 나와있던 frida script로 bypass가 가능했다.
TRUSTKIT PINNED REQUEST는 frida script에서 Trusted 값을 return 함으로써 bypass할 수 있다.
MANUALLY PINNED REQUEST
android sslpinning disable 명령어를 통해 아래와 같은 결과를 얻을 수 있다.
따라서 위의 함수들의 경로를 찾고 그것을 override 해야한다는 것을 알 수 있다.
SSLContext.init(), CertificatePinner.check(), CertificatePinner.check$okhttp(), TrustmanagerImpl.verifyChain(), TrustManagerImpl.verifyChain() 찾고, 그것을 overriding하는 방식으로 frida script를 작성하고, bypass 하였다.