一些Pwn操作中常见的迷思(持续更新)
system函数
我们使用system函数getshell时经常使用/bin/sh字符串,但这是必须的吗?首先我们需要了解system函数是如何工作的,通过查看glibc的源码,我们看到system函数最终使用了clone系统调用来创建一个新线程,然而该线程中执行的并非system函数的参数,而是一个以posix_spawn_args结构体为参数,名为__spawni_child的函数。接下来的一系列操作如图所示(根据glic 2.29源码绘制):
1 |
|
可惜在这里,我们依然无法回答上面提出的问题。要想回答这一问题并避免继续再函数实现中套娃,我们需要使用一种略微取巧的方法:我们可以使用strace -f来获得执行system函数中使用到的系统调用。写一个程序如下:
1 |
|
编译后使用strace -f ./sys运行,我们看到了下面的输出:
查找资料后我们发现,linux系统调用stat可以被用来确定一个文件的状态,可以看到我们的程序搜索了一系列路径,这些路径实际上是由PATH环境变量所规定的。相应的文件查找到之后,系统使用clone创建了一个线程,并在这个线程中使用execve系统调用来运行这个文件。 回答:我们在system函数中不一定需要指定绝对路径,对于位于PATH中的可执行文件,我们可以仅仅使用文件名来运行。
pwntools的NX enabled说明了什么
首先,将NX说成是栈不可执行是一种不全面的说法。实际上NX是AMD用于称呼他们的x86-64架构下也表条目的第63位(最高位)的说法,Intel将其称为XD位。这个标识位与所有页息息相关,不仅仅是栈所在的页。 然而pwntools是怎样得知程序是否为NX的呢?最快的方法是看源码,在源码中判断ELF是否为NX的代码如下:
1 |
|
可以看到,程序依据ELF文件Header Table中的信息来判断程序是否被NX。这里有一篇文章详细讲解了可执行栈的详细信息。 然而经过实验我们可以看到,关闭了nx的程序的bss段在程序运行期间是可执行的,具体原因为何还无从知晓。