木马隐藏端口的一种方法.htm

来自「关于win2000核心编程的文章」· HTM 代码 · 共 166 行

HTM
166
字号
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0059)http://jiurl.cosoft.org.cn/jiurl/document/NoPort/NoPort.htm -->
<HTML><HEAD><TITLE>Jiurl255</TITLE>
<META content="text/html; charset=gb2312" http-equiv=Content-Type>
<STYLE type=text/css>.title {
	FONT-FAMILY: "黑体", Arial, sans-serif; FONT-SIZE: 21px; FONT-WEIGHT: bold; LINE-HEIGHT: 48px; TEXT-DECORATION: none
}
.author {
	FONT-FAMILY: "宋体"; FONT-SIZE: 12px; LINE-HEIGHT: 16px
}
.content {
	FONT-SIZE: 14px; LINE-HEIGHT: 20px
}
</STYLE>

<META content="MSHTML 5.00.2614.3500" name=GENERATOR></HEAD>
<BODY bgColor=#f7f7f7 topMargin=5>
<DIV align=center>
<CENTER>
<TABLE border=0 cellPadding=0 cellSpacing=0 height=29 width="96%">
  <TBODY>
  <TR>
    <TD class=title height=41 width="100%">
      <P align=center><FONT face=宋体>木马隐藏端口的一种方法</FONT></P></TD></TR></CENTER>
  <TR>
    <TD class=author height=9 width="100%">
      <P align=center>作者: <A href="mailto:jiurl@mail.china.com">JIURL</A> 
  </P></TD></TR>
  <TR>
    <TD class=author height=6 width="100%">
      <P 
      align=center>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
      主页: <A href="http://jiurl.yeah.net/">http://jiurl.yeah.net/</A> </P></TD></TR>
  <TR>
    <TD class=author height=2 width="100%">
      <P align=center>&nbsp;&nbsp;&nbsp; 日期: 2003-1-13 
</P></TD></TR></TBODY></TABLE></DIV>
<DIV align=center>
<CENTER>
<TABLE border=0 cellPadding=0 cellSpacing=0 height=1 width="96%">
  <TBODY>
  <TR>
    <TD height=1 width="100%">
      <HR color=#396da5 SIZE=3>
    </TD></TR></TBODY></TABLE></CENTER></DIV>
