欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

frida 找不到so_当Frida来“敲”门

程序员文章站 2022-03-27 08:57:16
...

0x1 渗透测试瓶颈

目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。

frida 找不到so_当Frida来“敲”门

而现在挖漏洞除了拿到shell以外,客户又要求可以尽可能的挖到核心业务系统的漏洞,并将漏洞范围订在主域名,核心业务系统现在又基本集中在移动端,移动端现在都会进行APP加壳,流量加密。这就导致无法进行平常渗透测试过程,像老生常谈的中间人攻击,进行拦截,篡改数据包就很难进行。

接下来就尝试解决中间人攻击的问题,目标是

1.看到明文的request和response的数据包;

2.做到可以拦截,篡改数据包。

0x2 frida

frida是平台原生app的Greasemonkey,说的专业一点,就是一种动态插桩工具,可以插入一些代码到原生app的内存空间去,(动态地监视和修改其行为),这些原生平台可以是Win、Mac、Linux、Android或者iOS。而且frida还是开源的。

frida 找不到so_当Frida来“敲”门

环境需要越狱的IOS或者ROOT的Android。安装的版本需要一致

MAC:

frida 找不到so_当Frida来“敲”门

越狱Iphone:

frida 找不到so_当Frida来“敲”门

通过USB链接越狱手机,可以执行frida-ps -aU 就代表环境安装成功

frida 找不到so_当Frida来“敲”门

0x3 越狱检测绕过

启动目标APP时,APP自身会进行环境检测,如果处于越狱环境会提示如下:

frida 找不到so_当Frida来“敲”门

点击“我知道了”就直接退出APP。

所以先尝试先绕过第一步越狱环境检测。可以先尝试搜索包含“jail,jeil,jb,break"关键字的函数

关于函数追踪可以使用frida-trace,如:

# Trace recv* and send* APIs in Safari$ frida-trace -i "recv*" -i "send*" Safari# Trace ObjC method calls in Safari$ frida-trace -m "-[NSView drawRect:]" Safari​# Launch SnapChat on your iPhone and trace crypto API calls$ frida-trace -U -f com.toyopagroup.picaboo -I "libcommonCrypto*"

burp的插件brida也支持对函数名进行检索hook,和"Jail"相关的越狱检测函数如下:

**** Result of the search of JailOBJC: +[BLYDevice isJailBreak]OBJC: +[IFlySystemInfo isJailbroken]OBJC: +[UIScreen _shouldDisableJail]OBJC: +[UIStatusBarWindow isIncludedInClassicJail]OBJC: -[_UIHostedWindow _isConstrainedByScreenJail]OBJC: -[_UIRootWindow _isConstrainedByScreenJail]OBJC: -[_UISnapshotWindow _isConstrainedByScreenJail]OBJC: -[BLYDevice isJailbroken]OBJC: -[BLYDevice setJailbrokenStatus:]OBJC: -[RCCountly isJailbroken]OBJC: -[UIClassicWindow _isConstrainedByScreenJail]OBJC: -[UIDevice isJailbroken]OBJC: -[UIStatusBarWindow _isConstrainedByScreenJail]OBJC: -[UITextEffectsWindowHosted _isConstrainedByScreenJail]OBJC: -[UIWindow _clampPointToScreenJail:]OBJC: -[UIWindow _isConstrainedByScreenJail]

想将目标定在“OBJC: +[BLYDevice isJailBreak]”

frida启动APP,并加载脚本的命令如下:

frida -U -f com.x.x -l js-scripts

js脚本编写可以看官方文档:https://frida.re/docs/javascript-api/

//hook传入值,ObjC: args[0] = self, args[1] = selector, args[2-n] = arguments Interceptor.attach(myFunction.implementation, {   onEnter: function(args) {    var myString = new ObjC.Object(args[2]);    console.log("String argument: " + myString.toString());  }});//hook返回值,Interceptor.attach(Module.getExportByName('libc.so', 'read'), {  onEnter: function (args) {    this.fileDescriptor = args[0].toInt32();  },  onLeave: function (retval) {    if (retval.toInt32() > 0) {      /* do something with this.fileDescriptor */    }}});

