首页
社区
课程
招聘
[翻译]用不到10美元成本,自己DIY一个Proxmark设备
2018-2-1 12:59 8379

[翻译]用不到10美元成本,自己DIY一个Proxmark设备

2018-2-1 12:59
8379

(写在前面:翻译这篇文章实在有点力不从心,作者可能太极客,文章的逻辑不太强,语言指代有时候也不明确。我自己对于NFC也不是特别懂,还请大家将就着看,有疑惑请参照原文:https://www.pentestpartners.com/security-blog/building-half-a-proxmark-for-10/

Proxmark是一款出色的设备,我们机构有一些。 但对于NFC(近场通讯)业余爱好者来说,Proxmark有些过于昂贵,而可用的仿制设备则更少。但如果你有些焊接技能,通过学习下面的方法,用大约10美元的元件,便可以构造出一款NFC标签模拟器。


本篇文章将展示如何逆向构建ISO-14443A标准的协议,以查看哪里存在可利用的弱点。 我们创建了一个能够模拟Mifare标签的设备,尽管其加密技术存在已知的弱点,但它们通常被认为是具有严格和模糊访问控制的黑盒子。 我打算在加密层之外找到弱点,因为这些都是完全开放的。


使用设备


本项目中,我决定不用这种平台下的任何传统调试装置来开发这个设备。这包括一个传统的USB NFC读写器,如下所示:

https://www.amazon.co.uk/Yosoo-ACR122U-Contactless-Reader-5xMifare/dp/B00GYPIZG6/ref=sr_1_6?ie=UTF8&qid=1516009490&sr=8-6&keywords=nfc+reader


我也决定不用Proxmark3或Chameleon Mini这种更倾向服务于安全专业人士的工具:

https://store.ryscc.com/products/new-proxmark3-kit

https://www.kickstarter.com/projects/1980078555/chameleonmini-a-versatile-nfc-card-emulator-and-mo


在开发过程中,我发现了一个类似的项目(网址如下),它使用了可能已经改编的类似硬件。尽管这个项目有一些很好的想法,但我还是想从头开始设计。

http://blog.nonan.net/2013/11/simple-nfc.html


我想自己开发的原因是,尽管这些工具在性能上肯定非常优越,同时可以根据用户的需要随时修改。但仅仅使用这些工具,并不能让我得到与自己从头开发设备相同的见解。


调试本项目的关键装置是我的Hobby Components Logic Analyzer和RTL-SDR。 对于编程和开发,我使用了Arduino来编写成为项目核心的ATTiny84,并使用了STM32f401re开发板进行调试(后面会说明为什么必须这样做)。


创建调试工具


在开发过程中,我发现必须通过带外数据的方式来分析读写器中的命令 。 读取器本身无法直接访问这些信息,因为它的USB实现完全是作为HID(人机界面设备)进行设置的,对设备上的NFC硬件访问受限。 我决定了使用我信任的RTL-SDR来获取必要信息是最佳选择。 在过去,RTL-SDR已被证明能够查看NFC数据包,因此我觉得可以创建一个应用程序来执行此操作。


最初,我使用了我早前的一个项目,它允许用户查看SDR IQ样本及其幅度,并使用传统的逻辑分析软件对其进行分析:

https://github.com/Iskuri/RTLSDR-to-Pulseview


关于这个项目首先要注意的是,标准的RTL-SDR无法调谐到NFC读写器使用的相同频率,即13.56Mhz。但是,它不仅可以调谐到它的谐波频率之一 - 27.12Mhz ,同时我们在调谐至该频率并通过运行分析仪后发现,读写器的传输易于用标准进行查看,因此编写应用程序将其解码用于分析很简单。但可惜的是,由于使用了传输和调制方案(稍后会详细介绍),RTL-SDR标签的响应将不可见。考虑到这一信息,我创建了一个采样频率为27.12Mhz,采样率为1.695Mhz的应用程序(选择此采样率是因为它处于RTL-SDR的允许采样率范围内,并且也是读写器数据率的倍数)。从这里输出的数据中,我可以解析出读写器的命令,以便查看它们进行调试,最终创建这个小工具:

https://github.com/Iskuri/RTLSDR-NFC


不幸的是,由于这个工具只能分析读写器的命令,而不能分析标签的命令,所以在之后的调试中,特别是调试加密层时,还是有问题。通过使用逻辑分析仪来跟踪命令和响应,可以缓解这些问题。


硬件


我决定使用ATTiny84作为设备的核心MCU(微控制器),因为它可以很容易地使用外部时钟,具有相当大的程序空间,并且还具有板载EEPROM。 为了以正确的频率工作,我使用了一个13.56Mhz的晶体,配合适当的电容来匹配它,并且为了接收来自读写器的命令,我使用了一个谐振电感耦合器:

https://en.wikipedia.org/wiki/Resonant_inductive_coupling


馈入一个包络检测器

https://en.wikipedia.org/wiki/Envelope_detector


然后将其连接到GPIO输入引脚以接收信号。


使用该芯片有一个关键的弱点,那就是外部晶振的引脚与UART使用的引脚相同。 由于我为了实现在线串行编程器而安装的Arduino 不能通过任何其他方法进行调试,因此必须通过不同引脚上的任何调试字符串将时钟输出到STM32f401re板,该板再将其转换为UART。因为基于软件的UART 在这些频率上太不一致了。

为了减少噪音,我在电源和接地引脚之间增加了电解电容和超级电容。


然后将它汇总到以下原型电路板中:

协议


低级NFC协议非常简单。 读写器和标签使用两种不同的编码方案进行通信。

读写器使用一种称为修改米勒的编码方案,定义如下:

•      0比特跟着0比特:传输的前四分之一是低位,之后都是高位。

•      1比特:传输的前二分之一是高位,之后四分之一是低位,再之后都是高位。

•      1比特跟着1比特:整个传输都是高位。


用于发送命令的编码示例如下:


当读写器与标签进行通信时,会降低提供给标签用以通信的功率。 这种编码方案是专门设计用于当电源被禁用时,让标签有足够的剩余电力来处理交易。

标签使用了一种更传统的无线电通信编码 - 曼彻斯特编码。


该协议使用从高位到低位的设置来编码1,或者从低位到高位的设置来编码0.为了使用这个协议进行通信,它使用了所谓的“负载调制”。 这调制了一个信号,以便在发送给标签的功率上产生阻力,读写器可以将其理解为响应。


有关这些编码方案的更多信息,请查看:http://www.radio-electronics.com/info/wireless/nfc/near-field-communications-modulation-rf-signal-interface.php.

数据包由帧开始位,随后是帧的一个字节,以及基于字节中置位和未置位位数的奇偶校验位构成。 字节按顺序发送,先传送最低有效位,例如下面的命令:


0x26 – REQA:
Bits Sent: 0 0 1 1 0 0 1 0 0


上面的命令是REQA命令,用于请求任何新的读写器响应标签。


命令由标签发送和响应,以便在两个设备之间进行通信的状态机进行处理:

RD: 26 - REQA
TG: 0f 01 - ATQA
RD: 93 20 - SELECT1
TG: 04 ac e9 b2 f3 - UID
RD: 93 70 04 ac e9 b2 f3 f0 98 - SELECT
TG: 08 - ACK
RD: 50 00 57 cd – HALT


实现协议


由于在ATTiny上实现协议产生了一些问题,我进行了一些迭代处理,其中最关键的是时钟漂移。 一般情况下对于ATTiny来说,时钟漂移会有很大的问题,因此,我最初试图纯粹使用时钟和间隔来实现协议,以便为发送的修改的密勒比特接收一个位掩码,比如:


0b0111 – 0 after 0
0b1101 – 1
0b1111 – 0 after 1


只有60%的情况下通信能顺利完成。这是不够的,因为读写器会一直认为标签被移除,然后重新引入场。

由于这个原因,我们将定时器与GPIO中断一起使用,并检查每次引脚设置为低电平之间的时间,从而允许有足够的时钟漂移量,同时仍然获得完整的通信。

同时,通过将附加的GPIO引脚连接到接收引脚,并使用该引脚上的PWM来进行通信,以增加负载并执行负载调制。 这样做效果很好,但是如果芯片使用的电压太高,可能会对某些读写器造成问题。


加密


正如我打算仿效Mifare Classic Tags一样,我不得不实施Crypto-1加密算法。 这个算法是众所周知的弱,已经被打破了几次,但执行它是必要的。 作为参考,我使用了维基百科页面上的定义:https://en.wikipedia.org/wiki/Crypto-1以及内置于Mifare Classic Universal Toolkit中的着名的“Crapto1”库:https:https://github.com/nfc-tools/mfcuk。


写这些函数的类似实现是很容易的,但是有一些关键的缺点,这意味着很大部分必须被重写。其中最关键的是Crypto-1基于32位算术,因此在ATTiny的8位微控制器上执行的任何操作都需要长达四倍的时间。 除此之外,ATTiny缺乏一次移位多位的方法,这意味着它不适合处理大多数加密算法,因为它们通常非常依赖于数位偏移。这些弱点意味着设备响应加密命令的速度太慢,因此会与读写器不同步。 为了减轻这一点,我决定优化我的实现,并将其重写到AVR汇编中。


被发现消耗最多时间的函数是filter函数。 该函数具有最复杂的计算,并且由于其性质需要手动优化。下面的实现该函数的例子是从Crapto-1库中提取的:

int filter(uint32_t const x)
{
uint32_t f;
f  = 0xf22c0 >> (x       & 0xf) & 16;
f |= 0x6c9c0 >> (x >>  4 & 0xf) &  8;
f |= 0x3c8b0 >> (x >>  8 & 0xf) &  4;
f |= 0x1e458 >> (x >> 12 & 0xf) &  2;
f |= 0x0d938 >> (x >> 16 & 0xf) &  1;
return BIT(0xEC57E80A, f);
}

关于实现这个功能的重要几点:

•      五个24位常量用于位移,但实际上只有两个不同的常量,通过位移以优化一些计算。

•      尽管在处理函数时能够一次位移4位,但x值一直与其余的函数一起移位。

•      每行设置的每个值对应于特定级别的位移,因此可以独立处理。


上述重要几点有各自的优化方法:

•      24位常量的使用意味着转换为汇编并将算术处理为24位而不是32位,这意味着我们已经为这些函数节省了四分之一的计算时间。

•      在每行之外移位x值4位将节省更多的周期。 在汇编中,我最终将每个掩码值从x设置到每个寄存器中,因为这节省了大量的位移。

•      每行可以用不同的方式进行优化,以模拟循环移位。


最后一点是减少用于计算的周期的关键。 独立采取每条线路并执行不同的计算可以节省大量的时间。 每一位移位都完成了以下工作:

•      16位 - 将两个较高的寄存器复制为较低的两个寄存器

•      8位  - 将倒数第二低字节的值复制到最低字节

•      4位 - 使用AVR SWAP命令交换nybbles

•      2位 - 两个传统的位移

•      1位 - 一个传统的位移


为了执行这些优化,我不得不写了下面的汇编程序:


cryptoFilterAsm: ; sped up filter function for crypto1
push r18
push r17 ; push registers we want to use
push r16
mov r21, r22 ; set up each shift value into register
andi r22, 0xf
mov r20, r23
andi r23, 0xf
andi r24, 0xf
swap r21
andi r21, 0x0f
swap r20
andi r20, 0x0f
ldi r17, 0x0a ; set shift constant 0xEC57E80A - not using reserved registers to save push and pop cycles hence the weird choices
ldi r16, 0xe8
ldi r27, 0x57
ldi r26, 0xec
ldi ZH, hi8(firstLookupTable) ; set up first space for lookup
ldi ZL, lo8(firstLookupTable)
add ZL, r22
adc ZH, r1
lpm r22, Z
cpi r22, 0
breq endShiftSixteenBit
mov r16, r26 ; this will shift 16 bits in two operations rather than the ton it usually takes
mov r17, r27
endShiftSixteenBit:
ldi ZH, hi8(secondLookupTable) ; set up first space for lookup
ldi ZL, lo8(secondLookupTable)
add ZL, r21
adc ZH, r1
lpm r21, Z
cpi r21, 0
breq endShiftEightBit
mov r17, r16
endShiftEightBit:
ldi ZH, hi8(firstLookupTable) ; set up first space for lookup
ldi ZL, lo8(firstLookupTable)
add ZL, r23
adc ZH, r1
lpm r23, Z
cpi r23, 0
breq endShiftFourBit
swap r17
andi r17, 0x0f ; may not be necessary
endShiftFourBit:
ldi ZH, hi8(firstLookupTable)
ldi ZL, lo8(firstLookupTable)
add ZL, r20
adc ZH, r1
lpm r20, Z
cpi r20, 0 ; if its zero, skip
breq endShiftTwoBit
lsr r17
lsr r17
endShiftTwoBit:
ldi ZH, hi8(secondLookupTable)
ldi ZL, lo8(secondLookupTable)
add ZL, r24
adc ZH, r1
lpm r24, Z
cpi r24, 0
breq endShiftOneBit
lsr r17
endShiftOneBit:
andi r17, 0x01
mov r24, r17
pop r16
pop r17
pop r18
ret


优化这个功能使得加密功能运行的速度比原来的执行速度快10倍,并且允许在足够的时间内对命令和响应进行加密,以便读写器接收它们。


有趣的功能 - 模拟多个标签


我致力于添加我在其他设备(包括Proxmark和Chameleon Mini )上没有见过的功能。我还处在开发这个功能的阶段,一旦完成应该会很有意思,特别是尝试执行它时,会发现有趣的小错误。这是NFC读写器的核心功能,但由于其本质特征,似乎往往执行不力。

此功能是一次模拟多个NFC标签,除了此标签本身,还支持在同一领域的其他标签。 这有很多不同的用途,包括人们为不同的目的而将多张NFC卡放在一起,还有恶意用户的恶意使用,我们之后会谈到更多。


NFC通过使用防冲突程序来支持多个标签,读取器通过请求范围内的标签来验证其唯一ID的多个位,并且如果它们与读取器指定的相匹配,则进行响应。 这种二叉树搜索方法允许读写器在多个标签进入场时除去特定的标签。 更多信息可以参照:

http://nfc-tools.org/index.php?title=Libnfc:nfc-anticol

http://www.ti.com/lit/an/sloa136/sloa136.pdf


当两个标签同时响应时执行防冲突,从而使得传输无法被区分,因为读写器必须找到每个标签的唯一ID以独立地处理它们。 这些防冲突过程发生在最初的SELECT命令93 20和最终的SELECT命令93 70之间,并且按照上述TI pdf中的定义构建。 其他设备目前不实现这个功能,因为它通常在他们的用例之外,下面的Proxmark代码完全忽略了这个功能:

https://github.com/Proxmark/proxmark3/blob/master/armsrc/mifaresim.c#L393.


由于这个原因,NFC读写器中存在潜在的内存损坏漏洞往往不被考虑。 防冲突过程为UID响应提供了越来越多的位数,因此如果标签在同一时间连续响应,则可能被迫溢出到自己的存储器中。 这在第5页上面的TI pdf中有警告。


为了模拟多个标签,我的实现在收到来自读写器的关于标签的UID的请求时,发送长时间恒定负载调制流。 这使读写器相信两个标签正在通信,因此输入这些防冲突程序,然后设备可以为每个被模拟的UID处理这个程序。


我们在进行测试时考虑到了上述内存损坏的可能性。每次发送UID请求时,我都会让设备发送混乱的数据,从而导致读取器增加请求的位数。 随着读写器不断地请求更多的位, 设备会最终触发HardFault并拒绝响应,直到它被重新启动。


以下转储显示了这一过程:

00000041 727 RD: 93 37 ff 7f 00
00000042 715 RD: 93 40 ff ff 00
00000043 693 RD: 93 41 ff ff 01
00000044 711 RD: 93 42 ff ff 03
00000045 717 RD: 93 43 ff ff 07
00000046 722 RD: 93 44 ff ff 0f
00000047 764 RD: 93 45 ff ff 1f
00000048 748 RD: ff ff bf 00
00000049 746 RD: 93 47 ff ff 7f 00
0000004a 837 RD: 93 50 ff ff ff 00
0000004b 715 RD: 93 51 ff ff ff 01
0000004c 716 RD: 93 52 ff ff ff 03
0000004d 752 RD: 93 53 ff ff ff 07
0000004e 732 RD: 93 54 ff ff ff 0f
0000004f 770 RD: 93 55 ff ff ff 1f
00000050 730 RD: 93 56 ff ff ff 3f 00
00000051 742 RD: 93 57 ff ff ff 7f 00
00000052 679 RD: 93 60 ff ff ff ff 00
00000053 683 RD: 93 61 ff ff ff ff 01
00000054 670 RD: 93 62 ff ff ff ff 03
00000055 670 RD: 93 63 ff ff ff ff 07
00000056 756 RD: 93 64 ff ff ff ff 0f
00000057 765 RD: 93 65 ff ff ff ff 1f
00000058 716 RD: 93 66 ff ff ff ff 3f 00
00000059 634 RD: 93 67 ff ff ff ff 7f 00
0000005a 652 RD: 93 00 ff ff ff ff ff 00
0000005b 748 RD: 93 01 ff ff ff ff ff 01
...
00000096 3532 RD: 93 07 ff ff ff ff ff ff ff ff ff ff ff 7f 00
00000097 3536 RD: 93 00 ff ff ff ff ff ff ff ff ff ff ff ff 00
00000098 3530 RD: 93 01 ff ff ff ff ff ff ff ff ff ff ff ff 01
00000099 3437 RD: 93 03 ff ff ff ff ff ff ff ff ff ff ff ff 03
0000009a 3312 RD: 93 03 ff ff ff ff ff ff ff ff ff ff ff ff 07
0000009b 3434 RD: 93 07 ff ff ff ff ff ff ff ff ff ff ff ff 0f
0000009c 3434 RD: 93 05 ff ff ff ff ff ff ff ff ff ff ff ff 1f
0000009d 3366 RD: 93 06 ff ff ff ff ff ff ff ff ff ff ff ff 3f 00
0000009e 3379 RD: 93 07 ff ff ff ff ff ff ff ff ff ff ff ff 7f 00
0000009f 3618 RD: 93 00 ff ff ff ff ff ff ff ff ff ff ff ff ff 00
000000a0 3889 RD: 93 01 ff ff ff ff ff ff ff ff ff ff ff ff ff 01
000000a1 4215 RD: 93 03 ff ff ff ff ff ff ff ff ff ff ff ff ff 03


总结


所以你现在知道了,如何用10美元的成本创建一个可工作的NFC标签模拟器。


继续进行该项目应该有助于在NFC读写器中找到一些有趣的可利用的弱点。许多设备倾向于将加密作为最大的弱点,但协议的实现也可能有问题,特别是当涉及到内存损坏时。 我敢肯定,我们会找到一种方法来通过NFC恶作剧他人。



本文由看雪翻译小组 一壶葱茜 编译

原文链接: https://www.pentestpartners.com/security-blog/building-half-a-proxmark-for-10/


阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

最后于 2019-1-26 17:03 被admin编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (5)
雪    币: 371
活跃值: (94)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
darmao 1 2018-2-1 14:10
2
0
mark
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
csshaw 2018-2-1 16:20
3
0
mark
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
junkboy 2018-2-3 13:58
4
0
辛苦了
雪    币: 2057
活跃值: (2810)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
xiaohang 3 2018-2-6 16:23
5
0
啥时候我才能财务自由,就可以玩些乱七八糟的东西了
雪    币: 1507
活跃值: (265)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
一壶葱茜 2018-2-12 07:48
6
0
哈哈,这个门槛低,可以玩起~
游客
登录 | 注册 方可回帖
返回