[MicroCorruption] Jakarta

既然第一次写MicroCorruption,必须先安利一下这个 网站:https://microcorruption.com/

反正我安利的网站都有一个特点,就是很适合很适合小白,所以大佬们请移玉臀。

这是一张MicroCorruption网站的截图,网站的title其实是Embedded Security CTF,是嵌入式设备的CTF。

说得好听是嵌入式设备的CTF,其实只不过是单片机的Pwn而已。小白能力有限,Pwn一下Msp430,是一个不错的开始。

下面是游戏的界面。

这个游戏的设定是有一把Msp430控制的锁,你现在要在不知道密码的情况下,利用二进制漏洞把它打开。它的每一关都是世界上的一个地名,可能意思是要你征战全世界?Whatever.

游戏给你提供了一个调试器,可以从界面看到反汇编的代码,内存的情况,特殊寄存器的情况等。调试器通过Debugger Console控制。刚开始学习的话可以看看它给的Tutorial,非常有用。

于是我们就可以开始今天的游戏了。

学期开始的时候我花了两三天打了几个,感觉醍醐灌顶。但是后来苦于项目结题以及考试什么的,就一直搁置了…悲痛欲绝…

现在终于可以继续了!这次是Jakarta.

以下是汇编代码:

完整版的附件在此:pwn_integer_overflow

完整来看是有一丢丢的长,但其实我们关注的重点放在<login>函数就好了。

曾经我在Youtube上见过大神手画Control flow,很帅。

于是我也来画一下好了。

 

username输入 “AB”*8 观察一下内存:

这个字符串首先会被存在一个缓冲区

然后数完长度之后会被<strcpy>copy到目标的内存,其实也就是栈里。

这个时候我们看到了,在栈底,有一个似曾相识的数字,4044?是什么?

显然这就是小端存储的<login>的返回地址4440了,这也是我们通过栈溢出能压到的唯一一个返回地址。

这个程序比较奇葩的一点是长度检查是在copy之后进行的。

两次都是这个样子。其实送人头送得很明显,意思就是你无论如何都能把你的输入送到栈里,只不过后面的长度校验你可能通不过。

那于是我们的目标就会变成绕过后面的长度检查。这里的漏洞实际上就是这两句代码:

查一查cmp.b,就会知道.b是指令助记符后缀,会导致字节操作,相当于是判断下面这个式子。

也就是说,尽管r15是16位的寄存器,比较的时候也只比较低八位。所以就很清楚了,可以通过溢出r15到0x0100使得低八位小于等于0x20。

这个就有些类似于所谓的整数溢出漏洞。

于是我们就可以开始构造Payload。

需要注意两点:

  1. 第一轮的校验在长度不超过0x20的时候可以通过
  2. 第二轮的校验,因为需要覆盖<login>的返回地址,所以必须通过溢出r15绕过

所以将Payload放在第一轮的32个字节内,然后将返回地址覆盖为Payload的起始地址即可。

我们目标的内存状态是这样的:

这样通过整数溢出绕过第二轮的校验之后,<login>调用<test_username_and_password_valid>会得到密码错误,然后结束ret。

这个时候的返回地址被覆盖成了3ff2,于是程序寄存器就是变为3ff2,指向语句30401c46。

30401c46是 mov #461c, pc 的机器码,这个需要通过网站提供的汇编器获得,如下图。

于是可以将Payload构造如下:

username: “30401c46″+”41″*(0x20-4)

password: “42”*4+”f23f”+”42″*(0x100-0x20-6)

可见r15被溢出成了0x0100,内存也已经变成我们想要的样子了。

接下来我们看到,第二次校验被绕过,程序继续执行。

最后结果,当然是很明显的。

Leave a Comment