小区在很早之前就换了某科技的门禁系统
支持手机开门、门卡开门、人脸开门
所有信息均已脱敏和打马赛克
手机开门软件及其逆天,广告满天飞,一气之下就逆了(
image-11.png (182.43 KB, 下载次数: 0)
下载附件
2025-1-19 20:26 上传
0x01 准备
获取安装包
下载最新版发现加壳了,是 蛮犀加固企业壳
很久之前给这软件写过去广告模块,所以已知旧版本是无壳的
所以只用往回找没壳的版本,就能使用 Frida Hook 了
SSL 验证
使用代{过}{滤}理抓包发现无法抓到,并且有 SSL 验证
使用 IDA 打开 libflutter.so
image-0.png (100.87 KB, 下载次数: 0)
下载附件
2025-1-19 20:25 上传
搜索 ssl_client
image-1.png (293.16 KB, 下载次数: 0)
下载附件
2025-1-19 20:25 上传
获取到 SSL 验证 函数为 0x3E0F74
libapp.so 逆向
使用 Blutter 一把梭哈
把脚本导入 IDA
image-2.png (202.5 KB, 下载次数: 0)
下载附件
2025-1-19 20:25 上传
可以看到函数名也全部都还原了
0x02 抓包分析
初始化抓包
导出 Burp 的 SSL 证书,并存到 /data/local/tmp/cert-der.crt
使用 Blutter 提供的 frida 脚本
/*
Android SSL Re-pinning frida script v0.2 030417-pier
$ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt
$ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause
https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/
UPDATE 20191605: Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 !
*/
setTimeout(function () {
Java.perform(function () {
console.log("");
console.log("[.] Cert Pinning Bypass/Re-Pinning");
var CertificateFactory = Java.use("java.security.cert.CertificateFactory");
var FileInputStream = Java.use("java.io.FileInputStream");
var BufferedInputStream = Java.use("java.io.BufferedInputStream");
var X509Certificate = Java.use("java.security.cert.X509Certificate");
var KeyStore = Java.use("java.security.KeyStore");
var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
var SSLContext = Java.use("javax.net.ssl.SSLContext");
// Load CAs from an InputStream
console.log("[+] Loading our CA...");
var cf = CertificateFactory.getInstance("X.509");
try {
var fileInputStream = FileInputStream.$new(
"/data/local/tmp/cert-der.crt"
);
} catch (err) {
console.log("[o] " + err);
}
var bufferedInputStream = BufferedInputStream.$new(fileInputStream);
var ca = cf.generateCertificate(bufferedInputStream);
bufferedInputStream.close();
var certInfo = Java.cast(ca, X509Certificate);
console.log("[o] Our CA Info: " + certInfo.getSubjectDN());
// Create a KeyStore containing our trusted CAs
console.log("[+] Creating a KeyStore for our CA...");
var keyStoreType = KeyStore.getDefaultType();
var keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
console.log(
"[+] Creating a TrustManager that trusts the CA in our KeyStore..."
);
var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
console.log("[+] Our TrustManager is ready...");
console.log("[+] Hijacking SSLContext methods now...");
console.log("[-] Waiting for the app to invoke SSLContext.init()...");
SSLContext.init.overload(
"[Ljavax.net.ssl.KeyManager;",
"[Ljavax.net.ssl.TrustManager;",
"java.security.SecureRandom"
).implementation = function (a, b, c) {
console.log("[o] App invoked javax.net.ssl.SSLContext.init...");
SSLContext.init
.overload(
"[Ljavax.net.ssl.KeyManager;",
"[Ljavax.net.ssl.TrustManager;",
"java.security.SecureRandom"
)
.call(this, a, tmf.getTrustManagers(), c);
console.log("[+] SSLContext initialized with our custom TrustManager!");
};
}, 0);
var libflutter = null;
function onLibFlutterLoaded() {
const ssl_pinning_addr = 0x3e0f74;
Interceptor.attach(libflutter.add(ssl_pinning_addr), {
onEnter: function (args) {
console.log("Disabling SSL validation");
},
onLeave: function (retval) {
console.log("Retval: " + retval);
retval.replace(0x1);
},
});
}
function tryLoadLibFlutter() {
libflutter = Module.findBaseAddress("libflutter.so");
if (libflutter === null) setTimeout(tryLoadLibFlutter, 500);
else onLibFlutterLoaded();
}
tryLoadLibFlutter();
加上 Bypass SSL 验证
开始抓包
禁止检查更新
image-4.png (87.92 KB, 下载次数: 0)
下载附件
2025-1-19 20:25 上传
将 /v1/appVersion 地址替换为空即可绕过更新检查
发送验证码
Host: aHR0cHM6Ly9nYXRld2F5Mi5xaW5saW5rZWppLmNvbQ==
URL: /member/sms/sendSecurityCode
Header
[table]
[tr]
[td]Key[/td]
[td]Comment[/td]
[/tr]
[tr]
[td]Openid