มีวิธีการดำเนินการไบนารีพื้นเมืองจากไปป์หรือไม่


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

มีวิธีรันไบนารีเอาต์พุตบนระบบที่เหมือนยูนิกซ์หรือไม่?

แก้ไข:ฉันต้องการมันเพื่อเรียกใช้เอาต์พุตของ g ++ ในสภาพแวดล้อมแบบ sandbox ที่ฉันไม่สามารถเขียนไฟล์ใด ๆ (ไม่มีอันตรายฉันสัญญา)


ฉันเชื่อว่ากลไกความปลอดภัยขั้นพื้นฐานต้องป้องกันสิ่งนี้ แต่ถ้าความตั้งใจของคุณคือการเรียกใช้รหัส C cshon-the-บินเพียงแค่การใช้งาน
rozcietrzewiacz

คำตอบ:


10

ฉันไม่เชื่อว่าเป็นไปได้ การเรียกระบบexec (2)ต้องมีชื่อไฟล์หรือพา ธ สัมบูรณ์เสมอ (ชื่อไฟล์จะเป็นเสมอchar*) posix_spawnยังมีข้อกำหนดที่คล้ายกันสำหรับชื่อไฟล์

สิ่งที่ใกล้เคียงที่สุดที่คุณสามารถทำได้คือไพพ์เอาท์พุทลงในไพพ์ที่มีชื่อและลองดำเนินการจากไพพ์ อาจใช้งานได้แม้ว่าเชลล์อาจปฏิเสธที่จะเรียกใช้งานไฟล์ใด ๆ ที่ไม่มีการ--x--x--xตั้งค่าบิต สร้างไปป์ด้วยmkfifo(1)และดูว่าคุณสามารถทำให้มันใช้งานได้หรือไม่

อีกวิธีหนึ่งคือการเขียนสิ่งที่อ่านอินพุตมาตรฐานเขียนไฟล์ออกไปยังพื้นที่ temporay ตั้งค่าบิต --x บนส้อมและ execs แล้วลบไฟล์ ไอโหนดและเนื้อหาจะยังคงอยู่จนกว่าโปรแกรมจะเสร็จสิ้นการดำเนินการ แต่จะไม่สามารถเข้าถึงได้ผ่านระบบไฟล์ เมื่อกระบวนการยุติ inode จะถูกปล่อยออกมาและที่เก็บข้อมูลจะถูกส่งกลับไปยังรายการฟรี

แก้ไข:ตามที่ Mat ชี้ให้เห็นแนวทางแรกจะไม่ทำงานเนื่องจากตัวโหลดจะพยายามเรียกใช้เพจในไฟล์เรียกทำงานซึ่งจะสร้างทราฟฟิกค้นหาแบบสุ่มบนไฟล์และไม่สามารถทำได้ในไพพ์ วิธีนี้จะทำให้วิธีการบางอย่างเช่นที่สอง


2
ฉันจะแปลกใจจริง ๆ ถ้าเคล็ดลับไปป์ทำงาน - คุณไม่สามารถค้นหาแบบสุ่มบนไปป์และไม่สามารถ mmap พวกเขา - ฉันค่อนข้างแน่ใจว่าจะรบกวน runtime loader / linker :) ข้อเสนอแนะที่สองของคุณดูดี แม้ว่าจะไม่สามารถเกิดอะไรขึ้นได้หากไม่มีไฟล์ชั่วคราว
Mat

@ แมท - ฉันคิดว่าคุณพูดถูก ความต้องการการเพจในปฏิบัติการจะทำให้ปริมาณการเข้าถึงแบบสุ่มซึ่งจะไม่ทำงานบนไปป์ น่าแปลกที่มันอาจใช้งานได้กับ SVR2.0 (เวอร์ชันล่าสุดที่ไม่ได้ใช้ความต้องการการเพจ) - เพียงแค่แสดงอายุของฉันฉันเคยใช้ AT&T 3B2 / 400 ครั้งเดียวกับ SVR2.0 เป็น O / S
ConcOfOfTunbridgeWells

ลองคิดดูอีกทีฉันค่อนข้างมั่นใจว่าผู้แบ่งบรรจุ exe อย่าง UPX สามารถทำการคลายการบีบอัดและเรียกใช้งานบนสื่อแบบอ่านอย่างเดียว ปรับเปลี่ยนสิ่งที่ไม่สมบูรณ์ที่พวกเขายึดติดกับโปรแกรมที่บรรจุเพื่ออ่านจากไปป์แทนที่จะคลายการบีบอัดและ ... อาจทำงานได้
Mat

@Mat packers มีรูปภาพที่โหลดแล้วพวกเขาไม่ได้เริ่มกระบวนการใหม่ เพื่อทำสิ่งที่คล้ายกันฉันจำเป็นต้องมีหนึ่งในกระบวนการเพื่อทำการกระโดดเข้าสู่ข้อมูลอินพุตโดยพลการ (ซึ่งจะถือว่าเป็นช่องโหว่ด้านความปลอดภัย)
อเล็กซ์ 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/shสคริปต์เนื่องจากข้อบกพร่องใน linux ' fexecve()) นั่นไม่ซับซ้อนเกินไปคุณสามารถรวมตัวอย่างการทำงาน 20 บรรทัดในคำตอบของคุณ (เช่นgit gist นี้ - แม้ว่าจะไม่ใช่การแทนที่แบบดรอปอินสำหรับคุณelfexecเนื่องจากจะช่วยให้คุณสามารถระบุargv[0]และเรียกใช้ไบนารีเฉพาะจากไปป์ (UUoC ได้รับคำสั่ง ;-))
mosvy

ดังนั้นฉันจึงไม่เข้าใจว่ามันจะทำงานได้อย่างไร gcc จะเขียน.oไฟล์ไปยัง / tmp และตายหากไม่สามารถทำได้
Joshua

4

คุณสามารถลองtccซึ่งจะรวบรวมและรันโปรแกรมในขั้นตอนเดียวโดยไม่ต้องเขียนไฟล์ระดับกลางใด ๆ ไม่ใช่ gcc ซึ่งอาจเป็นปัญหาสำหรับคุณ แต่มันรวดเร็วน่าทึ่งดังนั้นมันจึงอาจพนันได้ดีกว่า gcc สำหรับจุดประสงค์ของคุณ


2

สิ่งนี้จะทำการรวบรวมรหัสของคุณโดยอัตโนมัติ แต่สร้างไฟล์ (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เพื่อเก็บไฟล์กลาง


สิ่งนี้จะใช้งานได้ แต่มันพลาดจุดสำคัญของคำถาม - เพื่อรันไบนารีโค้ดที่ไม่เคยเขียนลงดิสก์
rozcietrzewiacz

@rozcietrzewiacz ความหวังของฉันคือมันจะมีประโยชน์ถ้าเป้าหมายคือการเรียกใช้ snippit ของรหัสได้อย่างง่ายดายโดยไม่ต้องจัดการกับไฟล์ทางกายภาพที่ต้องการ
dtyler

ใช่ฉันเข้าใจแล้ว. cshแต่การที่หนึ่งก็สามารถใช้
rozcietrzewiacz

0

เช่นเดียวกับ@TheQUUX ที่แนะนำฉันไม่ได้ทดสอบด้วยตัวเอง แต่คุณอาจต้องการลองใช้cling- "ล่าม C ++ แบบโต้ตอบซึ่งสร้างขึ้นจากห้องสมุด LLVM และ Clang"

ค้นหาข้อมูลเพิ่มเติมได้ที่นี่: https://cdn.rawgit.com/root-project/cling/master/www/index.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.