ByteCTF2019之vip

先检查一下程序开的保护:

 程序只开了canary和nx保护.接下来用IDA分析反编译出的伪代码

 如上图,载edit函数中我们可以控制size的大小,并且程序没有做任何检查,我们再跟进去看下,

 第一个if语句中,因为dword_4040e0默认是0,所以我们不好利用。open函数正常情况下会返回一个文件描述符,read函数接下来会读入一些随机值,也不好控制。其实有办法控制open函数的返回值,这是这题的关键所在,接下来会讲。

程序还有自定义函数调用了prctl函数用来过滤一些系统调用,由于第一次碰到这个函数,所以我们着重分析一下。

查看man手册,给了如下解释:

prctl() is  called  with a first argument describing what to do (with values defined in <linux/prctl.h>), and further arguments with a significance depending onthe first one.

先看第一个程序给的第一个函数:

第一参数是38,我们需要查看一下宏定义才知道这个参数是什么意思,文件在/usr/include/linux/prctl.h中:

 接着查看man手册看看这个参数有什么作用:

PR_SET_NO_NEW_PRIVS (since Linux 3.5)
              Set  the  calling  thread's  no_new_privs bit to the value in arg2.  With no_new_privs set to 1, execve(2) promises not to grant privileges to do anything
              that could not have been done without the execve(2) call (for example, rendering the set-user-ID and set-group-ID mode bits, and  file  capabilities  non-
              functional).   Once set, this bit cannot be unset.  The setting of this bit is inherited by children created by fork(2) and clone(2), and preserved across
              execve(2).

              Since Linux 4.10, the value of a thread's no_new_privs bit can be viewed via the NoNewPrivs field in the /proc/[pid]/status file.

              For more information, see the kernel source file Documentation/userspace-api/no_new_privs.rst (or Documentation/prctl/no_new_privs.txt before Linux 4.13).
              See also seccomp(2).

由上可知当arg2的值为1时,execve不能使用了。题目给的第二个参数刚好是1,所以execve被禁了。

接下来看第二个prctl函数。

 还是先去/usr/include/linux/prctl.h查看对应的宏定义

 接着在man手册中查看该参数的含义

       PR_SET_SECCOMP (since Linux 2.6.23)
              Set the secure computing (seccomp) mode for the calling thread, to limit the available system calls.  The more recent seccomp(2) system  call  provides  a
              superset of the functionality of PR_SET_SECCOMP.

              The seccomp mode is selected via arg2.  (The seccomp constants are defined in <linux/seccomp.h>.)

              With  arg2 set to SECCOMP_MODE_STRICT, the only system calls that the thread is permitted to make are read(2), write(2), _exit(2) (but not exit_group(2)),
              and sigreturn(2).  Other system calls result in the delivery of a SIGKILL signal.  Strict secure computing mode is useful  for  number-crunching  applica‐
              tions  that may need to execute untrusted byte code, perhaps obtained by reading from a pipe or socket.  This operation is available only if the kernel is
              configured with CONFIG_SECCOMP enabled.

              With arg2 set to SECCOMP_MODE_FILTER (since Linux 3.5), the system calls allowed are defined by a pointer to a Berkeley  Packet  Filter  passed  in  arg3.
              This  argument  is  a pointer to struct sock_fprog; it can be designed to filter arbitrary system calls and system call arguments.  This mode is available
              only if the kernel is configured with CONFIG_SECCOMP_FILTER enabled.

              If SECCOMP_MODE_FILTER filters permit fork(2), then the seccomp mode is inherited by children created by fork(2); if execve(2) is permitted, then the sec‐
              comp mode is preserved across execve(2).  If the filters permit prctl() calls, then additional filters can be added; they are run in order until the first
              non-allow result is seen.

              For further information, see the kernel source file Documentation/userspace-api/seccomp_filter.rst (or Documentation/prctl/seccomp_filter.txt before Linux
              4.13).

由上可知arg2有两种选择,一种是SECCOMP_MODE_STRICT,另一种是SECCOMP_MODE_FILTER,我们还是在/usr/include/linux/seccomp.h中先查看一下宏定义,发现

 根据上面的解释可知arg3是一个struct sock_fprog的结构体(具体关于这个结构体读者可以自行百度,在此我就不再赘述),这个结构体决定prctl过滤什么系统调用。现在我们在看下IDA反编译出来的伪代码:

 很明显,我们在输入name时可以控制v1中的值从而控制这个结构体来禁用我们想要的系统调用。已知open函数在内部会调用openat函数,如果我们禁用调openat,open函数就会返回0,那么之前分析的存在溢出的read函数就可以利用了。

 这里我们需要一个工具:seccomp_tools,链接:https://github.com/david942j/seccomp-tools

猜你喜欢

转载自www.cnblogs.com/countfatcode/p/12506591.html
今日推荐