2017-06-02 11 views
1

私はアセンブリで書いていますが、execveのシステムコールを実行する方法を理解しようとしていますが、出力を端末に出力する代わりに、格納されている場所を知りたいので、パイピングコマンドのようなもの。アセンブリで実行した後、execveのシステムコールをレジスタまたはスタックに戻すにはどうすればいいですか?

例えば、ここでのアセンブリは、本質的に「LS $」コマンドを実行してはexecveを経由して「」、コマンドを実行するためです:

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

[出力をバッファまたはファイルにリダイレクトする](https://stackoverflow.com/questions/2605130/redirecting-exec-output-to-a-buffer-or-file)の重複が考えられます。 –

+0

execveが失敗しない限り返されません。 – stark

答えて

0

基本的に、あなたはこのいくつかのバリエーションを実行する必要があります。

  1. FIFOを作るためにpipe()システムコールを使用してください。
  2. fork()子プロセスをオフにします。親では、これは覚えておく必要がある子のプロセスIDを返します。子では、これはゼロを返します。
  3. 親では、fifoの書き込み終了を閉じ、子では読み取り終了を閉じます。
  4. 子では、dup2()を使用して、パイプの書き込み終了をファイル記述子1に移動します。次に、パイプの元のファイル記述子を閉じます。
  5. 子供の場合、実行するプログラムはexecveです。 execveは現在のプロセスを新しいイメージに置き換えているので、以前のプログラムがどのように動作するかはわかりません。
  6. 親では、EOFが発生するまで(つまり、read()がゼロを返すまで)パイプから読み取ります。あなたが読んだのは子供の標準出力です。その出力をバッファに格納します。
  7. 最後に、wait()を使用して、子の終了ステータスを収集します。もしあなたがこれをしなければ、死んだ子供はゾンビとしてプロセステーブルに留まり、資源を奪うでしょう。

パイプの代わりに、open()に出力を書き込むこともできます。これには、fstat()を使用して、プロセスが書き込んだ出力の量を知ることができるという利点があります。ただし、一時ファイルを作成して開くには、tmpfile関数と同様のロジックを実装する必要があります。

関連する問題