前言
在本文中,我将介绍一种优雅的技术,来获得一个shell访问易受攻击的远程机器。虽然这个技术不是我发明的,但我发现它的确很有趣,所以本文的重点是这种技术本身,而不是利用漏洞的具体方式。
设置环境
为了专注于远程shell代码本身,而不是把精力用在如何规避ASLR、非可执行堆栈等防御措施上面,我们将禁用这些安全功能。一旦熟悉了获取shellcode的方法,可以重新启用这些保护措施,以进一步练习如何突破这些安全设置。因此,这是一个非常有趣的练习,如果你想练手的话。
首先,我们将禁用ASLR。为此,可以使用以下命令:
这些设置都是临时性质的,在下次重新启动时会全部还原。如果你想要在不重新启动机器的情况下立即还原所有设置的话,可以使用如下所示的命令:
为了禁用其余的安全功能,我们可以使用以下选项来编译带有安全漏洞的 服务器 :
这些选项会禁用堆栈的canarie保护,并赋予堆栈执行权限。这样的话,我们就得到了一个非常容易利用的环境。
带有安全漏洞的服务
现在,让我们编写一个带有缓冲区溢出漏洞的小型回显服务器,这样我们就可以远程利用它了。这个程序很简单,你能发现代码中的缓冲区溢出漏洞吗? 你当然可以。
很好,下面我们就来编译它,让它变成一个最容易利用的服务器:
下面,我们来展示它的脆弱性。在一个终端运行这个带有安全漏洞的服务器,然后在另一个终端运行下列命令:
在运行服务器的终端中,我们将会看到如下所示的内容:
注意,我已经添加了打印局部变量的地址的语句,从而可以验证ASLR是否被禁用。每次执行这个二进制代码的时候,应该总是看到相同的数字(当然,如果你修改了这个程序,数字就会随之改变)。
现在,我们可以拿这个程序来练手,学习如何使用各种触手可及的shellcode来获取一个本地shell。尽管这个练习非常简单,但是我们建议您至少要练习一次。具体过程本文不作详细介绍,因为关于缓冲区溢出漏洞利用的教程,在网络上面数不胜数。
远程Shell
下面我们介绍如何获取远程shell。注意,这里的关键在于“远程”。这意味着在易受攻击的机器和攻击者之间,隔着一个网络。或者换句话说,我们必须通过一些套接字来发送/接收数据。根据这一要求,有两种方式可以用来获得远程shell:
如果你的shellcode创建一个服务器套接字来启用来自外部的连接请求,并从本地shell发送和接收数据 …那么,这就是一个直接远程shell。
如果你的shellcode连接回一个预先指定的主机,并且这个主机上运行的服务器软件正在等待受害者的连接…那么,这就这是一个反向远程shell。
关于这两种远程shell的详细信息,请访问。
看到这两个定义后,你可能会联想到RHOST/RPORT之类的变量….是的,它们可以用来告诉payload连接的主机地址和相应的端口。对于反向shell来说,您必须将这些信息存放到payload中,以便连接回来。对于直接shell你通常需要定义端口,服务器就会等待连接。
但是,至少对于Unix机器来说,还有第三种选择。
连接复用
当执行远程漏洞利用代码时,为了利用此漏洞,您已经连接到了服务器…所以,为什么不重用这个已经建立好的连接呢?这真是一个不错的想法,因为它不会显示任何会引起受害者怀疑的东西,例如来自服务器未知服务的开放端口等。
实现这一点的方法也非常巧妙。它是基于这样的事实,即系统是按顺序分配文件描述符的。知道了这一点,我们就可以在建立连接之后立即复制一个当前文件的描述符,除非服务器的负载很重,否则我们得到的文件描述符等于用于我们连接的套接字的文件描述符+1,这样很容易就能知道我们的连接的文件描述符了。
一旦知道了当前连接的文件描述符,我们只需要将它复制到文件描述符0、1和2(stdin、stdout和stderr),就可以生成一个shell了。这样一来,该shell的所有输入/输出都会被重定向到我们的套接字了。
还不明白吗?肯定没读过页面上的文章吧?不过没关系,现在去看也不晚。
相应的C代码如下所示:
看…根本就没有使用套接字代码!如果我们把它变成一个shellcode,并且设法利用远程服务器的漏洞来运行该代码,我们就能够获得一个shell来访问远程机器,而这个shell所使用的连接,正好就是原来向远程服务器投递利用代码的那个连接。
当然,也你已经注意到这种技术存在一些缺点。就像我们所提到的那样,如果服务器比较繁忙的话(同时建立许多连接),这种方法就很难奏效了。此外,正常的服务器会在变成守护进程之前关闭所有的文件描述符,因此我们可能需要尝试使用其他值来推测文件描述符。
这个技术是前一段时间跟@_py进行讨论的时候,由他想出来的。我们当时检查的原始代码可以在这里找到:
但是,这是一个32位代码,所以我重新制作了对应的64位版本,以及一个运行漏洞利用代码的Perl脚本。
64位版本的Shellcode
下面的代码您就将就着看吧(我这才发现自己的汇编技能真是生锈了),不过它确实可以正常运行,并且只比原来的32bits版本长了3个字节。我的64位版本的Shellcode如下所示:
对于不太容易理解的地方,我已经添加了相应的注释。同时,你可能也注意到了,代码里使用了许多的push/pop指令,这是因为一个PUSH/POP指令对占用2个字节,而MOV R1,R2指令则需要占用3个字节。虽然这会代码变得非常丑,但是却能节约一些空间…实际上也没有节约太多的地方,所以也算不上一个好主意。无论如何,您可以随意改进它,并欢迎在评论中发布您自己的版本。
生成Shellcode
现在,我们需要生成相应的shellcode,同时,其格式必须适合将其发送到远程服务器才行。为此,我们首先需要编译代码,然后从编译的文件中提取机器代码。编译代码非常简单,具体如下所示:
当然,从目标文件中获取二进制数据的方法有很多。我们这里使用的方法是生成具有易于添加到Perl或C程序中的格式的字符串。
上面的两个命令将产生以下shellcode:

接下来,我们就需要开始编写漏洞利用代码了。
漏洞利用代码
目前为止,我们已经搭设了一个带有远程利用漏洞的系统。同时,也了解了如何在低安全环境中利用缓冲区溢出漏洞,并生成了一个用于在远程系统上运行的shellcode。现在我们需要一个漏洞利用代码,把所有这些整合起来,从而获得我们梦寐以求的远程shell。
当然,编写漏洞利用代码的语言有很多,不过这里选用的是自己最熟悉的Perl。
我们的漏洞利用代码具体如下所示:
漏洞利用代码的开头部分几乎是标准式的。接下来,根据您利用gdb找出的魔法数字来生成payload(请注意,在您的系统中这些数字可能会有所不同,这样的话,这个漏洞利用代码,在您的系统中,可能就会无法正常工作)。
然后,我们必须针对自己的远程shell进行一些额外的工作。使用直接和反向shell时,一旦漏洞利用代码执行完毕,我们通常需要使用另一个程序/模块连接到远程机器,或接收来自远程机器的连接。为此,可以使用netcat或您喜欢的渗透测试平台,甚至是自己专门编写的工具…
但是,就本地而言,我们将使用已建立的连接来访问shell,这个连接就是之前用来发送payload的那个。所以我添加了一些代码,用来从stdin读取命令,并将它们发送到远程服务器,同时也从远程shell读取数据。这些都是些标准的网络代码,实在是没有什么特别之处。
现在,你可以尝试一下这个可以获取远程shell的漏洞利用代码了!
小结
在本文中,我们讨论了一种巧妙地技术,可以隐秘地获取shell来远程访问易受攻击的服务器,并且不需要跟系统提供的套接字API打交道。这使得shellcode的开发变得更简单,也使其更简洁(例如,你可以跟提供的代码比较一番。
谁可以帮我讲解下DOS:的ping,nbtstat,netstat,tracert,net,ftp这几个命令。
PING命令参数详解[编辑本段]-a 将目标的机器标识转换为ip地址-t 若使用者不人为中断会不断的ping下去-c count 要求ping命令连续发送数据包,直到发出并接收到count个请求-d 为使用的套接字打开调试状态-f 是一种快速方式ping。 使得ping输出数据包的速度和数据包从远程主机返回一样快,或者更快,达到每秒100次。 在这种方式下,每个请求用一个句点表示。 对于每一个响应打印一个空格键。 -i seconds 在两次数据包发送之间间隔一定的秒数。 不能同-f一起使用。 -n 只使用数字方式。 在一般情况下ping会试图把IP地址转换成主机名。 这个选项要求ping打印IP地址而不去查找用符号表示的名字。 如果由于某种原因无法使用本地DNS服务器这个选项就很重要了。 -p pattern 拥护可以通过这个选项标识16 pad字节,把这些字节加入数据包中。 当在网络中诊断与数据有关的错误时这个选项就非常有用。 -q 使ping只在开始和结束时打印一些概要信息。 -R 把ICMP RECORD-ROUTE选项加入到ECHO_REQUEST数据包中,要求在数据包中记录路由,这样当数据返回时ping就可以把路由信息打印出来。 每个数据包只能记录9个路由节点。 许多主机忽略或者放弃这个选项。 -r 使ping命令旁路掉用于发送数据包的正常路由表。 -s packetsize 使用户能够标识出要发送数据的字节数。 缺省是56个字符,再加上8个字节的ICMP数据头,共64个ICMP数据字节。 -v 使ping处于verbose方式。 它要ping命令除了打印ECHO-RESPONSE数据包之外,还打印其它所有返回的ICMP数据包。
命令中的netstat -an 是怎么看的,因为我想知道开放了哪些端口,这样我就会知道电脑是否有木马拜托各位大
netstat命令的功能是显示网络连接、路由表和网络接口信息,可以让用户得知目前都有哪些网络连接正在运作。 该命令的一般格式为: netstat [选项] 命令中各选项的含义如下: -a 显示所有socket,包括正在监听的。 -c 每隔1秒就重新显示一遍,直到用户中断它。 -i 显示所有网络接口的信息,格式同“ifconfig -e”。 -n 以网络IP地址代替名称,显示出网络连接情形。 -r 显示核心路由表,格式同“route -e”。 -t 显示TCP协议的连接情况。 -u 显示UDP协议的连接情况。 -v 显示正在进行的工作。 -A 显示任何关联的协议控制块的地址。 主要用于调试 -a 显示所有套接字的状态。 在一般情况下不显示与服务器进程相关联的套接字 -i 显示自动配置接口的状态。 那些在系统初始引导后配置的接口状态不在输出之列 -m 打印网络存储器的使用情况 -n 打印实际地址,而不是对地址的解释或者显示主机,网络名之类的符号 -r 打印路由选择表 -f address -family对于给出名字的地址簇打印统计数字和控制块信息。 到目前为止,唯一支持的地址簇是inet -I interface 只打印给出名字的接口状态 -p protocol-Name 只打印给出名字的协议的统计数字和协议控制块信息 -s 打印每个协议的统计数字 -t 在输出显示中用时间信息代替队列长度信息。 netstat命令的列标题 Name 接口的名字 Mtu 接口的最大传输单位 Net/Dest 接口所在的网络 Address 接口的IP地址 Ipkts 接收到的数据包数目 Ierrs 接收到时已损坏的数据包数目 Opkts 发送的数据包数目 Oeers 发送时已损坏的数据包数目 Collisions 由这个接口所记录的网络冲突数目 netstat的一些常用选项: netstat -s--本选项能够按照各个协议分别显示其统计数据。 如果你的应用程序(如Web浏览器)运行速度比较慢,或者不能显示Web页之类的数据,那么你就可以用本选项来查看一下所显示的信息。 你需要仔细查看统计数据的各行,找到出错的关键字,进而确定问题所在。 netstat -e--本选项用于显示关于以太网的统计数据。 它列出的项目包括传送的数据报的总字节数、错误数、删除数、数据报的数量和广播的数量。 这些统计数据既有发送的数据报数量,也有接收的数据报数量。 这个选项可以用来统计一些基本的网络流量)。 netstat -r--本选项可以显示关于路由表的信息,类似于后面所讲使用route print命令时看到的 信息。 除了显示有效路由外,还显示当前有效的连接。 netstat -a--本选项显示一个所有的有效连接信息列表,包括已建立的连接(ESTABLISHED),也包括监听连接请求(LISTENING)的那些连接。 bnetstat -n--显示所有已建立的有效连接。 AWKPHP经典 netstat -an中state含义 netstat -an中state含义 LISTEN:侦听来自远方的TCP端口的连接请求 SYN-SENT:再发送连接请求后等待匹配的连接请求 SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认 ESTABLISHED:代表一个打开的连接 FIN-WAIT-1:等待远程TCP连接中断请求,或先前的连接中断请求的确认 FIN-WAIT-2:从远程TCP等待连接中断请求 CLOSE-WAIT:等待从本地用户发来的连接中断请求 CLOSING:等待远程TCP对连接中断的确认 LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认 TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认 CLOSED:没有任何连接状态 其实可以man netstat , 看其中的stat部分解释 State The state of the socket. Since there are no states in raw mode and usually no states used in UDP, this column may be left blank. Normally this can be one of several values: ESTABLISHED The socket has an established connection. SYN_SENT The socket is Actively attempting to establish a connection. SYN_RECV A connection request has been received From the network. FIN_WAIT1 The socket is closed, and the connection is shutting down. FIN_WAIT2 Connection is closed, and the socket is waiting for a shutdown from the remote end. TIME_WAIT The socket is waiting after close to handle packets still in the network. CLOSED The socket is not being used. CLOSE_WAIT The remote end has shut down, waiting for the socket to close. LAST_ACK The remote end has shut down, and the socket is closed. Waiting for acknowledgement. LISTEN The socket is listening for incoming connections. Such sockets are not included in the output unless you specify the –listening (-l) or –all (-a) option. CLOSING Both sockets are shut down but we still don’t have all our data sent. UNKNOWN The state of the socket is unknown.
常常使用的ping指令有哪些功能
PING命令参数详解-a 将目标的机器标识转换为ip地址-t 若使用者不人为中断会不断的ping下去-c count 要求ping命令连续发送数据包,直到发出并接收到count个请求-d 为使用的套接字打开调试状态-f 是一种快速方式ping。 使得ping输出数据包的速度和数据包从远程主机返回一样快,或者更快,达到每秒100次。 在这种方式下,每个请求用一个句点表示。 对于每一个响应打印一个空格键。 -i seconds 在两次数据包发送之间间隔一定的秒数。 不能同-f一起使用。 -n 只使用数字方式。 在一般情况下ping会试图把IP地址转换成主机名。 这个选项要求ping打印IP地址而不去查找用符号表示的名字。 如果由于某种原因无法使用本地DNS服务器这个选项就很重要了。 -p pattern 拥护可以通过这个选项标识16 pad字节,把这些字节加入数据包中。 当在网络中诊断与数据有关的错误时这个选项就非常有用。 -q 使ping只在开始和结束时打印一些概要信息。 -R 把ICMP RECORD-ROUTE选项加入到ECHO_REQUEST数据包中,要求在数据包中记录路由,这样当数据返回时ping就可以把路由信息打印出来。 每个数据包只能记录9个路由节点。 许多主机忽略或者放弃这个选项。 -r 使ping命令旁路掉用于发送数据包的正常路由表。 -s packetsize 使用户能够标识出要发送数据的字节数。 缺省是56个字符,再加上8个字节的ICMP数据头,共64个ICMP数据字节。 -v 使ping处于verbose方式。 它要ping命令除了打印ECHO-RESPONSE数据包之外,还打印其它所有返回的ICMP数据包。
发表评论