<DIV align=center>
<TABLE border=0 cellPadding=0 cellSpacing=0 class=content height=6390 
width="96%">
  <TBODY>
  <TR>
    <TD height=376 vAlign=top width="131%">
      <P>&nbsp;&nbsp;&nbsp; 
      这是一种很特殊的方法,使用它通讯没有端口,而且由于它的特殊性,也许会带来一些其他的优点。但这种方法也有一个比较大的缺点。<BR>&nbsp;&nbsp;&nbsp; 
      它,也许该起个名字,比如叫Jiurl255。它不使用tcp协议,也不使用udp协议,也不使用icmp协议。它使用什么协议,就像乱起的那个名字一样,它使用255协议。
      <P><BR><IMG border=0 height=240 src="木马隐藏端口的一种方法.files/IPHEADER.gif" 
      width=546>
      <P>上面这幅图,是一个没有IP选项的IP头。其中有个字段为8位协议,一个字节长,系统就是通过这个字节中的值来区别上层协议是什么,通过这个字节的值来决定应该把数据交给谁来处理。TCP是十进制6,UDP是十进制17。就是说这个值是6的话就交给tcp处理,是17的话就交给udp处理。那么如果这个值是一个没有人处理的值会怎么样呢?比如222,255(8bit,最大255)。我觉得255漂亮些,就拿255说吧,其他没人用的值都是一样的。那么会怎么样呢?我猜测可以收到的,后来做了些小试验,说明我是对的。(我曾夜观天象,发现你有学计算机的命)。这个东西和tcp,udp没什么关系,自然也就不会有tcp,udp的端口号了。
      <P>好了,有兴趣的先试一试吧,使用Jiurl255做一次简单通讯的<A 
      href="http://jiurl.cosoft.org.cn/jiurl/document/NoPort/rclient.exe">客户端程序下载</A>,<A 
      href="http://jiurl.cosoft.org.cn/jiurl/document/NoPort/rserver.exe">服务器端程序下载</A>。<BR>服务器端叫rserver,客户端叫rclient。<BR>rserver 
      首先 theSocket = socket(AF_INET, SOCK_RAW, 
      255);建立一个使用Jiurl255的原始套接字,然后绑定本地地址,最后阻塞在recvfrom,等待着发往255协议的数据。收到之后,会将收到数据打印出来。<BR>rclient 
      首先 获得服务器的IP地址,然后 theSocket = socket(AF_INET, SOCK_RAW, 
      255);建立一个使用Jiurl255的原始套接字,然后让你从键盘输入些数据 就 sendto 用协议255向服务器端发送输入的数据。
      <P>第一个试验,进行一次收发,就可以发现,确实是可以利用没人用的协议号发送和接收数据。大概是这样的,系统收到ip包以后看该协议号有没有进程要接受,如果有的话,就发给那个进程。
      <P>第二个试验,运行一个rclient,运行两个rserver,发一次数据。可以发现,两个rserver都收到了rclient发的数据。说明系统会把收到的数据发给每个要接受这个协议号上数据的进程。
      <P>另一个试验,server端创建套接字时,指定协议号为200,client端创建套接字,填充ip头时,都指定协议号为255,结果server端就收不到client端发送的数据了。
      <P>当时试验后的笔记:"<BR>server端收数据<BR>client端发数据<BR>server端创建套接字时,指定协议号为255,<BR>client端创建套接字,填充ip头时,都指定协议号为255,<BR>结果server端收到了client端发送的数据。<BR><BR>server端创建套接字时,指定协议号为200,<BR>client端创建套接字,填充ip头时,都指定协议号为255,<BR>结果server端就收不到client端发送的数据了。<BR><BR>多个server端,都使用协议号255,<BR>client端也向255协议发数据,<BR>多个server端,都收到了数据。<BR>"
      <P>还有就是,如果程序既发又收的,并且是发往本机的,那么程序会收到自己发出的内容。没说清楚好像,比如吧,一个程序,发255的数据之后,就接收255上的数据,他把数据发往本机,那么它就会收到数据。
      <P><B>rclient:</B>
      <P>#include &lt;winsock2.h&gt;<BR>#include &lt;windows.h&gt;<BR>#include 
      &lt;stdio.h&gt;<BR>#include &lt;ws2tcpip.h&gt;&nbsp;<BR>#include 
      &lt;conio.h&gt;<BR><BR>#pragma 
      comment(lib,"ws2_32.lib")<BR><BR><BR>typedef struct ip_hdr 
      //定义IP首部<BR>{<BR>unsigned char h_verlen; //4位首部长度,4位IP版本号<BR>unsigned char 
      tos; //8位服务类型TOS<BR>unsigned short total_len; //16位总长度(字节)<BR>unsigned 
      short ident; //16位标识<BR>unsigned short frag_and_flags; //3位标志位<BR>unsigned 
      char ttl; //8位生存时间 TTL<BR>unsigned char proto; //8位协议 (TCP, UDP 
      或其他)<BR>unsigned short checksum; //16位IP首部校验和<BR>unsigned int sourceIP; 
      //32位源IP地址<BR>unsigned int destIP; //32位目的IP地址<BR>}IP_HEADER, 
      *PIP_HEADER;<BR><BR><BR>USHORT CheckSum(USHORT *buffer, int 
      size);<BR><BR>void RawClient( char *szServer );<BR><BR><BR>void 
      main()<BR>{<BR>WSADATA wsaData;<BR><BR>char 
      ServerAddr[256];<BR><BR>printf("Server Addr : 
      ");<BR>scanf("%s",ServerAddr);<BR>printf("\n");<BR><BR>WSAStartup(0x0202, 
      &amp;wsaData);<BR><BR>RawClient(ServerAddr);<BR><BR>WSACleanup();<BR>}<BR><BR>/////////////////////////////////////////////////<BR>USHORT 
      CheckSum(USHORT *buffer, int size)<BR>{<BR>unsigned long 
      cksum=0;<BR><BR>while (size &gt; 1)<BR>{<BR>cksum += *buffer++;<BR>size -= 
      sizeof(USHORT);&nbsp;<BR>}<BR>if (size)<BR>{<BR>cksum += 
      *(UCHAR*)buffer;&nbsp;<BR>}<BR>cksum = (cksum &gt;&gt; 16) + (cksum &amp; 
      0xffff);<BR>cksum += (cksum &gt;&gt;16);&nbsp;<BR><BR>return 
      (USHORT)(~cksum);&nbsp;<BR>}<BR><BR>//////////////////////////////////////////////////////////<BR>void 
      RawClient( char *szServer )<BR>{<BR>LPHOSTENT 
      lpHostEntry;<BR><BR>lpHostEntry = gethostbyname(szServer);<BR>if 
      (lpHostEntry == NULL)<BR>{<BR>printf("gethostbyname() 
      error\n");<BR>return;<BR>}<BR><BR>SOCKET theSocket;<BR><BR>theSocket = 
      socket(AF_INET, SOCK_RAW, 255);<BR>if (theSocket == 
      INVALID_SOCKET)<BR>{<BR>printf("socket() 
      error\n");<BR>return;<BR>}<BR><BR>int nRet;<BR>BOOL 
      optval;<BR><BR>optval=TRUE;<BR>nRet = setsockopt(theSocket, IPPROTO_IP, 
      IP_HDRINCL, (char*)&amp;optval, sizeof(optval));<BR>if (SOCKET_ERROR == 
      nRet)<BR>{<BR>printf("SetSockOpt Error!%d\n", 
      WSAGetLastError());<BR>return;<BR>}<BR><BR>SOCKADDR_IN 
      saServer;<BR><BR>saServer.sin_family = AF_INET;<BR>saServer.sin_addr = 
      *((LPIN_ADDR)*lpHostEntry-&gt;h_addr_list); // Let WinSock assign 
      address<BR>saServer.sin_port = 0; // Use port passed from user<BR><BR>char 
      szBuf[1024];<BR><BR>//////////////////////////////////////////////////////////////////<BR>memset(szBuf, 
      0, sizeof(szBuf));<BR><BR>int IpHdrLen=0;<BR>int 
      DataLen=0;<BR><BR>IP_HEADER *pIpHdr=NULL;<BR>char* 
      pData=NULL;<BR><BR>IpHdrLen=sizeof(IP_HEADER);<BR><BR>pIpHdr=(IP_HEADER*)szBuf;<BR><BR>pIpHdr-&gt;h_verlen=(4&lt;&lt;4)| 
      (sizeof(IP_HEADER) / sizeof(unsigned 
      long));<BR>pIpHdr-&gt;tos=0;<BR>pIpHdr-&gt;proto=255;<BR>pIpHdr-&gt;ttl=128;<BR>pIpHdr-&gt;ident=0;<BR>pIpHdr-&gt;checksum=0;<BR>pIpHdr-&gt;frag_and_flags=0;<BR>pIpHdr-&gt;sourceIP=inet_addr("1.1.1.1");<BR>pIpHdr-&gt;destIP=(unsigned 
      int)saServer.sin_addr.s_addr;<BR><BR>pData=(szBuf+IpHdrLen);<BR>printf("Type 
      a String 
      :");<BR>scanf("%s",pData);<BR>DataLen=strlen(pData);<BR><BR>pIpHdr-&gt;total_len=IpHdrLen+DataLen;<BR><BR>//////////////////////////////////////////////////////////////////<BR>nRet 
      = sendto(theSocket, // Socket<BR>szBuf, // Data 
      buffer<BR>IpHdrLen+DataLen, // Length of data<BR>0, // 
      Flags<BR>(LPSOCKADDR)&amp;saServer, // Server address<BR>sizeof(struct 
      sockaddr)); // Length of 
      address<BR>if(nRet!=SOCKET_ERROR)<BR>{<BR>printf("Client send: 
      %s\n",pData);<BR>}<BR><BR>getch();<BR>closesocket(theSocket);<BR>return;<BR>}<BR>
      <P><B>rserver:</B>
      <P>#include &lt;winsock2.h&gt;<BR>#include &lt;windows.h&gt;<BR>#include 
      &lt;stdio.h&gt;<BR>#include &lt;ws2tcpip.h&gt;&nbsp;<BR>#include 
      &lt;conio.h&gt;<BR><BR>#pragma comment(lib,"ws2_32.lib")<BR><BR>void 
      RawServer();<BR><BR>void main()<BR>{<BR>WSADATA 
      wsaData;<BR><BR>WSAStartup(0x0202, 
      &amp;wsaData);<BR><BR>RawServer();<BR><BR>WSACleanup();<BR>}<BR><BR>//////////////////////////////////////////////////////////<BR>void 
      RawServer()<BR>{<BR>int nRet;<BR>SOCKET theSocket;<BR><BR>theSocket = 
      socket(AF_INET, SOCK_RAW, 255);<BR>if (theSocket == 
      INVALID_SOCKET)<BR>{<BR>printf("socket() 
      error\n");<BR>return;<BR>}<BR><BR>SOCKADDR_IN 
      saServer;<BR><BR>saServer.sin_family = 
      AF_INET;<BR>saServer.sin_addr.s_addr = INADDR_ANY; // Let WinSock assign 
      address<BR>saServer.sin_port = 0; // Use port passed from user<BR><BR>nRet 
      = bind(theSocket, // Socket descriptor<BR>(LPSOCKADDR)&amp;saServer, // 
      Address to bind to<BR>sizeof(struct sockaddr) // Size of 
      address<BR>);<BR>if (nRet == SOCKET_ERROR)<BR>{<BR>printf("bind() 
      error\n");<BR>closesocket(theSocket);<BR>return;<BR>}<BR><BR>///////////////////////////////////////////////////<BR>int 
      nLen;<BR>nLen = sizeof(SOCKADDR);<BR>char szBuf[1024];<BR><BR>nRet = 
      gethostname(szBuf, sizeof(szBuf));<BR>if (nRet == 
      SOCKET_ERROR)<BR>{<BR>printf("gethostname() 
      error\n");<BR>closesocket(theSocket);<BR>return;<BR>}<BR><BR>LPHOSTENT 
      lpHostEntry;<BR>lpHostEntry = gethostbyname(szBuf);<BR><BR>printf("Server 
      named %s addr %s \n\n",<BR>szBuf, 
      inet_ntoa(*(LPIN_ADDR)lpHostEntry-&gt;h_addr));<BR>///////////////////////////////////////////////////<BR><BR>SOCKADDR_IN 
      saClient;<BR><BR>memset(szBuf, 0, sizeof(szBuf));<BR><BR>nRet = 
      recvfrom(theSocket, // Bound socket<BR>szBuf, // Receive 
      buffer<BR>sizeof(szBuf), // Size of buffer in bytes<BR>0, // 
      Flags<BR>(struct sockaddr*)&amp;saClient, // Buffer to receive client 
      address&nbsp;<BR>&amp;nLen); // Length of client address 
      buffer<BR>if(nRet!=SOCKET_ERROR)<BR>{<BR>printf("Server recv: 
      %s\n",szBuf+20);<BR>}<BR>else<BR>{<BR>printf("recv error: 
      %d\n",WSAGetLastError());<BR>closesocket(theSocket);<BR>return;<BR>}<BR><BR>getch();<BR>closesocket(theSocket);<BR>return;<BR>}<BR>
      <P>使用Jiurl255进行数据传输明显是没有tcp和udp的端口的,这样也就不会被 netstat -an 
      之类的命令看到。这和利用icmp传输数据很象,但是我觉得Jiurl255比用icmp传数据要来的好一些。它还有个比较大的缺点就是,由于直接使用的是ip,所以传输的数据是有可能丢失的,这是我观察后写的笔记:"使用ip,ip头字段中的上层协议填255,这是一个还没有人用的协议号。然后在网络中两个主机上分别运行c,s程序,c发送ip255报文,内容hello 
      n,共发50个,每秒发一个。s收ip255报文,确实收到,一次测试中,50个报文,收到了49个,也确实存在ip报丢失的情况。两个方向上都试了,是可行的。"<BR>因此用此方法隐藏端口是要多费不少力气的,我自己写的一个程序中,传送文件使用了一些简单的等待ack,超时重发的机制保证数据不会丢失和发生错误,传送命令,没有保证不会丢失。有时间的话,准备写个保证不丢失,不错误的收发函数。传送文件用的那些机制,参考了使用udp协议进行文件可靠传输的tftp协议。
      <P><B>终</B> 
      <P><A 
      href="http://jiurl.cosoft.org.cn/jiurl/document/NoPort/rclient.exe">编译好的客户端程序下载</A>&nbsp; 
      <A 
      href="http://jiurl.cosoft.org.cn/jiurl/document/NoPort/rserver.exe">编译好的服务器端程序下载</A>&nbsp; 
      <A 
      href="http://jiurl.cosoft.org.cn/jiurl/document/NoPort/JiurlNoPortShow.zip">源程序下载</A> 
      </P></TD></TR></TBODY></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?