echo 'main(){}' | gcc -xc - -o /dev/stdout | ???
มีวิธีรันไบนารีเอาต์พุตบนระบบที่เหมือนยูนิกซ์หรือไม่?
แก้ไข:ฉันต้องการมันเพื่อเรียกใช้เอาต์พุตของ g ++ ในสภาพแวดล้อมแบบ sandbox ที่ฉันไม่สามารถเขียนไฟล์ใด ๆ (ไม่มีอันตรายฉันสัญญา)
echo 'main(){}' | gcc -xc - -o /dev/stdout | ???
มีวิธีรันไบนารีเอาต์พุตบนระบบที่เหมือนยูนิกซ์หรือไม่?
แก้ไข:ฉันต้องการมันเพื่อเรียกใช้เอาต์พุตของ g ++ ในสภาพแวดล้อมแบบ sandbox ที่ฉันไม่สามารถเขียนไฟล์ใด ๆ (ไม่มีอันตรายฉันสัญญา)
คำตอบ:
ฉันไม่เชื่อว่าเป็นไปได้ การเรียกระบบexec (2)ต้องมีชื่อไฟล์หรือพา ธ สัมบูรณ์เสมอ (ชื่อไฟล์จะเป็นเสมอchar*
) posix_spawn
ยังมีข้อกำหนดที่คล้ายกันสำหรับชื่อไฟล์
สิ่งที่ใกล้เคียงที่สุดที่คุณสามารถทำได้คือไพพ์เอาท์พุทลงในไพพ์ที่มีชื่อและลองดำเนินการจากไพพ์ อาจใช้งานได้แม้ว่าเชลล์อาจปฏิเสธที่จะเรียกใช้งานไฟล์ใด ๆ ที่ไม่มีการ--x--x--x
ตั้งค่าบิต สร้างไปป์ด้วยmkfifo(1)
และดูว่าคุณสามารถทำให้มันใช้งานได้หรือไม่
อีกวิธีหนึ่งคือการเขียนสิ่งที่อ่านอินพุตมาตรฐานเขียนไฟล์ออกไปยังพื้นที่ temporay ตั้งค่าบิต --x บนส้อมและ execs แล้วลบไฟล์ ไอโหนดและเนื้อหาจะยังคงอยู่จนกว่าโปรแกรมจะเสร็จสิ้นการดำเนินการ แต่จะไม่สามารถเข้าถึงได้ผ่านระบบไฟล์ เมื่อกระบวนการยุติ inode จะถูกปล่อยออกมาและที่เก็บข้อมูลจะถูกส่งกลับไปยังรายการฟรี
แก้ไข:ตามที่ Mat ชี้ให้เห็นแนวทางแรกจะไม่ทำงานเนื่องจากตัวโหลดจะพยายามเรียกใช้เพจในไฟล์เรียกทำงานซึ่งจะสร้างทราฟฟิกค้นหาแบบสุ่มบนไฟล์และไม่สามารถทำได้ในไพพ์ วิธีนี้จะทำให้วิธีการบางอย่างเช่นที่สอง
วิธีแก้ปัญหาโดยใช้ 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);
memfd.h
ส่วนหัวเว้นแต่คุณต้องการที่จะใช้MFD_CLOEXEC
(ซึ่งจะทำลาย#! /bin/sh
สคริปต์เนื่องจากข้อบกพร่องใน linux ' fexecve()
) นั่นไม่ซับซ้อนเกินไปคุณสามารถรวมตัวอย่างการทำงาน 20 บรรทัดในคำตอบของคุณ (เช่นgit gist นี้ - แม้ว่าจะไม่ใช่การแทนที่แบบดรอปอินสำหรับคุณelfexec
เนื่องจากจะช่วยให้คุณสามารถระบุargv[0]
และเรียกใช้ไบนารีเฉพาะจากไปป์ (UUoC ได้รับคำสั่ง ;-))
.o
ไฟล์ไปยัง / tmp และตายหากไม่สามารถทำได้
คุณสามารถลองtccซึ่งจะรวบรวมและรันโปรแกรมในขั้นตอนเดียวโดยไม่ต้องเขียนไฟล์ระดับกลางใด ๆ ไม่ใช่ gcc ซึ่งอาจเป็นปัญหาสำหรับคุณ แต่มันรวดเร็วน่าทึ่งดังนั้นมันจึงอาจพนันได้ดีกว่า gcc สำหรับจุดประสงค์ของคุณ
สิ่งนี้จะทำการรวบรวมรหัสของคุณโดยอัตโนมัติ แต่สร้างไฟล์ (temparaily) ในระบบไฟล์เพื่อที่จะทำ
echo 'main(){}' | gcc -xc -o /tmp/a.out && chmod u+x /tmp/a.out && /tmp/a.out && rm -f /tmp/a.out
(ตอนนี้ฉันกำลังทดสอบอยู่ตอนนี้ แต่ฉันค่อนข้างแน่ใจว่าสิ่งนี้หรือสิ่งที่ใกล้เคียงกับมันจะใช้ได้ผลสำหรับคุณ)
แก้ไข: หากเป้าหมายของการวางท่อของคุณคือการตัดฟิสิคัลดิสก์ออกจากสมการสำหรับความเร็วให้พิจารณาสร้างram diskเพื่อเก็บไฟล์กลาง
csh
แต่การที่หนึ่งก็สามารถใช้
เช่นเดียวกับ@TheQUUX ที่แนะนำฉันไม่ได้ทดสอบด้วยตัวเอง แต่คุณอาจต้องการลองใช้cling
- "ล่าม C ++ แบบโต้ตอบซึ่งสร้างขึ้นจากห้องสมุด LLVM และ Clang"
ค้นหาข้อมูลเพิ่มเติมได้ที่นี่: https://cdn.rawgit.com/root-project/cling/master/www/index.html
csh
on-the-บินเพียงแค่การใช้งาน