如何复制一个我有执行权限但无复制权限的文件?

如何复制一个我有执行权限但无复制权限的文件?

我在 /etc/ 的子目录中有一个文件,我想复制该文件,我可以以普通用户身份运行该文件,但是当我运行时

cp /etc/subdir/desired_file .

我被拒绝许可。但是我可以在没有超级用户权限的情况下执行该文件。有没有办法让我将该文件复制到另一个目录中?

编辑:不更改文件权限

答案1

cp src dst读取文件的内容src 并将其写入dst其创建的新文件。

所以它需要对该文件的读取权限。

至少在 Linux 上以及某些文件系统(例如 )上btrfs,它可以用 a 替换read()s + write()s 来ioctl (dest_fd, FICLONE, src_fd)执行所谓的转发链接副本其中数据最初并未在磁盘上复制,但即使如此,它仍然需要打开源文件以读取到src_fd.

如果复制文件足以绕过读取限制,那么权限系统将被严重破坏。

现在,您可以使用不同的名称创建指向该文件的新链接,而不是复制文件:

后:

ln from/src to/dst

为此,您只需要对from目录进行搜索访问和对目录进行搜索+写入访问to,并且dstsrc.您最终会得到srcdst,但请注意,它们是链接到两个不同目录(或具有不同名称的同一目录)的同一文件。

现在,如果src可执行文件,并且是一种本机可执行格式(例如,与脚本相反,尽管您无法在没有读取权限的情况下运行脚本,因为解释器确实需要能够读取它),这意味着允许系统映射内容将可执行文件放入其中之一的内存中你的过程,这相当于代表您阅读它。

系统会注意不允许绕过读取限制。例如,至少在 Linux 上,当接收到 SIGQUIT 等信号(在Ctrl+上发送\ )时,进程不会生成核心转储。它不会让您阅读/proc/<pid>/maps/proc/<pid>/mem执行该过程:

$ cp /usr/bin/sleep .
$ chmod 111 sleep
$ ./sleep inf &
[1] 86474
$ cat /proc/$!/maps
cat: /proc/86474/maps: Permission denied
$ cat /proc/$!/mem
cat: /proc/86474/mem: Permission denied

它也不会让您附加调试器,即使使用kernel.yama.ptrace_scope = 0.

但进程本身显然可以读取自己的内存,所以如果你能说服它把它转储到某个地方,你就可以恢复一些文件中的数据。

如果文件是动态链接的 ELF 可执行文件,并且不是 setuid/setgid...(未启用安全执行模式),至少在 GNU/Linux 系统上,您可以说服动态链接器将任意代码注入可执行文件中机制$LD_PRELOAD,或者告诉它使用它所使用的共享库的修改版本,这些库已被劫持以通过更改$LD_LIBRARY_PATH.

例如:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

static void init(void) __attribute__((constructor));
static void init(void)
{
  FILE *maps, *dst;
  char exe[4096], path[4096];
  char *start, *end;
  off_t offset;
  int n;

  n = readlink("/proc/self/exe", exe, sizeof(exe));
  exe[n] = '\0';
  dst = fopen(getenv("DST"), "w");
  maps = fopen("/proc/self/maps", "r");

  while((n = fscanf(maps, "%p-%p%*s%lx%*s%*s%*[ ]%[^\n ]\n", &start, &end, &offset, path)) != EOF) {
    if (n == 4 && !strcmp(path, exe)) {
      printf("Dumping [%p - %p] from %s at offset %#lx\n", start, end, path, offset);
      fseek(dst, offset, SEEK_SET);
      fwrite(start, end - start, 1, dst);
    }
  }
  exit(0);
}

(错误处理留给读者作为练习)

编译为:

gcc -fPIC -shared -o hack.so that-file.c

运行src为:

DST=./dst LD_PRELOAD=./hack.so ./src
truncate -r src dst

会将文件中映射到内存的部分转储到./dst文件中。

如果您有以下内容的可读副本src并使用:

cmp -l src-copy dst | perl -pe 's/\d+/sprintf"%#x",$&-1/e'

并将输出与objdump -h src-copy偏移量上的输出进行匹配,您会发现它并不相同,因为某些部分丢失或已被动态链接器修改。在我的测试中,它们是:

 20 .init_array   00000008  0000000000009bb0  0000000000009bb0  00008bb0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 21 .fini_array   00000008  0000000000009bb8  0000000000009bb8  00008bb8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 22 .data.rel.ro  000000b8  0000000000009bc0  0000000000009bc0  00008bc0  2**5
                  CONTENTS, ALLOC, LOAD, DATA
 23 .dynamic      000001f0  0000000000009c78  0000000000009c78  00008c78  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 24 .got          00000190  0000000000009e68  0000000000009e68  00008e68  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 26 .bss          000001b8  000000000000a080  000000000000a080  00009080  2**5
                  ALLOC

.text.rodata部分至少是完整的,这表明尝试在不可读的动态链接 ELF 可执行文件中隐藏秘密是徒劳的。

答案2

这里可能有两种情况:

  1. 要么你缺乏读取权限所需文件。您可能拥有该文件的执行权限,但要查看或复制该文件,需要读取权限。

  2. 或者您缺乏目标目录的写权限。

请通过https://www.tutorialspoint.com/unix/unix-file-permission.htm。它将帮助您了解 unix 权限。

所有者可以使用以下方式授予权限chmod命令。

相关内容