lsof -i結果でコマンドのフルパスを見つける方法

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サーバー管理者にとって非常に便利です。

答え1

lsof -i:$PORTまず、grepを介してインターネットアドレスが与えられた$ PORT番号(またはサービス名)を使用するファイルのリストを選択する必要はありません。

lsof -i:smtp

あなたの場合はそれで十分です。

コマンド名が既にわかっている場合は、lsof -c $COMMAND$ COMMANDというコマンドを実行したプロセスのファイルのリストを選択してください。例:

lsof -c httpd.pl

3番目の概念:プロセスのPIDがわかっている場合は、次のコマンドを使用して完全なコマンドパスを取得できます。

ps -p $PID -o command

$PIDPID番号はどこにありますか?

したがって、lsofの結果からコマンドのフルパスを見つけるには、次のように使用できます。

ps -p $(lsof -i:$PORT |awk 'NR>1 {print $2}' |sort -n |uniq) -o comm

または

ps -p $(lsof -c $COMMAND |awk 'NR>1 {print $2}' |sort -n |uniq) -o comm

注1:awk、、、sortuniq出力からヘッダー行をスキップし、PID番号でリストを集計するために必要です。

注2:$ PORTを使用する宛先ポートが複数のプロセス(httpsなど)で使用されている場合は、各行を個別に解析する必要があります。

for PID in $(lsof -i:$PORT |awk 'NR>1 {print $2}' |sort -n |uniq); do
  ps -p $PID -o comm
done

答え2

1つの方法は、プロセスで開かれたファイルを確認することです。FD列に表示されるタイプlsof:

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

答え3

つまりhttpd.pl名前のコース。これは、プロセスが最後に実行したファイルのデフォルト名で初期化されますが、他の方法で変更できます。

の場合は、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

Perlコードが名前付きファイル(または他の関連ファイル)からhttpd.plロードされている場合、perlそのファイルは通常内容を読み取って閉じますlsof -p PID

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

これにより、パラメータとして渡されたファイルパスが表示されます。これは相対パスである可能性があり、その場合はそのエントリが表示され、スクリプトが現在の作業ディレクトリを変更cwdしないlsof限り役に立ちます。

スクリプトがシェルで実行されると、_環境変数(grep -z '^_=' /proc/PID/environLinuxの場合)にパス(相対パスでもあります)を見つけることもできます。

それにもかかわらず、スクリプトは最初に最初に自分で削除される可能性が高いです。

欲しいならバラよりこのコードでは、httpd.plプロセスメモリの内容をダンプすることをお勧めします(Linuxと同様にgcoreattachmentgdbまたはviews /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です。次に、プリコンパイルされたコードを見つけてデコードする必要があります。

このスタックオーバーフローのQ&Aこれはあなたがこれをするのに役立ちます。

答え4

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

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

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

もちろん、ファイルは実行可能でなければなりませんが、ファイルがロードする共有ライブラリも実行可能でなければなりません。本当に病的な場合は、共有ライブラリをロードするスクリプト(Pythonで書くなど)でプログラムを実行し、プロセスリストから名前を変更できます。

CentOSスレッドによると疑わしいプロセス httpd.pl、自分を呼び出すPHPスクリプトから始まるプロセスがありますhttpd.pl

興味のある人のために。これはPHPシェルによってインストールされるバックドアです。最初のクリーニングラウンドではこれをキャッチできませんでした。

別のスレッド、CentOSサーバーで実行される疑わしいプロセス詳細を提供してください。

httpd.plはPerlを実行するなりすましプロセスです。

これは通常PHPシェルによって設定されたバックドアで、ウェブサイトのどこかにロードされます。

追加資料:

関連情報