春节要来了,可是电视家却走了,没有春晚看了

查看 112|回复 15
作者:dksun1986   
春节马上就要到来,可是随着时代越来越进步,年味也越来越淡了,尤其在海外,更没有国内的气氛浓郁,所以只有每年看春晚才会让我感觉到今天又是新的一年了。
   而且长大后会发现更有年味的不是新年,而是新年前夕,家家户户都在忙着办年货,各种亲子活动,塞满汽车的街道,还有拥挤的地铁,与准备返乡的游子们,无处不在弥漫着迎新气氛。
   然而电视家却走了(其实和电视家没什么关系,只是剧情需要),少了个可以看春晚的应用,所以就在网上找了其他取代品。然后搜索到了一款名为“hdp直播”的应用,本以为可以好好观看,就将它安装上了,结果提示此版本已停用,并且提示更新,并命名为“黑白直播”。行,那就跟着提示操作一顿吧。
   安装完后,心想应该没问题了,结果当我打开软件的时候,出现了以下的画面


Screenshot_2024-01-23-14-37-36-03_28d9d14a88eaacfb6245c2ccd841b0d9.jpg (120.76 KB, 下载次数: 0)
下载附件
2024-1-23 17:54 上传

     什么鬼哦,还要微信扫码登录,一定没什么好康,我就不扫。那就逆它吧。
      温馨提示; 本教学不面向0基础,如果需要0基础教学,请翻看我往期的文章,因为人总要进步,不能总从0开始去解说。
      从接触到认知 到熟悉 再到累积,每个人在任何人事物上必定会经历的事情,逆向亦如此,当你累积到一定程度,基本上就会忽略掉很多没必要的繁杂步骤。就像各种一键工具,也是经过前人的累积制造出来便于简化后人使用的工具。
     所以在操作上也一样,并非每一次都得从0开始去部署到完成。
    那么从扫码界面,如果面对一位有经验者,自然直接就会想到,它的作用是限制未登录者使用,所以自然就会有个身份检测判断,检测用户信息之类的代码,这样就可以直接缩小范围定位到用户相关的范围,比如check user,login,userid 等等之类的关键词来精准定位到关键点。有了这初步信息,就可以进行反编译了。
    下图中可以看到代码虽然经过了混淆,但部分关键信息还是暴露了。


Screenshot_2024-01-23-15-12-01-26_9e8df3d0c7c1f50248b6ee043a653d26.jpg (193.72 KB, 下载次数: 0)
下载附件
2024-1-23 17:54 上传

    进入到checkusertype方法内,可以看到有一段检测用户信息的代码,但是在标记处,有一条Boolean判断,当boolean结果位true的时候,就会直接返回return-void,不再继续往下方代码执行。


Screenshot_2024-01-23-15-15-00-65_9e8df3d0c7c1f50248b6ee043a653d26.jpg (197.89 KB, 下载次数: 0)
下载附件
2024-1-23 17:54 上传

     那么就试试让它返回true,看看是不是就绕过了登录检测,修改代码如下


Screenshot_2024-01-23-15-19-27-45_9e8df3d0c7c1f50248b6ee043a653d26.jpg (48.61 KB, 下载次数: 0)
下载附件
2024-1-23 17:54 上传

     
     修改完毕后重新安装,会发现登录弹窗不见了,说明修改正确,但同时又遇到了新的问题,直播源不工作了。


Screenshot_2024-01-23-15-22-06-04_28d9d14a88eaacfb6245c2ccd841b0d9.jpg (166.08 KB, 下载次数: 0)
下载附件
2024-1-23 17:54 上传

     同时在设置菜单里发现了一段扫码捐赠的字眼,所以不排除扫码登录后也许还要捐赠才能正常使用(毕竟现在很多开发者都喜欢用捐赠的方式变相收费,要钱也不敢坦荡荡)。


