Bir borudan yerel bir ikili yürütmenin bir yolu var mı?


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

Çıktı ikili dosyasını unix benzeri bir sistemde çalıştırmanın bir yolu var mı?

EDIT: Ben herhangi bir dosya (kötü bir şey, söz veriyorum) yazamıyorum kum havuzlu bir ortamda g ++ çıktı çalıştırmak için gerekli .


Temel güvenlik mekanizmalarının bunu engellemesi gerektiğine inanıyorum. Ama niyetiniz anında C kodunu çalıştırmaksa, sadece kullanın csh.
rozcietrzewiacz

Yanıtlar:


10

Bunun mümkün olduğuna inanmıyorum. Exec (2) sistem çağrısı her bir dosya adı veya kesin yolu gerektirmektedir (dosya, her zaman olduğu char*). posix_spawndosya adı için de benzer gereksinimlere sahiptir.

Yapabileceğiniz en yakın şey, çıkışı adlandırılmış bir boruya bağlamak ve borudan yürütmeyi denemektir. Kabuk, --x--x--xbitleri ayarlanmamış herhangi bir dosyayı yürütmeyi reddedebilirse de bu işe yarayabilir . Boruyu ile oluşturun ve mkfifo(1)çalışıp çalışamayacağınızı görün.

Başka bir yaklaşım, standart girdiyi okuyan, bir dosyayı geçici alana yazan, üzerindeki --x bitlerini ayarlayan, çatallar ve yürütmelerden sonra dosyayı silen bir şey yazmak olacaktır. Program ve yürütme işlemi bitene kadar inode ve içerik kalır, ancak dosya sistemi üzerinden erişilemez. İşlem sona erdiğinde inode serbest bırakılacak ve depolama ücretsiz listeye geri döndürülecektir.

DÜZENLEME: Mat'ın işaret ettiği gibi, yükleyici yürütülebilir dosyadaki talep sayfasını çalışmaya çalışacağından ilk yaklaşım çalışmaz, bu da dosyada rastgele arama trafiği oluşturur ve bu bir kanalda mümkün değildir. Bu, ikincisi gibi bir tür yaklaşım bırakır.


2
Boru hilesi işe yaradıysa gerçekten şaşırırdım - bir boru üzerinde rastgele arama yapamazsınız ve onları eşleştiremezsiniz - Çalışma zamanı yükleyicisini / bağlayıcıyı rahatsız edecek eminim :) İkinci öneriniz iyi görünüyor ancak, geçici bir dosya olmadan hiçbir şey bulamazsınız.
Mat

@Mat - Bence haklısın. Yürütülebilir dosyada talep sayfalaması, kanalda çalışmayan rasgele erişim trafiğine neden olur. İronik bir şekilde, aslında SVR2.0 (talep çağrısını kullanmayan son sürüm) üzerinde çalışmış olabilir - Sadece yaşımı göstermek için aslında bir kez AT / T 3B2 / 400'ü bir kez O / S olarak SVR2.0 ile kullandım.
ConcernedOfTunbridgeWells

Biraz daha düşünerek, UPX gibi exe paketleyicilerinin dekompresyon ve yürütmeyi salt okunur medyada yapabileceğinden eminim . Sıkıştırmak yerine bir borudan okumak için paketlenmiş yürütülebilir dosyalara yapıştırdıkları saplamaları değiştirin ve ... işe yarayabilir.
Mat

@Mat paketleyicilerinde zaten yüklenmiş bir görüntü var, yeni bir işlem başlatmıyorlar. Benzer bir şekilde, giriş verilerine (bir güvenlik açığı olarak kabul edilir) keyfi bir sıçrama yapmak için süreçlerden birine ihtiyacım var.
Alex B

@Alex B: Özellikle giriş verilerine nasıl rasgele atlama yapılacağını soruyorsunuz. Tam olarak bunu yapmanız önerildiğinde neden şikayet edesiniz ki? Korumalı alanın amacı özellikle yapmaya çalıştığınız şeyi önlemek mi?
David Schwartz

7

Memfd syscall kullanan bir çözüm: https://github.com/abbat/elfexec

Bellekte kullanılabilecek adlandırılmış bir dosya tanımlayıcı oluşturur exec. Bir sözde kod:

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

1
Kullanmak memfd.histemediğiniz sürece başlığa ihtiyacınız yoktur (linux'daki hatalar nedeniyle komut dosyalarını MFD_CLOEXECkırar ). Bu çok karmaşık değil, cevabınıza 20 satırlık bir çalışma örneği ekleyebilirsiniz (örn. Bu git gist - bu sizin için bir damla yerine geçmez , çünkü bu da belirtmenize izin verir ve bir ikili çalıştırır) sadece bir borudan (UUoC zorunlu ;-))#! /bin/shfexecve()elfexecargv[0]
mosvy

Bu yüzden bunun nasıl çalışacağını anlamıyorum. gcc .o/ tmp dosyasına dosya yazacak ve yapamazsa ölecektir.
Joshua

4

Herhangi bir ara dosya yazmadan bir programı tek adımda derleyecek ve çalıştıracak tcc'yi deneyebilirsiniz . Gcc değil, bu sizin için bir sorun olabilir, ancak olağanüstü hızlıdır, bu nedenle amaçlarınız için gcc'den daha iyi bahis bile yapabilir.


2

Bu, kodunuzun derlenmesini otomatik olarak çalıştırır, ancak bunu yapmak için dosya sisteminde (geçici olarak) bir dosya oluşturur.

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

(Şu anda bunu test ediyorum, ancak bunun eminim, ya da buna yakın bir şey sizin için çalışacaktır)

DÜZENLEME: Boru tesisatınızın amacı, fiziksel diskleri hız denkleminden kesmekse , ara dosyayı tutmak için bir ram diski oluşturmayı düşünün .


Bu elbette işe yarayacak, ancak sorunun ana noktasını kaçırıyor - asla diske yazılmamış bir ikili kod yürütmek.
rozcietrzewiacz

@rozcietrzewiacz Umarım amaç, gerekli fiziksel dosyayla uğraşmadan anında bir kod snippitini kolayca çalıştırmak olsaydı yararlı olurdu.
dtyler

Evet anladım. Ama bunun için, sadece kullanabilirsiniz csh.
rozcietrzewiacz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.