揭露骗子利用微信“聊天记录中图片不可变”的骗局

news/2024/10/18 0:19:10/

一、起因

那是一个阴冷的夜晚,我的一个老乡怒气冲冲的给我拨了个微信视频,说他在微信上被人骗了。

他给我转发了一条骗子给他发的聊天记录,在点开之前是这样的:

图1 聊天记录

看上去是一个图片。点进去一看,果然是个图片。里面写了 4个数字。

从图上的“错一罚十”来看,貌似是某些“大神”给人推荐的一些“神秘数字”。

值得注意的一个细节是,当我点开菜单想用浏览器去打开这个图片的时候,发现很多菜单都被隐藏了。

图2 图片

老乡怒吼到:“奶奶的,老子前天找人花了一万块钱买的这个买马的推荐单,结果今天看到的数字,跟我昨天看到的数字完全不一样!”

这么一说我就明白了。原来骗子发了个图片来推荐受害人买马,里面手写了几个数字号称“预测绝对准确”。

然而,结果出来后,骗子又第一时间把图片改掉了,从而实现“绝对正确”。

我在心里说道“。。。卧槽,这你都能信”,嘴里说道:“。。这个在原理上当然可以实现啊,图片换掉了而已。”

老乡囔囔说:“现在这骗子说,这个是前天发出来的,聊天记录有时间作证,改不了的!他说除非我能发一个这样的记录给他,如果确实能够随便变图片,他就把钱还给我。”

我叹了口气,声色俱厉的教育了他,世界上没有未卜先知的大神。

老乡唯唯诺诺道:“好的我知道了!你才是大神,快给我做一个这样的记录出来!”

二、原理

首先可以确认的一点是,图1这种聊天记录,普通微信用户是做不出来的。

因为他既不是文字,又不是图片,他是微信公众号给用户发送的文章(Article)。

而骗子为了蒙骗不懂技术的老百姓,让人认为这就是个图片,在这个文章上做了几个细节:

1、聊天窗口上显示的文章卡片既没有标题,也没有链接,只有一个图片的缩略图,在心理上给人一种暗示,这就是一个图片。

2、文章点开后,是一张大图铺满屏幕,菜单里面没有“使用浏览器打开”、“复制链接”之类的菜单,因此很难让人想到这是一个网页。

因此,要复现这个骗局,需要:

1、有一个自己的通过认证的公众号。

2、使用该公众号给受害者推送一个没有标题、链接,只有缩略图的文章。

3、文章里的链接指向自己服务器的一个网页,网页域名要备案,网页内的图片要能变化

4、这个网页隐藏了微信菜单,如“使用浏览器打开”等。

现在基本原理已经了解了,就可以尝试复现这个骗局了。

三、技术点

骗子敢信誓旦旦的说有本事你弄一个给我看,底气在于对普通百姓而言,要复现这一套骗术还是相当有技术门槛和成本的。

下面一个一个讲解。

1、已认证的公众号

公众号如果不通过认证,在调用接口来隐藏微信菜单的时候会有局限性(由于我已经认证了,这一点没有亲自证实。)

认证需要的最简单的材料也需要个体工商户营业执照、300元的认证费用。

这部分就是费时费力费钱,跟技术关系不大。

2、给用户推送特殊的文章。

公众号给用户推送的所有信息都是用xml来描述的。可查阅微信官方文档。

不过值得吐槽的是,这个官方文档恰恰漏了推送文章的xml描述方式:

    <xml><ToUserName><![CDATA[{target}]]></ToUserName><FromUserName><![CDATA[{source}]]></FromUserName><CreateTime>{time}</CreateTime><MsgType><![CDATA[news]]></MsgType><Content><![CDATA[{content}]]></Content><ArticleCount>{count}</ArticleCount><Articles>{items}</Articles></xml>

可以发现<ArticleCount>定义了一个推送里有几篇文章,每一篇文章可以组装到<Articles>中,每个文章的描述如下:

    <item><Title><![CDATA[{title}]]></Title><Description><![CDATA[{description}]]></Description><PicUrl><![CDATA[{img}]]></PicUrl><Url><![CDATA[{url}]]></Url></item>

因此,只需要把Title、Description都置空,把PicUrl设置成骗子要显示的缩略图,Url设置为骗人图片的网页链接,把文章发送给用户就完成了。

3、网页显示图片,且图片可变

这里要解决的一个问题是:如果用户已经打开过这个网页,那么手机里必然有缓存。那么即使你在服务器上换掉了图片,用户还是能看到之前的图片。

解决图片缓存的思路很多。如果不想改变图片文件名,一种思路是给图片加上随机的后缀,如 1.png 改成 1.png?123456

这样,骗子只需要在适当的时候后台把1.png换掉即可。

另外一种思路是把正确的结果做成另外一个名字的图片,使用代码,设计成某种条件下切换要展示的图片文件名。

为方便演示,我准备了5张png图片,随机生成文件名来展示。JS代码如下:

<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js">
</script>    
<script type="text/javascript">// 随机选择5个图片$(function(){var randName = Math.floor(Math.random() * 65535) % 5$('.img_randPng').each(function(){this.src = this.src + randName + '.png';console.log(this.src)});});
</script>

然后在img标签里做修改即可:

<img src='https://********' class='img_randPng' />

4、隐藏微信菜单

最后一步是隐藏微信自带浏览器的部分菜单。这就要使用JS-SDK来实现了。

而麻烦的地方在于:所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用:

<script src='https://res.wx.qq.com/open/js/jweixin-1.6.0.js'>
</script>wx.config({debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: '', // 必填,公众号的唯一标识timestamp: , // 必填,生成签名的时间戳nonceStr: '', // 必填,生成签名的随机串signature: '',// 必填,签名jsApiList: ['hideAllNonBaseMenuItem'] // 必填,需要使用的JS接口列表
});wx.ready(function(){// 必须要放在这里才会生效wx.hideAllNonBaseMenuItem();
});

其中你需要调用JS的哪些api,都必须写到jsApiList中进行注册。

例如这里调用了'hideAllNonBaseMenuItem'接口来隐藏所有非必须的菜单。这个api必须在wx.read中调用。

上述配置信息注入最麻烦的地方在于需要签名,而签名需要向微信服务器请求获得jsapi_ticket,而jsapi_ticket又需要请求获得access_token。

官方文档中《获取access_token》说的足够详细了。https请求如下,要带上自己的appid和secret:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

access_token拿到之后再请求一个jsapi_ticket。https请求如下,要带上上面获得的access_token:

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

终于拿到jsapi_ticket,接下来就是签名算法了。可参阅《JS-SDK使用权限签名算法》。

Python代码如下:

# 当前访问的页面的完整URLurl = current_urlparameters = {"noncestr" : noncestr,"jsapi_ticket" : self.jsapi_ticket,"timestamp" : timestamp,"url" : current_url }# 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串unsinged_str = '&'.join(['{}={}'.format(key.lower(), parameters[key]) for key in sorted(parameters)])# 进行sha1签名,得到signaturesignedstr = hashlib.sha1(unsinged_str.encode("utf-8")).hexdigest()

noncestr为数字字母构成的随机数。

timestamp为时间戳,必须和请求jsapi_ticket的时间戳保持一致。

self.jsapi_ticket为上文获取到的jsapi_ticket。

url为准备调用JS-SDK接口的网页的url。

timestamp和noncestr随机数生成代码如下:

timestamp = int(time.time())
noncestr  = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))

将上述noncestr、timestamp、signedstr、appid插入到你的html模板中即可。

四、效果

最后展示下效果。每次打开,图片中第一个推荐的数字都会随机变化。

我把这条消息转给了老乡,说:“拿好,去干骗子吧。”

 

对了,这里漏了一点,为什么这个页面要备案?

因为如果不备案的话,这个网页打开一般都是这种结果:

这种情况当然你可以点申请恢复访问,但是申请的时候官方也要看你是否备案。。。

五、后续

几天后。

“怎么样,骗子退钱了没。”我问老乡。

老乡眉飞色舞的说:“退了退了,对了,这骗子还问我要你的微信,说他有一些全新的业务可以和你开展合作!

我:“。。。。。。”


http://www.ppmy.cn/news/581964.html

相关文章

QQ聊天记录器演示程序

QQ聊天记录器演示程序(可针对QQ2003和QQ2004版本) 注:本篇没有高手需要的内容(因为此文中的技术实在无新意可言,只是些简单的实现),各位高手可以就此打住,若浪费宝贵时间,吾将深感不安. 作者网站:http://asp.itdrp.com/hottey ----------------hottey 嘘!好不容易有了一点轻松…

Java Swing实现局域网QQ

写在前面 个人博客网址&#xff1a;https://jiong952.github.io/ 个人github网址&#xff1a;https://github.com/jiong952 源码地址&#xff1a;https://github.com/jiong952/QQ2.0 课程题目 实现一个带图形用户界面的 Java 版即时聊天程序。 【功能提示】 用户登录及登录…

仿QQ聊天室项目功能总结

项目源码开源在gitee&#xff08;码云&#xff09; 地址&#xff1a;https://gitee.com/xiaoclgitee/imitation-qq-chat-room 项目功能总结&#xff1a; 1、页面制作 采用Java 的Swing的Jframe 的框架进行GUI的制作 主要有三个界面&#xff1a;1、用户登录界面 2、用户聊天窗…

腾讯QQ的聊天记录中的图片记录造假

前不久和朋友在群里聊天时&#xff0c;突然出现了一个BUG&#xff0c;就是一个群友发了A图片&#xff0c;但在我这边显示得却是B图片。当时就猜测&#xff0c;腾讯为了节省流量或者手机资源的原因&#xff0c;给每一张图片弄了个唯一ID&#xff0c;遇到相同ID的就直接从本地调用…

基于 springboot+vue 进行多条件查询历史聊天记录

查询历史聊天记录 多条件查询记录是经常需要进行编写的功能&#xff0c;这里就以多条件查询历史聊天记录为例子来介绍如何进行基于关键字、日期、聊天记录类型 三种条件进行模糊查询、日期拼接、条件拼接查询。 前端 抽屉管理 首先我们控制 element ui 的 抽屉的打开与关闭 …

Vue3版本生命周期详解

介绍 vue3和vue2的生命周期改动不大,下面以图来展现两个版本的周期钩子 使用示例 配置项写法 vue3可以使用vue2版本的周期配置 准备一个HelloWord组件 使用App组件嵌套HelloWorld组件,并进行v-if判断是否卸载该组件,以此查看vue3的卸载钩子 测试: 可以看到当页面刷新后执行…

python qq群发消息_Python版QQ群发消息

PyQQ已经发布&#xff0c;利用web2qq协议&#xff0c;目前支持批量添加好友&#xff0c;批量群发消息等功能。 我的初衷是以PyQt为GUI做一个跨平台的QQ机器人&#xff0c;在win平台下不需要安装Python环境也能运行&#xff0c;能根据收到的消息自动回复。目前已经测试通过的只有…

JAVA 仿QQ聊天程序(附源码)

个人推荐: &#x1f4e2;&#x1f4e2;&#x1f4e2; 前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下 "通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。点击跳转到教程。 前言: 第一次通过java编写完了一个模拟QQ的C/S…