├── HTTPS抓包相关 ├── https1.png ├── README.md ├── iptables │ ├── android_redirect.sh │ └── README.md ├── frida_attach.py ├── 安装系统证书.md └── ssl_unpinning.js ├── 双向证书 └── 说明.md ├── 漏洞挖掘相关 ├── 说明.md └── auto_frida_dexdump.py ├── scripts ├── android-位置伪造.js └── android-注入恶意代码.js └── README.md /HTTPS抓包相关/https1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coffeehb/FridaHook/HEAD/HTTPS抓包相关/https1.png -------------------------------------------------------------------------------- /双向证书/说明.md: -------------------------------------------------------------------------------- 1 | ## 可以HOOK 得到证书加载密码: 2 | https://raw.githubusercontent.com/m0bilesecurity/Frida-Mobile-Scripts/master/Android/tracer_keystore.js 3 | 4 | ### 参考案例:Soul抓包记录 5 | https://mp.weixin.qq.com/s/LVX-EPlY4oqK1tzfhxxWMw 6 | 7 | -------------------------------------------------------------------------------- /漏洞挖掘相关/说明.md: -------------------------------------------------------------------------------- 1 | ## 参考 2 | https://github.com/zxhubo/frida-js 3 | 4 | ## 基础学习 5 | https://github.com/zxhubo/frida-all-in-one 6 | 7 | ## 自动批量脱壳 V1.0 8 | https://github.com/coffeehb/FridaHook/blob/master/%E6%BC%8F%E6%B4%9E%E6%8C%96%E6%8E%98%E7%9B%B8%E5%85%B3/auto_frida_dexdump.py 9 | -------------------------------------------------------------------------------- /scripts/android-位置伪造.js: -------------------------------------------------------------------------------- 1 | const lat = 27.9864882; 2 | const lng = 33.7279001; 3 | 4 | Java.perform(function () { 5 | var Location = Java.use("android.location.Location"); 6 | Location.getLatitude.implementation = function() { 7 | send("Overwriting Lat to " + lat); 8 | return lat; 9 | } 10 | Location.getLongitude.implementation = function() { 11 | send("Overwriting Lng to " + lng); 12 | return lng; 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /HTTPS抓包相关/README.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | ## ssl unpinning使用 4 | 5 | - 启动Frida-Server 6 | ``` 7 | adb forward tcp:27042 tcp:27042 8 | adb forward tcp:27043 tcp:27043 9 | adb shell /data/local/tmp/frida-server -D 10 | ``` 11 | - 配置全局代理到Burp 12 | 13 | - 打开APP,开始hook 14 | 15 | python frida_attach.py hooks.js com.sankuai.meituan.meituanwaimaibusiness 16 | 17 | - 完成HTTPS抓包 18 | 19 | ![avatar](https1.png) 20 | 21 | ## 参考 22 | hook anywhere、抓包 23 | 24 | https://www.anquanke.com/post/id/197657#h3-11 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FridaHook 2 | 记录学习Frida Hook时的知识点和小脚本 3 | 4 | ## 参考 5 | 学习Frida首推这个项目 6 | 7 | https://github.com/r0ysue/AndroidSecurityStudy 8 | 9 | Frida脱壳推荐这个项目 10 | 11 | https://github.com/hluwa/FRIDA-DEXDump 12 | 13 | ADB调试命令相关必推荐 14 | 15 | https://github.com/mzlogin/awesome-adb/blob/master/README.md 16 | 17 | 编写hook脚本练习 18 | 19 | https://github.com/m0bilesecurity/Frida-Mobile-Scripts/tree/master/Android 20 | 21 | ## 实战 22 | 23 | Brida插件加解密实战 24 | 25 | https://xz.aliyun.com/t/7562 26 | -------------------------------------------------------------------------------- /HTTPS抓包相关/iptables/android_redirect.sh: -------------------------------------------------------------------------------- 1 | # 在Android手机里使用iptables将指定进程的流量强制转到目的IP上,默认是转到8080端口 2 | # 使用场景: 解决Android手机HW P20 HTTPS无法抓包的问题 3 | # 1、HW手机无法进行Frida HOOK ,设置全局代理后 应用打开出现异常。 4 | # 2、HW 手机刷入了EdXposed 做了SSL Upinning (设置全局代理,大部分应用可以抓HTTPS的) 5 | # 解决:切换到root 后,强制把流量转到Burp代理。这样bypass了应用检测是否设置了系统代理 6 | #!/system/bin/sh 7 | 8 | 9 | function usage(){ 10 | echo "Usage: `basename $0` [-F] uid ip" 11 | } 12 | 13 | 14 | 15 | 16 | if [ $# != 2 -a $# != 1 ] 17 | then 18 | usage 19 | exit 55 20 | fi 21 | 22 | 23 | while getopts "AF" opt; do 24 | case $opt in 25 | F) 26 | echo "delete all redirect rule!" 27 | iptables -t nat -F 28 | exit 0 29 | ;; 30 | A) 31 | echo "redirect all tcp traffic" 32 | iptables -t nat -F 33 | 34 | iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination $2:8080 35 | iptables -t nat -A POSTROUTING -p tcp -j MASQUERADE 36 | exit 0 37 | ;; 38 | \?) 39 | echo "Invalid option: -$OPTARG" 40 | exit 0 41 | ;; 42 | esac 43 | done 44 | 45 | 46 | 47 | if [ $# == 2 ] 48 | then 49 | 50 | echo " uid: "$1" ip: "$2 51 | 52 | iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner $1 -j DNAT --to-destination $2:8080 53 | iptables -t nat -A POSTROUTING -p tcp -m owner --uid-owner $1 -j MASQUERADE 54 | exit 0 55 | 56 | fi 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /HTTPS抓包相关/frida_attach.py: -------------------------------------------------------------------------------- 1 | #coding:utf8 2 | 3 | import frida, sys,os,json,codecs 4 | import subprocess 5 | import time 6 | import ctypes 7 | 8 | if (len(sys.argv) == 3): 9 | jsfile = str(sys.argv[1].strip()) 10 | package_name = str(sys.argv[2]).strip() 11 | else: 12 | 13 | print "Usage: python frida_attach.py [hook.js] [package_name] " 14 | 15 | sys.exit(1) 16 | 17 | def print_result(message): 18 | print ("[!] Received: [%s]" %(message)) 19 | 20 | def stringFromArray(data): 21 | 22 | ret = '' 23 | for i in data: 24 | value = ctypes.c_uint8(i).value 25 | 26 | if value == 0: 27 | 28 | continue 29 | 30 | if value <=127: 31 | 32 | ret += chr(value) 33 | else: 34 | 35 | ret += '\\x' + hex(value)[2:] 36 | 37 | return ret 38 | 39 | 40 | def hex_stringFromArray(data): 41 | 42 | ret = '[' 43 | for i in data: 44 | value = ctypes.c_uint8(i).value 45 | 46 | ret += hex(value) + "," 47 | 48 | return ret + "]" 49 | 50 | def on_message(message, data): 51 | print(data) 52 | if 'payload' in message: 53 | data = message['payload'] 54 | 55 | if type(data) is list: 56 | 57 | print stringFromArray(data) 58 | 59 | else: 60 | print data 61 | 62 | else: 63 | if message['type'] == 'error': 64 | print (message['stack']) 65 | else: 66 | print message 67 | 68 | def main(): 69 | 70 | with codecs.open(jsfile, 'r', encoding='utf8') as f: 71 | jscode = f.read() 72 | 73 | process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name) 74 | script = process.create_script(jscode) 75 | script.on('message', on_message) 76 | script.load() 77 | sys.stdin.read() 78 | 79 | if __name__ == '__main__': 80 | main() 81 | -------------------------------------------------------------------------------- /HTTPS抓包相关/iptables/README.md: -------------------------------------------------------------------------------- 1 | ## bypass APP检测系统全局代理方法一 2 | 3 | ### 场景 4 | 5 | 在Android手机里使用iptables将指定进程的流量强制转到目的IP上,默认是转到8080端口【脚本来自我司大佬】 6 | 7 | 使用场景: 解决Android手机HW P20 HTTPS无法抓包的问题 8 | - 1、HW手机无法进行Frida HOOK ,设置全局代理后 应用打开出现异常。 9 | - 2、HW 手机刷入了EdXposed 做了SSL Upinning (设置全局代理,大部分应用可以抓HTTPS的) 10 | 11 | 解决:切换到root 后,强制把流量转到Burp代理。这样bypass了应用检测是否设置了系统代理 12 | 13 | ### 使用方法: 14 | 15 | - 首先找到目标APP 包名: 比如:HW的账号服务SDK的,com.huawei.hwid 16 | adb shell dumpsys activity | grep real 17 | 18 | ``` 19 | ➜ ~ adb shell dumpsys activity | grep real 20 | authority=com.huawei.jos.realname.provider 21 | realActivity=com.huawei.android.launcher/.unihome.UniHomeLauncher 22 | realActivity=com.huawei.hwid/com.huawei.hms.jos.api.account.JosSignInActivity 23 | realActivity=com.youdao.course/.activity.StartJumperActivity 24 | realActivity=com.huawei.android.launcher/.unihome.UniHomeLauncher 25 | realActivity=com.topjohnwu.magisk/a.c 26 | ``` 27 | 28 | - 然后通过报名找到进程ID:u0_a103 29 | adb shell ps -A | grep com.huawei.hwid 30 | 31 | ``` 32 | ➜ ~ adb shell ps -A | grep com.huawei.hwid 33 | u0_a103 1088 4521 4966304 117780 0 0 S com.huawei.hwid 34 | u0_a103 2334 4521 4291944 59976 0 0 S com.huawei.hwid.container1 35 | u0_a103 5886 4521 4297128 71536 0 0 S com.huawei.hwid.persistent 36 | u0_a103 5949 4521 4480996 73780 0 0 S com.huawei.hwid.core 37 | ➜ 38 | ``` 39 | 40 | - 然后上传脚本,使用如下: 41 | 42 | ``` 43 | 强制账号应用的流量转到10.222.333.34的8080端口 44 | HWEML:/ # sh /data/local/tmp/redirect.sh u0_a103 10.117.122.34 45 | uid: u0_a103 ip: 10.222.333.34 46 | 47 | ``` 48 | - 清除转发 49 | sh /data/local/tmp/redirect.sh -F 50 | 51 | 52 | ## 遗留问题 53 | 54 | - 1、如何安装Edxposed 55 | - 2、如何做到SSL Unpinning 56 | 57 | 参考: 58 | https://blog.csdn.net/Aaron_Miller/article/details/106958610 59 | 60 | u1s1, 我还没有是实操过。等我体验过后再分享。 61 | 62 | -------------------------------------------------------------------------------- /HTTPS抓包相关/安装系统证书.md: -------------------------------------------------------------------------------- 1 | # 安装Burp证书为Android的系统证书 2 | 3 | - 条件: 4 | 手机已root + BL已解锁 5 | 6 | 7 | ## 准备工作 8 | 9 | ### 先执行的命令 10 | 11 | 确认是否root,命令->```adb root``` 以及remount命令-> ```adb remount``` 12 | 确认之后,开始下面的操作 13 | 1. 第一步,配置burp代理,访问http://burp/ 下载证书 14 | 15 | 2. 第二步,制作证书,执行以下命令 16 | 17 | openssl x509 -inform DER -outform PEM -in cacert.der -out cacert.pem 18 | 19 | openssl x509 -subject_hash_old -in cacert.pem (执行后会得到一个hash 比如下面的:9a5ca275) 20 | 21 | 9a5ba575 22 | 23 | -----BEGIN CERTIFICATE----- 24 | 25 | MIIDyTCCArGgAwIBAgIEU65bkjANBgkqhkiG9w0BAQsFADCBijEUMBIGA1UEBhML 26 | 27 | UG9ydFN3aWdnZXIxFDASBgNVBAgTC1BvcnRTd2lnZ2VyMRQwEgYDVQQHEwtQb3J0 28 | 29 | U3dpZ2dlcjEUMBIGA1UEChMLUG9ydFN3aWdnZXIxFzAVBgNVBAsTDlBvcnRTd2ln 30 | 31 | Z2VyIENBMRcwFQYDVQQDEw5Qb3J0U3dpZ2dlciBDQTAeFw0xNDA2MjgwNjA3MTRa 32 | 33 | Fw0zOTA2MjgwNjA3MTRaMIGKMRQwEgYDVQQGEwtQb3J0U3dpZ2dlcjEUMBIGA1UE 34 | 35 | CBMLUG9ydFN3aWdnZXIxFDASBgNVBAcTC1BvcnRTd2lnZ2VyMRQwEgYDVQQKEwtQ 36 | 37 | b3J0U3dpZ2dlcjEXMBUGA1UECxMOUG9ydFN3aWdnZXIgQ0ExFzAVBgNVBAMTDlBv 38 | 39 | cnRTd2lnZ2VyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAius5 40 | 41 | fmizc2WJDmIITTuqtFi+6pFXAiLZvD7u7zXj2ihpQu1FrYllxQO8PgQAyhuM3A7Z 42 | 43 | wE10rpaOiDknefmd62RwCa+RfdvgR/K+zb9+vNO9hzYiPA7/YU8bxq8JuvnH7T9J 44 | 45 | YrkdbkWoeKoItB+Qh6zAHxijHiH9tbWYSs5LtTSvF+PT2yQGSdCfXYLv6D88w3m9 46 | 47 | PNXM5WQaeFWBtcV6uX2Ka9VGU84FpDE1A0tswU16n2XDcJFZMAsTL5wgWIrO1/um 48 | 49 | AiFfFnnF38i2csAWVXUGUyvcBMQfwNHavUSMGcAz58j0RS2GfazCV8X/GIGJBllL 50 | 51 | lTrA5b19i7BqXV7d7QIDAQABozUwMzASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1Ud 52 | 53 | DgQWBBSYKIxYVvF2ImxbLR475rBkjLD92TANBgkqhkiG9w0BAQsFAAOCAQEAeQuk 54 | 55 | MtO+41nBQ35l0o0vA7O6Q2WgHTvoikOrvoPio9Yt1gSZpL+gUpO6ywd/mjcCrdw4 56 | 57 | 2CvFcm/g5WgkCvJP4V0P/VCrKVxrvLtjuugOVS5SnmN2qT4aykySj/8Dxu+m4YA7 58 | 59 | rXRu5KWC+tpdewTNGQEJa5FmjNk2fX0wj53yPbcRPY1ERLChZagLMr1QEKKnNuUL 60 | 61 | /83fatk4ady1eHsx2E420ZQknLZTsK5XOGwv3sM4/MtCnOE8qq32z1uB68ZQvhtW 62 | 63 | mHGbgRV8yYvx90ABC85T9kmxKxdnRBiH5r8v4doXAztj+a4Jrvs7yuvxavJRbfPH 64 | 65 | ufuDtzbN7UWX4/xHBA== 66 | 67 | -----END CERTIFICATE----- 68 | 69 | 3. 第三步,push 证书到手机 70 | 制作.0的证书,用到上面的hash 71 | mv cacert.pem 9a5ca275.0 72 | push到手机 73 | adb push 9a5ba575.0 /system/etc/security/cacerts/ 74 | 75 | 到此,安装完成~ 76 | -------------------------------------------------------------------------------- /漏洞挖掘相关/auto_frida_dexdump.py: -------------------------------------------------------------------------------- 1 | # 自动批量脱壳 V1.0 2 | # By CFHB 3 | # 脚本思路: 4 | # 1、遍历base_path下面有哪些APK 5 | # 2、adb 强制安装APK 6 | # 3、adb 查找刚刚安装的APP的包名 7 | # 4、adb 寻找这个应用的主类并打开(打开应用) 8 | # 5、adb 运行Frida脱壳脚本 9 | # 6、记录脱壳成功的记录,写入文件 10 | # 7、adb 卸载这个应用 11 | # 8、继续 2~7步骤 12 | 13 | 14 | import time 15 | import os 16 | 17 | black_list = ['com.android.mms','com.ted.number'] 18 | base_path = "/Users/CFHB/androidapp/" 19 | cmd1 = 'adb install -r -d ' 20 | cmd2 = 'adb shell ls /data/data/ -alh | grep 2022-03 | awk \'OFS="\t"{print $8}\'' 21 | cmd5 = 'adb shell monkey -c android.intent.category.LAUNCHER -v -v -v 0 | grep %s |awk \'OFS="\t"{print $6}\'' 22 | cmd6 = 'adb shell am start -n ' 23 | cmd3 = 'python2 main.py' 24 | cmd4 = 'adb shell pm uninstall ' 25 | 26 | def init_blacklist_app(): 27 | cmd_bl = 'adb shell ls /data/data/ -alh | grep 2021-11 | awk \'OFS="\t"{print $8}\'' 28 | result = os.popen(cmd_bl) 29 | res = result.read() 30 | for line in res.splitlines(): 31 | if line not in black_list and len(line) > 5: 32 | black_list.append(line) 33 | 34 | init_blacklist_app() 35 | print(len(black_list) , " 个APP") 36 | 37 | def logger_file(pkname): 38 | with open ("success.txt", 'a+') as wf: 39 | wf.write(pkname) 40 | wf.write("\n") 41 | 42 | for fileapk in os.listdir(base_path): 43 | try: 44 | path = base_path+fileapk 45 | 46 | print("1. 开始安装 " + fileapk) 47 | os.system(cmd1 + path) 48 | pkname = '' 49 | print("2. 寻找包名 " + fileapk) 50 | result = os.popen(cmd2) 51 | res = result.read() 52 | for line in res.splitlines(): 53 | if line not in black_list and len(line) > 5: 54 | pkname = line 55 | if pkname =='': 56 | print("[WARNING] 找到黑名单类: " + fileapk) 57 | continue 58 | print ("3. 寻找应用的主类" + pkname) 59 | result = os.popen(cmd5 % pkname) 60 | res = result.read() 61 | for line in res.splitlines(): 62 | MainClass = line 63 | temp = MainClass.split(".")[-1] 64 | MainClass = MainClass.replace("."+temp,"/."+temp) 65 | 66 | print ("4. 打开应用的主类 " + MainClass) 67 | os.system(cmd6 + MainClass) 68 | time.sleep(8) 69 | print("5. 运行Frida脱壳") 70 | os.system(cmd3) 71 | print("6. 脱壳成功记录文件:%s <==> %s " % (path,pkname)) 72 | logger_file("dumpdex success: %s <==> %s " % (path,pkname)) 73 | # 7. 卸载这个包 74 | print("7. 开始卸载 --> " + pkname) 75 | os.system(cmd4 + pkname) 76 | # break 77 | except Exception as e: 78 | print (e) 79 | # break 80 | -------------------------------------------------------------------------------- /scripts/android-注入恶意代码.js: -------------------------------------------------------------------------------- 1 | /* 2 | 脚本来源: 3 | https://raw.githubusercontent.com/rsenet/FriList/main/04_Other/android-injector.js 4 | Description: Android Payload Injector 5 | Usage: frida -U -f XXX -l android-injector.js 6 | Credit: @Ch0pin 7 | */ 8 | 9 | Java.perform(function() 10 | { 11 | try 12 | { 13 | var systemProperties = Java.use('android.os.SystemProperties'); 14 | var networkInterface = Java.use('java.net.NetworkInterface'); 15 | var secureSettings = Java.use('android.provider.Settings$Secure'); 16 | var contentResolver = Java.use('android.content.ContentResolver'); 17 | var wifiInfo = Java.use('android.net.wifi.WifiInfo'); 18 | var bluetoothAdapter = Java.use('android.bluetooth.BluetoothAdapter'); 19 | var mediaDrm = Java.use('android.media.MediaDrm'); 20 | var telephonyManager = Java.use('android.telephony.TelephonyManager'); 21 | var build = Java.use('android.os.Build'); 22 | var buildProperties = Java.use('android.os.Build'); 23 | 24 | var payl0ad = "log4shell payload" 25 | console.log("Payload: " + payl0ad); 26 | 27 | //----------------------------------------------- 28 | buildProperties.MODEL.value = payl0ad; 29 | buildProperties.UNKNOWN.value = payl0ad; 30 | buildProperties.DEVICE.value = payl0ad; 31 | buildProperties.BOARD.value = payl0ad; 32 | buildProperties.PRODUCT.value = payl0ad; 33 | buildProperties.HARDWARE.value = payl0ad; 34 | buildProperties.FINGERPRINT.value = payl0ad; 35 | buildProperties.MANUFACTURER.value = payl0ad; 36 | buildProperties.BOOTLOADER.value = payl0ad; 37 | buildProperties.BRAND.value = payl0ad; 38 | buildProperties.HOST.value = payl0ad; 39 | buildProperties.ID.value = payl0ad; 40 | buildProperties.DISPLAY.value = payl0ad; 41 | buildProperties.TAGS.value = payl0ad; 42 | buildProperties.SERIAL.value = payl0ad; 43 | buildProperties.TYPE.value = payl0ad; 44 | buildProperties.USER.value = payl0ad; 45 | //----------------------------------------------- 46 | 47 | systemProperties.get.overload('java.lang.String').implementation = function(key) 48 | { 49 | console.log('[+] Get system properties called using key: ' + key + ', returning ' + payl0ad); 50 | return payl0ad; 51 | } 52 | 53 | build.getSerial.implementation = function() 54 | { 55 | console.log('[+] Application is fetching the OS serial, returning ' + payl0ad) 56 | return payl0ad; 57 | } 58 | 59 | telephonyManager.getLine1Number.overloads[0].implementation = function() 60 | { 61 | console.log('[+] Application is fetching the phone number, returning ' + payl0ad) 62 | return payl0ad; 63 | } 64 | 65 | telephonyManager.getSubscriberId.overload().implementation = function() 66 | { 67 | console.log('[i] Application asks for device IMSI, returning:' + payl0ad); 68 | return payl0ad; 69 | } 70 | 71 | telephonyManager.getSubscriberId.overload('int').implementation = function() 72 | { 73 | console.log('[i] Application asks for device IMSI, returning ' + payl0ad); 74 | return payl0ad; 75 | } 76 | 77 | telephonyManager.getDeviceId.overloads[0].implementation = function() 78 | { 79 | console.log('[i] Application asks for device IMEI, returning' + payl0ad); 80 | return payl0ad; 81 | } 82 | 83 | telephonyManager.getDeviceId.overloads[1].implementation = function(slot) 84 | { 85 | console.log('[i] Application asks for device IMEI, returning:' + payl0ad); 86 | return payl0ad; 87 | } 88 | 89 | telephonyManager.getImei.overloads[0].implementation = function() 90 | { 91 | console.log('[i] Application asks for device IMEI, returning :' + payl0ad); 92 | return payl0ad; 93 | } 94 | 95 | telephonyManager.getImei.overloads[1].implementation = function(slot) { 96 | console.log('[i] Application asks for device IMEI, returning: ' + payl0ad); 97 | return payl0ad; 98 | } 99 | 100 | telephonyManager.getSimOperator.overload().implementation = function() 101 | { 102 | console.log('[+] getSimOperator call detected, returning:' + payl0ad); 103 | return payl0ad; 104 | } 105 | 106 | telephonyManager.getSimOperator.overload('int').implementation = function(sm) 107 | { 108 | console.log('[+] getSimOperator call detected, returning:' + payl0ad); 109 | return payl0ad; 110 | } 111 | 112 | bluetoothAdapter.getAddress.implementation = function() 113 | { 114 | console.log("[+] Cloaking BT Mac Address, returning:" + payl0ad); 115 | return payl0ad; 116 | } 117 | 118 | wifiInfo.getMacAddress.implementation = function() 119 | { 120 | console.log("[+] Cloaking wifi Mac Address, returning:" + payl0ad); 121 | return payl0ad; 122 | } 123 | 124 | wifiInfo.getSSID.implementation = function() 125 | { 126 | console.log("[+] Cloaking SSID, returning:" + payl0ad); 127 | return payl0ad; 128 | } 129 | 130 | wifiInfo.getBSSID.implementation = function() 131 | { 132 | console.log("[+] Cloaking Router Mac Address, returning:" + payl0ad); 133 | return payl0ad; 134 | } 135 | 136 | contentResolver.query.overload('android.net.Uri', '[Ljava.lang.String;', 'android.os.Bundle', 'android.os.CancellationSignal').implementation = function(uri, str, bundle, sig) 137 | { 138 | if (uri == 'content://com.google.android.gsf.gservicesa') 139 | { 140 | console.log('[+] Cloaking Google Services Framework Identifier Query, returning null'); 141 | return null; 142 | } 143 | else 144 | return payl0ad; 145 | } 146 | 147 | contentResolver.query.overload('android.net.Uri', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String').implementation = function(uri, astr, bstr, cstr, dstr) 148 | { 149 | if (uri == 'content://com.google.android.gsf.gservicesa') 150 | { 151 | console.log('[+] Cloaking Google Services Framework Identifier Query, returning null'); 152 | return null; 153 | } 154 | else 155 | return getApplicationContext.getContentResolver.query(uri, astr, bstr, cstr, dstr); 156 | } 157 | 158 | contentResolver.query.overload('android.net.Uri', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'android.os.CancellationSignal').implementation = function(uri, astr, bstr, cstr, sig) 159 | { 160 | if (uri == 'content://com.google.android.gsf.gservicesa') 161 | { 162 | console.log('[+] Cloaking Google Services Framework Identifier Query, returning null'); 163 | return null; 164 | } 165 | else 166 | return payl0ad; 167 | } 168 | 169 | secureSettings.getString.implementation = function(contentresolver, query) 170 | { 171 | console.log('[+] Cloaking Android ID, returning dummy value:' + payl0ad); 172 | 173 | if (query == 'android_id') 174 | return payl0ad; 175 | else 176 | return this.getString(contentresolver, query); 177 | } 178 | } 179 | catch (error) 180 | { 181 | console.log(error) 182 | } 183 | }); 184 | -------------------------------------------------------------------------------- /HTTPS抓包相关/ssl_unpinning.js: -------------------------------------------------------------------------------- 1 | Java.perform(function() { 2 | /* 3 | UpdateTime: 4 | 2020.5.29 5 | Author: WooyunDota 6 | https://github.com/WooyunDota/DroidSSLUnpinning/blob/master/ObjectionUnpinningPlus/hooks.js 7 | 8 | hook list: 9 | 1.SSLcontext 10 | 2.okhttp 11 | 3.webview 12 | 4.XUtils 13 | 5.httpclientandroidlib 14 | 6.JSSE 15 | 7.network\_security\_config (android 7.0+) 16 | 8.Apache Http client (support partly) 17 | 9.OpenSSLSocketImpl 18 | 10.TrustKit 19 | 11.Cronet 20 | */ 21 | 22 | // Attempts to bypass SSL pinning implementations in a number of 23 | // ways. These include implementing a new TrustManager that will 24 | // accept any SSL certificate, overriding OkHTTP v3 check() 25 | // method etc. 26 | var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); 27 | var HostnameVerifier = Java.use('javax.net.ssl.HostnameVerifier'); 28 | var SSLContext = Java.use('javax.net.ssl.SSLContext'); 29 | var quiet_output = false; 30 | 31 | // Helper method to honor the quiet flag. 32 | 33 | function quiet_send(data) { 34 | 35 | if (quiet_output) { 36 | 37 | return; 38 | } 39 | 40 | send(data) 41 | } 42 | 43 | 44 | // Implement a new TrustManager 45 | // ref: https://gist.github.com/oleavr/3ca67a173ff7d207c6b8c3b0ca65a9d8 46 | // Java.registerClass() is only supported on ART for now(201803). 所以android 4.4以下不兼容,4.4要切换成ART使用. 47 | /* 48 | 06-07 16:15:38.541 27021-27073/mi.sslpinningdemo W/System.err: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing 49 | 06-07 16:15:38.542 27021-27073/mi.sslpinningdemo W/System.err: at android.net.http.X509TrustManagerExtensions.(X509TrustManagerExtensions.java:73) 50 | at mi.ssl.MiPinningTrustManger.(MiPinningTrustManger.java:61) 51 | 06-07 16:15:38.543 27021-27073/mi.sslpinningdemo W/System.err: at mi.sslpinningdemo.OkHttpUtil.getSecPinningClient(OkHttpUtil.java:112) 52 | at mi.sslpinningdemo.OkHttpUtil.get(OkHttpUtil.java:62) 53 | at mi.sslpinningdemo.MainActivity$1$1.run(MainActivity.java:36) 54 | */ 55 | var X509Certificate = Java.use("java.security.cert.X509Certificate"); 56 | var TrustManager; 57 | try { 58 | TrustManager = Java.registerClass({ 59 | name: 'org.wooyun.TrustManager', 60 | implements: [X509TrustManager], 61 | methods: { 62 | checkClientTrusted: function(chain, authType) {}, 63 | checkServerTrusted: function(chain, authType) {}, 64 | getAcceptedIssuers: function() { 65 | // var certs = [X509Certificate.$new()]; 66 | // return certs; 67 | return []; 68 | } 69 | } 70 | }); 71 | } catch (e) { 72 | quiet_send("registerClass from X509TrustManager >>>>>>>> " + e.message); 73 | } 74 | 75 | 76 | 77 | 78 | 79 | // Prepare the TrustManagers array to pass to SSLContext.init() 80 | var TrustManagers = [TrustManager.$new()]; 81 | 82 | try { 83 | // Prepare a Empty SSLFactory 84 | var TLS_SSLContext = SSLContext.getInstance("TLS"); 85 | TLS_SSLContext.init(null, TrustManagers, null); 86 | var EmptySSLFactory = TLS_SSLContext.getSocketFactory(); 87 | } catch (e) { 88 | quiet_send(e.message); 89 | } 90 | 91 | send('Custom, Empty TrustManager ready'); 92 | 93 | // Get a handle on the init() on the SSLContext class 94 | var SSLContext_init = SSLContext.init.overload( 95 | '[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom'); 96 | 97 | // Override the init method, specifying our new TrustManager 98 | SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) { 99 | 100 | quiet_send('Overriding SSLContext.init() with the custom TrustManager'); 101 | 102 | SSLContext_init.call(this, null, TrustManagers, null); 103 | }; 104 | 105 | /*** okhttp3.x unpinning ***/ 106 | 107 | 108 | // Wrap the logic in a try/catch as not all applications will have 109 | // okhttp as part of the app. 110 | try { 111 | 112 | var CertificatePinner = Java.use('okhttp3.CertificatePinner'); 113 | 114 | quiet_send('OkHTTP 3.x Found'); 115 | 116 | CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() { 117 | 118 | quiet_send('OkHTTP 3.x check() called. Not throwing an exception.'); 119 | } 120 | 121 | } catch (err) { 122 | 123 | // If we dont have a ClassNotFoundException exception, raise the 124 | // problem encountered. 125 | if (err.message.indexOf('ClassNotFoundException') === 0) { 126 | 127 | throw new Error(err); 128 | } 129 | } 130 | 131 | // Appcelerator Titanium PinningTrustManager 132 | 133 | // Wrap the logic in a try/catch as not all applications will have 134 | // appcelerator as part of the app. 135 | try { 136 | 137 | var PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager'); 138 | 139 | send('Appcelerator Titanium Found'); 140 | 141 | PinningTrustManager.checkServerTrusted.implementation = function() { 142 | 143 | quiet_send('Appcelerator checkServerTrusted() called. Not throwing an exception.'); 144 | } 145 | 146 | } catch (err) { 147 | 148 | // If we dont have a ClassNotFoundException exception, raise the 149 | // problem encountered. 150 | if (err.message.indexOf('ClassNotFoundException') === 0) { 151 | 152 | throw new Error(err); 153 | } 154 | } 155 | 156 | /*** okhttp unpinning ***/ 157 | 158 | 159 | try { 160 | var OkHttpClient = Java.use("com.squareup.okhttp.OkHttpClient"); 161 | OkHttpClient.setCertificatePinner.implementation = function(certificatePinner) { 162 | // do nothing 163 | quiet_send("OkHttpClient.setCertificatePinner Called!"); 164 | return this; 165 | }; 166 | 167 | // Invalidate the certificate pinnet checks (if "setCertificatePinner" was called before the previous invalidation) 168 | var CertificatePinner = Java.use("com.squareup.okhttp.CertificatePinner"); 169 | CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(p0, p1) { 170 | // do nothing 171 | quiet_send("okhttp Called! [Certificate]"); 172 | return; 173 | }; 174 | CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(p0, p1) { 175 | // do nothing 176 | quiet_send("okhttp Called! [List]"); 177 | return; 178 | }; 179 | } catch (e) { 180 | quiet_send("com.squareup.okhttp not found"); 181 | } 182 | 183 | /*** WebView Hooks ***/ 184 | 185 | /* frameworks/base/core/java/android/webkit/WebViewClient.java */ 186 | /* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */ 187 | var WebViewClient = Java.use("android.webkit.WebViewClient"); 188 | 189 | WebViewClient.onReceivedSslError.implementation = function(webView, sslErrorHandler, sslError) { 190 | quiet_send("WebViewClient onReceivedSslError invoke"); 191 | //执行proceed方法 192 | sslErrorHandler.proceed(); 193 | return; 194 | }; 195 | 196 | WebViewClient.onReceivedError.overload('android.webkit.WebView', 'int', 'java.lang.String', 'java.lang.String').implementation = function(a, b, c, d) { 197 | quiet_send("WebViewClient onReceivedError invoked"); 198 | return; 199 | }; 200 | 201 | WebViewClient.onReceivedError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function() { 202 | quiet_send("WebViewClient onReceivedError invoked"); 203 | return; 204 | }; 205 | 206 | /*** JSSE Hooks ***/ 207 | 208 | /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */ 209 | /* public final TrustManager[] getTrustManager() */ 210 | /* TrustManagerFactory.getTrustManagers maybe cause X509TrustManagerExtensions error */ 211 | // var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory"); 212 | // TrustManagerFactory.getTrustManagers.implementation = function(){ 213 | // quiet_send("TrustManagerFactory getTrustManagers invoked"); 214 | // return TrustManagers; 215 | // } 216 | 217 | var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection"); 218 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ 219 | /* public void setDefaultHostnameVerifier(HostnameVerifier) */ 220 | HttpsURLConnection.setDefaultHostnameVerifier.implementation = function(hostnameVerifier) { 221 | quiet_send("HttpsURLConnection.setDefaultHostnameVerifier invoked"); 222 | return null; 223 | }; 224 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ 225 | /* public void setSSLSocketFactory(SSLSocketFactory) */ 226 | HttpsURLConnection.setSSLSocketFactory.implementation = function(SSLSocketFactory) { 227 | quiet_send("HttpsURLConnection.setSSLSocketFactory invoked"); 228 | return null; 229 | }; 230 | /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */ 231 | /* public void setHostnameVerifier(HostnameVerifier) */ 232 | HttpsURLConnection.setHostnameVerifier.implementation = function(hostnameVerifier) { 233 | quiet_send("HttpsURLConnection.setHostnameVerifier invoked"); 234 | return null; 235 | }; 236 | 237 | /*** Xutils3.x hooks ***/ 238 | //Implement a new HostnameVerifier 239 | var TrustHostnameVerifier; 240 | try { 241 | TrustHostnameVerifier = Java.registerClass({ 242 | name: 'org.wooyun.TrustHostnameVerifier', 243 | implements: [HostnameVerifier], 244 | method: { 245 | verify: function(hostname, session) { 246 | return true; 247 | } 248 | } 249 | }); 250 | 251 | } catch (e) { 252 | //java.lang.ClassNotFoundException: Didn't find class "org.wooyun.TrustHostnameVerifier" 253 | quiet_send("registerClass from hostnameVerifier >>>>>>>> " + e.message); 254 | } 255 | 256 | try { 257 | var RequestParams = Java.use('org.xutils.http.RequestParams'); 258 | RequestParams.setSslSocketFactory.implementation = function(sslSocketFactory) { 259 | sslSocketFactory = EmptySSLFactory; 260 | return null; 261 | } 262 | 263 | RequestParams.setHostnameVerifier.implementation = function(hostnameVerifier) { 264 | hostnameVerifier = TrustHostnameVerifier.$new(); 265 | return null; 266 | } 267 | 268 | } catch (e) { 269 | quiet_send("Xutils hooks not Found"); 270 | } 271 | 272 | /*** httpclientandroidlib Hooks ***/ 273 | try { 274 | var AbstractVerifier = Java.use("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier"); 275 | AbstractVerifier.verify.overload('java.lang.String', '[Ljava.lang.String', '[Ljava.lang.String', 'boolean').implementation = function() { 276 | quiet_send("httpclientandroidlib Hooks"); 277 | return null; 278 | } 279 | } catch (e) { 280 | quiet_send("httpclientandroidlib Hooks not found"); 281 | } 282 | 283 | /*** 284 | android 7.0+ network_security_config TrustManagerImpl hook 285 | apache httpclient partly 286 | ***/ 287 | var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl"); 288 | // try { 289 | // var Arrays = Java.use("java.util.Arrays"); 290 | // //apache http client pinning maybe baypass 291 | // //https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#471 292 | // TrustManagerImpl.checkTrusted.implementation = function (chain, authType, session, parameters, authType) { 293 | // quiet_send("TrustManagerImpl checkTrusted called"); 294 | // //Generics currently result in java.lang.Object 295 | // return Arrays.asList(chain); 296 | // } 297 | // 298 | // } catch (e) { 299 | // quiet_send("TrustManagerImpl checkTrusted nout found"); 300 | // } 301 | 302 | try { 303 | // Android 7+ TrustManagerImpl 304 | TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) { 305 | quiet_send("TrustManagerImpl verifyChain called"); 306 | // Skip all the logic and just return the chain again :P 307 | //https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2017/november/bypassing-androids-network-security-configuration/ 308 | // https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#L650 309 | return untrustedChain; 310 | } 311 | } catch (e) { 312 | quiet_send("TrustManagerImpl verifyChain nout found below 7.0"); 313 | } 314 | // OpenSSLSocketImpl 315 | try { 316 | var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl'); 317 | OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, authMethod) { 318 | quiet_send('OpenSSLSocketImpl.verifyCertificateChain'); 319 | } 320 | 321 | quiet_send('OpenSSLSocketImpl pinning') 322 | } catch (err) { 323 | quiet_send('OpenSSLSocketImpl pinner not found'); 324 | } 325 | // Trustkit 326 | try { 327 | var Activity = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier"); 328 | Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(str) { 329 | quiet_send('Trustkit.verify1: ' + str); 330 | return true; 331 | }; 332 | Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(str) { 333 | quiet_send('Trustkit.verify2: ' + str); 334 | return true; 335 | }; 336 | 337 | quiet_send('Trustkit pinning') 338 | } catch (err) { 339 | quiet_send('Trustkit pinner not found') 340 | } 341 | 342 | try { 343 | //cronet pinner hook 344 | //weibo don't invoke 345 | 346 | var netBuilder = Java.use("org.chromium.net.CronetEngine$Builder"); 347 | 348 | //https://developer.android.com/guide/topics/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder.html#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean) 349 | netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.implementation = function(arg) { 350 | 351 | //weibo not invoke 352 | console.log("Enables or disables public key pinning bypass for local trust anchors = " + arg); 353 | 354 | //true to enable the bypass, false to disable. 355 | var ret = netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true); 356 | return ret; 357 | }; 358 | 359 | netBuilder.addPublicKeyPins.implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) { 360 | console.log("cronet addPublicKeyPins hostName = " + hostName); 361 | 362 | //var ret = netBuilder.addPublicKeyPins.call(this,hostName, pinsSha256,includeSubdomains, expirationDate); 363 | //this 是调用 addPublicKeyPins 前的对象吗? Yes,CronetEngine.Builder 364 | return this; 365 | }; 366 | 367 | } catch (err) { 368 | console.log('[-] Cronet pinner not found') 369 | } 370 | }); 371 | --------------------------------------------------------------------------------