Có cách nào để thực hiện nhị phân nguyên gốc từ một đường ống không?


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

Có cách nào để chạy nhị phân đầu ra trên một hệ thống giống như unix không?

EDIT: Tôi cần nó để chạy đầu ra của g ++ trong môi trường hộp cát nơi tôi không thể viết bất kỳ tệp nào (tôi hứa là không có gì độc hại).


Tôi tin rằng các cơ chế bảo mật cơ bản phải ngăn chặn điều này. Nhưng nếu ý định của bạn là chạy mã C một cách nhanh chóng, chỉ cần sử dụng csh.
rozcietrzewiacz

Câu trả lời:


9

Tôi không tin điều này là có thể. Cuộc gọi hệ thống exec (2) luôn yêu cầu tên tệp hoặc đường dẫn tuyệt đối (tên tệp luôn là a char*). posix_spawncũng có yêu cầu tương tự cho một tên tệp.

Cách gần nhất bạn có thể làm là chuyển đầu ra thành một ống có tên và thử thực hiện từ đường ống. Điều đó có thể hoạt động, mặc dù shell có thể từ chối thực thi bất kỳ tệp nào không có --x--x--xbit được đặt. Tạo đường ống với mkfifo(1)và xem nếu bạn có thể làm cho nó hoạt động.

Một cách tiếp cận khác là viết một cái gì đó đọc đầu vào tiêu chuẩn, ghi một tệp ra khu vực tạm thời, đặt các bit --x trên đó, rẽ nhánh và thực thi sau đó xóa tệp. Inode và nội dung sẽ vẫn còn cho đến khi chương trình kết thúc thực thi nhưng nó sẽ không thể truy cập được thông qua hệ thống tệp. Khi quá trình kết thúc, inode sẽ được giải phóng và bộ nhớ sẽ được đưa trở lại danh sách miễn phí.

EDIT: Như Mat chỉ ra, cách tiếp cận đầu tiên sẽ không hoạt động vì trình tải sẽ cố gắng yêu cầu trang trong tệp thực thi, điều này sẽ tạo ra lưu lượng tìm kiếm ngẫu nhiên trên tệp và điều này không thể thực hiện được trên đường ống. Điều này để lại một số cách tiếp cận như thứ hai.


2
Tôi thực sự ngạc nhiên nếu thủ thuật đường ống hoạt động - bạn không thể tìm kiếm ngẫu nhiên trên đường ống và không thể xử lý chúng - Tôi khá chắc chắn rằng điều đó sẽ gây khó chịu cho trình tải / trình liên kết thời gian chạy :) Đề xuất thứ hai của bạn có vẻ tốt mặc dù, không thể đưa ra bất cứ điều gì mà không có một tập tin tạm thời.
Mat

@Mat - Tôi nghĩ bạn đúng. Phân trang theo yêu cầu trong tệp thực thi sẽ gây ra lưu lượng truy cập ngẫu nhiên không hoạt động trên đường ống. Trớ trêu thay, nó có thể thực sự hoạt động trên SVR2.0 (phiên bản cuối cùng không sử dụng phân trang theo yêu cầu) - Chỉ để cho thấy tuổi của tôi, tôi thực sự đã từng sử dụng AT & T 3B2 / 400 một lần với SVR2.0 là O / S.
Mối quan tâmOfTunbridgeWells

Nghĩ về nó nhiều hơn, tôi khá chắc chắn các nhà đóng gói exe như UPX có thể thực hiện giải nén thực thi trên phương tiện chỉ đọc. Sửa đổi bất cứ thứ gì còn sơ khai mà họ xử lý thành các tệp thực thi được đóng gói để đọc từ một đường ống thay vì giải nén và ... có thể hoạt động.
Mat

Các nhà đóng gói @Mat đã tải hình ảnh, họ không bắt đầu một quy trình mới. Để làm điều tương tự tôi cần phải có một trong các quy trình để thực hiện một bước nhảy tùy ý vào dữ liệu đầu vào (sẽ được coi là một lỗ hổng bảo mật).
Alex B

@Alex B: Bạn đang hỏi cụ thể cách thực hiện một bước nhảy tùy ý vào dữ liệu đầu vào. Tại sao bạn lại phàn nàn khi đề nghị bạn làm chính xác điều đó? Mục đích của hộp cát có đặc biệt để ngăn chặn những gì bạn đang cố gắng làm không?
David Schwartz

7

Một giải pháp sử dụng tòa nhà memfd: https://github.com/abbat/elfexec

Nó tạo ra một mô tả tập tin có tên trong bộ nhớ có thể được sử dụng trong exec. Mã giả:

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

1
Bạn không cần memfd.htiêu đề trừ khi bạn muốn sử dụng MFD_CLOEXEC(sẽ phá vỡ #! /bin/shcác tập lệnh vì lỗi trong linux ' fexecve()). Điều đó không quá phức tạp, bạn có thể bao gồm một mẫu làm việc 20 dòng trong câu trả lời của mình (ví dụ: ý chính này - mặc dù đó không phải là sự thay thế thả xuống cho bạn elfexec, vì điều đó cũng sẽ cho phép bạn chỉ định argv[0]và sẽ chạy nhị phân chỉ từ một đường ống (bắt buộc
UUoC

Vì vậy, tôi không hiểu làm thế nào điều này dự kiến ​​sẽ làm việc cả. gcc sẽ ghi .otập tin vào / tmp và chết nếu không thể.
Joshua

4

Bạn có thể thử tcc , nó sẽ biên dịch và thực thi chương trình trong một bước, mà không cần viết bất kỳ tệp trung gian nào. Đó không phải là gcc, có thể là một vấn đề đối với bạn, nhưng nó rất nhanh, vì vậy nó thậm chí có thể đặt cược tốt hơn gcc cho mục đích của bạn.


2

Điều này sẽ tự động chạy quá trình biên dịch mã của bạn, nhưng tạo một tệp (tempar Daily) trên hệ thống tệp để thực hiện.

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

(Hiện tại tôi đang thử nghiệm điều này, nhưng tôi khá chắc chắn điều này hoặc một cái gì đó gần với nó sẽ hoạt động cho bạn)

EDIT: Nếu mục tiêu của đường ống của bạn là cắt các đĩa vật lý ra khỏi phương trình tốc độ, hãy xem xét việc tạo một đĩa ram để giữ tệp trung gian.


Điều này tất nhiên sẽ hoạt động, nhưng nó bỏ lỡ điểm chính của câu hỏi - để thực thi mã nhị phân không bao giờ được ghi vào đĩa.
rozcietrzewiacz

@rozcietrzewiacz Hy vọng của tôi là nó sẽ hữu ích nếu mục tiêu là dễ dàng chạy một đoạn mã khi đang di chuyển mà không phải xử lý tệp vật lý cần thiết.
dtyler

Tôi hiểu. Nhưng đối với điều đó, người ta có thể chỉ cần sử dụng csh.
rozcietrzewiacz

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.