不好意思,首发了安全客。如何报名参加看雪翻译组?
https://www.anquanke.com/post/id/92401
在Linux系统做未授权测试,我们须准备一个安全的渗透环境,通常第一件事就是安装虚拟机。且在攻击阶段中还需要对受害系统进行控制。常见的后门大多数是利用Metasploit生成,而目前反病毒产品遇到Metasploit文件签名的程序就会添加特征库作为查杀对象,所以开发出自己的后门程序非常必要。
这篇文章将介绍如何写一个具有反向连接功能的后门。
反向连接:通常的网络连接程序是由客户端通过服务器开放的端口连接到服务器,反向连接是客户端打开服务器端口,由服务器主动连接客户端。反向连接这种方式常用于绕过防火墙和路由器安全限制。
举个例子,防火墙隔离的计算机会阻止传入的连接,但对于连接Intnet服务器的出站连接则不做严格限制。一旦连接建立网络通讯,远程主机就可以向后门发送命令。这种通讯方法更有助于控制受控机器,也更不容易检测。
在本系列教程文章中,将分成3部分撰写,一步步介绍如何用Python语言开发一个反向TCP连接程序。每一个部分都会介绍一个新函数、命令或代码,使其更加灵活。
这一部分将介绍创建网络连接,发送和接受输出。
前面介绍过,攻击者并不会主动连接受控服务器,因为会被受控制服务器的防火墙拦截。
但是我们可以把自身当成服务器,让受控服务器作为客户端反向连接我们,然后向客户端发送命令。客户端与服务端安装套接字实现反向连接的代码如下:
让我们分解以上代码,逐行解释每段代码的作用:
整体思路:声明subprocess模块中的sp函数执行命令
1)监听信息:通过获取命令行参数得到套接字监听的主机IP、端口
2)套接字部分:安装套接字,绑定套接字,监听连接、接收客户端的连接
3)输出连接信息:如果有网络连接信息,就打印出来
4)循环部分:将脚本运行到一个while循环中,以便发送命令并接收输出
5)if判断-1: 如果输入的命令不是"exit()"程序继续运行,否则发送给客户端"exit()",让客户端关闭套接字连接
6)if判断-2:如果输入的命令是空的,我们再次跳过while循环。不执行后面的命令
7)发送、接收命令:如果if判断没有执行退出或者跳过,则负责发送和接收命令
8)处理接收结果:将接收的数据和数据实际大小切割开来存放
9)处理数据:如果接收的数据实际大小跟接收数据的大小不匹配,那就运行一个while循环把剩余的数据拼接起来,直到数据实际大小跟接收数据结果相等
10)打印结果过滤换行符
11)出现异常则关闭套接字
以上代码理解起来并不困难,但是随着代码的复杂度不会再逐行解释,只解释重要的部分。接下来让我们编写客户端的Socket部分。
受害者连接我们的代码不应该太多。
让我们分解以上代码,逐行解释每段代码的作用:
1)通过sys.argv模块的命令行接受Socket套接字信息
2)设置Socket套接字并连接到指定的主机IP、端口。
3)接收服务器发送的命令的部分放在一个循环语句内。
4)如果接收的命令不是exit(),就通过管道执行接收的命令。执行命令后的输出分配给变量sh。
5)(out,err)是标准的stdout和stderr流。
6)将流的输出分配给result变量。
7)将文件大小设置为16字节的long型,用于助服务器端(攻击者)识别文件大小。
8)计算长度并将其附加到输出里。
if-else后的部分:如果收到的命令是exit(),跳出循环和关闭连接。
执行我们的攻击者(服务器)脚本,看看结果如下:
客户端连接命令行的主机信息。
服务器脚本运行的截图:
正如预期,客户机控制台是空的,因为我们没有打印任何东西。预期编写完成后的截图如下:
到此我们已经将基础的反向TCP连接代码编写完成了,现在将继续编写些基础函数来帮助我们把程序界面改善,例如给Shell界面添加颜色。
这份代码在Windows上也可以运行,但Windows平台不是本系列教程的首选平台。
reverseTcp.py
connect.py
在第二部分教程中,我们会把服务器端脚本的Shell界面进行美化。
我们导入模块声明的语句如下:
这个函数将把我们的Shell中的文本替换得更加美观。
这个函数用指定的颜色来修饰传递给它的任何文本。接受的字符和显示颜色说明如下:
这些介绍的基础函数不是必需要写的代码,但是改善了用户使用的体验感,具体的美化效果可以自己定制。
编辑:我把“lgray”改成了“gray”。 我们可以根据个人喜好更改。
这个函数的具体作用是将程序说明文本的内容返回给调用者。
Main_control()函数的作用是接收服务器Socket套接字。在前面的文章中我们没有使用调用函数的方式编写代码,而是采用了过程化的代码。现在这些过程化代码被封装到Main_control()函数中,方便后续的修改。代码如下图所示:
看到这一坨代码请不要惊慌,我们只需要关注代码带来的脑力挑战即可。让我们分解一下代码开始解读吧?:
1)我们接受Socket套接字信息后将其传递给相应的变量host、port变量
2)如果异常没有捕获到任何错误,则借助script_color()函数打印出"Framework Started
Successfully"
3)调用banner()函数,打印函数里的文本到界面上
4)设置Socket套接字,绑定和监听
5)开头已经将主机作为空字符串参数传递。所以我们在设置套接字后,如果参数为空就将主机字符串默认设为“localhost”
6)打印出"Listening on host address:port number ..."
7)等待接收Socket套接字信息连接,捕获到错误输入则打印错误中断提示
8)如果客户端顺利连接,就会将Socket套接字数据和主机地址作为参数传递进入console()控制台函数
9)当console()函数执行完毕后,关闭创建的Socket套接字
这部分代码很容易令人灰心!只有坚持看下去才能渡过难关。console()控制台函数的代码如下:
以上的代码非常长,首先我们打印一个字符串表示从远程主机建立连接。然后我们从数据流中接收数据。数据流中包含有关于远程系统的信息(我们会在Client(客户端)执行)。以下是数据显示的布局内容:
所有信息都是来自OS模块的uname()和getlogin()函数(我们在Client(客户端)执行的代码)。
使用收到的信息为Shell创建自定义提示名称,例如:root@127.0.0.1。
然后我们进入while循环,该循环包含连接的命令。由于我们重新自定义了程序命令,因此原装操作系统命令类似于“ls -l”和其他linux命令将无法正常使用。
下面是我们的前5条内置命令。
exec——接收一个命令作为参数,并在远程主机上执行该命令。这是我们调用Linux命令的地方,例如:exec ls -l
cls - 清除终端显示的信息,使用默认的linux clear命令
help - 调用help函数打印帮助文本
sysinfo - 打印出收到的远程系统信息
exit() - 向远程shell发送一个停止命令,在本地退出控制界面。
任何非指定的命令都不会被接受,并且会在else语句中打印一条错误消息。
在内置的exec命令中,不会有任何的参数被传递并且会输出一个错误消息。我们在exec命令中有一个新的函数send_data。它接受连接流和要执行的命令。负责自动处理数据的发送和接收。
这段代码读者最好可以自己动手写一遍,这样就可以在代码运行后进行修改。如果在写作过程中进行修改的话,可能会导致很多问题。
所有内置在这个框架(脚本)中的命令都将在这里说明。
这个函数会按照顺序打印一个help_list字典,并对字符进行美化处理后循环输出来。
该函数计算数据的长度后将其与数据一起发送。
现在我们把调用函数组合放在一起。
我们必须调用函数,否则它自己是不会执行的。
至此我们完成了部分代码,现在让我们将客户机脚本也进行相应的修改。
客户端也需要遵守一些规则和命令,比如服务器脚本中的exec命令。我们的import声明应该改成:
我们首先建立的函数是connect()连接函数。
该函数跟名称含义一样,作用为跟指定的地址连接建立后发送自身系统信息,接收控制端的远程命令。
然后以连接流作为参数调用interactive_session()交互式会话函数。
该函数运行一个循环根据“if”语句接受和执行命令。
该函数使用另一个send_data()发送数据函数来发送数据。
该函数将计算数据执行后结果的总长度,将执行后的结果转换为字符串,填充为16位。将这个总长度跟执行后的结果数据一起发送出去。
为了便于将来的修改和添加功能,我们把所有的函数代码组合在一起,放到connect()函数里。
当然,在主函数里我们必须调用connect()函数,否则函数自己是不会自动执行的。
让我们执行服务器控制端的脚本,监听一个8000端口,看看得到了什么结果。
执行受控制客户端在命令行上连接控制端主机,输出命令的方式如下。
以下是攻击者服务器脚本的运行截图:
帮助选项如下:
通过NMap扫描远程系统得到的结果,受控制客户端已经打开了服务端口,正如预期的那样,客户端控制台显示出来的信息应该是空的,因为我们没有打印任何东西到终端界面上。
reverse_tcp_part2.py
connect_part2.py
随着某些勒索软件的教程,有些用户已经开始把文章中的代码装备到了自己写的恶意软件里。把知识用于恶意盈利,这不是作者愿意看到的局面。
这个TCP反向连接后门思路,已经事先写好了程序,并构建成了一个框架。作者实现了很多功能,比如远程导入、下载、获取root权限和升级攻击、网络摄像头、屏幕截图、情报搜集、窃取凭证等功能。为了让这个后门程序能够在大多数Linux发行版中得到充分的支持,已经尝试将其移植到各种发行版中,以解决不同的系统设计问题。
但是很不幸,作者删除了最后一个虚拟机(里面有程序最新的代码),因为硬件设备有限,只能通过利用虚拟机的方式来节省空间。如今只能把最后备份的文件贡献了出来,有兴趣的人可以把它继续开发得更加全面来帮助论坛。
为了让感兴趣的开发者了解项目中的信息,这里展示部分项目的截图。项目地址如下:
使用python zero.py命令在目录中启动程序。
这个本来有个横幅文字展示,但是为了节省展示空间,我删除掉了。输入help命令打印出帮助命令。这个程序首先检查状态是不是已经正常运行。是通过框架启动时加载的自定义别名文件实现的,在不同的端口上开始监听,而不是手动输入。运行状态文件使用相同的命令代码,类似在终端中输入使用的方式一样。
功能函数代码主要放置在configurations文件夹。使用start_services命令可以把程序运行起来,启动了多个监听器,使用HASH标签做注释。
随意使用命令,我演示的是start_server命令,它接受两个参数:主机和端口。如果要为主机输入空的double/single字符串,请改用localhost。只是为了帮助程序更好地显示。
我们可以在一个监听器上接受多个客户端,就不会中断同一监听端口上的其他连接。
客户端脚本使用connect.py文件。语法是:python connect.py <host> <port>。客户端具有自动连接功能,如果连接失败会重新连接。
当客户端连接时,我们在终端上得到类似的东西。
这不会让我们直接进入shell,而是将其推入后台,以便让我们继续做正在做的事情(Defaults idea)。程序可以使用sessions命令列出所有的会话连接。
然后可以使用interact命令和会话ID进行交互。
当连接到一个客户端,有一个全新的命令集(这是在没有备份的情况下进行开发的地方)。
开发命令是 host-scanner(需要的线程),check_vm(需要更多的跨平台的结果),webcam_list webcam_snap(代码已经毁擦除掉的虚拟机里),检索目录(嵌入到脚本中,但不会在屏幕中显示 - 克隆给定的目录 - 取得了一些进展但也毁在虚拟机里),截图(像lubuntu这样的老版本和裸发行版需要更多的库支持)。加密命令(重构为使用内部安全密钥与攻击者进行第一次数据通信,DH密钥交换和AES-SHA256进行数据传输)。
在执行sysinfo命令后会提示shell(会话)的签名信息。
该签名首先计算并存储在脚本部署之前的散列算法。我不知道是否在旧版本中实现了攻击者的检查特性,但整个想法是在接受连接之前检查shell签名。这是为了防止在脚本被发现时篡改,脚本使用它自己的源代码作为签名。如果签名不匹配,连接应该会删除。如果数据传输的加密不安全(用户可以先获得签名,然后用篡改的脚本发送相同的签名),那么该特性就可以被击败。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-2-1 16:40
被admin编辑
,原因: