吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11441|回复: 85
收起左侧

[Android 原创] 加菲猫 邀请协议-算法分析

    [复制链接]
yuanyxh 发表于 2021-12-2 22:00
本帖最后由 yuanyxh 于 2021-12-25 17:44 编辑

1.加菲猫影视1.6.2
2.小黄鸟
3.MT管理器
4.IDA



软件是别人发的,且被修改过,应该是服务器验证,所以没有尝试本地破解,直接进行算法分析;
本人技术有限,有说的不对的地方请大佬们指正{:1_936:} 。

一.黄鸟抓包
打开黄鸟选择目标为加菲猫影视,打开加菲猫影视并输入邀请码提交,黄鸟抓到包后,打开 "http://jk.b557b8.com/App/AppUserInvitation/beOne" 这一条封包信息,
1.jpg 2.jpg
从响应信息来看就是这一条,再看提交信息,我们要分析的有 "token","token_id"和"request_key",其中"request_key"明显是经过加密处理的,且每次都不一样,那我们就先分析这个。

二.MT静态分析
使用MT反编译软件,搜索字符串"request_key",只有两个结果,打开第二个,转成java看一下。
3.jpg 4.jpg 5.jpg
可以看到在f方法内进行了加密处理,key和iv来自c层。

三.IDA静态分析
用IDA打开 "libnative-lib.so",在导出列表里搜索Java,找到对应java层的函数,
2021-12-02_155209.png
点进去看发现都是明文
2021-12-02_155516.png 2021-12-02_155535.png
找个在线解密网站试一下,加密方式为"AES/CBC/PKCS5"(ps:找的解密网站不支持,不过通过试验"AES/CBC/PKCS7"也能正常解密),密文编码为"HEX",输出结果如下:
2021-12-02_161733.png
其中,"code"为邀请码,"nt"很明显是时间戳,"ns"看起来也是加密过的,那我们继续使用MT进行分析。

四.ns密文分析
继续使用MT反编译,搜索字符串"ns"并勾选区分大小写及完全匹配,搜索到5个,打开最后一个,转成java,
photo_2021-12-02_16-43-45.jpg
nt确实是时间戳,ns则是"com.video.test.utils.EncryptUtils"类"getEncryptKey"方法的返回值,传了两个参数:"Context"和当前时间戳的字符串;从前面的分析得知这个方法是一个native方法,具体实现在c层,所以继续使用IDA分析,
2021-12-02_171448.png
可以看到就是获取一系列字符串然后进行MD5加密,由于本人技术有限,能静态分析出来的只有:包名,传进来的时间戳,"&z4Y!s!2br";"GetSignatureString"函数的返回值实在是分析不出来,所以采用动态调试的方式实时观察每个寄存器的值,在关键地方下断点后运行APP,再观察寄存器的值,得到结果如下:
1.png 2.png 3.png 4.png 5.png
那么"ns"就是由:包名 + "1A060008D770327E3BC1521FAB2114C788B77435749590CBF4DA5B97512AC7FA" + " &z4Y!s!2br " + 时间戳 MD5加密得来的,功能就是验证请求是否有效。

