[2000년 자료] DDOS 탐지 툴 dds 에 대한 간단한 분석

mod777.inha.ac.kr 홈페이지, 2000년 6월 기고

 

 

dds는 DDOS 공격을 탐지하는 툴이지만, 직접적인 해킹을 막거나 하는 처방은 될 수 없다. 여기서는 dds를 살펴 보고 사용법과, 어떤 식으로 탐지가 이루어지는지에 관해 간단히 살펴 보도록 하자.

일단, dds는 원래 철조망 공격을 탐지하던 스캐너인 gag에 기반한 것이다. 그래서 두 소스에서 상당히 유사점을 발견할 수 있다. dds는 trinoo와 tfn을 탐지할 수 있으며, tfn2k는 탐지하지 못한다. 또한 그렇게 신뢰성이 좋은 편은 아니므로 참고용으로 사용할 수 있겠다. 일단은 대부분의 BSD 계열 유닉스에서 잘 돌아가는 것으로 알려져 있다. 사용법은 다음과 같다.

# ./dds 198.162.1.0/24

앞의것은 당연히 IP이고, 뒤의것은 넷마스크이다. 기본값은 32, 즉 자기 자신만 검색하는 것이다. 24는 C클래스를 나타낸다.

dds가 trinoo나 철조망의 공격을 받고 있다면 다음과 같이 화면에 나타날 것이다. 같은 네트워크 안의 컴퓨터들이 공격받는 것을 확인할 수 있다.

# ./dds 192.168.1.0/24
Received ‘PONG’ from 192.168.1.17 – probable trinoo agent
Received TFN Reply from 192.168.1.153 – probable tfn agent
Received ‘sicken’ from 192.168.1.202 – probable stacheldraht agent

아무런 공격의징후도 찾지 못하면 화면에 별다른 것이 뜨지 않는다. 지속적으로 일정한 시간마다 체크를 하고 싶다면 옵션 v를 주면 된다. 옵션을 주었을 때는 다음과 같다.

# ./dds -v 192.168.1.0/24
Mask: 24
Target: 192.168.1.0
dds $Revision: 1.3 $ – scanning…

Probing address 192.168.1.1
Probing address 192.168.1.2
. . .
Received ‘PONG’ from 192.168.1.17 – probable trinoo agent
. . .
Probing address 192.168.1.152
Received TFN Reply from 192.168.1.153 – probable tfn agent
. . .
Received ‘sicken’ from 192.168.1.202 – probable stacheldraht agent
Probing address 192.168.1.203
. . .
Probing address 192.168.1.254

프로그램의소스를 살펴 보면, 다음과 같은 부분이 있다. 만약 dds가 철조망이 기동될 때의 값인 669번에 의해 ICMP_ECHOREPLY패킷을 받았고, 패킷의 데이터에 sicken이 들어 있으면 철조망의 공격으로 판단을할것이다. 여기서는 그러한 각 해킹 툴의성격을 정의한다. 다른 것들을 탐지하는것도 같은 방식이 된다. 따라서 정석적인 공격이라면 어느 정도 탐지가 가능하지만, 상당히 변형된 방식이라면 탐지하지 못할 것임을 알 수 있다.

/* stacheldraht variables */
static int stach_test = 668; /* sends test */
static int stach_echo = 669; /* gets reply “sicken” */
char stach_gagstr[] = “gesundheit!”;
char stach_echostr[] = “sicken”;

/* trinoo variables */
static short trinoo_dstport = 27444; /* handler listen port */
static short trinoo_rctport = 31335; /* agent listen port */
char trinoo_scmd[] = “png”;
char trinoo_spass[] = “l44adsl”;
char trinoo_echostr[] = “PONG”;

/* TFN variables */
u_short tfn_test = 789;
u_short tfn_reply = 123;

다음의 코드들을 통해 각각을 검출해 낸다. 각 공격법에 따라 약간씩 차이가 있다.

/* child side listens for return packets */
if (pid == 0)
listener(); /*이 함수가 패킷들을 받고 확인하는 실질적으로 주된 역할을 수행한다.*/

/*이 부분의 앞에서 각 패킷들을 받고, 사이즈를 확인한다. 여기서 확인이 된 사이즈라던가 그런 것들을 아래의 부분에서 확인, 검출하는 작업을 거친다.*/

/* tfn check */
bzero(buf, sizeof(struct icmp) + sizeof(stach_gagstr));

if(dflg)
fprintf(stderr,”Sending tfn ICMP to: %sn”,
inet_ntoa(isa.sin_addr));
icmpi->icmp_type = ICMP_ECHOREPLY;
icmpi->icmp_code= icmpi->icmp_seq = 0;
icmpi->icmp_id = htons(tfn_test);
icmpi->icmp_cksum = ip_sum((u_short *)icmpi,
sizeof(struct icmp));
i = sendto(isock, buf, sizeof(struct icmp), 0,
(struct sockaddr *)&isa, sizeof(isa));
if(i != sizeof(struct icmp)){
perror(“Error sending full tfn packetn”);
break;
}

/* trinoo check */
bzero((char *) &usa, sizeof(usa));
usa.sin_family = AF_INET;
usa.sin_addr.s_addr = target_ip.s_addr;
usa.sin_port = htons(trinoo_dstport);

