《锁王创造营》 第一关:初出茅庐 – 作者:TC111金牛座

《锁王创造营》 第一关:初出茅庐

前言

0机关 (2).jpg

最近大热的网播剧《鬼吹灯之龙岭迷窟》着实让屏幕前的观众跟着过了一把古墓闯关寻宝的瘾,剧中主角胡八一、王胖子、shirley杨强强联手,带领一众人马凭着生平学识积累、过人的胆识以及精良的装备,破解重重机关锁制,最终取得龙骨天书,获取破解诅咒的关键线索。

0机关 (1).jpg

影视剧里,摸金校尉与墓主人穿越时空斗智斗勇,为取得墓室秘宝,破解墓主人设置的一道道关卡。而现实生活中,地面上的梁上君子也从未停止过对普通老百姓家门口那一把锁的“钻研热情”,从最早的溜门撬锁,到如今的锡纸开锁,真可谓焚膏继晷、通宵达旦。

0锁王.jpg

如今,物联网技术迅速发展,作为新时代守护老百姓生命财产的重要一环,智能锁已成为智能家居市场上发展最为迅速的品类之一。有研究表明,随着市场的需要,智能锁所占的份额逐年增加,大有超过传统锁具,成为主流的趋势。不过就目前而言,智能锁暴露的安全问题比传统机械锁更大,因为,机械锁具的攻击点主要在锁芯和锁体结构,而智能锁除以上提到的两点之外,还涉及到云端通信、移动端、集成电路模块、指纹、声纹、图像识别、RFID 等关键技术,所以暴露的攻击点更多、攻击方式更为隐蔽,造成的危害可能更大。此外,许多智能锁厂商并非由传统锁具厂商转型过来,在锁具生产加工制造上,更容易忽略某些机械和设计结构上的物理缺陷,这也是智能锁在安全问题上必须要重视的地方。

正因智能锁具已成为人们现实生活中新一代的保护神,其安全可靠性就是其生命力所在,不安全锁具无疑是给生活留下了极大的安全隐患。数智安全研究院对锁具安全研究着手多年,参与过很多智能锁具安全方面的会议、沙龙等,在锁具安全研究方面也有了些许成果。1.png

(破解某款智能锁)

2.png

(线下沙龙锁具安全展台)

近日,数智安全实验室的小伙伴本着猎奇心理参与了Microcorruption发起的一个智能锁破解闯关的游戏,18道关卡,历时五天,最终全部破解,由于游戏关卡设置的新颖以及破解过程的种种趣味体验,也为了让更多志同道合的朋友更好的了解智能锁具安全攻防,我们决定在每周更新的内容里增加一个《锁王创造营》系列,每期发布一些智能锁具安全方面的知识以及一道关卡的破解记录,感兴趣的小伙伴可以先不参考我们的思路,自己尝试着破解看看哦!

0机关 (1).png

(闯关开始啦,快速转动你们的小脑筋!!)

Microcorruption CTF

Microcorruption是Matasano Security 与 Square制作的一款智能锁在线CTF”游戏“,该CTF专注于嵌入式安全和挑战玩家逆向工程的一个虚构“Lockitall LockIT Pro”锁系统。

3.png

每一个Level都通过反汇编窗口,内存窗口,寄存器窗口和调试控制台进行调试,如图所示,这是由Web浏览器构建的调试器。在调试控制台上输入“help”,查看调试指令。若刚开始挑战,建议先完成Tutorial新手教程,它将为你介绍这个调试器,以及如何达成目标过关。

4.png

如反汇编窗口所示,它是由MSP430控制的锁,实时模拟真实设备,我们的目标是在内存中寻找特定的输入,或者找到漏洞然后进行利用达到解锁的目的。该CTF是对嵌入式安全性的不错介绍,不需要购买真实的硬件,甚至还有用户手册,非常适合初学者入门。

玩法介绍

下面我们先看第一level——Tutorial调试器指导教程,此教程将逐步介绍这个web调试器。

使用continuec命令运行程序。

5.png

运行后,若没有其它断点,将弹出IO控制窗口,这里显示控制台的输出,提示我们输入密码。

6.png

然后下面是用户输入文本框,我们输入“test”,然后“send”提交,锁将会提取该输入。

7.png

继续c命令运行。

8.png

运行完毕后可以看到,底下的另一个IO控制窗口提出输出:无效密码。

9.png

此时,意味着程序执行完毕,所以CPU将会关闭。需要在控制台上输入reset,进行重置CPU状态。

10.png

重置(reset)CPU以后,现在在main函数上设置断点,查看main函数做了什么事情。在控制台窗口输入命令:break main;或者输入:b main

11.png

使用c命令运行,程序将会断在main函数(红色代表正在待执行的指令)。由蓝色背景设置的就是断点的位置。我们也可以通过鼠标单击它,来删除断点或者设置断点。

12.png

寄存器窗口显示断点时的状态,它们都是由16进制显示。右侧显示当前程序计数器pc处的指令。

13.png

现在我们可以使用steps命令进行单步步入调试。该命令有可选参数,后面加上5a,将步过5a条指令。

14.png

现在执行到INT函数中,这是锁与用户交互的重要方式,通过发出中断,锁可以打印字符,请求输入或执行其他功能的操作。

15.png

继续使用`c命令运行,直到弹出请求输入。在不知道密码的情况下,仍输入“test”。

16.png

现在使用out或者f命令退出当前函数,它一直运行直到遇到下一条“ret”指令。经过几次“ret”之后,回到main函数中,0x444c是调用check_password函数,似乎是一个关键检查函数,尝试在该函数设置断点break check_password

17.png

使用c命令,程序成功断在check_password函数。待执行的指令是“mov.b @r15, r14”,这意味着将r15寄存器寻址的内容移动到r14寄存器中。

18.png

先查看r15寄存器,r15的值为0x439c。该地址正是“test”字符串的起始地址。

19.png

在控制台窗口输入s单步命令,再查看寄存器窗口中r14的变化。r14的值变为0x74,0x74是字符“t”的ascii码。

20.png

继续“s”命令单步执行,“inc r15”意味着r15自增1。

21.png

执行下一条指令,继续“s”命令单步执行,“inc r12”意味着r12自增1。

22.png

下一条指令,“tst r14”,这条指令比较r14是否为零。它将r14中的值与常数0进行比较,结果将在状态寄存器sr中;若r14为零,这里则设置零标志位。

23.png

单步执行“tst r14”后,紧接着是“jnz $-0x8”(如果不为零,则跳转),jnz是条件跳转指令,当未设置零标志位时,它将移动程序计数器pc,向后跳8个字节。

24.png

此时,我们将鼠标悬停在状态寄存器sr上,可以查看设置的标志位。“C”表示已设置进位标志位(Carry),这里未设置零标志位。所以这里”jnz“将实现跳转。

25.png

s执行单步之后,向前移动0x8个字节,回到了开始的地方。所以这个循环中的主要的操作是,读取一字节我们的输入,便将r12寄存器加1。

26.png

现在我们跳出这个循环,直到r14寄存器为0使,才会跳出循环,即在0x448e处设置断点break 448e。使用unbreak check_password可以删除其它断点。随后使用“c”命令运行。*

27.png

此时运行的指令是“cmp #0x9, r12”,它比较两个值,也就是把r12的值与立即数0x9进行比较,cmp的功能相当于减法指令,只是不保存结果,而是设置状态寄存器中的零标志位。此时我们的r12为5,这是因为我们输入了4个字符的密码,其中最后一个是空字节。

28.png

执行完“cmp #0x9, r12”后,紧接着是jeq/jz指令(如果相等则跳转/如果为0则跳转,它们是等效的),它和jnz一样都是条件跳转。如果cmp比较为真(如果r12为9),则移动pc向后跳转6个字节。但是在这里,cmp比较为假(因为r12为5),未设置状态寄存器的零标志位,所以不进行跳转。

29.png

命令s单步之后,将r15寄存器清0,然后返回。r15一般用作存放函数返回值结果,因此chekc_password函数的返回值为0。

30.png

我们在这里直接更改程序计数器pc,使用let pc = 4498,将pc指向地址0x4498(mov #0x1, r15),将立即数0x1移动到r15寄存器中。然后使用f命令回到main函数,我们看main函数将会发生什么。

31.png

在main函数中,再次运行”tst”指令,检查r15(check_password函数的返回值)是否非零,并相应地设置状态零标记位。我们知道r15为1,并且当r15不为0时发生跳转。使用s命令继续单步执行。

32.png

单步执行后,跳转到访问“Access Granted!”字符串,然后put打印。接着调用unlock_door函数解锁。

33.png

使用c命令运行。刚刚我们通过更改pc,到达所需指令进行欺骗。接下来需要通过正确的密码解锁。

34.png

reset之后,使用c运行到请求输入窗口。在请求窗口中,我们还可以勾选16进制编码输入。

35.png

现在输入正确的密码,在之前check_password时,我们知道r12必须是9。因此我们需要增加到8个字符的输入,末尾自动包含1个空字符。尝试使用8位的“password”作为输入。

36.png

使用c运行,密码正确!

37.png

现在我们在实锁中执行它,在控制台窗口输入solve。这时我们将无法进行任何调试,只能输入密码。

38.png

解锁成功!现在我们返回地图,挑战下一关。

42.png

第一关 New Orleans

经过Tutorial,我们对调试器已经有了详细的了解。现在开始正式关卡的挑战,它的每一关都是世界各地的某个城市名,随着level数量的增加,难度也在增加。现在开始第一个Level的挑战——New Orleans。

39.png

OVERVIEW

  • This is the first LockIT Pro Lock.

  • This lock is not attached to any hardware security module.

查看反汇编窗口,开头是一些初始化或设置工作的函数。我们选择在main处设置断点,在控制台窗口输入b main

4438 <main>
4438: 3150 9cff     add   #0xff9c, sp
443c: b012 7e44     call   #0x447e <create_password>
4440: 3f40 e444     mov   #0x44e4 "Enter the password to continue", r15
4444: b012 9445     call   #0x4594 <puts>
4448: 0f41           mov   sp, r15
444a: b012 b244     call   #0x44b2 <get_password>
444e: 0f41           mov   sp, r15
4450: b012 bc44     call   #0x44bc <check_password>
4454: 0f93           tst   r15
4456: 0520           jnz   #0x4462 <main+0x2a>
4458: 3f40 0345     mov   #0x4503 "Invalid password; try again.", r15
445c: b012 9445     call   #0x4594 <puts>
4460: 063c           jmp   #0x446e <main+0x36>
4462: 3f40 2045     mov   #0x4520 "Access Granted!", r15
4466: b012 9445     call   #0x4594 <puts>
446a: b012 d644     call   #0x44d6 <unlock_door>
446e: 0f43           clr   r15
4470: 3150 6400     add   #0x64, sp

浏览maincall的函数,create_passwordputsget_passwordcheck_passwordunlock_door函数,其中create_password似乎创建生成了密码,pust是打印提示字符串,get_password是请求输入密码,而check_password是对密码进行检查,和前一关一样unlock_door是解锁函数。

首先进入create_password看看。该函数正在mov.b一字节一字节的的数据到r15(0x2400)寻址的内存中,这些数据似乎是ascii码,最后一个字节以\x0结尾,合并在一起组成一个字符串。

447e <create_password>
447e: 3f40 0024     mov   #0x2400, r15
4482: ff40 4600 0000 mov.b   #0x46, 0x0(r15)
4488: ff40 6c00 0100 mov.b   #0x6c, 0x1(r15)
448e: ff40 6c00 0200 mov.b   #0x6c, 0x2(r15)
4494: ff40 4900 0300 mov.b   #0x49, 0x3(r15)
449a: ff40 6600 0400 mov.b   #0x66, 0x4(r15)
44a0: ff40 2800 0500 mov.b   #0x28, 0x5(r15)
44a6: ff40 3900 0600 mov.b   #0x39, 0x6(r15)
44ac: cf43 0700     mov.b   #0x0, 0x7(r15)
44b0: 3041           ret

我们n命令步过这个函数,然后查看内存0x2400的内容。"FllIf(9"莫非是密码?

40.png

接下来在check_password下断点,然后c命令运行。在请求输入时,选择以"FllIf(9"作为输入。

果然,在地址0x44c2中”cmp.b @r13, 0x2400(r14)“比较1个字节,r13寄存器寻址的正是我们输入的密码,而0x2400(r14)是create_password函数生成的字符串"FllIf(9"。经过循环比较每一个字节,判断我们的输入和"FFllIf(9"是否相等,最后设置返回值r15。

44bc <check_password>
44bc: 0e43           clr   r14
44be: 0d4f           mov   r15, r13
44c0: 0d5e           add   r14, r13
44c2: ee9d 0024     cmp.b   @r13, 0x2400(r14)
44c6: 0520           jne   #0x44d2 <check_password+0x16>
44c8: 1e53           inc   r14
44ca: 3e92           cmp   #0x8, r14
44cc: f823           jne   #0x44be <check_password+0x2>
44ce: 1f43           mov   #0x1, r15
44d0: 3041           ret
44d2: 0f43           clr   r15
44d4: 3041           ret

至此,我们已经猜中密码正是create_password函数生成的字符串,使用c命令运行,测试正确。

解锁

在控制台窗口输入”solve“,然后在请求输入窗口以字符串输入:FllIf(9,或者16进制输入:466c6c49662839。

41.png

参考

1、 MSP430 用户指南 http://www.ti.com.cn/cn/lit/ug/zhcu032i/zhcu032i.pdf

2、智能锁具攻防一:初探 https://yaseng.org/intelligent-lock-attack-and-defense-1.html

3、智能锁行业安全分析报告 https://yaseng.org/intelligent-lock-industry-safety-report.html

4、物联网安全百科 https://iot-security.wiki

来源:freebuf.com 2020-05-14 15:29:19 by: TC111金牛座

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论