美文网首页
mfw sigh signature 请求协议分析(2)

mfw sigh signature 请求协议分析(2)

作者: ever_hu | 来源:发表于2021-11-18 11:44 被阅读0次

mfw sigh signature 请求协议分析

环境

python: 3.8

frida: 12.8.0

objection: 1.8.4

app version: 9.3.7

oauth_signature

202111181138524.png

通过抓包,可以看到有个oauth_signature_method字段为HMAC-SHA1,由此初步推断oauth_signature的加密方法为HMAC-SHA1

HMAC算法

这里给一下标准HMAC的大致实现,以sha1为例,需要传入key和要加密的文本text

# 伪python代码
def hmac_sha1(key, text):
    if len(key) > 64:
        key = sha1(key)
    key = ljust(64, b'\x00')  # 在后面填充\x00,直到长度为64
    inner = sha1(key ^ 0x36 + text)
    outer = sha1(key ^ 0x5C + inner)

    return outer
Java层

之前已经提到过oauth_signature的加密方法是在com.mfw.tnative.AuthorizeHelper类的xAuthencode方法。

202111181138153.png

frida hook一下

// mfw_hmac.js
function dump(name, addr, legnth) {
    console.log("======================== " + name + " ============");
    console.log(hexdump(addr, {length:legnth||32}));
}

Java.perform(function(){
    var helper = Java.use("com.mfw.tnative.AuthorizeHelper");
    helper.xAuthencode.implementation = function(ctx, str1, str2, str3, z) {
        console.log("xAuthencode-str1", str1);
        console.log("xAuthencode-str2", str2);
        console.log("xAuthencode-str3", str3);
        console.log("xAuthencode-z", z);
        var ret = this.xAuthencode(ctx, str1, str2, str3, z);
        console.log("xAuthencode-ret", ret);
        return ret;
    }
})
202111181138798.png

小结一下,第二个参数str2就是要加密的参数,由url和params构造,其他的暂时不分析

固定参数

由于url和params参数经常变动,不利于分析,将加密的参数修改为ever

// mfw_hmac.js
function dump(name, addr, legnth) {
    console.log("======================== " + name + " ============");
    console.log(hexdump(addr, {length:legnth||32}));
}

Java.perform(function(){
    var helper = Java.use("com.mfw.tnative.AuthorizeHelper");
    helper.xAuthencode.implementation = function(ctx, str1, str2, str3, z) {
        str1 = "ever";
        console.log("xAuthencode-str1", str1);
        console.log("xAuthencode-str2", str2);
        console.log("xAuthencode-str3", str3);
        console.log("xAuthencode-z", z);
        var ret = this.xAuthencode(ctx, str1, str2, str3, z);
        console.log("xAuthencode-ret", ret);
        return ret;
    }
})

此时hook的结果为

202111181138635.png
so层

之前提到xAuthencode的真实函数为sub_2E3B8。ida查看

202111181138235.png

同样的,修改a1_JNIEnv

202111181138994.png

通过Java层的分析,我们知道a4是要加密的参数(native函数的参数是从第二个开始)

202111181138661.png

由于v29 = a4,因此v20就是要加密的字符串。那么sub_2F518就是对v20进行加密,看看sub_2F518

202111181138208.png

有点复杂,先不分析,hook看看它的输入

Java.perform(function(){
    var bptr = Module.findBaseAddress("libmfw.so");
    var ptr_0x2F518 = bptr.add(0x2F518 + 1);
    Interceptor.attach(ptr_0x2F518, {
        onEnter: function(args) {
            this.arg0 = args[0];
            console.log(args[0], args[1], args[2], args[3]);
            dump("0x2F518-arg0", args[0]);
            dump("0x2F518-arg1", args[1]);
        },
        onLeave: function(retval) {
            dump("0x2F518-arg0-ret", this.arg0);
            console.log("\n");
        }
    })
})
202111181138828.png 202111181138765.png

从图中可以看出,函数执行了多次,不过我们还是能够看到输入的文本ever。可以看到sub_2F518前面还执行了几次,而且看它的输入有点像key,既然这样,我们看一下前面的函数sub_2EA60

202111181138740.png

可以看到函数里面也执行了sub_2F518,hook一下sub_2EA60

Java.perform(function(){
    var bptr = Module.findBaseAddress("libmfw.so");

    Interceptor.attach(bptr.add(0x2EA60+1),{
        onEnter: function(args){
            dump("0x2EA60-arg0", args[0]);
            console.log("0x2EA60-arg1", args[1].readCString(parseInt(args[2])));
        }
    })
})
202111181138826.png

我们试着把它作为key,用标准HMAC-SHA1试一试输出

import base64
import hashlib
import hmac

KEY = b'9c2d2df9a049d1c489d084ca535daada&b51c30e9ec2b3beb549cbb2f6e766abd'
s = b'ever'
digest = hmac.new(KEY, s, hashlib.sha1).digest()
s0 = base64.b64encode(digest).decode()
print(s0)

assert s0 == 'gwOgWNY2tQTPMyJ4GIgoBLk9eCQ=', 'Not equal'
202111181139060.png

直接就出来了,说明并没有修改HMAC算法,而且使用的也是标准的sha1算法。

实现
import base64
import hmac
import hashlib

from functools import partial
from urllib.parse import urlencode, quote

KEY = b'9c2d2df9a049d1c489d084ca535daada&b51c30e9ec2b3beb549cbb2f6e766abd'

quote = partial(quote, safe='')


def calc_hmac(url, params, method='GET'):
    data = method + '&' + quote(url) + '&' + quote(urlencode(sorted(params)))
    data = data.encode('utf8')
    digest = hmac.new(KEY, data, hashlib.sha1).digest()
    sign = base64.b64encode(digest).decode()
    return sign
验证
202111181139637.png

其他

事实上,我们可以在Java层通过hook得出,app是不验证zzzghostsigh参数的,也就是说,zzzghostsigh可以随便赋值,甚至可以不要这个字段,只要oauth_signature是正确的就能正常返回结果。还有就是,请求里面有个oauth_token字段,这个token是不能缺少的,也不能随机生成,暂时没有去研究它的有效时长以及生成的机制。

以上代码仅供把玩,本人并未采集任何数据。

相关文章

网友评论

      本文标题:mfw sigh signature 请求协议分析(2)

      本文链接:https://www.haomeiwen.com/subject/tcpdtrtx.html