逆向工程我的圣诞树

2020-12-29 21:34:11

在过去一年半的时间里,我一直在做一些关于无线电工作方式的自我指导的学习。我从对无线通信的最基本的理解(我猜通常是某种天线?)一直到学习和实现一组库来使用我现在强大的SDR来调制和解调数据的过程。我一直是根据第一原理实施所有RF处理代码的,并且纯粹是基于其他原语,我已经写了我自己,向自己证明我在继续之前理解每个概念。

我认为这里有一个有趣的“顶峰”-盲目的反向工程和协议的实现(我廉价的Amazon电源开关用于打开和关闭圣诞树)。感谢汤姆·贝雷克内伊(Tom Bereknyei)和赫里伯曼(hlieberman)在解调过程中的帮助,这篇文章中描述的所有工作已经完成了几个小时。

当我第一次获得开关时,我检查了它是否有FCC标记,以便查找FCC文件来确定设备的工作频率,也许还可以找到一些其他信息,例如声明的调制方式,甚至零件号和/或图表。但是,除了一些法规标签外,设备上没有FCC ID或其他可区分的ID。更糟糕的是,它似乎是另一种产品的白标版本,因此在Google上搜索该产品名称非常无助。

由于此设备的操作未经许可,因此我认为我将开始关注ISM频段。我见过的最常见的频段是从433.05MHz到434.79MHz的频段。我启动了可信任的瀑布,将其调整为433.92MHz的中心频率(因为它正好位于频段的中间,它让我在频段的上下都可以看到足够远的距离,以便发现遥控器)并按下了几个按钮。当我意识到该设备的工作频率为433.920MHz(恰好是死点)时,我会感到惊讶。很奇怪,但是很幸运!

进行捕获后,我开始着眼于了解信号的调制类型以及如何对其进行解调。使用inspectrum,我能够清楚地看到捕获中的信号,并立即将其突出显示使用OOK / ASK进行编码。

接下来,我开始测量最小的脉冲,看看是否可以每秒推断出符号,然后尝试手动解码。这些类型的信号通常很容易用肉眼解码。

这给了我2.2 Ksym / s的符号率,这比我预期的要快得多。在我手工工作时,汤姆用Python解调了一些消息,并注意到,如果将bitinto分成4组,则可能有1000或1110,这使我意识到这是使用我在其他地方记录的内容编码的不同于摩尔斯电码,the0是一个“短”脉冲,而数字1是一个“长”脉冲,但是每个符号占用固定的时间长度(等距莫尔斯电码?)。宽度,并用手将其解调。这样可以很好地进行解调(并且前同步码/时钟同步可以表示为重复的0,这很方便!),并为我们提供了每秒612(ish)个符号的符号率,与我的预期相差很多。

如果我们在上面的检查区捕获中采用“打开”的代码并手动进行解调,则会得到0000000000110101100100010(将短脉冲处理为0,将长脉冲处理为1)。如果您有兴趣在家中跟随,请单击检查图像,并写下您看到的内容,然后将其与我所拥有的进行比较!

是的,从目前为止我们可以看出,数据包看起来像这样:

接下来,我捕获了所有按钮按下的信息,并手工对其进行了解调,然后将它们放入表格中以尝试了解消息的格式:

大!因此,我认为这足以尝试用它来控制树,因此编写了一个简单的调制器。我的方法是利用我可以将一个符号分解为4个“子符号”组成部分的事实–也就是说,回到将1表示为1110,将0表示为1000。这使我可以为该符号分配IQspace ,将其分成4个符号,如果该符号为1,则将载波中的值(实际值中的cos和虚部值中的sin)写入缓冲区。现在,我可以将比特数据转换为IQ数据了,现在可以使用PlutoSDR或HackRF传输IQ数据并尝试控制mytree。我试了一下,树眨了眨眼!

但是,等等-这对我来说还不够-我知道我不能永远解调比特并尝试并永久重放比特-诸如地址,密钥和填充之类的东西,我想让其中的第二个起作用。让我们来看看这些位,看看我们是否发现任何有趣的东西。有趣。

乍一看,有些事情让我感到奇怪吗?首先是前同步码是10位长(很好,让我们继续前进-也许恰好需要连续8位,而有2位可以确保时钟同步?)。其次是消息长度不一样。我检查了一下邮件(是三遍!),的确如此,邮件的长度不尽相同。最后增加一点点都没有破坏任何东西,但是我想知道这是否仅是由于实现而不是协议。

但是,好消息是,我们似乎有一个固定的前缀来发送来自远程的消息-必须是我设备的地址!立刻跳出来的稳定的6位是110101。尽管有些限制,但对于某些有限的嵌入式设备来说,有些奇怪的事情还是显得有些奇怪。为什么是6?但是,嘿,等等,我们的前导中有10位,如果我们有8位地址,那意味着我的设备是00110101,而前导是8 0个符号!这些是在8位对齐平台上工作的人会选择的数字!为了测试这一点,我在序言中添加了0,以查看消息是否从前1开始,或者它是否要求所有位都被完全解码,并且瞧,树没有打开或关闭。在我看来,这似乎是为了确认0是地址的一部分,并且我可以假设我们在消息的前缀中有两个8位对齐的字节。

现在,当我们经历9到10位的“内容”时,我们看到各种各样的怪异的东西到处漂浮。前4位看起来是1001或0001,但除此之外,还有很多混乱。这是真的很糊涂的地方。我需要更多信息来尝试解决此问题,但是无论我发送了多少次命令,它始终是相同的位(因此,没有计数器),并且感觉仍然很不透明。

我要取得任何进展的唯一方法是获得另一个开关,并查看远程消息如何更改。我去了亚马逊,并命令从同一页面进行另一次切换,并热切地等待它的到来。

第二个开关出现了,我急忙拆开工具箱的包装,将电池放入遥控器中,并发射了我的SDR进行捕获。按下第一个按钮(“关”)后,当我看到连接到#1开关的灯闪烁时,我的心沉没了。显然,新交换机和旧交换机具有相同的确切地址。可以肯定的是,我像以前一样对消息进行了解调,并以完全相同的位模式显示出来。这是一个挫折和失望–我希望独立控制我的开关,但这也意味着我没有关于地址或按钮格式的其他信息。

但是,所有这些操作的好处是,由于开关是由任何一个远程控制的,所以我只需要一个远程,那么为什么不将其拆开,看看我是否能弄清楚它用来传输什么组件,并找到我能找到的任何数据表。 PCB非常简单,我最终在PCB上找到了“ WL116SC” IC。

谷歌搜索后,我发现了一个单独的中文数据表。值得庆幸的是,Google Translate在技术用语方面似乎做得很好,并且我可以根据提供的文档至少收集了一点理解。我在下面截取了一些屏幕截图-我将Google翻译的文字放在了汉字上方。从那张纸上,我们可以看到我们对“ 1”和“ 0”符号的编码有了正确的理解(我中途期望比特被翻转),并且通过对消息中的比特进行描述而获得了巨大的发现!

令人遗憾的是,我们错过了数据消息之前的时钟同步/前同步脉冲,但这在某种程度上是可以的。事实证明,“ 0#34; s”的8或10位序列完全没有时钟同步-它是地址的一部分!由于还证明该制造商制造的所有设备的硬编码地址均为[] byte {0x00,0x35},因此,对于由此制造的任何遥控器上的任何按钮按下,发送的绝大多数位总是相同的供应商。对我来说似乎有点浪费,但是,嘿,我知道些什么。

此外,这还告诉我们尾随零不是数据编码方案的一部分,这是进步!

现在,根据数据表验证的假设,这是我们发现的扫描代码的更新列表:

有趣的是,我认为“ Dim”键可以确认我们的演示良好-底部的代码缺少最高有效位,当我回顾数据表中的scancode表时,它们会形成一个有趣的模式-底部两行,右侧和左侧的值匹配!如果看一看,Dim 100%是“ S1”,Dim 75%是“ S19”,Dim 50%是“ S8”,Dim 25%是“ S20”。凉!

由于没有其他代码排队,因此我敢打赌,最高有效位是“组合”指示器,而不是按钮的一部分(为键代码保留7位)。

更有趣的是,在示例中,我们的扫描代码之一(“ Off”,即0x94)显示在此表的正下方。

总的来说,我认为这告诉我们我们有正确的判断力来确定扫描代码!好消息!

因此,有了这些知识,我就能够重构我的代码以匹配数据表中概述的时机和理解,并确保一切仍然正常。仍然有效。很难知道这是否正确,但是如果没有其他要求,匹配的文档似乎更稳定。

这段代码确实可靠,并且在无法确定的情况下也能正常工作。我一直在使用非常低的功率来避免任何干扰,而且它非常坚固-证明了插座硬件的工程设计,尽管它的成本比许多其他开关要低!我对制造此设备的人表示敬意-它非常简单,可靠,而且我猜想即使在某些相当恶劣的RF环境中,该设备也能正常工作。

唯一的缺点是制造商在所有设备上使用了相同的地址,而不是为每个插座编程一个唯一的地址,并在底层WL116SC芯片支持时为其远程编程。我敢肯定,这样做是为了避免组装的复杂性(例如,将遥控器和插座配对,并在组装过程中将这两项保持在一起),但这仍然很麻烦。我看了一下交换机,看看是否可以转储EEPROM并在ROM中更改地址,但是整个设备都用防水环氧树脂灌封,如果在户外使用,这是一个很好的功能。不过,这不是一个好消息!

在这一点上,即使我足够了解该协议来控制该设备,但仍然感觉我陷入了僵局。我无法弄清楚扫描代码是如何实现的,并将其分解为更具体的部分。它们是稳定的,并基于遥控器的物理布线,因此我想给它一个神奇的数字。我已经在寻找什么了,即使我确实知道如何创建代码,这些魔术常数似乎也是可以使用的正确常数。

这确实给我们留下了一些我们从未解决过的问题,为确保我不会忘记它们,我将在下面对此加以纪念。

问题1:根据数据表,应该有一个序言。为什么我看不到第一个消息的开头?

我的直觉是,有效负载末尾的结尾“ 0”实际上只是下一条消息的序言(总是使第一条消息无效?)。这可以让我们声称我们出于工程原因而忽略了这些奇怪的地方,并从文档中解释了一些内容。这很奇怪,它不会出现在第一条消息中。

可以通过测量时序并将其与数据表进行比较来证实这一理论,但它也不完全符合数据表时序(具体而言,相差200µs,对于使用400µstimings的系统来说,这是很多东西)。我认为我可以在最后一个“ 0”上选择任一种方式作为下一条消息的序言。第一条消息可能在技术上是无效的,也可能是供应商未针对此特定应用程序/设备实施或未主动禁用此消息。很难知道没有在此特定遥控器中获得WL116SC芯片的源代码,也无法在插座本身中获得源代码。

我仍然不知道为什么有时8位键码字段中有时会有8位(例如“ On”),而有时又有9位(例如“ Off”)。

我花了一些时间处理“尾随”零,当我尝试发送具有最高有效8位(无最低有效/ last9th位,即“ 0”)的“关”时,它不会转动树关。如果我发送一个带有9位的“开”(最低有效位后再加一个0),它确实起作用,但是当我发送带有尾随零填充的10、11或12位时,“开”和“关”都起作用。我怀疑开关“完成”读取位后,无论尾随零如何,我的插座都会忽略数据。文档告诉我应该只有8位,但是除非我为某些命令发送9位,否则它将无法工作。这里有些混乱,数据表也不是完全正确的。

这个让我发疯。我花了无数时间来尝试解决这个问题,包括向制造WL116SC的公司发送电子邮件(真是太好了!),尽管它们非常友好,慷慨地提供了文档和示例源,但我仍然很难将他们的文档和示例与我从遥控器上看到的内容对齐。我认为myremote和switch的制造商已经对协议进行了足够的修改,以适应实际发生的变化。笨蛋

我选择了最后的解决方法–让Signal上的朋友尝试看看他们是否可以找到一个模式,并对Twitter圈进行多次请愿,但无济于事(但要感谢Ben Hilburn,devnulling,Andreas Bombe和Larmefor您的答复,帮助和建议!)

我仍然不了解它们如何组装扫描代码-例如,如果仅添加,您将不知道0x05的按键是0x03 + 0x02还是0x01 + 0x04。另一方面,将其视为两个4位整数对于0x10到​​0x15不起作用(因为它们需要5位才能表示)。最高有效位也可能是组合指示符,它仅保留7位用于实际按键数据。将10位数据填充到7位中可能会导致某些真正复杂的位工作。最后一阵奇想,我尝试对数学进行XOR运算,但是鉴于所提供的示例并没有任何结果,因此我进行了一些初步的强制使数学运算起作用。这可能是一个我不太了解的领域,但是我认为如果没有内部知识和更多工作,我就无法在这方面取得进展。

如果有人对这些代码的工作方式有任何想法,我很想听听!向我发送电子邮件或推文之类的东西-我有些困惑。

这里有一些技巧,用于以可解码的方式对组合键进行编码。如果它实际上是不可解码的(这是现实的可能性!),则它可以充当唯一的按钮组合“哈希”,这使接收者实际上无法确定按下了哪些键,但是有一个唯一的“按钮”,当组合键被按下时会发送该按钮。用过的。我不确定我是否了解足够的理论。