首页
社区
课程
招聘
[原创]深度揭秘:全仿 Telegram 诈骗软件的幕后技术链条
发表于: 2025-2-18 17:12 4758

[原创]深度揭秘:全仿 Telegram 诈骗软件的幕后技术链条

2025-2-18 17:12
4758

背景

在一次偶然的网络浏览中,我遇到了一系列令人起疑的诈骗软件。这些软件虽然图标与名称各异,但其内部界面却如同 Telegram 的孪生兄弟,惊人的相似。更令人费解的是,它们涉及的诈骗场景广泛,从刷单、返现到彩票、菠菜、招女票,无所不包,仿佛是为满足各种诈骗需求而量身定制的全场景工具。

面对如此精妙的设计,我不禁好奇:这些软件究竟是直接修改了官方版,还是完全从零开始打造的呢?

诈骗软件的 “精细化” 运营

如今的诈骗分子,在筛选目标客户群体时,已经展现出了极高的精细化程度。他们不再满足于广撒网式的诈骗手段,而是更加注重精准定位,利用专业的套路和软件实施诈骗。为了获取诈骗样本,我前前后后套路了小半个月,往抖音、快手直播间投了一堆简历(女 / 25-30 岁 / 打字员),终于有 2 个骗子上钩了。

逆向分析

签名分析

在通过精心设计的钓鱼策略后,我成功获取了两个诈骗软件的样本,其面对的场景不同,一个是刷单返利诈骗,还有一个是彩票包中奖诈骗。但是他们的版本是一致的,都是 9.6.6,而且界面也几乎完全一致。首先,我查看了软件的签名信息,虽然签名中无法直接获取具体信息,但发现了一个明显的联系方式,指向一个 APK 防毒服务提供商。(PS: 这里提一嘴,下载安装包的时候可以发现,即使是用同一个链接下载的,下载回来的安装包包名也没有一致的,似乎是自动随机生成的)。

然而,深入分析后发现,该防毒服务似乎只是随机更改了安装包名,而未进行任何实质性的加壳处理。(那多少有点黑吃黑了,连壳都不加,就改个包名也算防毒?)这让我怀疑,该服务提供商可能并不具备开发诈骗软件的能力,真正的开发者另有其人。(PS: 能傻到去 Telegram 买防毒的,估计作者也不是很懂,毕竟这种一看就是纯骗钱。找个白手套用免费的 360 加固都比这玩意好使多了)。

初见端倪

由于没有加壳,直接拖进 JADX 就可以反编译了,反编译的包名连混淆都没得,一眼就能发现 org.telegram 包,其内容结构和 Telegram 的官方安装包基本一致。因此可以初步断定,这个应用和 Telegram 有密不可分的关联。

分析一个聊天软件,最重要的就是逆向其通信协议。对于仿 Telegram 的软件来说,由于 Telegram 早就在国内被屏蔽,因此首要分析的是这款软件是如何连接到后端服务器的。

通过 URL 筛选,不难找到在 cos.MyCOSService 中存在大量相似 URL,初步怀疑是远程配置文件。(PS: 这里的服务器大部分都部署在腾讯云上,多少也有点胆子太大了,怕蜀黍请不到人?)

IP 归属地
139.186.137.58 中国 重庆市【腾讯云】
212.64.20.52 中国 上海市【腾讯云】
150.109.240.160 韩国首尔特别市【腾讯云】
43.138.148.109 中国广东省广州市【腾讯云】
43.130.228.128 日本东京都【腾讯云】
99.83.138.65 泛播【亚马逊云】
75.2.107.146 泛播【亚马逊云】

前后浏览一下代码,可以看到,响应体使用 ConnectionsManager.decryptHex​ 函数进行解密,解密完的结果使用 JSON 进行解析,其中 gfw​ 中的 IP 地址和端口列表用于设置应用的 Datacenter 地址。

由于 decryptHex​ 实际上是在 so 层里实现的,这里为了方便,直接用 frida hook 参数和返回值。

可以看到,参数值是一串 HEX 字符串,返回的是一个完整的 JSON 字符串。不过瞪眼一看就能发现,这个所谓的解密只是进行了异或,根本没有用的 AES、Base64 等复杂的技巧。这里用 IDA 淦多少有点掉价,直接口算一下就能找到异或数为 211。

然而,新的问题也随之而来:这些服务器是仅仅作为透明传输到 Telegram 官方服务器的中转站,还是自己实现的完整后端和数据库?

深度探索

假设诈骗分子用的就是 Telegram 的官方服务器作为后端,上文所设置的 DC 地址只是作为透明代理,那么诈骗分子必然要为每一位受害者准备一个 Telegram 账户用于聊天。但是 Telegram 的注册需要手机号且风控较严,现在甚至连 +86 的手机号都注册不了,因此大量账户注册的难度也不小,手里掌握一大把的账户也不是很现实。因此有理由推测开发者有可能是自己实现了一个后端。

直接判断一个 IP 是不是透明代理是一件很难的事,但是如果只判断是不是官方 Telegram 服务器,则可以用一些取巧的方式。例如,可以通过握手过程中使用的公钥签名来判断。

Telegram 在初次握手的时候,会发送一个当前握手使用的 RSA 公钥签名,这个公钥会被用于后面交换 DH 参数,而私钥只有官方掌握。如果是自己实现的后端,就一定需要自定义公钥,否则就无法解密握手消息,完成后续握手流程。

这里就直接用 telethon 库进行握手测试。

1
2
3
4
5
6
7
8
9
10
11
from telethon import TelegramClient
from telethon.network.connection import *
 
client = TelegramClient(
    None,
    4,
    "014b35b6184100b085b0d0572f9b5103",
    connection=ConnectionTcpAbridged,
)
client.session.set_dc(1, "36.140.117.88", 31097)
client.connect()

运行以后控制台会提示握手的公钥签名并不存在 telethon 提供的公钥库中。

1
Attempt 1 at new auth_key failed: Step 2 could not find a valid key for fingerprints: 7382190280322232797

因此,可以判断为自定义的后端实现。

那么,你有可能会问,楼主楼主,万一是 Telegram 更新了公钥但 telethon 更新没有那么及时呢?

确实有一定可能,毕竟 telethon 作为第三方的库,更新速度确实不如官方快,因此不排除是更新滞后导致的新增公钥不在库中。可以直接把公钥导出来,全网对比一下。(PS: 这里提一下,Telegram 官方对于兼容性是有很大考量的,如果有一个公钥没有被内置,那么就会自动更换一个,直到有一个是可以用的。因此即使万年不更新公钥库也不影响使用)

首先定位到 Handshake::beginHandshake 的握手函数中。可以看到,在原来公钥的地方变为了一段 HEX 字符串。通过和解密远程配置相同的 decrypt 函数进行解密,可以得到公钥。

这里就不 hook 了,直接异或 211 得到公钥。在 GitHub 搜索后,没有任何一个项目使用了这个公钥,因此可以判断这个公钥应该是开发者自行持有的。

那么,你有可能会问,楼主楼主,万一开发者只是做了中间人转发(MitM)呢?他们的 DC 后端先解密再加密,最后又发给 Telegram 官方服务器了呢?

这个确实不排除,毕竟 MitM 也需要修改公钥。这个就可以考虑另一种方法判断。众所周知,Telegram 的用户名是唯一的,即使是在不同的 DC 区(官方是有 5 个区)。在注册页面允许用户自定义用户名,可以看到,SpamBot 之类的保留用户名都是可以注册的。而在官方服务器上肯定是不行的。

那么,你有可能会问,楼主楼主,万一开发者做了特殊设计,实际的用户名并不是你所填写的,而是加了自定义的前缀或者后缀等等呢?

这种情况下确实也有可能可以注册。因此需要直接看一下当前登录用户的用户名。获取用户名可以直接使用 frida hook……

楼主楼主,你的 frida 确实强,但太吃操作,有没有更加简单又强势的方法推荐一下?

有的,兄弟,有的。首先需要了解一下 Telegram 的会话存储方式。Telegram 将每一个用户的登录信息、DC 地址都存储在 tgnet.dat 中。而这个文件的格式是通用的,既可以被官方 Telegram 解析,也可以被所有第三方 Telegram 魔改客户端所解析。因此,直接找个其它的客户端将会话文件放进去就能够登录。

那么,你可能会问,楼主楼主,前面不是说过 RSA 公钥被修改了嘛,如果你使用其他的客户端,它们并没有被注入新的 RSA 公钥,那不是不能用吗?

其实 RSA 公钥的作用只在握手阶段,一旦握手完成,之后则使用 authKey 对通讯进行加解密,不需要 RSA 公钥的参与。而直接导入 tgnet.dat 就跳过了握手一步,因此就不必要将 RSA 公钥进行注入。

不过由于 Telegram 的 API 会随着版本而更新,需要尽可能相近的版本。具体是哪个版本呢?是 Telegram 9.6.6 吗?毕竟很多诈骗应用的版本号是随机生成的,不一定代表真实版本。

直接解压安装包,在 lib​ 目录下有 tdlib 库 libtmessages.45.so​ 。其中的 45 就指代了 tdlib 的版本。从官方的 GitHub 库中可以找到修改历史,只有 9.6.0 - 10.0.7 是 45 版本的。因此推测大概率是 9.6.6 版本。这里为了方便,找了个第三方的客户端进行安装。

安装以后将 tgnet.dat 导入,不出所料,直接就可以登录上去,甚至可以发送消息到收藏夹。在设置页面就可以看到当前的手机号是 +jmt 开头的,用户名确实和注册的一致,但是使用官方 Telegram 没有办法搜索到指定用户。因此,这个诈骗软件的后端确实是自定义实现的。(PS: 这里不要把自定义实现 Telegram 后端想得过分复杂了,现在网上有一大堆的复刻实现,不论是三端的客户端,还是后端数据库都有开源实现。)

而正是由于是自定义实现,所以有一些功能是无法使用的。

节外生枝

本来这章到这里也就差不多结束了,毕竟后端的通信协议没有修改,远程配置的加密方式被逆向了,现在也能够用其他客户端来实现替代了。但是,另一个样品表现得却比较奇怪,同样是导入会话文件,但是却没有办法正常和服务器通信。

难道是之前的分析有问题?

首先可以确定的是样本版本号类似,推测大部分的代码都不会发生变化,因此可疑的改动范围就缩小在了一些编译选项。仔细对比了两份文件的 org.telegram.messenger.BuildVars​,发现了一处很小的不同。旧样本的 sendNewProtocol​ 是 false​,而这个新样本的 sendNewProtocol​ 是 true​。因此可以推测是存在两套协议,并且新样本的协议是不兼容旧协议的。

那么新的协议究竟发生了什么变化呢?如何去定位呢?首先需要了解一下 Telegram 实现通信的方式。

以握手部分为例,整个过程始于一个名为 Handshake::beginHandshake 的函数。这个握手函数会调用 Handshake::sendRequestData 方法,该方法负责准备并发送请求数据,将原本的 RPC 类型的请求数据封装在一个 NativeByteBuffer 对象中。

接下来,Connection::sendData 方法被调用,它接收来自 Handshake 模块的 NativeByteBuffer 数据,并对其进行加密处理,以确保数据传输的安全性。加密后的数据依然以 NativeByteBuffer 的形式存在,但此时数据内容已被加密。

加密后的数据随后被传递给 ConnectionSocket::writeBuffer 方法,这个方法负责将数据写入到套接字的缓冲区中。为了管理数据流和确保数据的有序传输,这些数据首先被放入一个队列(Queue)中等待处理。这个队列起到了缓冲和调度的作用,确保数据按照正确的顺序被发送。

一旦 ConnectionSocket::onEvent 方法准备就绪,就会从队列中取出数据,最终将这些数据通过网络发送出去,完成了从握手开始到数据发送的整个流程。

如果要修改协议,直接修改 TLObject​ 的定义不是很现实,毕竟 RPC 类型实在是太多了,而在数据发送的过程中进行修改则比较简单。官方 Telegram 中的 MTProxy 处理和数据加密都是在 Connection::sendData​ 中实现的,因此初步怀疑是这个函数被动了手脚。(PS: 其实如果确定了是由于 sendNewProtocol​ 修改导致协议更换,最简单的方式就是搜索 sendNewProtocol​ 的出现位置,而 ConnectionsManager::getsendNewProtocol​ 是一个导出函数,直接 xref 就能定位)

和原版的处理逻辑对比一下,很快就能发现多了一段 custom send​ 的逻辑。

简单阅读代码和对比抓包结果,可以很快看到多了一段 0x5D9848A​ 的头和长度指示。之后就跟着原先的数据包了。因此,这个新协议似乎是一个卖点,加钱了有,没加钱就没。不过加了和没加也差不多,改动只有 5 个字节。

溯源

初步了解

该软件工程的规模不容小觑,它需要对客户端和服务器都进行不同程度的修改,这与往常那些使用一套 PHP 和宝塔就能搞定的菠菜站和普通诈骗站大相径庭。正因如此,它基本上只能以卖全套服务(SaaS)的形式存在,而非仅仅出售代码。其部署、维护及升级都 高度依赖 于软件的作者。此外,由于该软件能够覆盖所有诈骗类别,这明显不符合园区内开发的风格。园区内的产品往往有着明确的定位,而且一般不会对外出售,多是自给自足。(毕竟不怕同行过得苦,就怕同行开路虎。)

在上文的逆向分析过程中有提到,这些软件的远程配置大部分都托管在腾讯云上,多少感觉有点蠢到家了。毕竟,在菠菜或诈骗领域,使用腾讯云并不常见,包括国内的其他云服务提供商也鲜有涉足。因此,我们推测开发者很可能是个人,且之前可能使用过腾讯云开发产品,对腾讯云有着特殊的癖好。

深入分析

尽管逆向部分主要分析了通信协议,但仍有其他细节值得挖掘。例如,在进行负载均衡时,会对每一个数据中心(DC)进行连通性检测,而这一检测和排序过程是在 libgojni.so 文件中实现的。前面的逆向已经看出,开发者就只会写写代码,根本不懂逆向。因此这个 so 文件并未进行混淆处理,甚至连函数名都没有去掉。而 Go 语言有一个特性,就是包管理器全靠 GitHub,不像 pip 和 npm 有个中心仓库。因此,拉取或使用包的时候,除了仓库名,还会带上用户名

在函数列表有一堆 github_com_jmt_tg_packet_obfuscation_lib_polib​ 开头的函数。

由于编译信息并没有被擦除,以 github_com_jmt_tg_packet_obfuscation_lib_polib_LeadIp_func1​ 为例,可以很清晰地看到,是来自于 github.com/jmt-tg/packet-obfuscation-lib/polib.LeadIp.func1 包的​。

求证过程

进到 jmt-tg​ 仓库镜像,可以看到只有 3 个公开的仓库,没有所谓的 packet-obfuscation-lib​。大概率是由于这个仓库是私有的,在构建的时候才使用授权账号进行依赖包拉取。

对于 jmt 这三个英文字母,其实并没有感到意外。例如,在 org.telegram.tgnet 中,有一系列以 TLRPC$JMT_ 开头的新定义的 RPC 结构,如 TLRPC$JMT_RedPacket,它便是用于发送红包的请求对象结构体。

此外,在社交媒体上,也有人提及 JMT-OA 是诈骗软件。或许,JMT-OA 只是一个试验品,没想到效果出奇地好,之后便为各类诈骗分子量身定制软件。

话说回来,在 GitHub 的组织中,尽管成员被隐藏,但仓库中仍有大量信息可供溯源。其中,最重要的是提交记录,其次是代码,还有一些点赞、复刻信息也能为我们提供线索。

提交关联

通过观察提交记录,我们发现两个仓库 镜像1 镜像2 都只有一个人的提交记录,用户名是 GitHub@showurl。进入其主页,我们发现他竟实名上网 镜像。通过进一步排查记录,我们找到了以下关联:

  1. 【同提交人】从 2023 年 4 月 23 日至 2023 年 7 月 11 日,提交了 cherish-chat(“惺惺” 社交平台)的代码。镜像
  2. 【同提交人】从 2023 年 10 月 4 日至 2023 年 10 月 6 日,参与了 peergoim 的开发。镜像
  3. 【互联网同姓名和用户名/同提交人】从 2022 年 5 月 18 日至 2022 年 5 月 31 日,在开源项目 openim 的基础上开发了 Path-IM-Server。镜像1 镜像2 镜像3
  4. 【企业信息】于 2022 年 7 月 13 日,成立了北京惺惺科技有限公司(集群注册)。

以下是这些事件的时间线图:

由此可见,这位开发者之前曾是开源社区的贡献者,专注于社交软件,甚至创建了社群和企业。然而,或许由于社交软件领域竞争激烈,他的项目一个接一个地失败。于是,他可能走上了致富的捷径。

代码关联

另外再来翻翻代码,在 jmt-tg/ezinstalljmt-tg/ip2region 仓库中的 Makefile 脚本中,找到了远程 Docker 仓库的地址 镜像

该域名是在腾讯云购买的,服务器也是腾讯云的 IP。(PS: 不知道为啥对腾讯云这么情有独钟?)

以下是相关 IP 信息:

IP 归属地
harbor.jimatongim.com【43.135.25.88】 中国 香港【腾讯云】

该域名地址与 JMT 有相似之处,可能是 JiMaTong 的缩写。在互联网上搜索,可以找到同名的社交账号 Telegram@jimatongim,该账号用于出售所谓的 继码通 的软件定制服务。

下载了公开的演示 APP,发现其下载页面和软件页面都与之前的样本惊人地相似。逆向分析后的软件结构也与两个样本一致。

值得注意的是,频道所提供的下载链接中出现了一个新域名 tgjmtim.com 镜像。该域名是通过腾讯云平台完成购买的,并且在域名解析方面,其对应的 DNS 服务器与 jimatongim.com 域名完全相同。众所周知,使用 Cloudflare 来托管域名时,在同一账号下所设置的 DNS 服务器对于该账号内的所有域名而言都是一致的。因此可以确定这两个域名是绑定在同一个 Cloudflare 账户下的。

域名 DNS 服务器
jimatongim.com rodney.ns.cloudflare.com / aliza.ns.cloudflare.com
tgjmtim.com rodney.ns.cloudflare.com / aliza.ns.cloudflare.com

点赞关联

在所有公开仓库中可以发现,jmt-tg/ezinstall​ 有一个点赞。但是这个仓库相当定制化,并没有办法用在其他场景,因此怀疑点赞的有可能是团队成员。

检查点赞者 @DevAtDawn 后发现,其点赞过的仓库数量高达 1.3K,怀疑是机器人账号。在其所有点赞的仓库中发现两个 ezinstall​ 仓库,有可能是因为搜索结果过于相似导致误点了,可以排除与本事件的关联。

至此,所有溯源结束。

溯源总结

以下是整个溯源过程的流程图:

尾声

光看个人简介的话,开发者的年龄并不大,尽管曾有机会为开源社区做出贡献,甚至创建了企业,但最终却选择了为诈骗分子提供定制服务这条不归路。不过实际上也由于技术的欠缺,导致能够被很轻易地给跟踪到背后的自然人。Telegram 的记录显示,最早于 2023 年 9 月 2 日开始,向外网接受诈骗软件定做的单子,满打满算也有快一年半了 镜像。网上被该类定做软件诈骗的人不计其数。尽管他并不直接参与引流和诈骗,但其行为无疑与诈骗分子同流合污。

在追踪这些诈骗软件的过程中,我深刻体会到了技术与道德之间的微妙平衡。一方面,这些软件的开发者利用自己的技术才能,创造出了高度仿真的诈骗工具,给无数受害者带来了巨大的经济损失和心理创伤。另一方面,他们的技术才能本身并无善恶之分,只是在被用于非法目的时才显得可怕。

这不禁让我思考:作为技术人员,我们应该如何看待和利用自己的技术才能?是应该为了追求利益而不择手段,还是应该坚守道德底线,用技术为社会创造价值?在这个问题上,我认为每一个技术人员都应该有自己的判断和选择。我们应该时刻提醒自己,技术只是工具,真正的价值在于我们如何使用它。

回顾整个溯源过程,我深感震撼和惋惜。这位年轻的开发者本有机会用自己的技术才能为社会做出积极的贡献,但最终却选择了走上犯罪的道路。我希望这篇文档能够引起更多技术人员的关注和反思,共同营造一个更加健康、安全的网络环境。同时,我也呼吁那些仍在从事诈骗软件开发和定制的人员,尽早收手,回归正道。


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

最后于 2025-2-18 17:21 被wx_张三_488编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (4)
雪    币: 0
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
很有启发,感谢大佬分享!不过大佬文章的图全部被吞掉了,能否补充一下或者指个路呢~
2025-3-3 15:17
1
雪    币: 214
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
很有启发,感谢大佬分享!不过大佬文章的图全部被吞掉了,能否补充一下或者指个路呢~,跪求!
2025-4-8 13:26
0
雪    币: 461
活跃值: (192)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
原帖指路:cdfK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3f1#2x3Y4m8G2K9X3W2W2i4K6u0W2j5$3&6Q4x3V1k6@1K9s2u0W2j5h3c8Q4x3X3b7J5x3o6l9%4x3K6R3H3i4K6u0V1x3g2)9J5k6o6q4Q4x3X3g2Z5N6r3#2D9
2025-5-4 01:00
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
是原创吗
2025-6-1 16:27
0
游客
登录 | 注册 方可回帖
返回