在过去的几个小时内,十几个新闻报道已经破坏了攻击者如何利用BGP漏洞来企图(也许是管理)窃取加密货币。

1.jpg

什么是BGP?

互联网由链路组成。比如我们的DNS域名解析1.1.1.1,我们告诉世界所有在1.1.1.0到1.1.1.255范围内的IP都可以通过任何Cloudflare PoP(point-of-presence,网络服务接入点)访问。

对于没有直接链接到我们路由器的人,他们通过中转提供商接收路由,他们将数据包发送到这些地址,因为它们连接到Cloudflare和其他Internet。

这是互联网正常运作的方式。

有些机构(地区互联网注册管理机构或RIRs)负责分配IP地址,以避免使用相同地址而导致冲突。他们有:IANA,RIPE,ARIN,LACNIC,APNIC和AFRINIC。

什么是BGP泄露?

2.png

BGP泄露的广义定义是由非空间持有者对外广播的IP空间。当中转服务提供商接收到Cloudflare的1.1.1.0/24广播并将其公布给互联网时,我们允许他们这样做。他们还使用只有Cloudflare可以提供给他的RIR(区域互联网地址注册机构)进行安全校验。

尽管检查所有广播公告可能会非常麻烦。尤其面对互联网上700000+的路由,以及线供应商之间流量交换的场景下。

从本质上讲,路由泄漏是本地化的。你本地化连接越多,接受泄漏路线的风险就越小。

为了被接收一个合法的路由,路由必须是:

较小的前缀(10.0.0.1/32 = 1 个IP与10.0.0.0/24 = 256 个IP)

比具有相同长度的前缀具有更好的metrics值(更短的路径)

BGP泄露的原因通常是由于配置错误:路由器突然广播它学到的IP。或者以更小的前缀在内部的流量项目用于突然被发布到外网了。

但也有可能是被人恶意利用发布的。前缀可以重新路由以便被动地分析数据。或者有人也可以建立一个中继服务来非法应答。这种情况以前也屡有实例。

25号发生了什么?

Cloudflare维护的一些收集来自全球数百台路由器BGP信息的服务器,在大概UTC时间11:05:00 到 UTC时间12:55:00之间,收到以下公告:

BGP4MP|04/24/18 11:05:42|A|205.251.199.0/24|10297

BGP4MP|04/24/18 11:05:42|A|205.251.197.0/24|10297

BGP4MP|04/24/18 11:05:42|A|205.251.195.0/24|10297

BGP4MP|04/24/18 11:05:42|A|205.251.193.0/24|10297

BGP4MP|04/24/18 11:05:42|A|205.251.192.0/24|10297

BGP4MP|04/24/1811:05:54|A|205.251.197.0/24|4826,6939,10297

这些是更具体的公告中提到的IP范围:

  • 205.251.192.0/23
  • 205.251.194.0/23
  • 205.251.196.0/23
  • 205.251.198.0/23

该IP空间分配给亚马逊(AS16509)。但是公告ASN显示却来自eNet公司(AS10297)并将其转交给Hurricane Electric(AS6939)。

这些IP用于亚马逊AWS 的Route53 DNS服务器。当你查询的是他的客户区域时,这些服务器将会应答。

在两个小时内,IP范围内的服务器泄露,只对“myetherwallet.com”的查询做出应答。有些人可能注意到SERVFAIL。

当查询任何由Route53解析的域名都会先去查询已经通过BGP泄漏接管的授权服务器。这个中毒的DNS解析器的路由器已经接受了这个路由。

这其中就包括Cloudflare DNS解析器1.1.1.1。我们在芝加哥,悉尼,墨尔本,珀斯,布里斯班,宿雾,曼谷,奥克兰,马斯喀特,吉布提和马尼拉都得服务都受到影响。其他地方的,1.1.1.1服务正常。

今天早上的BGP劫持事件影响了亚马逊DNS。俄亥俄州哥伦布市的eNet(AS10297)今天公布了从UTC 时间11:05到13:03的以下亚洲线路的更多细节:

205.251.192.0/24

205.251.193.0/24

205.251.195.0/24

205.251.197.0/24

205.251.199.0/24

3.png

InternetIntelligence(@InternetIntel)2018年4月24日

更正:今天早上的BGP劫持是针对AWS DNS而不是Google DNS。

InternetIntelligence(@InternetIntel)2018年4月24日

例如,以下查询将返回合法的Amazon IP:

$ dig + short myetherwallet.com @ 205.251.195.239

54.192.146.xx

但在劫持期间,它返回了与俄罗斯DNS供应商(AS48693和AS41995)相关的IP。你不需要接受被劫持的路由,只要你使用了已经中毒的DNS解析服务器就会中标。

4.png

如果你使用了HTTPS,假网站将显示由未知权威机构签名的TLS证书(证书中列出的域名是正确的,但是是自签名的)。如果你选择继续并接受错误的证书。那么你发送的所有内容都将被加密,但是解密内容的密钥却在攻击者手里

如果你已经登录过,你浏览器会通过cookie发送登录信息。否则,如果你在登录页面上输入用户名和密码,就会发送用户名和密码,虽然内容是加密的,但是攻击者用手中的密钥就可以解密获得这些嘻嘻你。

一旦攻击者获得了登录信息(账号密码或者token),它就会在网站上合法使用它们转移和窃取以太坊。

过程图示

正常情况

5.png

BGP路由泄露后

6.png

受影响的地区

如前所述,AS10279宣布了这条路由。但是只有一些地区受到影响。HurricaneElectric在澳大利亚拥有强大的影响力,主要是因为上网比较便宜。芝加哥受到影响,因为AS10279的在直接的有一个物理点。

下图显示受影响区域和未受影响区域(Y轴做了归一化)的流量。流量大幅下降是因为授权服务器drop了所有的请求(它只响应一个网站而所有其他亚马逊域被忽略)。

7.png

eNet(CenturyLink,Cogent和NTT)使用的其他交易似乎并未接受此路线:一个原因可能是他们有过滤器,还有就是Amazon是他们的客户。

eNet提供IP服务,所以他们的一个客户可能已经宣布了它。

谁的锅?

由于参与者众多,大家都难究其责。涉及者:

宣布它并不拥有的子网的ISP

中转提供商在转播之前未检查通告。

接受该路由的ISP

DNS解析服务器和权限缺乏保护。

俄罗斯钓鱼网站提供商

未执行合法TLS证书的网站

即使提示TLS证书无效,还继续点击的用户

就像区块链一样,网络更改通常是可见的和存档的。 RIPE维护了一个用于此用途的数据库。

如何避免此类事件发生?

这是一个难以回答的问题。有关于保护BGP的建议:

1、有些关键字可以添加到RIR数据库中,因此可以生成允许的来源列表:

$ whois -h whois.radb.net ' -M 205.251.192.0/21' |egrep '^route:|^origin:|source:' | paste - - - | sort

route:     205.251.192.0/23   origin:     AS16509    source:     RADB

route:     205.251.192.0/23   origin:     AS16509    source:     REACH

2、使用RIR建立RPKI/ROA记录作为与路径路径相关的真实来源,尽管不是每个人都创建这些记录或验证它们。 IP和BGP是几十年前创建的,关于完整性和真实性(较少路由)有着不同的要求。

可以在网络堆栈的上层完成一些操作。

3、关于DNS上,你可以使用DNSSEC作为你的记录签名。假冒的DNS返回的IP不会被签名,因为它们没有私钥。

如果你将Cloudflare用作DNS,则可以在面板中只需简单点击几个按钮来启用DNSSEC。

4、关HTTPS方面,你的浏览器将检查网站提供的TLS证书。如果启用了HSTS,浏览器将始终需要有效的证书。为域生成合法TLS证书的唯一方法是中毒证书颁发机构的非DNSSEC DNS解析器的缓存。

DANE提供了一种使用DNS将证书固定到域名的方法。

通过HTTPS的DNS还可以验证你是否正确地与正确的解析器通信,以防DNS泄漏发生在DNS截些服务器而不是DNS权限。

没有完美而独特的解决方案。这些保护措施越多,恶意行为者就越难执行这种攻击。

* 本文虫虫译自cloudflare官方博客,原作者Louis Poinsignon,转载注明来自FreeBuf.com

作为日常研究工作的一部分,作者最近发现了一个问题,允许攻击者向Google提交一个XML站点地图,以查找未被谷歌收录的的站点。由于这些文件可以包含索引指令,如hreflang,因此攻击者可以利用这些指令帮助自己的网站在Google搜索结果中的排名。

为了测试,仅仅花了12美元就完成了测试环境的搭建,将一个新注册的没有任何入站链接的域名,推在了谷歌搜索结果的顶级收费搜索主题结果的第一页排名中。

XML 站点地图和Ping机制

Google允许通过提交XML网站地图,用于帮助引擎爬虫主动发现URL,他还允许使用hreflang指令用于翻译一个页面国际化的各不同语言版本的内容(例如,“hey Google, this is the US page, but I have a Germanpage on this URL…”)。目前还不清楚Google是如何使用解析和使用这些指令的(就像任何与Google搜索算法相关的指令一样),但似乎hreflang允许一个URL从另一个URL “借用”索引权重和将一个已有URL的索引权重用于另一个URL(比如大多数人链接到US.com版本,但是德国版的版本可以借用这个权重,以便在Google.de中获得更好的排名)。

你可以通过Google Search Console,在robots.txt中或通过特殊的“ping”URL,为你的域名提交XML 站点地图。谷歌自己的文档似乎有点矛盾。在页面的顶部,他们建议是通过ping机制提交站点地图,但在页面的底部又对此发出警告:

1.png

 

但是,根据经验判断,你完全可以通过ping机制提交一个新的XML站点地图,Googlebot通常在ping后的10-15秒内获取文件。重要的是,Google在页面上也提到过几次,如果你通过ping机制提交站点地图,它将不会显示在你的搜索Console中:

2.png

作为一个相关测试,我测试了是否可以通过XML站点地图添加其他已知的搜索指令(比如noindex,rel-canonical),以及尝试一堆XML攻击,但似乎对Google并没有使用到。

Google Search Console(GSC)提交

如果你尝试在GSC中提交XML站点地图,而且其中包含了你未被授权的其他域的URL,则GSC会拒绝他们:

3.png

开放重定向

许多网站使用URL参数来控制重定向:

4.png

在这个例子中,我将被重定向(登录后)到page.html。安全限制不好的网站允许使用所谓的“开放重定向”,这些参数允许重定向到不同的域:

5.png

通常不需要任何交互(如登录),所以会立即将用户重定向:

6.png

开放重定向非常普遍,通常认为不有什么危险;由于这些原因,Google也没有将他们纳入到bug奖励计划中。但是,在可能的情况下,企业应该会尽量避免这些情况发生,但你通常可以绕过他们的保护:

7.png

Tesco是一家英国零售商,收入超过500亿英镑,超过10亿英镑的收入来自其网站。我向特易购(Tesco)报告了这个例子(还有在我的研究中发现的其他公司),他们已经修复了这个问题。

通过打开重定向Ping Sitemaps

现在,你可能已经猜到了我要尝试的方法。事实证明,当你ping一个XML站点地图时,如果你提交的URL是一个重定向,谷歌将跟着他重定向,即便跨域了。而且,它似乎还将该XML站点地图与进行重定向到域进行关联,并将重定向后发现的站点地图视为该域的授权。例如:

8.png

本例中,evil.xml站点地图托管在blue.com上,但Google会将其关联为green.com的所有权并为其授权。使用此功能,你可以为没有权限的网站提交XML站点地图,并发送Google搜索指令。

实验:使用hreflang指令免费“窃取”权重排名

现在我了知道了各个细节部分,但是还没有证实谷歌会真的相信跨域重定向的XML站点地图,所以我做了一个试验来测试它。我还做了很多更小的测试来了解了解(可能能各种死路)各部分,但并没有指望这个试验能够像预期的那样行得通。

我为一家没有在美国经营的英国零售公司创建了一个虚假域名,并且在AWS服务器上创建了一个模仿该网站(主要是通过收集合法内容并对其进行重新设计,例如修改货币/地址等)。为了保护他们,在此我隐匿公司名(和行业),我们姑且称他为victim.com。

我在evil.com上创建了一个虚假的站点地图,只包含victim.com的URL。这些URL包含hreflang条目指向evil.com上等效URL,表明victim.com的美国版本。现在,我用Google的ping机制通过victim.com上的开放重定向URL提交了网站地图。

在48小时内,该网站开始有了少量来自于搜索引擎为长尾访问(SEMRush屏幕截图):

9.png

 

再过两天,可以有相关主题的结果第一页上开始出现,同页上有如亚马逊和沃尔玛等。

 10.png

此外,evil.com的Google Search Console也显示victim.com正在链接到evil.com,但实际上这明显是不对的:

11.png

同时,我还发现我也能在evil.com的GSC中为victim.com提交XML站点地图:

12.png

Google似乎已将这些网站链接起来,在evil.com的GSC现在有些功能可以影响victim.com的设置。我现在也可以跟踪我提交的站点地图的索引(你可以看到我现在有数千页索引)。

Searchmetrics显示了流量的增长和其价值:

13.png

此站点的GSC显示通过Google有超过100万的搜索,展示次数和超过10,000次点击次数;然而,除了提交XML站点地图,我什么都没做!

注意到,我并没有对这个evil站点做任何展示,如果想要利用他来欺骗人们点击的话,应该可以赚很多钱。或者通过设置广告,甚至还可以想办法把这种流量变现。在我看来,这给Google访问者带来了严重的风险,同时也给依赖Google搜索流量的公司带来了风险。访问量还在增长,但我关闭了我的试验站,并放弃了后续实验,因为害怕造成损害。这是一个真正黑客应该具有的职业道德,点赞。

讨论

对于victim.com来说,这种方法完全无法检测,XML站点地图不会显示在他们的终端,如果有人做了想我做事情的,并且用它谋取经济利益的话,那么也没有啥方法监控的到。除了你的竞争对手会对你的站点排名感到不可思意外。(如上面例子中的亚马逊,沃尔玛和塔吉特等的搜索结果,他们可都是花了重金才拿到那个位置的)。

就黑帽SEO而言,这是一个明确的用法,而且这使我意识到对算法漏洞的彻底利用第一个例子,而不是操纵其他排名因子。这个问题的潜在财务影响的也并非微不足道,想象一下以特易购或类似网站为目标的潜在利润(如果有机会我会做更多的测试以便收集信息,但会严格限制在没有任何潜在的危害的情况下)。

Google已经为此奖励了1337美元的奖金,一如既往,于Google团队打交道非常开心,感谢他们。

披露时间表

•2017年9月23日,我提交初步的bug报告。

•2017年9月25日,谷歌回应 – 他们调整了bug并正在研究它。

•2017年10月2日,我发送了更多细节。

•10月9日到11月6日,一些来回状态更新。

•2017年11月6日 – 谷歌表示:“本报告难以确定可以采取哪些措施来防止此类行为及其对搜索结果的影响。我已与团队联系以获得最终决定。正对你的报告,他们一直在对数据进行筛选,以确定你描述的行为有多普遍,以及这是否应该立即采取相应措施。”

2017年11月6日,我回复说,他们没有遵循针对ping的站点地图的跨域重定向,没有什么好的理由,它可能只是GSC的唯一功能。

2018年1月3日,我要求更新状态。

2018年1月15日,谷歌搜索回复道:“对于延期抱歉,我不想过早结束这份报告,因为我们还无法做出明确的决定,是否可以用重定向链解决这种行为而不会破坏很多合法用例。我已经回到团队审查这份报告以得到最终答案,我已经回到团队审查这份报告以获得最终答案,并会在本周回复你。”

2018年2月15日,谷歌更新,让我知道报告中存在一个错误,VRP董事会将讨论奖励。

2018年3月6日,谷歌让我知道通知过他们已批复1337美元的奖金。

2018年3月6日,我与Google分享了这篇文章的草稿,并要求允许得到公开。

2018年3月12日,谷歌让我知道他们还没有完成修复,并要求不要公开。

2018年3月25日,谷歌证实该修补程序已经生效,并允许我发布文章。

本文编译自 Tom Anthony的博客,原文地址

作为日常研究工作的一部分,作者最近发现了一个问题,允许攻击者向Google提交一个XML站点地图,以查找未被谷歌收录的的站点。由于这些文件可以包含索引指令,如hreflang,因此攻击者可以利用这些指令帮助自己的网站在Google搜索结果中的排名。

为了测试,仅仅花了12美元就完成了测试环境的搭建,将一个新注册的没有任何入站链接的域名,推在了谷歌搜索结果的顶级收费搜索主题结果的第一页排名中。

XML 站点地图和Ping机制

Google允许通过提交XML网站地图,用于帮助引擎爬虫主动发现URL,他还允许使用hreflang指令用于翻译一个页面国际化的各不同语言版本的内容(例如,“hey Google, this is the US page, but I have a Germanpage on this URL…”)。目前还不清楚Google是如何使用解析和使用这些指令的(就像任何与Google搜索算法相关的指令一样),但似乎hreflang允许一个URL从另一个URL “借用”索引权重和将一个已有URL的索引权重用于另一个URL(比如大多数人链接到US.com版本,但是德国版的版本可以借用这个权重,以便在Google.de中获得更好的排名)。

你可以通过Google Search Console,在robots.txt中或通过特殊的“ping”URL,为你的域名提交XML 站点地图。谷歌自己的文档似乎有点矛盾。在页面的顶部,他们建议是通过ping机制提交站点地图,但在页面的底部又对此发出警告:

1.png

 

但是,根据经验判断,你完全可以通过ping机制提交一个新的XML站点地图,Googlebot通常在ping后的10-15秒内获取文件。重要的是,Google在页面上也提到过几次,如果你通过ping机制提交站点地图,它将不会显示在你的搜索Console中:

2.png

作为一个相关测试,我测试了是否可以通过XML站点地图添加其他已知的搜索指令(比如noindex,rel-canonical),以及尝试一堆XML攻击,但似乎对Google并没有使用到。

Google Search Console(GSC)提交

如果你尝试在GSC中提交XML站点地图,而且其中包含了你未被授权的其他域的URL,则GSC会拒绝他们:

3.png

开放重定向

许多网站使用URL参数来控制重定向:

4.png

在这个例子中,我将被重定向(登录后)到page.html。安全限制不好的网站允许使用所谓的“开放重定向”,这些参数允许重定向到不同的域:

5.png

通常不需要任何交互(如登录),所以会立即将用户重定向:

6.png

开放重定向非常普遍,通常认为不有什么危险;由于这些原因,Google也没有将他们纳入到bug奖励计划中。但是,在可能的情况下,企业应该会尽量避免这些情况发生,但你通常可以绕过他们的保护:

7.png

Tesco是一家英国零售商,收入超过500亿英镑,超过10亿英镑的收入来自其网站。我向特易购(Tesco)报告了这个例子(还有在我的研究中发现的其他公司),他们已经修复了这个问题。

通过打开重定向Ping Sitemaps

现在,你可能已经猜到了我要尝试的方法。事实证明,当你ping一个XML站点地图时,如果你提交的URL是一个重定向,谷歌将跟着他重定向,即便跨域了。而且,它似乎还将该XML站点地图与进行重定向到域进行关联,并将重定向后发现的站点地图视为该域的授权。例如:

8.png

本例中,evil.xml站点地图托管在blue.com上,但Google会将其关联为green.com的所有权并为其授权。使用此功能,你可以为没有权限的网站提交XML站点地图,并发送Google搜索指令。

实验:使用hreflang指令免费“窃取”权重排名

现在我了知道了各个细节部分,但是还没有证实谷歌会真的相信跨域重定向的XML站点地图,所以我做了一个试验来测试它。我还做了很多更小的测试来了解了解(可能能各种死路)各部分,但并没有指望这个试验能够像预期的那样行得通。

我为一家没有在美国经营的英国零售公司创建了一个虚假域名,并且在AWS服务器上创建了一个模仿该网站(主要是通过收集合法内容并对其进行重新设计,例如修改货币/地址等)。为了保护他们,在此我隐匿公司名(和行业),我们姑且称他为victim.com。

我在evil.com上创建了一个虚假的站点地图,只包含victim.com的URL。这些URL包含hreflang条目指向evil.com上等效URL,表明victim.com的美国版本。现在,我用Google的ping机制通过victim.com上的开放重定向URL提交了网站地图。

在48小时内,该网站开始有了少量来自于搜索引擎为长尾访问(SEMRush屏幕截图):

9.png

 

再过两天,可以有相关主题的结果第一页上开始出现,同页上有如亚马逊和沃尔玛等。

 10.png

此外,evil.com的Google Search Console也显示victim.com正在链接到evil.com,但实际上这明显是不对的:

11.png

同时,我还发现我也能在evil.com的GSC中为victim.com提交XML站点地图:

12.png

Google似乎已将这些网站链接起来,在evil.com的GSC现在有些功能可以影响victim.com的设置。我现在也可以跟踪我提交的站点地图的索引(你可以看到我现在有数千页索引)。

Searchmetrics显示了流量的增长和其价值:

13.png

此站点的GSC显示通过Google有超过100万的搜索,展示次数和超过10,000次点击次数;然而,除了提交XML站点地图,我什么都没做!

注意到,我并没有对这个evil站点做任何展示,如果想要利用他来欺骗人们点击的话,应该可以赚很多钱。或者通过设置广告,甚至还可以想办法把这种流量变现。在我看来,这给Google访问者带来了严重的风险,同时也给依赖Google搜索流量的公司带来了风险。访问量还在增长,但我关闭了我的试验站,并放弃了后续实验,因为害怕造成损害。这是一个真正黑客应该具有的职业道德,点赞。

讨论

对于victim.com来说,这种方法完全无法检测,XML站点地图不会显示在他们的终端,如果有人做了想我做事情的,并且用它谋取经济利益的话,那么也没有啥方法监控的到。除了你的竞争对手会对你的站点排名感到不可思意外。(如上面例子中的亚马逊,沃尔玛和塔吉特等的搜索结果,他们可都是花了重金才拿到那个位置的)。

就黑帽SEO而言,这是一个明确的用法,而且这使我意识到对算法漏洞的彻底利用第一个例子,而不是操纵其他排名因子。这个问题的潜在财务影响的也并非微不足道,想象一下以特易购或类似网站为目标的潜在利润(如果有机会我会做更多的测试以便收集信息,但会严格限制在没有任何潜在的危害的情况下)。

Google已经为此奖励了1337美元的奖金,一如既往,于Google团队打交道非常开心,感谢他们。

披露时间表

•2017年9月23日,我提交初步的bug报告。

•2017年9月25日,谷歌回应 – 他们调整了bug并正在研究它。

•2017年10月2日,我发送了更多细节。

•10月9日到11月6日,一些来回状态更新。

•2017年11月6日 – 谷歌表示:“本报告难以确定可以采取哪些措施来防止此类行为及其对搜索结果的影响。我已与团队联系以获得最终决定。正对你的报告,他们一直在对数据进行筛选,以确定你描述的行为有多普遍,以及这是否应该立即采取相应措施。”

2017年11月6日,我回复说,他们没有遵循针对ping的站点地图的跨域重定向,没有什么好的理由,它可能只是GSC的唯一功能。

2018年1月3日,我要求更新状态。

2018年1月15日,谷歌搜索回复道:“对于延期抱歉,我不想过早结束这份报告,因为我们还无法做出明确的决定,是否可以用重定向链解决这种行为而不会破坏很多合法用例。我已经回到团队审查这份报告以得到最终答案,我已经回到团队审查这份报告以获得最终答案,并会在本周回复你。”

2018年2月15日,谷歌更新,让我知道报告中存在一个错误,VRP董事会将讨论奖励。

2018年3月6日,谷歌让我知道通知过他们已批复1337美元的奖金。

2018年3月6日,我与Google分享了这篇文章的草稿,并要求允许得到公开。

2018年3月12日,谷歌让我知道他们还没有完成修复,并要求不要公开。

2018年3月25日,谷歌证实该修补程序已经生效,并允许我发布文章。

本文编译自 Tom Anthony的博客,原文地址

本文虫虫编译,源blog地址请参考。原作者Julia Evans是一个科技漫画作者。有很多很不错的编程漫画作品,可以观看学习。

5.png

我日常喜欢画些有关编程的漫画。 在上周四,我买了一个iPad 和Apple Pencil,因为Apple Pencil是一个非常好的绘图工具。我开始使用iPad的Notability应用程序,他看起来非常不凑。但是我遇到了一个不爽的事情:

我使用的Android应用程序中有很多的原始图片,但是用的格式是Squid!

Notability可以导入pdf,但它们会变成只读,你可以在其上绘制,但不能编辑它们。很烦人,不是吗?

趣味问答开始:

Julia:“我想把我的旧图纸转换到新的app里,但是没有办法做到这一点!”

Kamal:“那么如果你反向工程Notability文件格式呢?”

Julia:“呃,听起来好像需要很长时间”

Kamal:“也许只要花上一个小时,看看会发生什么!”

Julia:“好吧!”

本文旨在弄清如何将SVG转换为Notability的原生格式(.note)。这是一种专有格式,而且好像还没有人对其进行过反向工程,所以我们的从头开始。

如果你是伸手党,想直接用现成的程序SVG转换为Notability,可以参考github repo:svg2notability。它就用了不到200行的Python代码来实现。

我会写出逆向工程这个文件格式的过程,因为它并没那么困难,逆向工程往往看起来很可怕,有点不可亲近。但是我昨天就开始做了,直到今天晚上,已经做了一些成果,已经足够实际使用。

在这篇文章中,我会解释如何破解Notability的 .note格式的构的。

Ox00从.note文件开始

我从APP中导出了一个.note文件,将它放入Dropbox,并将其复制到我的Linux工作机上。这简单,这个文件是template.note。

 Ox01 解压缩文件

什么是.note文件呢?找出答案的方法就是用file命令探测他。原来它是一个zip包:


$ file template.note

template.note:Zip archive data, at least v2.0 to extract

$ unzip template.note

 解压缩到名为template /的目录中。这里是它里面的文件组成:


$ find template/

template/

template/thumbnail

template/Assets

template/Session.plist

template/thumb3x.png

template/Recordings

template/Recordings/library.plist

template/thumb2x.png

template/thumbnail2x

template/metadata.plist

template/Images

template/thumb6x.png

template/thumb.png

不错,好整洁!咦,有个.plist文件?

0×02解码.plist文件

通过谷歌(和file)搜索,我们得知.plist文件是某种苹果文件格式。谷歌显示,可以为XML格式或二进制格式。这里他是苹果二进制格式。

$ file template/Session.plist

template/Session.plist:Apple binary property list

 我但是对此有点担心,但还有一些谷歌搜索显示有一个名为plistutil的Linux工具,我可以在对其进行转化。先安装plistutil。

我吧所有的二进制.plist文件转换XML,看看它们,很清楚的表明template/ Session.plist是具有绘图数据的文件。一旦将其解码为XML,你可以看到它在这里的样子:notability_session.xml。

你怎么知道这是绘图数据的地方,Julia?那么,它的内容内容这些非常动人关键字,如“curvespoints”。比如这个:

 <key>curvespoints</key>


<data>

mgG+QjOrB0NmuUBDVT3MQgA5kUNEJIlCTBXCQ2YWDEIAT7JCM4tqQ+YFUEMzGVlDJnKj

QzOnR0Na4d5DMzU2QzMzukKafLZDM5dZQ2aDrkNmCqtDM4qmQzNJ6UMAkZ5DZpadQjPQ

A0SFx51CsM4DRHjvnUI7zQNEsRCeQrTLA0QiU55CpsgDRKl6nkJUxQNEzZqeQs3AA0Sv

rp5CEr8DRHW3nkIdvQNEM82eQma4A0RNHJ9CrqkDRNV2n0KUmANEmtGfQs2IA0QoPqBC

p3UDRJugoEINZQNEANagQs1eA0SKIaFCC1QDREOEoULIRgNEzQyiQoA1A0TpVKJCUSsD

ROCWokKvIgNEzcmiQrMdA0SVk6NCtAgDRH10pEJr9gJEzZOlQmbfAkTyaadCkrUCRFb8

qUKYewJEmjCtQmY+AkTkaLBCSQICRKEqtEIkyAFEAPi3QjOSAUS+RbtCMGMBRK6lvkKk

MwFEANDBQmYDAURBQMZCHb0ARCxqykKSdgBEzQDPQrMwAET6vtNCwdL/Q34M2UJwPv9D

mT7eQpm6/kNsXuNCcjr+QzQE6EIV2f1DM7vsQjNi/UMSDu9C6CT9Qztz8UIY4fxDmRD0

QpmY/EMwL/ZC3F/8Q0Fu+EKoJPxDM8L6Qmbl+0N9tf1Ck5P7Q6JnAENsOvtDmu4BQ5nf

+kOgxgJDQK36Q0OWA0MCe/pDmmQEQ5lF+kNbgQVDQ/v5Q6yaBkMkr/lDZr0HQzNk+UPB

</data>

有人可能会认为这个“curvespoint”数据代表了文件中曲线上的点。答对了:它的就是。

 0×03解码曲线上的点

这听起来很直接,但在实际的工作中,这是让我最头疼,最讨厌的部分。以下是我如何解读这个“curvespoints”的内容:

 1.发现他是base 64编码。这一部分很简单:我之前使用过base64编码数据,二进制数据通常是在文本文件中编码的。酷!

2.在hexdump中的查看他数据

3.混淆(“这只是随机字节?!!?我怎么知道这意味着什么?”)

4.试着看看它是否是msgback(no),bencode(no)。感到困惑。抱怨。重复一个小时左右。

5.最后,等等,突然想到,如果它只是一个32位浮点数阵列?这将是简单的,好像有道理的!。

6.尝试将其解码为32位浮点数组

7.OK,他工作正常。


importsubprocess

importplistlib

importstruct

 

defunpack_struct(string, fmt):

    returnstruct.unpack(‘{num}{format}’.format(num=len(string)/4, format=fmt), string)

 

plistlib.readPlistFromString(subprocess.check_output(['plistutil','-i', 'file.plist']))

curves_points= pl['$objects'][8]['curvespoints'].data

unpack_struct(curvespoints,’f')

这里有一些来自于我文件的浮点数。这些看起来非常清晰,就是曲线上的点:它是一个浮点数组,每个连续2个浮点组都是曲线上的一个点。干的好!


(407.59869384765625,

 396.6827087402344,

 408.05926513671875,

 396.3546447753906,

 408.2127990722656,

 396.2452697753906,

 408.3787536621094,

 396.1249084472656,

 408.55938720703125,

 395.9921875)

0×04解码其他字段

解码其他字段很简单:

curvenumpoints:32位整数数组,它是每条曲线上的点数(unpack_structcurves ['curvesnumpoints'].Data, ‘i’)),

curveswidth:32位浮点数组,每条曲线的厚度

curvescolors:32位RGBA值的数组(0x00FFEEFF是十六进制代码#00FFEE,最后一位是不透明度)

curvesfractionalwidths:可变长度曲线的宽度乘数。我不关心这些,我把它们全部设置为1.0。

eventTokens:不确定,我只是将所有这些设置为浮点数1.0,它似乎都工作正常

0×05在图上绘制点数

 

为了确保这些点实际上是点,我要把他们绘制在图上,在本例中,我实际上是使用了一个源于zine的关于你和你经理的对话。以下是它的样子:

1.png

非常酷!!!!我对我的成功感到非常激动。于是下午5点,我有时间去朋友家吃晚饭,所以我这样做了。

0×06生成.note文件

好的,现在我们有一些眉头,我们知道这个文件格式是如何运作的。我们如何生成这种格式的文件呢?

 基本的步骤如下:

1、从现有的空的.note文件开始。

2、除了Session.plist文件(绘图数据所在的位置)之外,所有内容都保持一致。

3、设置curvesnumpointscurveswidthcurvescolors等数据

4、将它用Zip打包,将其导入我的app,并希望它能正常工作!

 有一种debug策略帮助我一路成功,那就是我尝试重新生成已有的.plist文件。我得到了我认为它表达的点的列表,并且自己生成了curvesnumpoints等字段,并确保它们与Notability对这些文件的真实数据相匹配。然后我进行单元测试!

一路上有很多奇怪的工件和错误,但是这篇博文已经很长了,我不认为解释这个很有趣。

0×07 结果

结果如下!首先,我输入到我的svg2notability程序中的SVG如下所示:

2.png

在我转换它之后,它在Notability中!它看起来基本相同!而且我可以轻松编辑它,这就是要点。颜色,样式等一切都正常!

3.png

0×08未尽的部分

1、生成具有多个页面的文档(没有尝试)

2、绘制正方形,我的一些绘图有完美的正方形,并且还有一个问题,我还没有制定出来

3、在Notability中更改纸张尺寸以匹配原始纸张尺寸。相反,我只是缩放宽度以匹配Notability的默认纸张宽度,这已经可以了,但还可以更好。

 0×09后记

 我认为使逆向工程不那么难的事情是,开发人员重复使用代码!人们通常不会发明完全自定义的文件格式!这里没有任何东西真的很复杂,它只是一些现有的标准格式(zip,苹果plist,一组浮点数数组)以非常简单的方式组合在一起。

 这个事情很有趣,从一个看似棘手或非常繁重的任务开始, “等等,我是一名程序员!!”,并设法使用编程的力量来达成我想做的事情(至少是这样)!

我发现所有这些移动绘图应用程序(Squid,Notability,Goodnotes等)都使用专有文件格式,如果没有逆向工程,就不能在对其互相转换。但逆向工程是就可以! squid_decoder反向工程了Squid格式(它基本上是一个谷歌缓冲协议)

 如果你想觉得看文章费劲,直接看代码:  https://github.com/jvns/svg2notability。

本文虫虫编译,源blog地址请参考。原作者Julia Evans是一个科技漫画作者。有很多很不错的编程漫画作品,可以观看学习。

5.png

我日常喜欢画些有关编程的漫画。 在上周四,我买了一个iPad 和Apple Pencil,因为Apple Pencil是一个非常好的绘图工具。我开始使用iPad的Notability应用程序,他看起来非常不凑。但是我遇到了一个不爽的事情:

我使用的Android应用程序中有很多的原始图片,但是用的格式是Squid!

Notability可以导入pdf,但它们会变成只读,你可以在其上绘制,但不能编辑它们。很烦人,不是吗?

趣味问答开始:

Julia:“我想把我的旧图纸转换到新的app里,但是没有办法做到这一点!”

Kamal:“那么如果你反向工程Notability文件格式呢?”

Julia:“呃,听起来好像需要很长时间”

Kamal:“也许只要花上一个小时,看看会发生什么!”

Julia:“好吧!”

本文旨在弄清如何将SVG转换为Notability的原生格式(.note)。这是一种专有格式,而且好像还没有人对其进行过反向工程,所以我们的从头开始。

如果你是伸手党,想直接用现成的程序SVG转换为Notability,可以参考github repo:svg2notability。它就用了不到200行的Python代码来实现。

我会写出逆向工程这个文件格式的过程,因为它并没那么困难,逆向工程往往看起来很可怕,有点不可亲近。但是我昨天就开始做了,直到今天晚上,已经做了一些成果,已经足够实际使用。

在这篇文章中,我会解释如何破解Notability的 .note格式的构的。

Ox00从.note文件开始

我从APP中导出了一个.note文件,将它放入Dropbox,并将其复制到我的Linux工作机上。这简单,这个文件是template.note。

 Ox01 解压缩文件

什么是.note文件呢?找出答案的方法就是用file命令探测他。原来它是一个zip包:


$ file template.note

template.note:Zip archive data, at least v2.0 to extract

$ unzip template.note

 解压缩到名为template /的目录中。这里是它里面的文件组成:


$ find template/

template/

template/thumbnail

template/Assets

template/Session.plist

template/thumb3x.png

template/Recordings

template/Recordings/library.plist

template/thumb2x.png

template/thumbnail2x

template/metadata.plist

template/Images

template/thumb6x.png

template/thumb.png

不错,好整洁!咦,有个.plist文件?

0×02解码.plist文件

通过谷歌(和file)搜索,我们得知.plist文件是某种苹果文件格式。谷歌显示,可以为XML格式或二进制格式。这里他是苹果二进制格式。

$ file template/Session.plist

template/Session.plist:Apple binary property list

 我但是对此有点担心,但还有一些谷歌搜索显示有一个名为plistutil的Linux工具,我可以在对其进行转化。先安装plistutil。

我吧所有的二进制.plist文件转换XML,看看它们,很清楚的表明template/ Session.plist是具有绘图数据的文件。一旦将其解码为XML,你可以看到它在这里的样子:notability_session.xml。

你怎么知道这是绘图数据的地方,Julia?那么,它的内容内容这些非常动人关键字,如“curvespoints”。比如这个:

 <key>curvespoints</key>


<data>

mgG+QjOrB0NmuUBDVT3MQgA5kUNEJIlCTBXCQ2YWDEIAT7JCM4tqQ+YFUEMzGVlDJnKj

QzOnR0Na4d5DMzU2QzMzukKafLZDM5dZQ2aDrkNmCqtDM4qmQzNJ6UMAkZ5DZpadQjPQ

A0SFx51CsM4DRHjvnUI7zQNEsRCeQrTLA0QiU55CpsgDRKl6nkJUxQNEzZqeQs3AA0Sv

rp5CEr8DRHW3nkIdvQNEM82eQma4A0RNHJ9CrqkDRNV2n0KUmANEmtGfQs2IA0QoPqBC

p3UDRJugoEINZQNEANagQs1eA0SKIaFCC1QDREOEoULIRgNEzQyiQoA1A0TpVKJCUSsD

ROCWokKvIgNEzcmiQrMdA0SVk6NCtAgDRH10pEJr9gJEzZOlQmbfAkTyaadCkrUCRFb8

qUKYewJEmjCtQmY+AkTkaLBCSQICRKEqtEIkyAFEAPi3QjOSAUS+RbtCMGMBRK6lvkKk

MwFEANDBQmYDAURBQMZCHb0ARCxqykKSdgBEzQDPQrMwAET6vtNCwdL/Q34M2UJwPv9D

mT7eQpm6/kNsXuNCcjr+QzQE6EIV2f1DM7vsQjNi/UMSDu9C6CT9Qztz8UIY4fxDmRD0

QpmY/EMwL/ZC3F/8Q0Fu+EKoJPxDM8L6Qmbl+0N9tf1Ck5P7Q6JnAENsOvtDmu4BQ5nf

+kOgxgJDQK36Q0OWA0MCe/pDmmQEQ5lF+kNbgQVDQ/v5Q6yaBkMkr/lDZr0HQzNk+UPB

</data>

有人可能会认为这个“curvespoint”数据代表了文件中曲线上的点。答对了:它的就是。

 0×03解码曲线上的点

这听起来很直接,但在实际的工作中,这是让我最头疼,最讨厌的部分。以下是我如何解读这个“curvespoints”的内容:

 1.发现他是base 64编码。这一部分很简单:我之前使用过base64编码数据,二进制数据通常是在文本文件中编码的。酷!

2.在hexdump中的查看他数据

3.混淆(“这只是随机字节?!!?我怎么知道这意味着什么?”)

4.试着看看它是否是msgback(no),bencode(no)。感到困惑。抱怨。重复一个小时左右。

5.最后,等等,突然想到,如果它只是一个32位浮点数阵列?这将是简单的,好像有道理的!。

6.尝试将其解码为32位浮点数组

7.OK,他工作正常。


importsubprocess

importplistlib

importstruct

 

defunpack_struct(string, fmt):

    returnstruct.unpack(‘{num}{format}’.format(num=len(string)/4, format=fmt), string)

 

plistlib.readPlistFromString(subprocess.check_output(['plistutil','-i', 'file.plist']))

curves_points= pl['$objects'][8]['curvespoints'].data

unpack_struct(curvespoints,’f')

这里有一些来自于我文件的浮点数。这些看起来非常清晰,就是曲线上的点:它是一个浮点数组,每个连续2个浮点组都是曲线上的一个点。干的好!


(407.59869384765625,

 396.6827087402344,

 408.05926513671875,

 396.3546447753906,

 408.2127990722656,

 396.2452697753906,

 408.3787536621094,

 396.1249084472656,

 408.55938720703125,

 395.9921875)

0×04解码其他字段

解码其他字段很简单:

curvenumpoints:32位整数数组,它是每条曲线上的点数(unpack_structcurves ['curvesnumpoints'].Data, ‘i’)),

curveswidth:32位浮点数组,每条曲线的厚度

curvescolors:32位RGBA值的数组(0x00FFEEFF是十六进制代码#00FFEE,最后一位是不透明度)

curvesfractionalwidths:可变长度曲线的宽度乘数。我不关心这些,我把它们全部设置为1.0。

eventTokens:不确定,我只是将所有这些设置为浮点数1.0,它似乎都工作正常

0×05在图上绘制点数

 

为了确保这些点实际上是点,我要把他们绘制在图上,在本例中,我实际上是使用了一个源于zine的关于你和你经理的对话。以下是它的样子:

1.png

非常酷!!!!我对我的成功感到非常激动。于是下午5点,我有时间去朋友家吃晚饭,所以我这样做了。

0×06生成.note文件

好的,现在我们有一些眉头,我们知道这个文件格式是如何运作的。我们如何生成这种格式的文件呢?

 基本的步骤如下:

1、从现有的空的.note文件开始。

2、除了Session.plist文件(绘图数据所在的位置)之外,所有内容都保持一致。

3、设置curvesnumpointscurveswidthcurvescolors等数据

4、将它用Zip打包,将其导入我的app,并希望它能正常工作!

 有一种debug策略帮助我一路成功,那就是我尝试重新生成已有的.plist文件。我得到了我认为它表达的点的列表,并且自己生成了curvesnumpoints等字段,并确保它们与Notability对这些文件的真实数据相匹配。然后我进行单元测试!

一路上有很多奇怪的工件和错误,但是这篇博文已经很长了,我不认为解释这个很有趣。

0×07 结果

结果如下!首先,我输入到我的svg2notability程序中的SVG如下所示:

2.png

在我转换它之后,它在Notability中!它看起来基本相同!而且我可以轻松编辑它,这就是要点。颜色,样式等一切都正常!

3.png

0×08未尽的部分

1、生成具有多个页面的文档(没有尝试)

2、绘制正方形,我的一些绘图有完美的正方形,并且还有一个问题,我还没有制定出来

3、在Notability中更改纸张尺寸以匹配原始纸张尺寸。相反,我只是缩放宽度以匹配Notability的默认纸张宽度,这已经可以了,但还可以更好。

 0×09后记

 我认为使逆向工程不那么难的事情是,开发人员重复使用代码!人们通常不会发明完全自定义的文件格式!这里没有任何东西真的很复杂,它只是一些现有的标准格式(zip,苹果plist,一组浮点数数组)以非常简单的方式组合在一起。

 这个事情很有趣,从一个看似棘手或非常繁重的任务开始, “等等,我是一名程序员!!”,并设法使用编程的力量来达成我想做的事情(至少是这样)!

我发现所有这些移动绘图应用程序(Squid,Notability,Goodnotes等)都使用专有文件格式,如果没有逆向工程,就不能在对其互相转换。但逆向工程是就可以! squid_decoder反向工程了Squid格式(它基本上是一个谷歌缓冲协议)

 如果你想觉得看文章费劲,直接看代码:  https://github.com/jvns/svg2notability。

1.png

根据Under Armour周四透露,大约1.5亿MyFitnessPal应用用户可能受2月份发生的数据泄露的影响。 UnderArmour表示,在意识到未经授权的者访问了MyFitnessPal数据之后,上周日已经查明了违规行为。泄露的数据可能包括用户名,电子邮件地址和密码哈希等信息,但是不涉及支付信息。 MyFitnessPal表示,会通知受影响的用户有关泄密时间,让他们修改密码,并会建议他们更改其他可能用过此账号和密码的平台的相关信息。

MyFitnessPal应用程序会存储大量详细的个人隐私信息和地理数据,可用于查询和跟踪个人。获得这些信息后,黑客可以会利用它组件社工数据库,来进行人肉和追踪个人信息。根据MyFitnessPal隐私政策显示,他可以收集用户的精确位置信息和性能数据。

关于MyFitnessPal

MyFitnessPal是安卓系统的最好,最流行的健身APP,这款软件拥有安卓上最全面的食品数据库及运动项目资料,用户可以很方便的保存和添加每天的膳食,制定每天的健身计划,健身饮食数据还通过网络上次。国内也有大量用户在用这款APP。

2.png

攻击途径未查明,安全实践较好

5.png

目前还没有具体数据被窃取的详细途径,有1.5亿用户受到影响,这是有记录以来最大的泄露之一。

好在Under Armour和MyFitnessPal在数据安全上做还比较好,这些好的实践可以作为其他公司做的借鉴:

支付信息与一般用户信息保持分开,一般用户信息与用户上传的应用程序数据分开存储

 UnderArmour在得知数据泄露事件后几天后似乎也迅速做出了反应,并在几天后向用户和公众发出,这与其他公司(如优步、雅虎)通过付费给黑客隐瞒了数据泄露事件形成了鲜明的对比。

给个人的启迪?

4.png

通过此事件我们要意识到,被黑客攻克不是能不能的问题而是什么时候的问题。

无论你是看起来多么微不足道,你个人数据都容易被黑客拿到。所有智能手机,智能手表、手环等可穿戴设备和相关的APP,每天都会收集大量的关于我们生活的数据项。你的卡路里摄入、你步数对黑客来说没有啥意义。但与健身追踪器收集的其他信息配合使用,例如你在哪里工作、离家多久了,在不在家,通过大数据和统计方法,甚至是大数据,可以帮黑客或者别有用心的公司描绘出来,注意电影里演的不全是科幻,而是现实、现实、现实!

1.png

根据Under Armour周四透露,大约1.5亿MyFitnessPal应用用户可能受2月份发生的数据泄露的影响。 UnderArmour表示,在意识到未经授权的者访问了MyFitnessPal数据之后,上周日已经查明了违规行为。泄露的数据可能包括用户名,电子邮件地址和密码哈希等信息,但是不涉及支付信息。 MyFitnessPal表示,会通知受影响的用户有关泄密时间,让他们修改密码,并会建议他们更改其他可能用过此账号和密码的平台的相关信息。

MyFitnessPal应用程序会存储大量详细的个人隐私信息和地理数据,可用于查询和跟踪个人。获得这些信息后,黑客可以会利用它组件社工数据库,来进行人肉和追踪个人信息。根据MyFitnessPal隐私政策显示,他可以收集用户的精确位置信息和性能数据。

关于MyFitnessPal

MyFitnessPal是安卓系统的最好,最流行的健身APP,这款软件拥有安卓上最全面的食品数据库及运动项目资料,用户可以很方便的保存和添加每天的膳食,制定每天的健身计划,健身饮食数据还通过网络上次。国内也有大量用户在用这款APP。

2.png

攻击途径未查明,安全实践较好

5.png

目前还没有具体数据被窃取的详细途径,有1.5亿用户受到影响,这是有记录以来最大的泄露之一。

好在Under Armour和MyFitnessPal在数据安全上做还比较好,这些好的实践可以作为其他公司做的借鉴:

支付信息与一般用户信息保持分开,一般用户信息与用户上传的应用程序数据分开存储

 UnderArmour在得知数据泄露事件后几天后似乎也迅速做出了反应,并在几天后向用户和公众发出,这与其他公司(如优步、雅虎)通过付费给黑客隐瞒了数据泄露事件形成了鲜明的对比。

给个人的启迪?

4.png

通过此事件我们要意识到,被黑客攻克不是能不能的问题而是什么时候的问题。

无论你是看起来多么微不足道,你个人数据都容易被黑客拿到。所有智能手机,智能手表、手环等可穿戴设备和相关的APP,每天都会收集大量的关于我们生活的数据项。你的卡路里摄入、你步数对黑客来说没有啥意义。但与健身追踪器收集的其他信息配合使用,例如你在哪里工作、离家多久了,在不在家,通过大数据和统计方法,甚至是大数据,可以帮黑客或者别有用心的公司描绘出来,注意电影里演的不全是科幻,而是现实、现实、现实!

本文笔者翻译自hacker博客,原文地址:(https://medium.com/@a.nikishaev/how-i-hacked-xiaomi-miband-2-to-control-it-from-linux-a5bd2f36d3ad)
00.png

这个故事源于我在Facebook一个帖子,帖子中讨论了运动健身追踪器都缺乏API接口的问题,还有为啥不用它帮助数据专家为做一个炫酷的东西。

帖子发出之后,我的好基友Volodymyr Shymanskyy就响应来帮助我,并在github上找了Leo Soares项目,为我的健身追踪器小米手环2找了一些代码。他尝试运行它,但是连接出现了一些链接问题,所以他花了几个小时修复了他。之后,他提交了个commit,并给了我链接。

那满足了我的初步需求,已经相当OK了。那代码可以连接到手环,发布通知,并获取一次拍摄心脏测量。但这对我来说还有点不够,因为我想从传感器获得实时原始数据,以便在我的数据科学实验中使用(想要做一个健身运动预测器)。

正文才开始……

在此之前,我没有任何使用蓝牙设备的经验,所以首先我试着了解了所有这些东西是如何组织和工作的。事实证明,也没啥难得。

每个蓝牙设备都会启动几个的服务,每个服务都有特征,并且一些特征具有描述符(如果特征有多个参数或工作类型(阅读|通知))。某些特性只有读/写访问权限,比如当前时间,电池状态或修订信息。其中一些更复杂并且通过请求/通知循环工作,例如实时心率监视器和授权。基本上,你需要知道这一切的,才能开始使用它。

您还需要两个应用程序来帮助调试蓝牙设备:Wireshark和BLE debugger。你还需要需要访问安卓手机开发者选项(对不起,对于iOS家伙我还不知道如何做到这点)。

首先,您需要从手机应用程序中取消小米手环2的配对。

现在让我们看看手环有什么服务和特征。让我们打开BLE debugger,开始扫描,你会看到类似这样的东西:

01.png

将设备的MAC地址保存下,后续操作会用到它。

现在让我们连接它,看看它跑了什么服务和特征。

02.png

以上两个简单的操作中,我们已经获得了一些有用的设备信息。

另一种方法是使用控制台工具hcitool和gatttool。

Scan:

sudo hcitool lescan

连接并获取服务和描述符:


sudo gatttool -b YOUR_MAC -I -t random

> connect

> primary

> char-desc

在某些情况下,BLE栈可能会出现故障,您可以打开/关闭蓝牙或运行以下命令:

sudo hciconfig hci0 reset

数据嗅探

为了我们的手机<->基带通信中嗅探数据,我们需要启用蓝牙在开发设置记录日志。要做到这一点,您需要先打开安卓手机上的开发人员设置。

以下是操作的详细步骤:

在Android 4.1及更低版本上,开发者选项屏幕默认可用。在Android 4.2及更高版本中,您必须按如下所示启用此屏幕:

1.打开手机设置

2.(仅适用于Android 8.0或更高版本)选择系统

3.滚动到底部并选择关于手机

4.滚动到底部并点击Build number 7次。

5.返回到上一屏幕以查找底部附近的开发人员选项

现在打开开发设置并找到“启用BleutoothHCI snoop log”并启用它。这样,所有蓝牙通信都会被被记录。然后你需要找到名为btsnoop_hci.log的文件(在我手机中(Android 7.0)它位于/mtklog/btlog/btsnoop_hci.log)

认证

现在我们还要要执行一下步骤来获取有关认证(配对)如何工作的一些信息。

1.打开蓝牙和HCI日志。

2.将您的设备与小米安卓程序配对。

3.关闭蓝牙。

4. 下载btsnoop_hci.log到你的电脑。

5.用Wireshark打开它。

6.找到第一个处理0×0055的ATT协议请求

你会看到如图的界面:

1.png

这是验证步骤:

配对设备

主要服务UUID

0000fee1-0000–1000–8000–00805f9b34fb

认证特征 (Char) UUID 

00000009–0000–3512–2118–0009af100700

通知描述符 (Des) 处理

0×2902 (所有的过程都一样)

1.通过向Des发送2个字节请求 \x01\x00来设置auth通知(以获得响应)。

2.用命令将16字节的加密密钥发送给Char,并附加2字节\x01\x00 + KEY

3.通过发送2个字节\x02\x00到Char来向设备请求带有命令的随机密钥。

4.从设备响应中获取随机密钥(最后的16个字节)。

5.使用我们的16字节密钥,用AES/ECB/ NoPadding(来自Crypto.Cipher import AES)对此随机数进行加密,并将其发送回Char(\x03\x00+编码数据

认证

1.通过发送2个字节\x02 \x00到Char来向设备请求带有命令的随机密钥。

2.从设备响应中获取随机密钥(最后16个字节)。

3.使用我们的16字节密钥和使用AES / ECB / NoPadding(来自Crypto.Cipher import AES)对此随机数进行加密,并将其发送回Char(\ x03 \ x00 +编码数据)

实时数据

这在认证过程中稍微复杂一些,因为我没有看到在这个过程中犯了一个错误:)并且因为这个心率监视器在15秒后关闭。

硬件服务(HRDW)UUID

0000fee0-0000-1000-8000-00805f9b34fb

心脏监护仪服务(HMS)UUID

 0000180d-0000-1000-8000-00805f9b34fb

心率测量特征(HRM)UUID

00002a37-0000-1000-8000-00805f9b34fb

心脏监护仪控制特性(HMC)UUID

00002a39-0000-1000-8000-00805f9b34fb

传感器特性(SENS)UUID

00000001-0000-3512-2118-0009af100700

通知描述符(DES)句柄

0×2902(所有过程都一样)

1.关闭当前监听的测量。

2. 通过向HMC发送请求\x15\x02\x00进行一次性测量。

3. 通过向HMC发送请求\x15\x01\x00进行连续测量。

4.通过向SENS发送命令到\x01\x03\x19来启用陀螺仪和心脏原始数据

5.通过向HRM写入DES \x01\ x00启用通知

6.通过向HMC发送请求\x15\x01\x01来启动连续的心脏测量

7.发送命令到SENS \x02(不知道为什么需要这指令)

8.然后,在每12秒收到一次通知时,需要将\x16 ping发送到HCM

解析数据

这是最枯燥部分,因为基本上你需要找出如何解包来自设备的打包数据。

它的一部分可以从日志中解析出来,有些不能。

2.png

这是当前时间的设备的响应

找到合适的数据包和编码可能需要一些时间。就我的例子而言,我需要找到相邻的数据包中相似的字节出现次数,有些重复的数据包。


Raw heart: 02102d8c348c448c458c3d8c428c488c 16

Raw heart: 0218468c418c3d8c468c3f8c398c418c 16

Realtime heart: 93

Raw heart: 0220408c448c3f8c428c498c3c8c3d8c 16

Raw heart: 02283d8c398c488c3e8c468c488c328c 16

Realtime heart: 99

Raw heart: 0230438c408c378c3a8c318c458c388c 16

Realtime heart: 102

Raw heart: 02404f8c408c458c428c4d8c558c4d8c 16

Raw heart: 02483e8c3b8c3f8c348c398c318c428c 16

Realtime heart: 98

Raw heart: 02504c8c428c5e8c4f8c588c498c558c 16

Raw heart: 0258478c458c3c8c4e8c3f8c468c4d8c 16

Realtime heart: 100

Raw heart: 0260518c4d8c4f8c4b8c4f8c528c458c 16

Raw heart: 0268408c3f8c538c4d8c408c548c598c 16

Realtime heart: 102

Raw heart: 0278418c508c4e8c548c588c468c498c 16

Raw heart: 0280368c328c2e8c3c8c338c308c3f8c 16

Realtime heart: 101

从中我们可以看到清晰的数据,重复368c 328c 2e8c 3c8c 338c 308c 3f8c,数据包长度为16字节。因此,如果我们用2个字节的无符号短数据解压缩,那么我们可以得到7个心脏传感器的原始测量结果。我们也看到第二个字节只是迭代,我认为它只是测量之间的时间差异(我指的是响应的时间差)


Raw gyro: 01de49ffd9ff3c004cffd8ff3b004dffdcff4400

Raw gyro: 01df4cffd6ff44004dffd8ff40004cffd1ff4700

Raw gyro: 02e1103231323d3274328e329632af32c732cf32

Raw gyro: 01e34fffd7ff56004bffc7ff590049ffccff4c00

Raw gyro: 01e443ffccff43004effcdff40005bffd4ff4c00

Raw gyro: 01e558ffc9ff5f005effbfff66005fffb0ff5900

Raw gyro: 01e64cffacff60005cffa7ff410066ffc9ff4600

Raw gyro: 01e760ffdcff4b0051ffe4ff4f0034ffdeff5300

Raw gyro: 02e903365c36813663361036543688374139fe3a

Raw gyro: 01eb4bffc3ff50004fffc1ff430047ffbbff4100

Raw gyro: 01ec3effb2ff3c0050ffbfff560047ffccff7300

Raw gyro: 01ed4fffe0ff78005cffebff8e0056fff6ff8300

Raw gyro: 01ee7efffbffa1008bff0f00bc00b1ff1900b800

Raw gyro: 01ef9bff0c00d10095fff3ffd600b7ff0800df00

Raw gyro: 02f12445314600479e473348aa481c499749244a

Raw gyro: 01f3c3ff1600fe00beff1800f200a6ff0800e700

Raw gyro: 01f4a9fff8ffd300a7fff3ffd700a9fff1ffdf00

Raw gyro: 01f5b1fff8ffe800b4fff1fff700acfffcffef00

Raw gyro: 01f67ffff7ffc0006bfff4ffb00078ffe9ffb600

Raw gyro: 01f786ffecffc0006ffff0ffbc0060fff1ffc000

Raw gyro: 02f9ca4cbb4c784c964ca84c784c854c444c1b4c

Raw gyro: 01fb7cff0f00bb007eff2700ae0083ff30009800

Raw gyro: 01fc79ff1800b00076ff0f00bc0068ff0900d900

Raw gyro: 01fd78ff07000c01f6fffbff19011c000b00f600

Raw gyro: 01fe4b001100d30054000700c3004300efffeb00

Raw gyro: 01ff1f00d0ff1701fbffe8ff1b01e3ffffff1101

Raw gyro: 0201214b014bec4ad04aba4acb4abe4aba4abd4a

Raw gyro: 0103efffecfffc00e3fff3fff300defff3fffc00

Raw gyro: 0104e3fff0fff400e6ffefff0301dbffe9ff0c01

Raw gyro: 0105e3fff0ff0301e6ffe6fffc00dcffecfffc00

Raw gyro: 0106dffff0fff700dbffeefff600d6fff0fff400

Raw gyro: 0107dfffecffff00e1fff0ff0301defff3fffc00

至于陀螺仪,就有点困难。但是我的想法是它应该与心脏数据类似的方式打包,但在这种情况下,我们对每个应该签名的陀螺仪轴进行3次测量,数据包长度为20个字节。因此,12 x,y,z测量不会覆盖所有包,但3将会保留前2个字节(与之前的包相同)。所以我这样试了,过不然工作是正常的。

代码

代码,你可以找到我的github仓库(https://github.com/creotiv/MiBand2)下载所有的代码,所有代码使用python实现。老司机们应该都知道怎么做,在此就不多赘述。
原作者可能是个毛子,如果你们觉得他的思路对你有用,可以给他捐点钱,卖酒喝(他自己的话,github里面可捐款)。

本文笔者翻译自hacker博客,原文地址:(https://medium.com/@a.nikishaev/how-i-hacked-xiaomi-miband-2-to-control-it-from-linux-a5bd2f36d3ad)
00.png

这个故事源于我在Facebook一个帖子,帖子中讨论了运动健身追踪器都缺乏API接口的问题,还有为啥不用它帮助数据专家为做一个炫酷的东西。

帖子发出之后,我的好基友Volodymyr Shymanskyy就响应来帮助我,并在github上找了Leo Soares项目,为我的健身追踪器小米手环2找了一些代码。他尝试运行它,但是连接出现了一些链接问题,所以他花了几个小时修复了他。之后,他提交了个commit,并给了我链接。

那满足了我的初步需求,已经相当OK了。那代码可以连接到手环,发布通知,并获取一次拍摄心脏测量。但这对我来说还有点不够,因为我想从传感器获得实时原始数据,以便在我的数据科学实验中使用(想要做一个健身运动预测器)。

正文才开始……

在此之前,我没有任何使用蓝牙设备的经验,所以首先我试着了解了所有这些东西是如何组织和工作的。事实证明,也没啥难得。

每个蓝牙设备都会启动几个的服务,每个服务都有特征,并且一些特征具有描述符(如果特征有多个参数或工作类型(阅读|通知))。某些特性只有读/写访问权限,比如当前时间,电池状态或修订信息。其中一些更复杂并且通过请求/通知循环工作,例如实时心率监视器和授权。基本上,你需要知道这一切的,才能开始使用它。

您还需要两个应用程序来帮助调试蓝牙设备:Wireshark和BLE debugger。你还需要需要访问安卓手机开发者选项(对不起,对于iOS家伙我还不知道如何做到这点)。

首先,您需要从手机应用程序中取消小米手环2的配对。

现在让我们看看手环有什么服务和特征。让我们打开BLE debugger,开始扫描,你会看到类似这样的东西:

01.png

将设备的MAC地址保存下,后续操作会用到它。

现在让我们连接它,看看它跑了什么服务和特征。

02.png

以上两个简单的操作中,我们已经获得了一些有用的设备信息。

另一种方法是使用控制台工具hcitool和gatttool。

Scan:

sudo hcitool lescan

连接并获取服务和描述符:


sudo gatttool -b YOUR_MAC -I -t random

> connect

> primary

> char-desc

在某些情况下,BLE栈可能会出现故障,您可以打开/关闭蓝牙或运行以下命令:

sudo hciconfig hci0 reset

数据嗅探

为了我们的手机<->基带通信中嗅探数据,我们需要启用蓝牙在开发设置记录日志。要做到这一点,您需要先打开安卓手机上的开发人员设置。

以下是操作的详细步骤:

在Android 4.1及更低版本上,开发者选项屏幕默认可用。在Android 4.2及更高版本中,您必须按如下所示启用此屏幕:

1.打开手机设置

2.(仅适用于Android 8.0或更高版本)选择系统

3.滚动到底部并选择关于手机

4.滚动到底部并点击Build number 7次。

5.返回到上一屏幕以查找底部附近的开发人员选项

现在打开开发设置并找到“启用BleutoothHCI snoop log”并启用它。这样,所有蓝牙通信都会被被记录。然后你需要找到名为btsnoop_hci.log的文件(在我手机中(Android 7.0)它位于/mtklog/btlog/btsnoop_hci.log)

认证

现在我们还要要执行一下步骤来获取有关认证(配对)如何工作的一些信息。

1.打开蓝牙和HCI日志。

2.将您的设备与小米安卓程序配对。

3.关闭蓝牙。

4. 下载btsnoop_hci.log到你的电脑。

5.用Wireshark打开它。

6.找到第一个处理0×0055的ATT协议请求

你会看到如图的界面:

1.png

这是验证步骤:

配对设备

主要服务UUID

0000fee1-0000–1000–8000–00805f9b34fb

认证特征 (Char) UUID 

00000009–0000–3512–2118–0009af100700

通知描述符 (Des) 处理

0×2902 (所有的过程都一样)

1.通过向Des发送2个字节请求 \x01\x00来设置auth通知(以获得响应)。

2.用命令将16字节的加密密钥发送给Char,并附加2字节\x01\x00 + KEY

3.通过发送2个字节\x02\x00到Char来向设备请求带有命令的随机密钥。

4.从设备响应中获取随机密钥(最后的16个字节)。

5.使用我们的16字节密钥,用AES/ECB/ NoPadding(来自Crypto.Cipher import AES)对此随机数进行加密,并将其发送回Char(\x03\x00+编码数据

认证

1.通过发送2个字节\x02 \x00到Char来向设备请求带有命令的随机密钥。

2.从设备响应中获取随机密钥(最后16个字节)。

3.使用我们的16字节密钥和使用AES / ECB / NoPadding(来自Crypto.Cipher import AES)对此随机数进行加密,并将其发送回Char(\ x03 \ x00 +编码数据)

实时数据

这在认证过程中稍微复杂一些,因为我没有看到在这个过程中犯了一个错误:)并且因为这个心率监视器在15秒后关闭。

硬件服务(HRDW)UUID

0000fee0-0000-1000-8000-00805f9b34fb

心脏监护仪服务(HMS)UUID

 0000180d-0000-1000-8000-00805f9b34fb

心率测量特征(HRM)UUID

00002a37-0000-1000-8000-00805f9b34fb

心脏监护仪控制特性(HMC)UUID

00002a39-0000-1000-8000-00805f9b34fb

传感器特性(SENS)UUID

00000001-0000-3512-2118-0009af100700

通知描述符(DES)句柄

0×2902(所有过程都一样)

1.关闭当前监听的测量。

2. 通过向HMC发送请求\x15\x02\x00进行一次性测量。

3. 通过向HMC发送请求\x15\x01\x00进行连续测量。

4.通过向SENS发送命令到\x01\x03\x19来启用陀螺仪和心脏原始数据

5.通过向HRM写入DES \x01\ x00启用通知

6.通过向HMC发送请求\x15\x01\x01来启动连续的心脏测量

7.发送命令到SENS \x02(不知道为什么需要这指令)

8.然后,在每12秒收到一次通知时,需要将\x16 ping发送到HCM

解析数据

这是最枯燥部分,因为基本上你需要找出如何解包来自设备的打包数据。

它的一部分可以从日志中解析出来,有些不能。

2.png

这是当前时间的设备的响应

找到合适的数据包和编码可能需要一些时间。就我的例子而言,我需要找到相邻的数据包中相似的字节出现次数,有些重复的数据包。


Raw heart: 02102d8c348c448c458c3d8c428c488c 16

Raw heart: 0218468c418c3d8c468c3f8c398c418c 16

Realtime heart: 93

Raw heart: 0220408c448c3f8c428c498c3c8c3d8c 16

Raw heart: 02283d8c398c488c3e8c468c488c328c 16

Realtime heart: 99

Raw heart: 0230438c408c378c3a8c318c458c388c 16

Realtime heart: 102

Raw heart: 02404f8c408c458c428c4d8c558c4d8c 16

Raw heart: 02483e8c3b8c3f8c348c398c318c428c 16

Realtime heart: 98

Raw heart: 02504c8c428c5e8c4f8c588c498c558c 16

Raw heart: 0258478c458c3c8c4e8c3f8c468c4d8c 16

Realtime heart: 100

Raw heart: 0260518c4d8c4f8c4b8c4f8c528c458c 16

Raw heart: 0268408c3f8c538c4d8c408c548c598c 16

Realtime heart: 102

Raw heart: 0278418c508c4e8c548c588c468c498c 16

Raw heart: 0280368c328c2e8c3c8c338c308c3f8c 16

Realtime heart: 101

从中我们可以看到清晰的数据,重复368c 328c 2e8c 3c8c 338c 308c 3f8c,数据包长度为16字节。因此,如果我们用2个字节的无符号短数据解压缩,那么我们可以得到7个心脏传感器的原始测量结果。我们也看到第二个字节只是迭代,我认为它只是测量之间的时间差异(我指的是响应的时间差)


Raw gyro: 01de49ffd9ff3c004cffd8ff3b004dffdcff4400

Raw gyro: 01df4cffd6ff44004dffd8ff40004cffd1ff4700

Raw gyro: 02e1103231323d3274328e329632af32c732cf32

Raw gyro: 01e34fffd7ff56004bffc7ff590049ffccff4c00

Raw gyro: 01e443ffccff43004effcdff40005bffd4ff4c00

Raw gyro: 01e558ffc9ff5f005effbfff66005fffb0ff5900

Raw gyro: 01e64cffacff60005cffa7ff410066ffc9ff4600

Raw gyro: 01e760ffdcff4b0051ffe4ff4f0034ffdeff5300

Raw gyro: 02e903365c36813663361036543688374139fe3a

Raw gyro: 01eb4bffc3ff50004fffc1ff430047ffbbff4100

Raw gyro: 01ec3effb2ff3c0050ffbfff560047ffccff7300

Raw gyro: 01ed4fffe0ff78005cffebff8e0056fff6ff8300

Raw gyro: 01ee7efffbffa1008bff0f00bc00b1ff1900b800

Raw gyro: 01ef9bff0c00d10095fff3ffd600b7ff0800df00

Raw gyro: 02f12445314600479e473348aa481c499749244a

Raw gyro: 01f3c3ff1600fe00beff1800f200a6ff0800e700

Raw gyro: 01f4a9fff8ffd300a7fff3ffd700a9fff1ffdf00

Raw gyro: 01f5b1fff8ffe800b4fff1fff700acfffcffef00

Raw gyro: 01f67ffff7ffc0006bfff4ffb00078ffe9ffb600

Raw gyro: 01f786ffecffc0006ffff0ffbc0060fff1ffc000

Raw gyro: 02f9ca4cbb4c784c964ca84c784c854c444c1b4c

Raw gyro: 01fb7cff0f00bb007eff2700ae0083ff30009800

Raw gyro: 01fc79ff1800b00076ff0f00bc0068ff0900d900

Raw gyro: 01fd78ff07000c01f6fffbff19011c000b00f600

Raw gyro: 01fe4b001100d30054000700c3004300efffeb00

Raw gyro: 01ff1f00d0ff1701fbffe8ff1b01e3ffffff1101

Raw gyro: 0201214b014bec4ad04aba4acb4abe4aba4abd4a

Raw gyro: 0103efffecfffc00e3fff3fff300defff3fffc00

Raw gyro: 0104e3fff0fff400e6ffefff0301dbffe9ff0c01

Raw gyro: 0105e3fff0ff0301e6ffe6fffc00dcffecfffc00

Raw gyro: 0106dffff0fff700dbffeefff600d6fff0fff400

Raw gyro: 0107dfffecffff00e1fff0ff0301defff3fffc00

至于陀螺仪,就有点困难。但是我的想法是它应该与心脏数据类似的方式打包,但在这种情况下,我们对每个应该签名的陀螺仪轴进行3次测量,数据包长度为20个字节。因此,12 x,y,z测量不会覆盖所有包,但3将会保留前2个字节(与之前的包相同)。所以我这样试了,过不然工作是正常的。

代码

代码,你可以找到我的github仓库(https://github.com/creotiv/MiBand2)下载所有的代码,所有代码使用python实现。老司机们应该都知道怎么做,在此就不多赘述。
原作者可能是个毛子,如果你们觉得他的思路对你有用,可以给他捐点钱,卖酒喝(他自己的话,github里面可捐款)。

本文笔者翻译自hacker博客,原文地址:(https://medium.com/@a.nikishaev/how-i-hacked-xiaomi-miband-2-to-control-it-from-linux-a5bd2f36d3ad)
00.png

这个故事源于我在Facebook一个帖子,帖子中讨论了运动健身追踪器都缺乏API接口的问题,还有为啥不用它帮助数据专家为做一个炫酷的东西。

帖子发出之后,我的好基友Volodymyr Shymanskyy就响应来帮助我,并在github上找了Leo Soares项目,为我的健身追踪器小米手环2找了一些代码。他尝试运行它,但是连接出现了一些链接问题,所以他花了几个小时修复了他。之后,他提交了个commit,并给了我链接。

那满足了我的初步需求,已经相当OK了。那代码可以连接到手环,发布通知,并获取一次拍摄心脏测量。但这对我来说还有点不够,因为我想从传感器获得实时原始数据,以便在我的数据科学实验中使用(想要做一个健身运动预测器)。

正文才开始……

在此之前,我没有任何使用蓝牙设备的经验,所以首先我试着了解了所有这些东西是如何组织和工作的。事实证明,也没啥难得。

每个蓝牙设备都会启动几个的服务,每个服务都有特征,并且一些特征具有描述符(如果特征有多个参数或工作类型(阅读|通知))。某些特性只有读/写访问权限,比如当前时间,电池状态或修订信息。其中一些更复杂并且通过请求/通知循环工作,例如实时心率监视器和授权。基本上,你需要知道这一切的,才能开始使用它。

您还需要两个应用程序来帮助调试蓝牙设备:Wireshark和BLE debugger。你还需要需要访问安卓手机开发者选项(对不起,对于iOS家伙我还不知道如何做到这点)。

首先,您需要从手机应用程序中取消小米手环2的配对。

现在让我们看看手环有什么服务和特征。让我们打开BLE debugger,开始扫描,你会看到类似这样的东西:

01.png

将设备的MAC地址保存下,后续操作会用到它。

现在让我们连接它,看看它跑了什么服务和特征。

02.png

以上两个简单的操作中,我们已经获得了一些有用的设备信息。

另一种方法是使用控制台工具hcitool和gatttool。

Scan:

sudo hcitool lescan

连接并获取服务和描述符:


sudo gatttool -b YOUR_MAC -I -t random

> connect

> primary

> char-desc

在某些情况下,BLE栈可能会出现故障,您可以打开/关闭蓝牙或运行以下命令:

sudo hciconfig hci0 reset

数据嗅探

为了我们的手机<->基带通信中嗅探数据,我们需要启用蓝牙在开发设置记录日志。要做到这一点,您需要先打开安卓手机上的开发人员设置。

以下是操作的详细步骤:

在Android 4.1及更低版本上,开发者选项屏幕默认可用。在Android 4.2及更高版本中,您必须按如下所示启用此屏幕:

1.打开手机设置

2.(仅适用于Android 8.0或更高版本)选择系统

3.滚动到底部并选择关于手机

4.滚动到底部并点击Build number 7次。

5.返回到上一屏幕以查找底部附近的开发人员选项

现在打开开发设置并找到“启用BleutoothHCI snoop log”并启用它。这样,所有蓝牙通信都会被被记录。然后你需要找到名为btsnoop_hci.log的文件(在我手机中(Android 7.0)它位于/mtklog/btlog/btsnoop_hci.log)

认证

现在我们还要要执行一下步骤来获取有关认证(配对)如何工作的一些信息。

1.打开蓝牙和HCI日志。

2.将您的设备与小米安卓程序配对。

3.关闭蓝牙。

4. 下载btsnoop_hci.log到你的电脑。

5.用Wireshark打开它。

6.找到第一个处理0×0055的ATT协议请求

你会看到如图的界面:

1.png

这是验证步骤:

配对设备

主要服务UUID

0000fee1-0000–1000–8000–00805f9b34fb

认证特征 (Char) UUID 

00000009–0000–3512–2118–0009af100700

通知描述符 (Des) 处理

0×2902 (所有的过程都一样)

1.通过向Des发送2个字节请求 \x01\x00来设置auth通知(以获得响应)。

2.用命令将16字节的加密密钥发送给Char,并附加2字节\x01\x00 + KEY

3.通过发送2个字节\x02\x00到Char来向设备请求带有命令的随机密钥。

4.从设备响应中获取随机密钥(最后的16个字节)。

5.使用我们的16字节密钥,用AES/ECB/ NoPadding(来自Crypto.Cipher import AES)对此随机数进行加密,并将其发送回Char(\x03\x00+编码数据

认证

1.通过发送2个字节\x02 \x00到Char来向设备请求带有命令的随机密钥。

2.从设备响应中获取随机密钥(最后16个字节)。

3.使用我们的16字节密钥和使用AES / ECB / NoPadding(来自Crypto.Cipher import AES)对此随机数进行加密,并将其发送回Char(\ x03 \ x00 +编码数据)

实时数据

这在认证过程中稍微复杂一些,因为我没有看到在这个过程中犯了一个错误:)并且因为这个心率监视器在15秒后关闭。

硬件服务(HRDW)UUID

0000fee0-0000-1000-8000-00805f9b34fb

心脏监护仪服务(HMS)UUID

 0000180d-0000-1000-8000-00805f9b34fb

心率测量特征(HRM)UUID

00002a37-0000-1000-8000-00805f9b34fb

心脏监护仪控制特性(HMC)UUID

00002a39-0000-1000-8000-00805f9b34fb

传感器特性(SENS)UUID

00000001-0000-3512-2118-0009af100700

通知描述符(DES)句柄

0×2902(所有过程都一样)

1.关闭当前监听的测量。

2. 通过向HMC发送请求\x15\x02\x00进行一次性测量。

3. 通过向HMC发送请求\x15\x01\x00进行连续测量。

4.通过向SENS发送命令到\x01\x03\x19来启用陀螺仪和心脏原始数据

5.通过向HRM写入DES \x01\ x00启用通知

6.通过向HMC发送请求\x15\x01\x01来启动连续的心脏测量

7.发送命令到SENS \x02(不知道为什么需要这指令)

8.然后,在每12秒收到一次通知时,需要将\x16 ping发送到HCM

解析数据

这是最枯燥部分,因为基本上你需要找出如何解包来自设备的打包数据。

它的一部分可以从日志中解析出来,有些不能。

2.png

这是当前时间的设备的响应

找到合适的数据包和编码可能需要一些时间。就我的例子而言,我需要找到相邻的数据包中相似的字节出现次数,有些重复的数据包。


Raw heart: 02102d8c348c448c458c3d8c428c488c 16

Raw heart: 0218468c418c3d8c468c3f8c398c418c 16

Realtime heart: 93

Raw heart: 0220408c448c3f8c428c498c3c8c3d8c 16

Raw heart: 02283d8c398c488c3e8c468c488c328c 16

Realtime heart: 99

Raw heart: 0230438c408c378c3a8c318c458c388c 16

Realtime heart: 102

Raw heart: 02404f8c408c458c428c4d8c558c4d8c 16

Raw heart: 02483e8c3b8c3f8c348c398c318c428c 16

Realtime heart: 98

Raw heart: 02504c8c428c5e8c4f8c588c498c558c 16

Raw heart: 0258478c458c3c8c4e8c3f8c468c4d8c 16

Realtime heart: 100

Raw heart: 0260518c4d8c4f8c4b8c4f8c528c458c 16

Raw heart: 0268408c3f8c538c4d8c408c548c598c 16

Realtime heart: 102

Raw heart: 0278418c508c4e8c548c588c468c498c 16

Raw heart: 0280368c328c2e8c3c8c338c308c3f8c 16

Realtime heart: 101

从中我们可以看到清晰的数据,重复368c 328c 2e8c 3c8c 338c 308c 3f8c,数据包长度为16字节。因此,如果我们用2个字节的无符号短数据解压缩,那么我们可以得到7个心脏传感器的原始测量结果。我们也看到第二个字节只是迭代,我认为它只是测量之间的时间差异(我指的是响应的时间差)


Raw gyro: 01de49ffd9ff3c004cffd8ff3b004dffdcff4400

Raw gyro: 01df4cffd6ff44004dffd8ff40004cffd1ff4700

Raw gyro: 02e1103231323d3274328e329632af32c732cf32

Raw gyro: 01e34fffd7ff56004bffc7ff590049ffccff4c00

Raw gyro: 01e443ffccff43004effcdff40005bffd4ff4c00

Raw gyro: 01e558ffc9ff5f005effbfff66005fffb0ff5900

Raw gyro: 01e64cffacff60005cffa7ff410066ffc9ff4600

Raw gyro: 01e760ffdcff4b0051ffe4ff4f0034ffdeff5300

Raw gyro: 02e903365c36813663361036543688374139fe3a

Raw gyro: 01eb4bffc3ff50004fffc1ff430047ffbbff4100

Raw gyro: 01ec3effb2ff3c0050ffbfff560047ffccff7300

Raw gyro: 01ed4fffe0ff78005cffebff8e0056fff6ff8300

Raw gyro: 01ee7efffbffa1008bff0f00bc00b1ff1900b800

Raw gyro: 01ef9bff0c00d10095fff3ffd600b7ff0800df00

Raw gyro: 02f12445314600479e473348aa481c499749244a

Raw gyro: 01f3c3ff1600fe00beff1800f200a6ff0800e700

Raw gyro: 01f4a9fff8ffd300a7fff3ffd700a9fff1ffdf00

Raw gyro: 01f5b1fff8ffe800b4fff1fff700acfffcffef00

Raw gyro: 01f67ffff7ffc0006bfff4ffb00078ffe9ffb600

Raw gyro: 01f786ffecffc0006ffff0ffbc0060fff1ffc000

Raw gyro: 02f9ca4cbb4c784c964ca84c784c854c444c1b4c

Raw gyro: 01fb7cff0f00bb007eff2700ae0083ff30009800

Raw gyro: 01fc79ff1800b00076ff0f00bc0068ff0900d900

Raw gyro: 01fd78ff07000c01f6fffbff19011c000b00f600

Raw gyro: 01fe4b001100d30054000700c3004300efffeb00

Raw gyro: 01ff1f00d0ff1701fbffe8ff1b01e3ffffff1101

Raw gyro: 0201214b014bec4ad04aba4acb4abe4aba4abd4a

Raw gyro: 0103efffecfffc00e3fff3fff300defff3fffc00

Raw gyro: 0104e3fff0fff400e6ffefff0301dbffe9ff0c01

Raw gyro: 0105e3fff0ff0301e6ffe6fffc00dcffecfffc00

Raw gyro: 0106dffff0fff700dbffeefff600d6fff0fff400

Raw gyro: 0107dfffecffff00e1fff0ff0301defff3fffc00

至于陀螺仪,就有点困难。但是我的想法是它应该与心脏数据类似的方式打包,但在这种情况下,我们对每个应该签名的陀螺仪轴进行3次测量,数据包长度为20个字节。因此,12 x,y,z测量不会覆盖所有包,但3将会保留前2个字节(与之前的包相同)。所以我这样试了,过不然工作是正常的。

代码

代码,你可以找到我的github仓库(https://github.com/creotiv/MiBand2)下载所有的代码,所有代码使用python实现。老司机们应该都知道怎么做,在此就不多赘述。
原作者可能是个毛子,如果你们觉得他的思路对你有用,可以给他捐点钱,卖酒喝(他自己的话,github里面可捐款)。