五.token及token_id的分析
MT反编译后搜索"token"和"token_id",可以搜索到,但是一直分析不出来源头,不过分析代码知道每次使用时是从"SharedPreferences"获取的,那我们直接在软件的数据目录"shared_prefs"文件夹进行搜索,
photo_2021-12-02_20-51-45.jpg
这样就有思路了,有获取就有写入,只需要找到写入的地方就能分析出来,继续反编译软件搜索,搜索目标换成"userToken"及"userTokenid",但是通过分析依旧找不到源头,
photo_2021-12-02_21-05-37.jpg photo_2021-12-02_21-10-08.jpg photo_2021-12-02_21-05-43.jpg
查找"setToken"及"setToken_id"的调用无法找到,那就只能换一个思路了,能看到上图中有"login success"的字样,猜测是发送登录请求后返回的"token"和"token_id",继续使用黄鸟抓包,并找到 "http://jk.256537.com/App/User/newLogin" 这一条封包,信息如下:
photo_2021-12-02_21-29-47.jpg photo_2021-12-02_21-29-50.jpg
其中请求信息中的"token"和"token_id"新用户应该为"no",但是我在写教程的时候抓不到包了,所以用的是以前的抓包信息,我们继续使用解密网站解密"request_key"和"response_key",第一张图片是响应的,第二张是请求,
2021-12-02_213735.png 2021-12-02_214004.png
现在明确了"token"和"token_id"是通过发送登录请求后返回的,而登录请求中:"new_key"是设备id(通过之前的截图能看到),"old_key"通过多次试验是固定不变的,"ns"已经分析过,"nt"是时间戳,其他的不需要改变;到这里邀请协议所需要的信息全部分析完成。

2021/12/25补充
ns密文中的"GetSignatureString"返回值应该是软件的SHA256签名,而登录请求中的"old_key"也不是固定不变的,而是阿里的库生成的UTDID,每个设备都不同,具体实现在com.ta.utdid2.device.c.h方法内,感兴趣的大佬可以去研究一下,最后感谢@低调(d-iao) 大佬的提醒;

七.结语
写了一下午,越写越糊涂,感觉写的好烂,希望看到的大佬们轻点骂{:301_980:}
下面是从网上搜索,拼拼补补写的一个py脚本,经过大佬@正己 优化的:
# -*- coding: utf-8 -*-
import binascii
import re
import requests
import time
import random
import hashlib
from Cryptodome.Cipher import AES

AESKEY = '8jhM5h6dezq4QifP'  # 请修改 一定是 16位的字符串
AESIV = 'tho3aAHJyZCWAfTG'  # 和KEY保持一致即可

class AESTool:
    def __init__(self):
        self.key = AESKEY.encode('utf-8')
        self.iv = AESIV.encode('utf-8')

    def pkcs7padding(self, text):
        """
        明文使用PKCS7填充
        """
        bs = 16
        length = len(text)
        bytes_length = len(text.encode('utf-8'))
        padding_size = length if (bytes_length == length) else bytes_length
        padding = bs - padding_size % bs
        padding_text = chr(padding) * padding
        self.coding = chr(padding)
        return text + padding_text

    def aes_encrypt(self, content):
        """
        AES加密
        """
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        # 处理明文
        content_padding = self.pkcs7padding(content)
        # 加密
        encrypt_bytes = cipher.encrypt(content_padding.encode('utf-8'))
        # 重新编码
        result = binascii.b2a_hex(encrypt_bytes).upper()
        return result

    def aes_decrypt(self, content):
        """
        AES解密
        """
        generator = AES.new(self.key, AES.MODE_CBC, self.iv)
        content += (len(content) % 4) * '='
        # decrpyt_bytes = base64.b64decode(text)           #输出Base64
        decrpyt_bytes = binascii.a2b_hex(content)  # 输出Hex
        meg = generator.decrypt(decrpyt_bytes)
        # 去除解码后的非法字符
        try:
            result = re.compile('[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f\n\r\t]').sub('', meg.decode())
        except Exception:
            result = '解码失败,请重试!'
        return result