Screenshot_2024-01-23-15-24-39-16_28d9d14a88eaacfb6245c2ccd841b0d9.jpg (108.58 KB, 下载次数: 0)
下载附件
2024-1-23 17:52 上传

      由于此处是教学,为了验证直播源不工作是另一个问题,下图提供一张在对原包不做任何改动下仅更换签名的结果。


Screenshot_2024-01-23-15-34-25-45_28d9d14a88eaacfb6245c2ccd841b0d9.jpg (124.3 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

      并且从上面第一张图里也可以看出,在未登录的情况下,直播是可以正常播放,只是多了一幕遮拦窗口。
       至此可以百分百确定,软件有自校验,防止他人二次修改/破解。这里先说明一下,java层是有签名验证,主要作用是让直播源无法正常播放,关于java层的签名保护,一般使用各类一键过签都能解决。这里就不做说明了。
      教学主要讲解直播源不工作的校验,那么从经验上来说,这年头 搞开发的一般做保护基本都不会着重于java层了,大部分都会在so层做手脚。所以先排除java层吧,先看看lib里都有哪些文件吧?
      图中可以看到一共有14个so文件,但是大部分都认识,所以可以排除,如果真的不认识也可以借用libchecker这软件来查询,基本大众的so库都会有收录。


Screenshot_2024-01-23-15-48-33-76_9e8df3d0c7c1f50248b6ee043a653d26.jpg (112.54 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

      不知道大家是否还记得在文章开头介绍过这软件的名称为“黑白直播”,可是在直播源不工作界面,又有了另一个名称“橙色直播”,英文“orange live”。那么刚好so里也有一个名为orange开头的so文件“liborange_params.so”,文件体积也不大,只有72.23k。
       所有巧合必有故事,所以不可能刚好也以orange命名,那么可以先从java层看看,到底调用了orange_params哪些函数吧。
        图中可以看到只有三个函数被调用,然而这三个函数返回的都是字符串类型,那么定位一下调用的位置,看看具体这些函数代表什么吧。


Screenshot_2024-01-23-15-57-06-92_9e8df3d0c7c1f50248b6ee043a653d26.jpg (181.87 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

       下图中可以看到,ok和os分别是AccessKeyId和AccessKeySecret,其实这两个作用是用来连接阿里云OSSService的key和密钥。


Screenshot_2024-01-23-15-59-02-39_9e8df3d0c7c1f50248b6ee043a653d26.jpg (245.18 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传



Screenshot_2024-01-23-15-59-19-80_9e8df3d0c7c1f50248b6ee043a653d26.jpg (227.56 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

       接着再看看pt,它作用是用来播放pcdn直播源的token,所以这三个值都必须有,才能能播放指定的直播源。


Screenshot_2024-01-23-16-07-04-73_9e8df3d0c7c1f50248b6ee043a653d26.jpg (202.82 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

       由于这三个函数都在java层,也就没必要去分析orange_params的内容了,只要把这三个值取出来就好。所以可以直接hook获取。
      先来看看假设对不对,可以先hook改过的包,看看返回值都有哪些。然而从图中可以看到结果为三个值都返回null,说明触发了校验。


Screenshot_2024-01-23-16-15-10-35_3640f6bcd0ec72328b9113e5106e374f.jpg (25.7 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

  
      那么接下来再看看原版的返回值,可以看到是有返回值的,并且经过测试,返回值是固定的。


Screenshot_2024-01-23-16-17-18-58_3640f6bcd0ec72328b9113e5106e374f.jpg (47.49 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

     至此orange_params.so已经没有用处了,可以在修改版上把它删去。直接在java层实现返回值即可。修改结果如下。
修改前:


Screenshot_2024-01-23-16-21-00-31_9e8df3d0c7c1f50248b6ee043a653d26.jpg (197.04 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

修改后:


Screenshot_2024-01-23-16-21-33-46_9e8df3d0c7c1f50248b6ee043a653d26.jpg (143.99 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

    完成后再次安装测试,发现还是出现了同样的界面,直播源依然不工作。说明还有其他地方有校验。由于从上面的分析过程得出,校验大概率在so层,同时文件体积基本不会很大。所以符合小体积,又陌生的文件得出结果有4个。这是初步锁定。


Screenshot_2024-01-23-16-24-29-36_9e8df3d0c7c1f50248b6ee043a653d26.jpg (120.64 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

    接着通过试试抓包抓一下直播源看看,直播源都是以zip压缩打包,运行程序的时候都会把直播源都下载到本地,但是直播源都是经过加密的。所以第二步猜测直播源是不是没有正常解密。


Screenshot_2024-01-23-16-29-18-27_9e8df3d0c7c1f50248b6ee043a653d26.jpg (163.59 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

    最后再来定位到错误界面的位置。错误界面是一张图,所以只要找出了资源ID,就可以再java层定位。如下图可以看见触发条件有两个,当advertDetailModel类为null或geturl为空则触发错误。


Screenshot_2024-01-23-16-32-03-70_9e8df3d0c7c1f50248b6ee043a653d26.jpg (92 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传



Screenshot_2024-01-23-16-33-43-31_9e8df3d0c7c1f50248b6ee043a653d26.jpg (92.54 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传

     所以总结得出结果最大可能就是stream_decode.so这个文件有问题,就如字面上的意思,流媒体解码。和orange_params同样的操作手法,先看看java层调用了哪些函数?
    下图中可以看见只有一条函数被java层调用。


Screenshot_2024-01-23-16-43-07-47_9e8df3d0c7c1f50248b6ee043a653d26.jpg (96.54 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传

      同样的hook一下修改版的这条函数看,可以看见输出和输入结果一模一样。说明直播源根本没有解密,真是吃啥拉啥(dcc是传入加密的数据,dc是返回解密后的数据)。所以才导致了直播源不工作。


Screenshot_2024-01-23-16-46-09-07_3640f6bcd0ec72328b9113e5106e374f.jpg (117.12 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传

      那么是不是说明我们得使用ida来反编译so分析算法了?答案是否定的,像我这样懒的人能不用电脑就不用电脑。这个时候该怎么做呢?
      答案就是先hook原版看看,如下图所示,原版的的dc输出结果是有完成解密的。但是同时也告诉了我们不需要去分析so里的算法了,直接肉眼就可以解密。


Screenshot_2024-01-23-16-17-41-62_3640f6bcd0ec72328b9113e5106e374f.jpg (154.57 KB, 下载次数: 0)
下载附件
2024-1-23 17:51 上传

      我们来看看一条比较短的加密前和解密后的数据。可以看见加密的前两位v1和解密后的最后两位pc做了对调,然后其余数据照常,至于{y变成了://,然后就这样简单的完成解密了(难道这就是传说中的看图破解?)。


Screenshot_2024-01-23-16-51-16-62_99c04817c0de5652397fc8b56c3b3817.jpg (21.76 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传

     所以得出结论就是除了头尾二个字符对调,并且以"{"开头的两个字符会和so里的对照表进行转换之外,其余字符都照旧。所以只要我们多抓几条直播源的加解密结果,就能得到了"{"完整的对照表。这里就不一一演示了,直接给出修改结果。同样的stream_decode.so也可以删掉了,直接在java层修改。
修改前:


Screenshot_2024-01-23-17-00-54-70_9e8df3d0c7c1f50248b6ee043a653d26.jpg (157.33 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传

修改后:


IMG_20240123_170139.jpg (387.7 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传



Screenshot_2024-01-23-17-02-05-06_9e8df3d0c7c1f50248b6ee043a653d26.jpg (112.61 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传

最后来看看最终结果,你学会了吗?


Screenshot_2024-01-23-17-03-29-54_28d9d14a88eaacfb6245c2ccd841b0d9.jpg (175.8 KB, 下载次数: 0)
下载附件
2024-1-23 17:50 上传

下载次数, 下载附件

mrysoft   


52pojie11023995 发表于 2024-1-23 22:00
跟着做,修改完OrangeParams后,无法启动APP了,AccessKeyId和AccessKeySecret这些,如果发文字出来就可以 ...

满足你
# classes.dex
.class public Lcom/hdpfans/params/OrangeParams;
.super Ljava/lang/Object;
.source "OrangeParams.java"
# direct methods
.method public constructor ()V
    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;->()V
    return-void
.end method
.method public static ok(Landroid/content/Context;)Ljava/lang/String;
    .registers 4
    const-string v0, "LTAI4GHP5RsWf21dtmK7xj7C"
    return-object v0
.end method
.method public static os(Landroid/content/Context;)Ljava/lang/String;
    .registers 4
    const-string v0, "fsbTRI6dUJLz1cVnvki73T9i6Beopx"
    return-object v0
.end method
.method public static pt(Landroid/content/Context;)Ljava/lang/String;
    .registers 4
    const-string v0, "60009102005af1602fa4e40179deca22e08f7f0e3b969c5146"
    return-object v0
.end method
# classes.dex
.class public Lcom/hdpfans/stream_decode/StreamDecode;
.super Ljava/lang/Object;
.source "StreamDecode.java"
# direct methods
.method public constructor ()V
    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;->()V
    return-void
.end method
.method public static decode(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;
    .registers 15
    invoke-virtual {p1}, Ljava/lang/String;->length()I
    move-result v0
    const v1, 0x2
    const v6, 0x0
    sub-int v0, v0, v1
    invoke-virtual {p1, v0}, Ljava/lang/String;->substring(I)Ljava/lang/String;
    move-result-object v2
    invoke-virtual {p1, v1, v0}, Ljava/lang/String;->substring(II)Ljava/lang/String;
    .line 518
    move-result-object v3
    invoke-virtual {p1, v6, v1}, Ljava/lang/String;->substring(II)Ljava/lang/String;
    .line 518
    move-result-object v4
    new-instance v5, Ljava/lang/StringBuilder;
    .line 9
    invoke-direct {v5}, Ljava/lang/StringBuilder;->()V
    invoke-virtual {v5, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    invoke-virtual {v5, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    invoke-virtual {v5, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    .line 27
    move-result-object v5
    const-string v1, "{r"
    const-string v2, "http"
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    const-string v1, "{q"
    const-string v2, "p2p"
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    const-string v1, "{y"
    const-string v2, "://"
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    const-string v1, "{1"
    const-string v2, "."
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    const-string v1, "{k"
    const-string v2, "fans"
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    const-string v1, "{x"
    const-string v2, "m3u8"
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    const-string v1, "{g"
    const-string v2, "dli"
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    const-string v1, "{e"
    const-string v2, "com"
    invoke-virtual {v5, v1, v2}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
    .line 132
    move-result-object v5
    return-object v5
.end method
D咗耳   

我宁愿看高等数学也不想看春晚
超逸绝尘   

https://hub.fgit.cf/lizongying/my-tv/releases
no1434   

虽然看不懂,但是觉得很厉害
zj23308   

科目三
饺子
科目三
饺子科目三
饺子
难忘今宵
anwen   

我是直接拿别人的电视app壳,
再找别人没加固的app,
提取里面的源
再把源下载后
自己搞了链接源!
然后,自己看自己做的电视app了哈。。。
FYF   

感谢大佬 顺便吃个瓜~ 前排卖瓜子花生矿泉水啦
Name147   


Ritadoudou 发表于 2024-1-24 09:16
楼主NB,至从电视家被封了之后几乎都找不到什么好的直播软件了。

小微直播 自从电视家没了一直在用
13393401349   

厉害呀 只会用tvbox 上源 来看.
您需要登录后才可以回帖 登录 | 立即注册