파이프에서 네이티브 바이너리를 실행하는 방법이 있습니까?


13
echo 'main(){}' | gcc -xc - -o /dev/stdout | ???

유닉스 계열 시스템에서 출력 바이너리를 실행하는 방법이 있습니까?

편집 : 내가 쓸 수있는 샌드 박스 환경에서 g의 출력 ++ 실행하는 데 필요한 모든 (I 약속, 악성 아무것도) 파일을.


기본 보안 메커니즘이이를 방지해야한다고 생각합니다. 그러나 C 코드를 즉석에서 실행 해야하는 경우을 사용하십시오 csh.
rozcietrzewiacz

답변:


10

나는 이것이 가능하다고 생각하지 않습니다. 간부 (2) 시스템 콜은 항상 파일 이름 또는 절대 경로 요구 (파일명 항상이다 char*). posix_spawn파일 이름에 대한 요구 사항도 비슷합니다.

가장 가까운 것은 출력을 명명 된 파이프로 파이프하고 파이프에서 실행을 시도하는 것입니다. 셸에서 --x--x--x비트가 설정 되지 않은 파일의 실행을 거부 할 수도 있지만 작동 할 수 있습니다 . 파이프를 작성하고 mkfifo(1)작동시킬 수 있는지 확인하십시오.

또 다른 방법은 표준 입력을 읽고, 파일을 템포 레이 영역에 쓰고, -x 비트를 설정하고, 포크와 execs를 삭제 한 파일을 작성하는 것입니다. inode와 내용은 프로그램 실행이 끝날 때까지 유지되지만 파일 시스템을 통해 액세스 할 수 없습니다. 프로세스가 종료되면 inode가 해제되고 스토리지가 사용 가능 목록으로 리턴됩니다.

편집 : Mat가 지적한 것처럼 로더가 실행 파일에서 요청 페이지를 요청하려고 시도하면 파일에서 무작위 탐색 트래픽이 생성되고 파이프에서는 불가능하므로 첫 번째 접근 방식이 작동하지 않습니다. 이것은 두 번째와 같은 접근 방식을 남깁니다.


2
파이프 트릭이 작동하면 정말 놀랐습니다. 파이프에서 무작위 탐색을 할 수 없으며 mmap 할 수 없습니다-런타임 로더 / 링커를 귀찮게 할 것입니다. :) 두 번째 제안은 좋을 것 같습니다. 그러나 임시 파일이 없으면 아무 것도 만들 수 없습니다.
Mat

@ 매트-당신이 옳은 것 같아요. 실행 파일의 요구 페이징은 파이프에서 작동하지 않는 임의 액세스 트래픽을 발생시킵니다. 아이러니하게도 실제로 SVR2.0 (요청 페이징을 사용하지 않은 마지막 버전)에서 실제로 작동했을 수도 있습니다. 내 나이를 보여주기 위해 실제로 SVR2.0을 O / S로 한 번 AT & T 3B2 / 400을 사용했습니다.
ConcernedOfTunbridgeWells

UPX와 같은 exe 패커 는 읽기 전용 미디어 에서 압축 해제 실행을 수행 할 수 있다고 확신 합니다. 압축 풀기보다는 파이프에서 읽을 수 있도록 압축 된 실행 파일에 고정 된 스텁을 수정하면 작동 할 수 있습니다.
Mat

@ 매트 패커는 이미 이미지를로드했지만 새로운 프로세스를 시작하지 않습니다. 비슷한 작업을 수행하려면 입력 데이터 (보안 취약점으로 간주 됨)로 임의로 이동하는 프로세스 중 하나가 필요합니다.
Alex B

@Alex B : 입력 데이터로 임의 점프하는 방법을 구체적으로 묻습니다. 정확히 그렇게 하자고 불평하는 이유는 무엇입니까? 샌드 박스의 목적은 특히 수행하려는 작업을 방지하기위한 것입니까?
David Schwartz

7

memfd syscall을 사용하는 솔루션 : https://github.com/abbat/elfexec

에서 사용할 수있는 명명 된 파일 디스크립터를 메모리에 작성합니다 exec. 의사 코드 :

#include <linux/memfd.h>
...
int memfd = syscall(SYS_memfd_create, "someName", 0);
...
write(memfd,... elf-content...);
...
fexecve(memfd, argv, environ);

1
memfd.h사용하지 않으려면 헤더 가 필요하지 않습니다 MFD_CLOEXEC( #! /bin/shlinux '의 버그로 인해 스크립트 가 중단됩니다 fexecve()). 너무 복잡 아니에요, 당신은 (당신의 대답에 20 라인 작업 샘플을 포함 할 수 있습니다 예를 들어. 이 자식 요점을 - 즉 드롭에 대한 대체하지 비록 elfexec그 또한 사용자가 지정 할 수 있기 때문에 argv[0], 그리고 바이너리를 실행합니다 파이프에서만 (UUoC 필수 ;-))
mosvy

따라서 이것이 어떻게 작동하는지 전혀 알지 못합니다. gcc는 .o파일을 / tmp에 쓰지 못하면 죽습니다.
여호수아

4

tcc를 시도 하면 중간 파일을 쓰지 않고도 한 단계로 프로그램을 컴파일하고 실행할 수 있습니다. gcc가 아니므로 문제가 될 수 있지만 놀랍도록 빠르므로 목적에 따라 gcc보다 더 좋을 수도 있습니다.


2

그러면 코드 컴파일이 자동으로 실행되지만이를 수행하기 위해 파일 시스템에 파일이 생성됩니다.

echo 'main(){}' | gcc -xc -o /tmp/a.out && chmod u+x /tmp/a.out && /tmp/a.out && rm -f /tmp/a.out

(나는 현재 이것을 테스트하고 있지만, 이것이 확실하거나 그와 비슷한 것이 당신을 위해 효과가 있다고 확신합니다)

편집 : 파이핑의 목표가 물리 디스크를 속도 방정식에서 잘라내는 것이라면 중간 파일을 보관할 램 디스크 를 만드는 것을 고려 하십시오.


이것은 물론 작동하지만 디스크에 쓰여지지 않은 이진 코드를 실행하는 문제의 요점을 놓칩니다.
rozcietrzewiacz

@rozcietrzewiacz 내 목표는 필요한 실제 파일을 처리하지 않고 즉시 코드 스 니핏을 쉽게 실행하는 것이 유용 할 것입니다.
dtyler

네 이해했습니다. 그러나이를 위해 간단히 사용할 수 있습니다 csh.
rozcietrzewiacz

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.