def invite():
    #随机手机型号
    model_name = ["oppo-pedm00","oppo-peem00","oppo-peam00","oppo-x907","oppo-x909t",
                      "vivo-v2048a","vivo-v2072a","vivo-v2080a","vivo-v2031ea","vivo-v2055a",
                      "huawei-tet-an00","huawei-ana-al00","huawei-ang-an00","huawei-brq-an00","huawei-jsc-an00",
                      "xiaomi-mi 10s","xiaomi-redmi k40 pro+","xiaomi-mi 11","xiaomi-mi 6","xiaomi-redmi note 7",
                      "meizu-meizu 18","meizu-meizu 18 pro","meizu-mx2","meizu-m355","meizu-16th plus",
                      "samsung-sm-g9910","samsung-sm-g9960","samsung-sm-w2021","samsung-sm-f7070","samsung-sm-c7000",
                      "oneplus-le2120","oneplus-le2110","oneplus-kb2000","oneplus-hd1910","oneplus-oneplus a3010",
                      "sony-xq-as72","sony-f8132","sony-f5321","sony-i4293","sony-g8231",
                      "google-pixel","google-pixel xl","google-pixel 2","google-pixel 2 xl","google-pixel 3"]
    random_model_name = random.choice(model_name)

    #调用aes加密
    aes = AESTool()

    #注册账户
    t = str(int(round(time.time() * 1000)))
    #随机设备id
    device_id = "".join(random.choice("0123456789ABCDEF") for i in range(32))
    ns = 'com.jfm2110152DAA94115DC5C48038693654FFCC3AA095CBD093165B47BD7F15C8F83CA1BC9B&z4Y!s!2br' + t
    MD5ns = hashlib.md5(ns.encode(encoding='UTF-8')).hexdigest()
    Request_key = '{"new_key":"' + device_id + '","phone_type":"1","ns":"' + MD5ns + '","nt":"' + t + '","old_key":"YYqIkUniVrkDAACxRfIkIvsY","recommend":""}'
    MD5Request_key = aes.aes_encrypt(Request_key)
    HexMD5Request_key = MD5Request_key.decode('unicode_escape')
    body = 'token=no&token_id=no&phone_type=1&versions_code=1402&phone_model='+ random_model_name +'&request_key=' + HexMD5Request_key + '&app_id=1&ad_version=1'
    header = {
        'Cache-Control': 'no-cache',
        'Version': '210930',
        'channel_code': 'xc_tg18',
        'Referer': 'http://jk.b557b8.com',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'jk.b557b8.com',
        'User-Agent': 'okhttp/3.12.0'
    }
    urls = 'http://jk.256537.com/App/User/newLogin'
    Response_body = requests.post(url=urls, data=body, headers=header).text
    Response_body_Encrypt = Response_body[49:241]
    Response_body_Decrypt = aes.aes_decrypt(Response_body_Encrypt)
    token_id = Response_body_Decrypt[13:22]
    token = Response_body_Decrypt[33:65]

    #邀请
    Request_key2 = '{"code":"2UDYUB","ns":"' + MD5ns + '","nt":"' + t + '"}'  #code后填入你的邀请码
    Request_key_Encrypt2 = aes.aes_encrypt(Request_key2)
    HexRequest_key_Encrypt2 = Request_key_Encrypt2.decode('unicode_escape')
    body2 = 'token=' + token + '&token_id=' + token_id + '&phone_type=1&versions_code=1402&phone_model=' + random_model_name + '&request_key=' + HexRequest_key_Encrypt2 + '&app_id=1&ad_version=1'
    urls2 = 'http://jk.b557b8.com/App/AppUserInvitation/beOne'
    Response_body = requests.post(url=urls2, data=body2, headers=header) # 返回200即邀请成功
    print(Response_body.text)

if __name__ == '__main__':
    j = 0
    for i in range(50):  # 五十次即可永久去广告
        time.sleep(random.randint(1, 15))  # 设置随机延时
        invite()
        print("已刷{}次".format(i))
        j += 1
        if j == 50:
            break

免费评分

