web-dev-qa-db-ja.com

lsof -iの結果からコマンドの完全なパスを見つける方法

lsofは優れたユーティリティであり、使用を開始したばかりです。

lsof -i | grep smtp =>これにより、次の結果が得られます。

httpd.pl  212548          global    3u  IPv4 893092369      0t0  TCP server07.Host...blah...

上記の例では、httpd.plはスパムスクリプトを送信するPerlスクリプトです。

コマンドの完全パスを知るにはどうすればよいですか。つまり、上記の結果httpd.plの完全パスを知りたい

ホームディレクトリで検索してみましたが、httpd.plファイルがありません。また、lsof -p PIDを試しましたが、これもそのパスを示していません。

方法はありますか?そのファイルの完全なパスを取得できますか?

注:この種の問題は、共有ホスティング環境では非常に一般的です。したがって、共有ホスティングやWebサーバー管理者にとって非常に便利です。

6
Mani

そのhttpd.plには、プロセスのnameがあります。これは、プロセスが最後に実行したファイルのベース名から初期化されますが、他の方法で変更することもできます。

Perlを使用すると、$0に値を割り当てるだけです。

$ Perl -e '$0 = "httpd.pl"; sleep 10' & ps -fp $!
[2] 11954
UID        PID  PPID  C STIME TTY          TIME CMD
stephane 11954 31685  0 09:57 pts/8    00:00:00 httpd.pl

したがって、そのhttpd.plがそのような名前のファイルなのか他の何かなのかはわかりません。 Perlは、-eとして、または別のファイルから、あるいはstdinから渡されたコードで実行された可能性があります...

Perlコードがhttpd.plと呼ばれるファイル(またはその他の重要なファイル)からロードされた場合、Perlは通常、ファイルの内容を読み取った後にファイルを閉じるため、表示されません。 lsof -p PIDの出力に表示されます。

スクリプトが実際にPerlインタープリターに渡され、Perlコードがその後にプロセス名または引数を変更しない場合は、ps -fp PIDを使用してコマンドライン引数を確認することで手掛かりを得ることができます。

次に、引数として渡されたファイルのパスが表示されます。相対パスの場合もあります。その場合は、cwdlsofエントリを確認できます。これは、スクリプトが現在の作業ディレクトリを変更しない限り役立ちます。

スクリプトがシェルによって開始された場合、_環境変数(Linuxではgrep -z '^_=' /proc/PID/environ)でパスを(場合によっては相対パスで)見つけることもできます。

いずれの場合も、スクリプトは最初に非常にうまく削除できます。

そのhttpd.plのコードを参照したい場合は、そのプロセスのメモリの内容をダンプするのが最適です(gcoreのように、 gdbと一緒に出荷されるか、Linuxの/proc/PID/{maps,mem}を参照)。そこにあるコードを探します。

たとえば、NUL区切りのレコードで#!を検索します。

Perl -e '$p=shift;open MAPS, "/proc/$p/maps";
  open MEM, "/proc/$p/mem" or die "open mem: $!";
  for $m (grep !m{/|\[v}, <MAPS>){
    ($a,$b) = map hex, $m =~ /[\da-f]+/g;
    seek MEM, $a, 0 or die "seek: $!";
    read MEM, $c, $b - $a or die "read: $!";
    print $c
  }' PID | grep -z '#!'

YYMVとしても、元のソースコードは存在しない可能性があります。次に、プリコンパイルされたコードを探してデコードする必要があります。

このstackoverflowのQ&A は、それを行うのに役立ちます。

1

1つの方法は、そのプロセスによって開かれたファイルを調べることです。 FDlsof列に示されているタイプのうち:

FD         is the File Descriptor number of the file or:

               cwd  current working directory;
               ...
               txt  program text (code and data);

だから、試してみてください:

lsof -a -d txt -p 212548

スクリプトの場合、これは使用されるインタープリターのパスを示します(/bin/bashなど)。シェルスクリプトの場合、システムのfd 255でスクリプトファイルが開いているように見えましたが、Perlスクリプトの場合、lsof出力にスクリプトファイルの記述がまったくありませんでした。

1
muru

lsof -i自体は、インターネット情報のみをリストします。 -dオプションを使用して、ファイル情報を追加(または代わりにを表示)できます。例えば:

lsof -d txt | grep -E '/httpd.pl$'

(プロセスが実行する名前を変更しない限り)コマンド名はロードされた実際のファイル名と一致するためです。

もちろん、そのファイルは実行可能でなければなりません—しかし、ロードする共有ライブラリもそうである可能性があります。本当に病的なケースでは、共有ライブラリをロードし、プロセスリストで自分自身の名前を変更するスクリプト(たとえば、Pythonで記述))からプログラムを実行することができます。

CentOSスレッド不審なプロセスhttpd.plによると、PHP自身を呼び出すスクリプトhttpd.pl

興味を持った人のために。これは、phpシェルによってインストールされたバックドアでした。クリーンアップは最初のラウンドでそれをキャッチできませんでした。

別のスレッド CentOSサーバーで実行中の不審なプロセス に詳細が表示されます:

Httpd.plは、Perlを実行しているスプーフィングされたプロセスです。

それは通常、どこかのウェブサイトにロードされるphp Shellによってセットアップされるバックドアです。

参考文献:

0
Thomas Dickey