├── README.md └── flutter-bypass-sslpinning.js /README.md: -------------------------------------------------------------------------------- 1 | # Flutter SSL Pinning Bypass 32bit and 64bit. 2 | 3 | Frida script to bypass SSL Pinning on Android application built using Flutter SDK. 4 | It was working well for bypassing SSL pinning protection on Flutter framework (BoringSSL). 5 | 6 | This script has been used on this article: https://id.horangi.com/blog/bypass-ssl-pinning-di-flutter-library/ 7 | 8 | Reference: 9 | * https://blog.nviso.eu/2019/08/13/intercepting-traffic-from-android-flutter-applications/ 10 | * https://blog.nviso.eu/2020/05/20/intercepting-flutter-traffic-on-android-x64/ 11 | * https://frida.re/docs/javascript-api/ 12 | 13 | Requirement: 14 | * Frida - https://frida.re/ 15 | 16 | How to: 17 | * Modify variable *pattern* 18 | * Modify variable *armversion* 19 | * Execute: `$ frida -Ul flutter-bypass-sslpinning.js -f com.package.name --no-pause` 20 | -------------------------------------------------------------------------------- /flutter-bypass-sslpinning.js: -------------------------------------------------------------------------------- 1 | setTimeout(function () { 2 | // pattern bytes 3 | var pattern = "ff 03 05 d1 fd 7b 0f a9 bc de 05 94 08 0a 80 52 48" 4 | // library name 5 | var module = "libflutter.so" 6 | // define your arm version 7 | var armversion = 8 8 | // expected return value 9 | var expectedReturnValue = true 10 | 11 | // random string, you may ignore this 12 | console.log("Horangi - Bypass Flutter SSL Pinning") 13 | // enumerate all process 14 | Process.enumerateModules().forEach(v => { 15 | // if the module matches with our library 16 | if(v['name'] == module) { 17 | // debugging purposes 18 | console.log("Base: ", v['base'], "| Size: ", v['size'], "\n") 19 | // scanning memory - synchronous version 20 | // compare it based on base, size and pattern 21 | Memory.scanSync(v['base'], v['size'], pattern).forEach(mem => { 22 | // assign address to variable offset 23 | var offset = mem['address'] 24 | if(armversion === 7) { 25 | // armv7 add 1 26 | offset = offset.add(1) 27 | } 28 | // another debugging purposes 29 | console.log("Address:",offset,"::", mem['size']) 30 | // hook to the address 31 | Interceptor.attach(offset, { 32 | // when leaving the address, 33 | onLeave: function(retval) { 34 | // execute this debugging purpose (again) 35 | console.log("ReturnValue",offset,"altered from", +retval,"to", +expectedReturnValue) 36 | // replace the return value to expectedReturnValue 37 | retval.replace(+expectedReturnValue); 38 | } 39 | }) 40 | }) 41 | } 42 | }); 43 | }, 1000) // wait for 1 sec until the app load the library. 44 | --------------------------------------------------------------------------------