【发布时间】:2018-04-21 05:13:15
【问题描述】:
[编辑]
这只是我进行的一个实验,我想看看我是否可以欺骗内核从一个未命名的管道执行一个精灵,并使用 /lib64/ld-linux-x86-64.so.2 进行进程替换,我知道这是在黑暗中拍摄的,但我只是希望看看是否有人可以回答我为什么它不起作用
$ /lib64/ld-linux-x86-64.so.2 <(gcc -c -xc <(echo $'#include <stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o /dev/stdout)
/tmp/ccf5sMql.s: Assembler messages:
/tmp/ccf5sMql.s: Fatal error: can't write /dev/stdout: Illegal seek
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
/tmp/ccf5sMql.s: Fatal error: can't close /dev/stdout: Illegal seek
/dev/fd/63: error while loading shared libraries: /dev/fd/63: file too short
我认为这可能是由于我得到的结果不同。
$ /lib64/ld-linux-x86-64.so.2 <(gcc -fPIC -pie -xc <(echo $'#include
<stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o
/dev/stdout|cat|perl -ne 'chomp;printf')
/dev/fd/63: error while loading shared libraries: /dev/fd/63: ELF load
command past end of file
$ /lib64/ld-linux-x86-64.so.2 <(gcc -fPIC -pie -xc <(echo $'#include
<stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o
/dev/stdout|cat|perl -0 -ne 'chomp;printf')
/dev/fd/63: error while loading shared libraries: /dev/fd/63: ELF file ABI
version invalid
所以我在玩 ASM 并注意到您无法将输出组装或链接到标准输出。
$ as /tmp/lol.s -o /dev/stdout
/tmp/lol.s: Assembler messages:
/tmp/lol.s: Fatal error: can't write /dev/stdout: Illegal seek
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
as /tmp/lol.s -o /tmp/test.o
$ ld /tmp/test.o -o what -lc
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002a0
$ exec 9< <(ld /tmp/test.o -o /dev/stdout -lc)
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002a0
ld: final link failed: Illegal seek
给定代码如下:
.file "63"
.section .rodata
.LC0:
.string "I work"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-16)"
.section .note.GNU-stack,"",@progbits
.file "63"
.section .rodata
谁能告诉我为什么不能组装对象或将对象链接到标准输出?请尽可能深入。要查看编译器生成该代码的完整过程,您可以使用以下命令:
$ exec 7< <(gcc -c -xc <(echo $'#include <stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o /dev/stdout)
如果您组装和链接我之前提供的程序集并希望正确执行它,您需要调用 /lib64/ld-linux-x86-64.so.2 /path/to/output 否则它只会说糟糕的精灵解释器。
# ./what
bash: ./what: /lib/ld64.so.1: bad ELF interpreter: No such file or directory
# /lib64/ld-linux-x86-64.so.2 ./what
I work
【问题讨论】:
-
如果
stdout是一个可查找的文件,您可能可以。as的第一个错误意味着它生成的目标文件是伪造的 (Fatal error: can't write /dev/stdout: Illegal seek)。所以即使ld可以从管道中读取目标文件,它也不起作用。 -
另外,如果您不使用
--dynamic-linker更改非工作默认值,您的“bad ELF interpreter”错误是正常的。 stackoverflow.com/questions/5821237/…。 IDK 为什么 binutils 不会将ld的默认值更改为/lib64/ld-linux-x86-64.so.2的正常多架构位置 -
你为什么这么问?几句关于动机和背景的句子会很有帮助(我确实试着猜测它们)。所以编辑你的问题来改进它!
-
是的,我想了很多,或者您可以按照答案中的说明链接到 crt 的东西。我的目标是试图欺骗内核从 procfs 中执行 elf(知道这可能行不通,但听起来很有趣)。