2016-03-27 22 views
0

Geçtiğimiz günlerde gcc'nin inline derlemesine girdim ve temel montaj bilgisine sahip oldum, bir ya da daha fazla argümanla basit bir sys_execve yapmaya çalışana kadar syscall'leri nasıl iyi yapılacağını anladım. Sistem çağrısı execve, herhangi bir ek parametreyi geçirmiyorsa iyi çalışır ve herhangi bir dosyayı iletmeye çalışırken parametreler olmadan çalıştırılabilir.Inline assembly'ı çalıştırın

#include <stdio.h> 

char *argv[]={"/bin/echo","parameter test", NULL}; 

int main(){ 
    __asm__ volatile ("int $0x80" 
      : 
      :"a"(11), // syscall number (execve) 
      "b"(argv[0]), // filename 
      "c"(argv), // arguments 
      "d"(0)); // env 
    return 0; 
} 

ben

execve(argv[0], argv, NULL); 

ile bu test ettik ve beklendiği gibi çalıştı gibi yanlış gidebileceğini hiçbir fikrim yok.

+2

[sys_execve] için api'ye bakın (http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html) Parametreleri doğru yaptığınızdan emin değilim. Ayrıca, x64 için mi derliyorsunuz? Eğer öyleyse, int 0x80 kullanmanız gerekmiyor. –

+0

Ben x64 için derleme am ve herhangi çalıştırılabilir ben işlere devam etmek deneyin beri benim şimdiki ilerlemeyle, dosya adı bölümü, doğrudur. Takıldığım kısım ona herhangi bir parametre veriyor. Neyi geçmek zorunda olduğumu belirlemek için kullanıcı [this] (http://syscalls.kernelgrok.com/). – LazyShpee

cevap

4

32 bit kod kullanılarak 32 bit kodu. gcc -m32 kullanarak derleyin ve işe yarayacak.

#include <stdio.h> 

char *argv[]={"/bin/echo","parameter test", NULL}; 

int main(){ 
    int ret; 
    __asm__ volatile ("syscall" 
      :"=a" (ret) 
      :"a"(59), // syscall number (execve) 
      "D"(argv[0]), // filename 
      "S"(argv), // arguments 
      "d"(0) // env 
      :"rcx","r11","cc"); 
    return 0; 
} 

gerçek sorun dizide 64 bit işaretçileri olması, ancak 32 bit uyumluluk tabii kullandıkları kesme 32 bitlik poiters bekler: Alternatif gibi uygun 64 bit sürümüne geçin.

+2

'= a' açıkça işaret etmeye değer: sistem çağrısı' eax' (veya 'rax') kaydında bir değer döndürür, böylece derleyicinin bunun olduğunu bilmesi gerekir. Aksi takdirde asm kodu 'eax' değiştirilmemiş bırakır üstlenecek ve daha sonra kodda değeri 59 gerekiyorsa, o eax'' dan yüklemek deneyebilir. Bu, sorunlara yol açacaktır, çünkü 'eax', sistem çağrısının geri dönüş değeri ile yazılmıştır. Muhtemelen bu kodda bir soruna neden olması muhtemel değildir, ancak genel olarak dikkat edilmesi önemlidir. –

+2

Bu arada, amd64 abi'de okuduğumdan, bir sistem çağrısı "r11" in yanı sıra "rcx" işlevini görebiliyor. –

+1

@NateEldredge: Bu doğru, 'syscall' /' sysret''in tasarımı, bir 'syscall'ın her zaman rcx ve r11'i (RIP ve RFLAGS ile) kopyalayacağını garanti eder. Çekirdeğin bu reglerde ne olduğunu görmesi bile kullanıcı-alanı işbirliğini gerektirecektir (örneğin bunları yığına koymak). Linux syscalls, kullanıcı alanı yığınına bakmaz, dolayısıyla ABI bunu basit tutar ve sistem çağrıları, yalnızca 'eax' değiştirilen (dönüş değeri) 32bit' int 0x80'den farklı olarak, amd64'teki bu iki reg'ı çağrıştırır. –