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
,这也没有给出它的路径。
有什么方法可以获取该文件的完整路径吗?
注意:这种问题在共享主机环境中很常见。因此,它对于共享主机或任何网络服务器管理员来说都非常有用。
答案1
首先,您不需要通过 grep:lsof -i:$PORT
选择其任何 Internet 地址使用给定 $PORT 号(或服务名称)的文件列表,因此
lsof -i:smtp
在你的例子中就足够了。
如果您已经知道命令名称,lsof -c $COMMAND
请选择执行名为 $COMMAND 的命令的进程的文件列表,例如:
lsof -c httpd.pl
第三个概念:如果您知道进程的 PID,则可以使用以下命令获取其完整命令路径
ps -p $PID -o command
其中$PID
是它的 PID 号。
因此,如果您需要从 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
、sort
、uniq
是从输出中跳过标题行并按 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
一种方法是检查该进程打开的文件。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
)。对于 shell 脚本,脚本文件似乎在我的系统上的 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
除非脚本更改当前工作目录,否则会有所帮助。
如果脚本是由 shell 启动的,您还可以在_
环境变量(grep -z '^_=' /proc/PID/environ
在 Linux 上)中找到路径(同样可能是相对路径)。
无论如何,脚本很可能在启动时首先删除自己。
如果你想看对于该代码httpd.pl
,最好是转储该进程内存的内容(如Linux 上的gcore
、附带gdb
或查看/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 问答然后会帮助你做到这一点。
答案4
其本身lsof -i
仅列出互联网信息。您可以添加文件信息(或显示反而)使用该-d
选项。例如:
lsof -d txt | grep -E '/httpd.pl$'
因为(除非进程更改其运行名称)命令名称将与加载的实际文件名匹配。
当然,该文件必须是可执行的 - 但它加载的共享库也可以。在真正病态的情况下,您可以让一个程序从加载共享库的脚本(例如用 Python 编写)运行 - 并在进程列表中重命名自身。
根据 CentOS 线程可疑进程 httpd.pl,有一个从 PHP 脚本启动的进程,该脚本调用自身httpd.pl
:
对于任何感兴趣的人。这是由 php shell 安装的后门。第一轮的清理工作并没有抓住它。
另一个线程,CentOS 服务器中运行的可疑进程提供更多详细信息:
httpd.pl 是一个运行 perl 的欺骗进程。
它通常是由 php shell 设置的后门,将加载到网站的某个位置
进一步阅读: