2017-06-02 61 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函数的逻辑来创建并打开一个临时文件。