天天看点

write up --RCTF2017 Recho

RCTF2017的一题pwn题,之所以把这一题分享给大家是因为,这一题不像我们想象的那样简单,RCTF的质量还是很高的,接下来我们来看看这一题。

write up --RCTF2017 Recho

可以看到只有一个栈不可执行的保护。

write up --RCTF2017 Recho

可以看到这一题的漏洞点是很明显的,我刚开始想的是直接rop梭哈了,但是等我exp一半的时候,发现while里的read函数的返回值一直都是真,所以这个循环一直都是出不去的,那这不完犊子了吗。

这该咋解啊,出题人这么阴间的吗?在Linux上我们可以直接Ctrl+D结束我们的输入,但是我们打远程这种情况就莫得办法了呀。

然后就看了一些大佬的write up,发现pwntools里面有个函数shutdown函数可以强行的去结束获取输入,这样就可以结束这个循环了。

但是这样结束的话就不能进行ROP了,那这样我们还怎么泄漏libc基址来攻击呢?

这样我们就得重新分析了,我们再来看一看IDA的反编译代码看看还有什么可以利用。

溢出的漏洞已经有了

write up --RCTF2017 Recho

有上图的这些函数可以用

write up --RCTF2017 Recho

可以看到data段有个flag,那么也就是说,对应的远程主机上有这么一串flag只要我们能读取并输出即可。

这两个有用的信息一结合,在使用之前我做到的一题存在沙箱的一题,我一下就明白了,大佬们的思想,使用orw来把flag输出出来。

那你可能会问了这程序也没调用过open函数啊,你咋用open打开flag文本呢?

小了,我只能说小伙子你思考的范围小了,老夫给你看一样东西glibc源码,看完你就懂了。

小伙子你看好了老夫只教你一遍

write up --RCTF2017 Recho

这里可以看到alarm加上5的地方就是64位的系统调用syscall的地址。

在我们学习系统调用的时候是不是学到过,把相应的系统调用号放到rax(eax)寄存器中,然后使用syscall来进行系统调用。

write up --RCTF2017 Recho

然后看着一段汇编代码,先来了解一下al寄存器,首先在x86系统下的通用寄存器中有一个eax一般是用来保存返回值的,eax的低十六位是ax寄存器,而ax又分为高八位和低八位,而al寄存器正好是ax寄存器的低八位。

如果rdi寄存器中存的是alarm的got表,那利用这段汇编代码,使rdi里的地址再加上5,那rdi里的地址不就是syscall的首部了吗?

那这样我们调用alarm函数是不是就相当于是调用syscall

这样我们就有了syscall,那我们在找一个pop eax(rax)不就能想用什么系统调用自己就能实现什么系统调用了吗。

这样缺少open函数的问题就解决了,那么就可以使用orw来读取对应的远程主机的flag,然后将flag输出出来了。

那么我们打开flag文本进行读取,该读到什么地方呢?

我们可以读到bss段啊对吧,bss段也是可读可写的段,这样一来,我们就可以使用open打开flag的文本,把其中的内容read到bss段的某处,然后利用printf函数将flag里的内容输出出来。

可用的bss

write up --RCTF2017 Recho

我们来重新的捋一捋攻击的过程

利用有用的信息将alarm表里的内容改为syscall的首部,从而实现调用alarm函数就是调用syscall。

利用open函数打开远程主机的flag文本,然后使用read函数将flag的内容读取到bss段的某个位置。

然后利用printf函数将这段内容输出。

(当然我们还需要使用ROPgadget工具来找到可以被我们利用的pop rdi ,pop eax,pop rsi,pop rdx等等)

接下来就可以编写exp了。

继续阅读