定义js脚本后,尝试hook出“OBJC: +[BLYDevice isJailBreak]”的传入值和返回值,

function hook_specific_method_of_class(className, funcName){    var hook = ObjC.classes[className][funcName];    Interceptor.attach(hook.implementation, {      onEnter: function(args) {        // args[0] is self        // args[1] is selector (SEL "sendMessageWithText:")        // args[2] holds the first function argument, an NSString        console.log("[*] Class Name: " + className);        console.log("[*] Method Name: " + funcName);        //For viewing and manipulating arguments        //console.log("[-] Value1: "+ObjC.Object(args[2]));        //console.log("[-] Value2: "+(ObjC.Object(args[2])).toString());        console.log("[-]arg value   "+args[2]);        Interceptor.attach(hook.implementation,             {              onLeave: function(retval) {                console.log("[*] Class Name: " + className);                console.log("[*] Method Name: " + funcName);                console.log("[-] Return Value: " + retval);             }}            );      }    });}//Your class name  and function name herehook_specific_method_of_class("BLYDevice", "- isJailbroken")
frida 找不到so_当Frida来“敲”门

篡改后,发现未能绕过,可能不是这个函数做最终的逻辑判断,想到竟然都弹窗提示了,和UI有关系。

那么可能是“OBJC: -[UIDevice isJailbroken]这个类,最终构造绕过越狱检测代码如下:

if (ObjC.available){    try    {        var className = "UIDevice";        var funcName = "- isJailbroken";        var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');//目标类+方法        Interceptor.attach(hook.implementation,         {          onLeave: function(retval) {            console.log("[*] Class Name: " + className);            console.log("[*] Method Name: " + funcName);            console.log("[-] Return Value: " + retval);//输出原本的返回值            var newretval = ptr("0x0")             retval.replace(newretval)//替换新的返回值            console.log("[-] New Return Value: " + newretval)         }}        );    }    catch(err)    {        console.log("[!] Exception2: " + err.message);    }    }else{    console.log("Objective-C Runtime is not available!");}

执行结果如下:

frida 找不到so_当Frida来“敲”门

成功绕过。

frida 找不到so_当Frida来“敲”门

0x4 HOOK加解密函数

越狱检测绕过后,进一步开始尝试定位加解密的函数。

关于定位加解密函数这块在Android可以尝试使用traceview去分析追踪函数。

https://developer.android.google.cn/studio/profile/traceview

frida 找不到so_当Frida来“敲”门

IOS可以尝试使用runtime去追踪函数,uidump从界面按钮入手,Nslog日志等位置入手,或者直接找相关关键字的函数去入手。

例如crypt(decryot,encrypt),HTTP,Network,目标厂商的名字简写找不到,可以尝试搜索NSString系统库等。

这边推荐一个大佬的GitHub项目。使用可以参考这个GitHub项目,非常好用,先用之前写好的绕过越狱检测的脚本启动APP,这边通过查找函数名找到对方关键的加解密函数“*encryptor”。

github项目:https://github.com/lyxhh/lxhToolHTTPDecrypt

frida 找不到so_当Frida来“敲”门

hook此函数的所有方法,在点击登录按钮后,观察到有请求的数据包被当做参数传入到-[XXEncryptor RSAEncrypt:]方法内,并返回了加密后的字符串。-[XXEncryptor setRSAPublicKey:]根据定义的方法名判断应该是RSA公钥信息。

frida 找不到so_当Frida来“敲”门

其他方法则去处理了返回包。如-[XXEncrytor AESDecrypt:]方法,将服务端返回的加密字段,使用AES对称解密解密为明文。

frida 找不到so_当Frida来“敲”门

之前我们在Hook请求包函数的时候发现明文的数据包里面带有aeskey,说明此处的逻辑应该是:

本地生成aeskey代入到request包->使用定义的RSA公钥加密request->发送到服务端并解密request后->处理请求包内容,并使用AESkey加密Response返回到客户端->客户端在使用Aeskey解密服务端的Response包。

frida 找不到so_当Frida来“敲”门

大概是这么一个流程,事实也证明返回包确实可以使用hook到的aeskey进行解密。

frida 找不到so_当Frida来“敲”门

后面的思路是hook[XXEncrytor AESDecrypt:]解密方法去解密请求包和返回包,返回包是可以解,但是突然想到请求包是RSA非对称的,需要私钥。想尝试在客户端找到RSA的私钥或者RSA解密方法,结果也确实有RSADecrypt方法。

frida 找不到so_当Frida来“敲”门

但是事实是,从头到尾这个方法都没有被使用过,没有参数被传入,也没有返回值。所以想,可能本地不做请求包的解密。那么调用他的函数解密返回包可行,但解密请求包不行。但是咱们之前是有Hook到明文的request,可以再request被传入到-[XXEncryptor RSAEncrypt]方法前,先去修改arg。

frida 找不到so_当Frida来“敲”门

具体操作方法可以参考lyxhh,将加密前的请求包转入Burp后就可以实现篡改数据了。

lyxhh:https://github.com/lyxhh/lxhToolHTTPDecrypt

frida 找不到so_当Frida来“敲”门

新手的话可以先用la0s的JS,先看看对方是不是使用了IOS统一封装的Crypto库,js脚本如下:

JS:https://la0s.github.io/2018/12/07/iOS_Crypto/

/ Intercept the CCCrypt call.Interceptor.attach(Module.findExportByName('libcommonCrypto.dylib', 'CCCrypt'), {    onEnter: function (args) {        // Save the arguments        this.operation   = args[0]        this.CCAlgorithm = args[1]        this.CCOptions   = args[2]        this.keyBytes    = args[3]        this.keyLength   = args[4]        this.ivBuffer    = args[5]        this.inBuffer    = args[6]        this.inLength    = args[7]        this.outBuffer   = args[8]        this.outLength   = args[9]        this.outCountPtr = args[10]        console.log('CCCrypt(' +             'operation: '   + this.operation    +', ' +            'CCAlgorithm: ' + this.CCAlgorithm  +', ' +            'CCOptions: '   + this.CCOptions    +', ' +            'keyBytes: '    + this.keyBytes     +', ' +            'keyLength: '   + this.keyLength    +', ' +            'ivBuffer: '    + this.ivBuffer     +', ' +            'inBuffer: '    + this.inBuffer     +', ' +            'inLength: '    + this.inLength     +', ' +            'outBuffer: '   + this.outBuffer    +', ' +            'outLength: '   + this.outLength    +', ' +            'outCountPtr: ' + this.outCountPtr  +')')        if (this.operation == 0) {            // Show the buffers here if this an encryption operation            console.log("In buffer:")            console.log(hexdump(ptr(this.inBuffer), {                length: this.inLength.toInt32(),                header: true,                ansi: true            }))            console.log("Key: ")            console.log(hexdump(ptr(this.keyBytes), {                length: this.keyLength.toInt32(),                header: true,                ansi: true            }))            console.log("IV: ")            console.log(hexdump(ptr(this.ivBuffer), {                length: this.keyLength.toInt32(),                header: true,                ansi: true            }))        }    },    onLeave: function (retVal) {        if (this.operation == 1) {            // Show the buffers here if this a decryption operation            console.log("Out buffer:")            console.log(hexdump(ptr(this.outBuffer), {                length: Memory.readUInt(this.outCountPtr),                header: true,                ansi: true            }))            console.log("Key: ")            console.log(hexdump(ptr(this.keyBytes), {                length: this.keyLength.toInt32(),                header: true,                ansi: true            }))            console.log("IV: ")            console.log(hexdump(ptr(this.ivBuffer), {                length: this.keyLength.toInt32(),                header: true,                ansi: true            }))        }    }})

如果只能hook到部分明文流量,再考虑去对方定义的函数里去找关键的加密函数,如这个APP的关键的XXEncryptor类。

相关标签: frida 找不到so