botpop/plugins/network.rb

179 lines
5.8 KiB
Ruby

#encoding: utf-8
module BotpopPlugins
module Network
MATCH = lambda do |parent, plugin|
parent.on :message, "!ping" do |m| plugin.exec_ping m end
parent.on :message, /!ping #{Botpop::TARGET}\Z/ do |m| plugin.exec_ping_target m end
parent.on :message, /!httping #{Botpop::TARGET}\Z/ do |m| plugin.exec_ping_http m end
parent.on :message, /!dos #{Botpop::TARGET}\Z/ do |m| plugin.exec_dos m end
parent.on :message, /!fok #{Botpop::TARGET}\Z/ do |m| plugin.exec_fok m end
parent.on :message, /!trace #{Botpop::TARGET}\Z/ do |m| plugin.exec_trace m end
parent.on :message, /!poke #{Botpop::TARGET}\Z/ do |m| plugin.exec_poke m end
end
HELP = ["!ping", "!ping [ip]", "!httping [ip]",
"!dos [ip]", "!fok [nick]", "!trace [ip]", "!poke [nick]"]
CONFIG = Botpop::CONFIG['network'] || raise(MissingConfigurationZone, 'network')
ENABLED = CONFIG['enable'].nil? ? true : CONFIG['enable']
private
# Conversion of the string to value in ms
def self.config_string_to_time(value)
value.match(/\d+ms\Z/) ? value.to_f / 100.0 : value.to_f
end
public
DOS_DURATION = CONFIG['dos_duration'] || '2s'
DOS_WAIT_DURATION_STRING = CONFIG['dos_wait'] || '5s'
DOS_WAIT_DURATION = config_string_to_time DOS_WAIT_DURATION_STRING
# Trace is complexe. 3 functions used exec_trace_display_lines, exec_trace_with_time, exec_trace
TRACE_DURATION_INIT_STRING_DEFAULT = "0.3s"
TRACE_DURATION_INIT_STRING = CONFIG['trace_duration_init'] || TRACE_DURATION_INIT_STRING_DEFAULT
TRACE_DURATION_INCR_STRING_DEFAULT = "0.1s"
TRACE_DURATION_INCR_STRING = CONFIG['trace_duration_incr'] || TRACE_DURATION_INCR_STRING_DEFAULT
TRACE_DURATION_INIT = config_string_to_time TRACE_DURATION_INIT_STRING
TRACE_DURATION_INCR = config_string_to_time TRACE_DURATION_INCR_STRING
# @param what [Net::Ping::External]
# @param what [Net::Ping::HTTP]
def self.ping_with m, what
ip = BotpopBuiltins.get_ip m
p = what.new ip
str = p.ping(ip) ? "#{(p.duration*100.0).round 2}ms (#{p.host})" : 'failed'
m.reply "#{ip} > #{what.to_s.split(':').last} ping > #{str}"
end
def self.exec_ping m
m.reply "#{m.user} > pong"
end
def self.exec_ping_target m
ping_with m, Net::Ping::External
end
def self.exec_ping_http m
ping_with m, Net::Ping::HTTP
end
def self.exec_poke m
nick = BotpopBuiltins.get_ip_from_nick(m)[:nick]
ip = BotpopBuiltins.get_ip_from_nick(m)[:ip]
return m.reply "User '#{nick}' doesn't exists" if ip.nil?
# Display
response = BotpopBuiltins.ping(ip) ? "#{(p.duration*100.0).round 2}ms (#{p.host})" : "failed"
m.reply "#{nick} > poke > #{response}"
end
def self.dos_check_ip(m, ip)
return true if BotpopBuiltins.ping(ip)
m.reply "Cannot reach the host '#{ip}'"
return false
end
def self.dos_replier m, ip, s
if s.nil?
m.reply "The dos has failed"
elsif BotpopBuiltins.ping(ip)
m.reply "Sorry, the target is still up !"
else
m.reply "Target down ! --- #{s}"
end
end
# This function avoid overusage of the resources by using mutex locking.
# It execute the lamdba function passed as 2sd parameter if resources are ok
# At the end of the attack, it wait few seconds (configuration) before
# releasing the resources and permit a new attack.
#
# @arg lambda [Lambda] lambda with one argument (m). It wil be executed
def self.dos_execution(m, lambda)
@dos ||= Mutex.new
if @dos.try_lock
lambda.call(m)
sleep DOS_WAIT_DURATION
@dos.unlock
else
m.reply "Wait for the end of the last dos"
end
end
def self.dos_ip(ip)
return BotpopBuiltins.dos(ip, DOS_DURATION).split("\n")[3].to_s rescue nil
end
def self.exec_dos m
dos_execution m, lambda {|m|
ip = BotpopBuiltins.get_ip m
return if not dos_check_ip(m, ip)
m.reply "Begin attack against #{ip}"
s = dos_ip(ip)
dos_replier m, ip, s
}
end
def self.exec_fok m
dos_execution m, lambda {|m|
nick = BotpopBuiltins.get_ip_from_nick(m)[:nick]
ip = BotpopBuiltins.get_ip_from_nick(m)[:ip]
return m.reply "User '#{nick}' doesn't exists" if ip.nil?
return m.reply "Cannot reach the host '#{ip}'" if not BotpopBuiltins.ping(ip)
s = dos_ip(ip)
r = BotpopBuiltins.ping(ip) ? "failed :(" : "down !!!"
m.reply "#{nick} : #{r} #{s}"
}
end
def self.trace_display_lines m, lines
lines.select!{|e| not e.include? "no reply" and e =~ /\A \d+: .+/}
duration = TRACE_DURATION_INIT
lines.each do |l|
m.reply l
sleep duration
duration += TRACE_DURATION_INCR
end
m.reply 'finished'
end
def self.trace_with_time ip
t1 = Time.now
s = BotpopBuiltins.trace ip
t2 = Time.now
return [s, t1, t2]
end
# see {trace_execution}. Seem system without sleep
#
# @arg lambda [Lambda] lambda with one argument (m). It wil be executed
def self.trace_execution(m, lambda)
@trace ||= Mutex.new
if @trace.try_lock
lambda.call(m) rescue nil
@trace.unlock
else
m.reply "A trace is still running"
end
end
def self.exec_trace m
trace_execution m, lambda {|m|
ip = BotpopBuiltins.get_ip m
m.reply "It can take time"
begin
# Calculations
s, t1, t2 = trace_with_time ip
m.reply "Trace executed in #{(t2 - t1).round(3)} seconds"
rescue => e
m.reply "Sorry, but the last author of this plugin is so stupid his mother is a tomato"
end
# Display
trace_display_lines m, s
}
end
end
end