分段错误时未写入核心转储

分段错误时未写入核心转储

我现在正在阅读 Shellcoder 手册:发现和利用安全漏洞,第二版。

在第二章中考虑了像这样的简单缓冲区溢出问题(C代码):

int main () {
    int array[5];
    int i;
    for (i = 0; i <= 255; i++ ) {
        array[i] = 10;
    }
}

作者编译代码cc并执行它:

shellcoders@debian:~/chapter_2$ cc buffer2.c
shellcoders@debian:~/chapter_2$ ./a.out
Segmentation fault (core dumped)

然后查看了写入的核心转储gdb

shellcoders@debian:~/chapter_2$ gdb -q -c core
Program terminated with signal 11, Segmentation fault.
#0 0x0000000a in ?? ()
(gdb)

问题是我的情况下还没有写入核心转储。我只有一条消息:zsh: segmentation fault ./a.out

我在 VirtualBox 中使用 Kali 2021.4a。我曾尝试更改默认 shell,chsh -s /bin/bash但它没有改变任何内容,并且终端保持打开状态zsh

如何在错误时写入核心转储?看起来它应该是与可执行文件写入同一目录中的文件。

答案1

首先,您需要使用ulimit命令(在 bash 或 zsh 中)检查限制内的核心文件大小。

# ulimit -c
0

如果它为零,则需要增加它。例如,将其增加到无限:

# ulimit -c unlimited
# ulimit -c          
unlimited

其次,您需要检查 coredump 是在哪里创建的。在较旧的发行版上,默认值通常是 CWD 中名为“core”的文件。这可能是本书撰写时的默认设置。

# /sbin/sysctl kernel.core_pattern
kernel.core_pattern = core

然而,如今在大多数发行版上,情况已不再如此。今天通常使用以下方式生成核心systemd-coredump(8)

# /sbin/sysctl kernel.core_pattern
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e

来自男人systemd-coredump(8)

默认情况下,systemd-coredump 会将核心转储记录到日志中,如果可能的话还包括回溯,并将核心转储(进程内存内容的映像)本身存储在外部文件中 /var/lib/systemd/coredump

您可以在该目录中找到核心转储,也可以使用coredumpctl列出这些(您可能需要 sudo 或以 root 身份运行):

# coredumpctl list
TIME                            PID   UID   GID SIG PRESENT EXE
Wed 2022-01-26 12:53:06 IST   10347   111   222 11  *       /tmp/a.out

*“PRESENT”下方的 表示已创建核心转储文件。

您可以使用以下命令查看(压缩的)核心转储的位置coredumpctl info <pid>

# coredumpctl info 10347 |grep Coredump
      Coredump: /var/lib/systemd/coredump/core.a\x2eout.111.1bd8e22a25e844f1b03a87d378b4ed9b.10347.1643194386000000.xz

您可以使用xz命令解压缩该文件:

# xz --decompress --stdout '/var/lib/systemd/coredump/core.a\x2eout.111.1bd8e22a25e844f1b03a87d378b4ed9b.10347.1643194386000000.xz' > core

或者使用以下命令将核心转储到某个目的地。

# coredumpctl -o core dump 10347

这些命令中的任何一个都会创建该文件:

# gdb -q -c core
[New LWP 10347]
Core was generated by `/tmp/a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000000af7a56725 in ?? ()

答案2

根据man core,有多种情况不生成核心转储文件:

   *  The process does not have permission to write the core file.…

   *  A (writable, regular) file with the same name as would be used
      for the core dump already exists, but there is more than one
      hard link to that file.

   *  The filesystem where the core dump file would be created is
      full; or has run out of inodes; or is mounted read-only; or
      the user has reached their quota for the filesystem.

   *  The directory in which the core dump file is to be created
      does not exist.

   *  The RLIMIT_CORE (core file size) or RLIMIT_FSIZE (file size)
      resource limits for the process are set to zero;…

   *  The binary being executed by the process does not have read
      permission enabled.…

   *  The process is executing a set-user-ID (set-group-ID) program
      that is owned by a user (group) other than the real user
      (group) ID of the process, or the process is executing a
      program that has file capabilities…

   *  /proc/sys/kernel/core_pattern is empty and
      /proc/sys/kernel/core_uses_pid contains the value 0.  

   *  (Since Linux 3.7) The kernel was configured without the
      CONFIG_COREDUMP option.

因此,您应该首先检查这些条件,特别是最有可能的最后一个:CONFIG_COREDUMP 内核选项

顺便说一句,还请注意:

在使用 systemd(1) 作为 init 框架的系统上,核心转储可能会放置在由 systemd(1) 确定的位置。

在许多实现下,它对应于某个/var/lib/systemd子目录。

相关内容