if (dflg)
fprintf(stderr,”Sending UDP to: %sn”,
inet_ntoa(usa.sin_addr));
if ((usock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror(“cannot open UDP socket”);
exit(1);
}

i = sendto(usock,sbuf,strlen(sbuf), 0,
(struct sockaddr *)&usa,
sizeof(usa));

if (i < 0) {
char ebuf[BS];
sprintf(ebuf,”sendto: udp %s”,
inet_ntoa(usa.sin_addr));
perror(ebuf);
break;
}

/*실질적으로 많은 일을 수행하는 함수 listener이다. 이것을 각 해킹 툴의 소스와 비교하여 읽어 보는 것도 재미있는 일이다.*/

static void listener()
{

/* child becomes a listener process */

if ((isock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror(“cannot open raw ICMP socket”);
exit(1);
}
if ((usock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror(“cannot open raw UDP listen socket”);
exit(1);
}

bzero((char *) &sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons(trinoo_rctport);

if (bind(usock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror(“cannot bind to socket”);
exit(-1);
}

while (1) {
/* if parent has exitted, die */
if(getppid() == 1)
exit(0);

FD_ZERO(&fdset);
FD_SET(isock, &fdset);
FD_SET(usock, &fdset);
timi.tv_sec = 1;
timi.tv_usec = 0;
select(FD_SETSIZE, &fdset, NULL, NULL, &timi);
usleep(100);
if (FD_ISSET(isock, &fdset)) {
/* read data from ICMP listen socket */
memset((void *) &ipacket, 0, sizeof(struct icmppkt_t));
i = read (isock, (char *) &ipacket, BS) –
(sizeof (struct ip) + sizeof (struct icmp));
sa.sin_addr.s_addr = ipacket.ipi.ip_src.s_addr;
if(dflg)
fprintf(stderr,”Listener got an ICMP packetn”);

/* stacheldraht check */
if ((ipacket.icmpi.icmp_type == ICMP_ECHOREPLY) &&
(ntohs(ipacket.icmpi.icmp_hun.ih_idseq.icd_id)
== stach_echo)) {
if (strstr(ipacket.buffer, stach_echostr)) {
printf(“Received ‘%s’ from %s”,
stach_echostr,
inet_ntoa(sa.sin_addr));
printf(” – probable stacheldraht agentn”);
}
else {
printf(“Unexpected ICMP packet from %sn”,
inet_ntoa(sa.sin_addr));
}
}

/* TFN Check */
if ((ipacket.icmpi.icmp_type == ICMP_ECHOREPLY) &&
(ntohs(ipacket.icmpi.icmp_hun.ih_idseq.icd_id) ==
tfn_reply)) {
printf(“Received TFN Reply from %s”,
inet_ntoa(sa.sin_addr));
printf(” – probable tfn agentn”);
}

}

if (FD_ISSET (usock, &fdset)) {
/* read data from UDP listen socket */
memset((void *) &upacket, 0, sizeof(struct udppkt_t));
len = sizeof(from);
#if 1
if ((i = recvfrom(usock, buf, BS, 0,
(struct sockaddr *) &from, &len)) < 0) {
perror(“recvfrom”);
continue;
}
#else
i = read (usock, (char *) buf, BS) –
(sizeof (struct ip) + sizeof (struct udphdr));
#endif
sa.sin_addr.s_addr = upacket.ipi.ip_src.s_addr;
if(dflg)
fprintf(stderr,
“Listener got a UDP packet on port %sn”,
trinoo_rctport);

/* trinoo check */
if (strstr(buf,trinoo_echostr)) {
printf(“Received ‘%s’ from %s”,
trinoo_echostr,
inet_ntoa(from.sin_addr));
printf(” – probable trinoo agentn”);
}
else {
printf(“Unexpected UDP packet received on port %d from %sn”,
trinoo_rctport, inet_ntoa(from.sin_addr));
}
}
}
}

어떠한 해킹 공격이 개발되어 널리 퍼지면, 그를 확인하고 탐지하여 공격을 예방하자는 탐지, 방어툴이 개발되기 마련이다. DDOS 공격은 공격받고 있음을 탐지하더라도 실질적으로 방어를 해 내는 방법이 없는 것이 사실이므로, 탐지 툴의 존재의 이유 역시 희미하다고 할 수는 있겠다. 이번에 분석한 dds도 감히 “상당히 실망스러웠다”고 하고 싶다. 해킹이 정형화된 방식으로 이루어지는 것이 아닐진대, 변형 공격은 물론 정석적인 공격도 정확도가 그리 훌륭하지만은 않은 프로그램이라는 것은. 그러나 탐지 툴의 알고리즘을 확인하고 새로운 공격법과 그에 대한 방어를 연구하는 것은 좋은 공부가 되는일이라고 생각한다.

만화 “명탐정 코난”에 나오는 말인데…… 괴도 키드가 코난에게 하는 말이 있다. “도둑은 창조적인 예술가이지만, 탐정은 비평가에 불과하다.”고. 마찬가지일 듯. 언제나 결론은 뛰는 보안기술 위에 날아가는 해킹 기술이 있다는 것인 듯하다.

 

 

출 처 :
dds 소스를 기반으로 분석.dds README 파일 참조.

비주얼 노벨 만들기 툴……(Python)

http://www.renpy.org

renpy. 파이선 기반 툴로 쓸만한 듯 하다.

utf-8 지원.맥/리눅스용으로 변환 가능.

폰트가 게임 경로에 설치되어 있을 경우 폰트 지정 및 한글 사용 가능.

init:
$ style.default.font = “ahn_m.ttf”
$ style.default.language = “eastasian”

안상수 미들을 넣고 실행할 때에는 저렇게.

생각하는 시나리오는 있음. 슬슬 만들어 볼까.