源码

源码来自:https://github.com/Ch3nYe/httpstest

参考文章:https://ch3nye.top/Android-HTTPS%E8%AE%A4%E8%AF%81%E7%9A%84N%E7%A7%8D%E6%96%B9%E5%BC%8F%E5%92%8C%E5%AF%B9%E6%8A%97%E6%96%B9%E6%B3%95%E6%80%BB%E7%BB%93

打包好的APP,启动目录下的http_server,同时修改host把www.test.com指向本地。包名为:com.example.httpstest

安装后如下所示:

image-20211216112037976

然后为了方便代理,我们安装一个ProxyDroid:https://github.com/madeye/proxydroid

可以从谷歌商店代理下载:https://apkpure.com/store/apps/details?id=org.proxydroid

这个东西是利用Android iptables代理,捕获所有APP数据包。一般做WiFi代理的话,有些流量不会走代理,或者还可以使用VPN的代理模式比如Postern。

一开始的两个直接做了代理就可以抓到,就不演示了。

HTTPS系统证书校验

在Android7以上的系统,用户证书不再信任,此处配置证书到系统证书目录。

openssl x509 -inform DER -in burp.der -out cacert.pem
openssl x509 -inform PEM -subject_hash_old -in cacert.pem     =>  hash
mv cacert.pem <hash>.0
adb push hash.0 /sdcard    //由于系统读写权限问题,不一定能直接上传到system目录。
mount -o remount,rw /system   //root权限下执行
cp /sdcard/hash.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/hash.0

第一行就是那个hash

image-20211216135309890

后续点击执行

image-20211216135944342

SSLPINNING 代码校验

这里的校验是公钥,由于中间穿插了burp,所以burp即是客户端,又是服务端,app校验的是burp的公钥导致校验失败。此处使用的是frida,先去下载frida:https://github.com/frida/frida/releases

adb push frida-server /data/local/tmp
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
cd /data/local/tmp/
chmod 755 frida-server
./frida-server

作者提供了一个frida脚本,但是按照使用方式我这边会重启模拟器,也许是模拟器的原因?这里按照一个python脚本来调用这个js脚本。

#coding:utf8

import frida, sys,os,json,codecs
import subprocess
import time
import ctypes

if (len(sys.argv) == 3):
    jsfile = str(sys.argv[1].strip())
    package_name = str(sys.argv[2]).strip()
else:
  print "Usage: python frida_attach.py [hook.js] [package_name] "
  sys.exit(1)

def print_result(message):
    print ("[!] Received: [%s]" %(message))

def stringFromArray(data):
    ret = ''
    for i in data:
        value = ctypes.c_uint8(i).value
        if value == 0:
            continue
        if value <=127:
            ret += chr(value)
        else:
            ret += '\\x' + hex(value)[2:]
    return ret

def hex_stringFromArray(data):
    ret = '['
    for i in data:
        value = ctypes.c_uint8(i).value
        ret += hex(value) + ","
    return ret + "]"

def on_message(message, data):
    print(data)
    if 'payload' in message:
        data = message['payload']
        if type(data) is list:
            print stringFromArray(data)
        else:
            print data   
    else:
        if message['type'] == 'error':
            print (message['stack'])
        else:
            print message

def main():
    with codecs.open(jsfile, 'r', encoding='utf8') as f:
         jscode  = f.read()
    process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name)
    script = process.create_script(jscode)
    script.on('message', on_message)
    script.load()
    sys.stdin.read()

if __name__ == '__main__':
    main()

执行如下后,就可以bypass。

python .\frida_attach.py .\new_sslpinning.js httpstest

image-20211216154316093

配置文件校验跟上面的形式差不多,只是一个代码实现,一个在res/xml/network_security_config.xml配置文件中实现。

单向校验的话,还可以使用Xposed和justtrustme一起配合来绕过。

双向校验

需要先启动目录下的http_server服务,如果访问的话,浏览器会显示异常的链接请求。

需要先把certs目录下的client.p12安装到访问浏览器,密码是clientpassword。再去访问浏览器发现可以显示,同样需要把证书加到burp,让证书可以用证书进行认证。

在user options – TLS – Client TLS certificates中添加,填入域名www.test.com,输入密码即可。

image-20211216161336849

也就是如果需要绕过这种双向验证,需要客户端的证书来对请求进行身份验证。一般情况下这个证书获取从APP

解压,查看assets或者res目录内,查找是否有pfx、cer、p12格式的证书。最后我们需要导入p12的证书。

frida(1)

当然不少的APP可能存在加壳加密等办法,证书和密码的获取不是那么简单,这里提供一种利用frida来获取证书和密钥的办法。

下载frida-extract-keystore:https://gist.github.com/ceres-c/cb3b69e53713d5ad9cf6aac9b8e895d2

运行脚本后,会自动的启动APP,需要在脚本内修改APP包名,点击需要执行的功能,也就是触发请求。

image-20211217113149894

脚本会自动抓取写在代码内的密码和保存证书,以jks的形式。然后需要去提取公钥。

keytool -list -rfc -keystore .\keystore1.jks -storepass clientpassword

把显示的内容保存在cer格式的证书中。导出私钥先转换为pfx。

keytool -v -importkeystore -srckeystore server.jks -srcstoretype jks -srcstorepass clientpassword -destkeystore server.pfx -deststoretype pkcs12 -deststorepass clientpassword -destkeypass 12345678

利用pfx导出key,密码还是上面查到的密码

openssl pkcs12 -in server.pfx -nocerts -nodes -out server.key

再利用key和证书生成p12证书,可以导入burp的那种,密码是我们上面设置的12345678。

openssl pkcs12 -export -clcerts -in client-cert.cer -inkey client-key.key -out client.p12

当没有配置证书的时候,抓包显示Communication error。配置进行这个p12。密码为12345678

image-20211217134216895

再次访问即可成功。

frida(2)

如果能获取证书,但是需要查找密码,而又懒得去解包或者不好脱壳,可以尝试查密码的frida脚本。

frida js :https://raw.githubusercontent.com/m0bilesecurity/Frida-Mobile-Scripts/master/Android/tracer_keystore.js

使用上面的python2脚本来调用。

python .\frida_attach.py .\tracer_keystore.js httpstest

点击触发功能,会显示如下

image-20211217134908128

由于可以解包获取其中的p12证书,所以直接导入证书和密码到burp即可。





# Android逆向  

tocToc: