打信安国赛的时候碰到了一个关于传感器报文的misc问题

原理

曼彻斯特编码

曼彻斯特编码将时钟和数据包含在数据流中,在传输代码信息的同时,也将时钟同步信号一起传输到对方,每位编码中有一跳变,不存在直流分量,因此具有自同步能力和良好的抗干扰性能。但每一个码元都被调成两个电平,所以数据传输速率只有调制速率的1/2。 曼彻斯特编码表示0或1有两种不同的方法: 第一种G. E. Thomas, Andrew S. Tanenbaum1949年提出的,它规定0是由低-高的电平跳变表示,1是高-低的电平跳变。 按此规则有: - 编码0101(即0x5),表示原数据为00; - 编码1001(0x9)表示10; - 编码0110(0x6)表示01; - 编码1010(0xA)表示11。 第二种IEEE 802.4(令牌总线)和低速版的IEEE 802.3(以太网)中规定, 按照这样的说法, 低-高电平跳变表示1, 高-低的电平跳变表示0。 - 编码0101(0x5)表示11; - 编码1001(0x9)表示01; - 编码0110(0x6)表示10; - 编码1010(0xA)表示00;

差分曼彻斯特编码:

在信号位开始时不改变信号极性,表示辑"1" 在信号位开始时改变信号极性,表示逻辑"0" ; 【注意】:如果在最初信号的时候,即第一个信号时: 如果中间位电平从低到高,则表示0; 如果中间位电平从高到低,则表示1; 后面的(从第二个开始)就看每个信号位开始时有没有跳变来决定

校验位

有几种产生方法:

奇偶校验

异或校验

crc循环冗余校验

LRC校验(纵向冗余校验)

BCC校验(异或校验)

关于crc循环冗余校验,这里有一篇文章

奇偶校验:

所谓通讯过程的校验是指在通讯数据后加上一些附加信息,通过这些附加信息来判断接收到的数据是否和发送出的数据相同。比如说RS232串行通讯可以设置奇偶校验位,所谓奇偶校验就是在发送的每一个字节后都加上一位,使得每个字节中1的个数为奇数个或偶数个。比如我们要发送的字节是0x1a,二进制表示为0001 1010。

采用奇校验,则在数据后补上个0,数据变为0001 1010 0,数据中1的个数为奇数个(3个)

采用偶校验,则在数据后补上个1,数据变为0001 1010 1,数据中1的个数为偶数个(4个)

接收方通过计算数据中1个数是否满足奇偶性来确定数据是否有错。

奇偶校验的缺点也很明显,首先,它对错误的检测概率大约只有50%。也就是只有一半的错误它能够检测出来。另外,每传输一个字节都要附加一位校验位,对传输效率的影响很大。因此,在高速数据通讯中很少采用奇偶校验。奇偶校验优点也很明显,它很简单,因此可以用硬件来实现,这样可以减少软件的负担。因此,奇偶校验也被广泛的应用着。

CRC循环冗余校验

CRC 算法的基本思想是将传输的数据当做一个位数很长的数。将这个数除以另一个数。得到的余数作为校验数据附加到原数据后面。还以上面例子中的数据为例:

6、23、4 可以看做一个2进制数: 0000011000010111 00000010

假如被除数选9,二进制表示为:1001

则除法运算可以表示为:

可以看到,最后的余数为1。如果我们将这个余数作为校验和的话,传输的数据则是:6、23、4、1

CRC 算法和这个过程有点类似,不过采用的不是上面例子中的通常的这种除法。在CRC算法中,将二进制数据流作为多项式的系数,然后进行的是多项式的乘除法。还是举个例子吧。

比如说我们有两个二进制数,分别为:1101 和1011。

1101 与如下的多项式相联系:1x3+1x2+0x1+1x0=x3+x2+x0

1011与如下的多项式相联系:1x3+0x2+1x1+1x0=x3+x1+x0

两个多项式的乘法:(x3+x2+x0)(x3+x1+x0)=x6+x5+x4+x3+x3+x3+x2+x1+x0

得到结果后,合并同类项时采用模2运算。也就是说乘除法采用正常的多项式乘除法,而加减法都采用模2运算。所谓模2运算就是结果除以2后取余数。比如3 mod 2 = 1。因此,上面最终得到的多项式为:x6+x5+x4+x3+x2+x1+x0,对应的二进制数:111111

下面是一个例子:

要传输的数据为:1101011011

除数设为:10011

在计算前先将原始数据后面填上4个0:11010110110000,之所以要补0,后面再做解释。

从这个例子可以看出,采用了模2的加减法后,不需要考虑借位的问题,所以除法变简单了。最后得到的余数就是CRC 校验字。为了进行CRC运算,也就是这种特殊的除法运算,必须要指定个被除数,在CRC算法中,这个被除数有一个专有名称叫做“生成多项式”。生成多项式的选取是个很有难度的问题,如果选的不好,那么检出错误的概率就会低很多。好在这个问题已经被专家们研究了很长一段时间了,对于我们这些使用者来说,只要把现成的成果拿来用就行了。

最常用的几种生成多项式如下:

CRC8=X8+X5+X4+X0

CRC-CCITT=X16+X12+X5+X0

CRC16=X16+X15+X2+X0

CRC12=X12+X11+X3+X2+X0

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0

有一点要特别注意,文献中提到的生成多项式经常会说到多项式的位宽(Width,简记为W),这个位宽不是多项式对应的二进制数的位数,而是位数减1。比如CRC8中用到的位宽为8的生成多项式,其实对应得二进制数有九位:100110001。另外一点,多项式表示和二进制表示都很繁琐,交流起来不方便,因此,文献中多用16进制简写法来表示,因为生成多项式的最高位肯定为1,最高位的位置由位宽可知,故在简记式中,将最高的1统一去掉了,如CRC32的生成多项式简记为04C11DB7实际上表示的是104C11DB7。当然,这样简记除了方便外,在编程计算时也有它的用处。

对于上面的例子,位宽为4(W=4),按照CRC算法的要求,计算前要在原始数据后填上W个0,也就是4个0。

位宽W=1的生成多项式(CRC1)有两种,分别是X1和X1+X0,读者可以自己证明10 对应的就是奇偶校验中的奇校验,而11对应则是偶校验。因此,写到这里我们知道了奇偶校验其实就是CRC校验的一种特例,这也是我要以奇偶校验作为开篇介绍的原因了。

传感器0

5555555595555A65556AA696AA6666666955
这是某压力传感器无线数据包解调后但未解码的报文(hex)
已知其ID为0xFED31F,请继续将报文完整解码,提交hex。
tips:flag是flag{破译出的明文}
提示1:曼联

直接曼彻斯特编码,得到一个解密后的报文:

11111111 11111111 01111111 11001011 11111000 00100110 00001010 10101010 10011111

bin->hex,对比ID并不重合,根据八位倒序传输协议将二进制每八位reverse,转hex即可

flag:FFFFFED31F645055F9

传感器1

已知ID为0x8893CA58的温度传感器的未解码报文为:3EAAAAA56A69AA55A95995A569AA95565556

此时有另一个相同型号的传感器,其未解码报文为:3EAAAAA56A69AA556A965A5999596AA95656

请解出其ID,提交flag{不含0x的hex值}

通过差分曼彻斯特编码得到结果,也不需要什么八位倒序传输协议reverse

a = 0x3EAAAAA56A69AA55A95995A569AA95565556
b = 0x3EAAAAA56A69AA556A965A5999596AA95656
ba = bin(b)
print ba
ss = ""

for i in xrange(len(ba[2:])/2):

    a1 = ba[i*2:i*2+2]
    a2 = ba[i*2+2:i*2+4]
    # print 'a1:'+a1
    # print 'a2:'+a2

    if a2 !='10' and a2 !='01':
        continue
    if a1 !='10' and a1 !='01':
        ss+='1'
        continue

    if a1!=a2:
        ss+='1'
    else:
        ss+='0'

    # print ss

print ss
print len(ss)

ret = ''

# if '8893CA58' in ret:
print hex(int(ss,2)).upper()

#0X10024D8893CA584181L
#0X30024D8845ABF34119L

传感器2

已知ID为0x8893CA58的温度传感器未解码报文为:3EAAAAA56A69AA55A95995A569AA95565556

为伪造该类型传感器的报文ID(其他报文内容不变),请给出ID为0xDEADBEEF的传感器1的报文校验位(解码后hex),以及ID为0xBAADA555的传感器2的报文校验位(解码后hex),并组合作为flag提交。

例如,若传感器1的校验位为0x123456,传感器2的校验位为0xABCDEF,则flag为flag{123456ABCDEF}。

温度传感器报文解码后为 0X10024D8893CA584181L

由校验位的产生可以知道(但是crc算法有点多,而且我也对这个东西不是很熟悉,最后还是没做出来。)

所以以024D8893CA5841为数据位,那么用数据位进行CRC8可以得到其校验位(02+id+41)