参与人数 56威望 +2 吾爱币 +163 热心值 +51 收起 理由
qsj521521 + 1 + 1 谢谢@Thanks!
taxuewuhen + 1 + 1 谢谢@Thanks!
WY1234 + 1 + 1 热心回复!
jiangjc97 + 1 + 1 1月21日测试 token的机制变化了 不能用了
73033 + 1 + 1 <font style="vertical-align: inherit;"><font style=
LonelyFish + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
sr123 + 1 + 1 这就是大佬吗
iceSleeping + 1 + 1 我很赞同!
victos + 1 + 1 谢谢@Thanks!
sunlei658 + 1 + 1 我很赞同!
xiaoyu0814 + 1 热心回复!
吾爱破解双11 + 1 我很赞同!
superain + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
温柔的一哥 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
破解的味道 + 1 用心讨论,共获提升!
1saltedfish + 1 谢谢@Thanks!
w7220050 + 1 + 1 我很赞同!
liyuan689 + 1 我很赞同!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
TonyKing + 1 我很赞同!
lvzhenbo + 2 + 1 我很赞同!
xiaoshutong + 1 + 1 用心讨论,共获提升!
goodluck1122 + 1 + 1 我很赞同!
zhixiangwangluo + 1 + 1 谢谢@Thanks!
Mariolll + 1 + 1 用心讨论,共获提升!
笙若 + 1 + 1 谢谢@Thanks!
石碎大胸口 + 1 + 1 谢谢@Thanks!
niexin + 1 + 1 谢谢@Thanks!
gaosld + 1 + 1 谢谢@Thanks!
soyiC + 1 + 1 热心回复!
zhchxu123 + 1 + 1 用心讨论,共获提升!
404undefined + 1 + 1 我很赞同!
azcolf + 1 + 1 热心回复!
_小白 + 1 + 1 我很赞同!
yixi + 1 + 1 热心回复!
guyinqian + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
darklure + 1 + 1 热心回复!
T626 + 1 + 1 谢谢@Thanks!
佚名RJ + 2 + 1 用心讨论,共获提升!
huiye123 + 1 热心回复!
香芋 + 1 + 1 用心讨论,共获提升!
nightmare77 + 1 + 1 好好学习!紧跟大佬步伐!
FJie + 1 + 1 热心回复!
独行风云 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wangyftr + 1 + 1 我很赞同!
芽衣 + 3 + 1 我很赞同!
254760273 + 1 我很赞同!
Tonyha7 + 1 我很赞同!
megshang886 + 1 + 1 热心回复!
lgc81034 + 1 谢谢@Thanks!
scAnn + 1 + 1 我很赞同!
努力加载中 + 1 + 1 热心回复!
buzaizhuai + 1 + 1 我很赞同!
LaoDingY + 1 谢谢@Thanks!
正己 + 8 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
涛之雨 + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

guoxue332 发表于 2021-12-3 00:24
一脸懵逼的进,一脸懵逼的出
慵懒丶L先森 发表于 2021-12-3 01:34
感谢分享,以前碰到算法类的直接战术后退了,看了大佬的分享和解密过程受益匪浅
正己 发表于 2021-12-2 22:30
这就是简仙人的实力吗?

免费评分

参与人数 2吾爱币 +3 热心值 +2 收起 理由
佚名RJ + 2 + 1 正己大佬牛逼,这就去来一波邀请。
yuanyxh + 1 + 1 跟着大佬混,三天饿九顿,偶尔还要挨钢棍

查看全部评分

 楼主| yuanyxh 发表于 2021-12-2 22:35
正己 发表于 2021-12-2 22:30
这就是简仙人的实力吗?

被大佬摩擦的实力
littleWhiteDuck 发表于 2021-12-2 22:37
简仙人厉害,学习了
 楼主| yuanyxh 发表于 2021-12-2 22:43
littleWhiteDuck 发表于 2021-12-2 22:37
简仙人厉害,学习了

日常催更新
怜渠客 发表于 2021-12-2 23:01
简仙人加油!向简大佬学习
 楼主| yuanyxh 发表于 2021-12-2 23:05
lianquke 发表于 2021-12-2 23:01
简仙人加油!向简大佬学习

向大佬学习
yuyi0 发表于 2021-12-3 00:33
加油,向大佬学习
evill 发表于 2021-12-3 01:18
实力爆棚
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 13:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表