2017-06-02 59 views
1

我正在寫彙編,我想弄清楚如何執行一個execve系統調用,而不是輸出打印到終端,我想知道它的存儲位置,所以我可以稍後使用它,有點像管道命令。在彙編中執行它後,如何將execve系統調用的輸出返回到寄存器或堆棧?

例如,這裏的組件,用於執行所述命令「其」經由execve的,基本上執行命令「$其中LS」:

GLOBAL _start 
SECTION .TEXT 

_start: 
    XOR   EAX,EAX 
    PUSH  EAX 
    PUSH  0x68636968 
    PUSH  0x772f6e69 
    PUSH  0x622f7273 
    PUSH  0x752f2f2f 
    MOV   EBX, ESP 
    PUSH  EAX 
    PUSH  0x736c 
    MOV   ESI, ESP 
    XOR   EDX, EDX 
    PUSH  EDX 
    PUSH  ESI 
    PUSH  EBX 
    MOV   ECX, ESP 
    MOV   AL, 0x0B; EXECVE SYSCALL NUMBER 
    INT   0x80 

7-10行推/usr/bin/which到堆棧的地址,和第13行將參數ls推入堆棧。然後它將參數數組推入堆棧並將其存儲在ECX中,使EBX指向/usr/bin/which位置的地址,並將EAX設置爲execve系統調用的系統調用號0xb(11)。執行時,它會返回/bin/ls,我們要求它找到ls的位置。

如何將/bin/ls的結果存儲在某處供其他用途使用?就像如果我想繼續編寫代碼並使用這裏返回的代碼作爲下一段代碼的一部分,我該如何將返回值保存在寄存器或堆棧中?

+0

[重定向exec輸出到緩衝區或文件]的可能重複(https://stackoverflow.com/questions/2605130/redirecting-exec-output-to-a-buffer-or-file)。 –

+0

execve不會返回,除非它失敗。 – stark

回答

0

基本上,你必須做的這一些變化:

  1. 使用pipe()系統調用做出FIFO。
  2. fork()關閉子進程。在父項中,這將返回您需要記住的子進程ID。在孩子中,這返回零。
  3. 在父母中,關閉fifo的寫作結束,在子女關閉閱讀結束。
  4. 在子項中,使用dup2()將管道的寫入端移至文件描述符1.然後關閉管道的原始文件描述符。
  5. 在孩子,execve你想運行的程序。請注意0​​用新圖像替換當前進程,所以我不確定您以前的程序是如何工作的。
  6. 在父級中,從管道中讀取,直到遇到EOF(即read()返回零)。你讀的是孩子的標準輸出。將該輸出存儲在緩衝區中。
  7. 最後,使用wait()收集到孩子的退出狀態。如果你不這樣做,這個死去的孩子將會像殭屍一樣在流程表中徘徊,佔用資源。

而不是一個管道,你也可以open()一個文件來寫輸出。這樣做的好處是您可以使用fstat()來了解過程寫入的輸出量。但是,您需要實現類似於tmpfile函數的邏輯來創建並打開一個臨時文件。