前言
最近看了一些关于Windows后门的编程,感触颇深,学到了很多,特此分享下来。
从套接字到后门
说起后门,其实就是一个功能丰富的客户端与服务器端的程序。在我们初学每种编程语言的时候,都会或多或少的学到关于那种语言的网络编程,那个时候就会接触到socket套接字。
因为后门,在我看来就是一个植入在受害者机器上的一个服务器端程序(正向后门)/客户端程序(反向后门),它们会受害者机器上执行一些危险的命令,并通过网络来将结果发送给攻击者,而既然是通过网络的,那么就必然需要socket啦。
在Windows中,想要使用套接字的话就要include<winsock2.h>
,以及#pragma comment(lib, "ws2_32.lib")
,这个lib库文件可以在c:\\windows\\system32
下找到的。
对于socket编程,熟悉的小伙伴必然是知道套路的:socket初始化
-> bind
-> listen
-> accept
,这样,我们就完成了初步的一个服务器端的代码了,但是既然是后门,那么应该是能够执行命令的呀,一般我们会用c:\\windows\\system32\\cmd.exe
这个程序,该程序就是我们常用的cmd终端了,他是在系统目录下的已经存在的程序,除非管理员故意删除,否则没台windows电脑上都会有的。
从命令执行到后门
既然想要执行cmd的命令,那么之前说的,我们可以利用cmd.exe
这个文件,但是我们的后门是一个程序,执行之后就是一个进程,而cmd.exe执行之后也是一个进程,这样就涉及到了一个概念:进程间通信。
这个我们给出的解决方案就是利用管道的方式,来将我们的输入以及cmd执行后的结果通过管道来传递。
说到管道,那么什么是管道呢?你可以简单的想象成一个管子,水管也行。管道有两端,那么一端一个进程不就可以实现进程的通信了嘛。
但是管道有两种,一个叫做匿名管道,一个叫做命名管道。
匿名管道只能用于有血缘关系的两个进程之间的通信,大多是父子进程的通信,而命名管道是两个独立的进程,通过访问一个管道服务器来进行数据的交换的,那么一看就是命名管道好复杂的,所以我们还是用匿名管道吧,但是利用匿名管道的话就需要父进程和子进程了。咋办呢?我们可以用让我们的后门fork一个子进程,这个子进程就是cmd.exe
,这样不就好了嘛。
在Windows中,创建匿名管道使用函数CreatePipe
,而创建子进程是CreateProcess
函数。那么创建好了,如何通信的具体操作又是如何呢?如何让这两个进程相连呢?
我们在CreatePipe的时候,需要用到四个参数,分别是hRead句柄,hWrite句柄,SECURITY_ATTRIBUTES结构体,还有一个0作为缺省值就行了。其中前两个句柄分别是管道的读和写的方式。
而CreateProcess会先使用GetStartupInfo
这个函数,该函数接收一个STARTUPINFO参数,该参数有StdInput、StdOutput、StdError,如果了解linux系统的就知道这三个是干啥的了,分别是标准输入、标准输出、标准错误,我们将之前的hRead句柄和标准输入相连,hWrite句柄和StdOutput和StdError相连,这样就可以将cmd.exe
与后门相连了。
到此,一个简单的后门程序就搞定了。
从单线程到多线程
刚才我们说的只是一个简单的单线程后门的例子,但是这样有个问题就是该后门只能给一个连接使用,那么我们想要多个连接都连接到这个线程怎么办呢?显而易见,答案就是多线程了。我们知道在写socket编程的时候,服务器端会在accept
函数出阻塞,等待客户端的连接,因此,如果我们想写一个多线程来实现多连接的话,那么就要在这里使用循环来实现多个accept函数阻塞等待多个连接,需要注意的是,这里的循环次数最好和之前listen
函数的次数是一样的。
还有一点是,在windows下,想要实现多线程的话,需要创建线程函数,至于线程线程函数是如何的,可以看我之前的博文————Windows编程之进程与线程
无管道后门
当然了,如果我们希望在完成后门的时候不需要管道,觉得写管道太过于麻烦了,那么也可以不用管道的。这里就要提出新的概念了,那就是WSASocket,WSASocket是windows专用的socket,与通用的socket不同的是,WSASocket是非阻塞的,并且在处理消息的时候是可以重叠使用的,可以不断的接受消息,组成消息队列,而不是像socket那样,只能接受之后发送才能再接受新的消息。
在使用WSASocket,需要在socket初始化的时候将socket变为WSASocket,当然了,对应的参数也是要改变的。后面创建进程之前的STARTUPINFO结构体,将StdOutput、StdInput、StdError直接和WSASocket句柄相连,即可,这样就实现了无管道后门的操作。