All pastes #15161 Raw Edit

Someone

public text v1 · immutable
#15161 ·published 2005-06-20 22:31 UTC
rendered paste body
### Gowap's botnet stats system v5.18
##
# Noyga <Benoit.Timbert@free.fr>

### variables ###
# 1j bottree timeout
set bottree-timeout 86400
# 12j known-bot timeout
set knownbot-timeout 777777
set bottree_file "./scripts/info.cfg"
set linked_bots ""
set known_bots ""
set timeout_bots ""
set max_botcount 0
set max_bottime [unixtime]

set dcc.bold_color "\[1m"
set dcc.link_color "\[1;32m"
set dcc.unlink_color "\[1;31m"
set dcc.stop_color "\[0m"

set html.branch_color "#777799"
set html.link_color "<font color =\"#00FF00\">"
set html.unlink_color "<font color =\"#FF0000\">"
set html.stop_color "</font>"

# fields: botnick uplink linktime unlinktime link-type
set bottree_list ""

### list interface
proc bnl:search_bot {bot} {
	global known_bots

	return [lsearch -exact [string tolower $known_bots] [string tolower $bot]]	
}
proc bnl:search_linked_bot {bot} {
	global linked_bots

	return [lsearch -exact [string tolower $linked_bots] [string tolower $bot]]	
}
proc bnl:read_bot {bot} {
	global bottree_list

	return [lindex $bottree_list [bnl:search_bot $bot]]
}
proc bnl:write_bot {bot hub linktime unlinktime link_type} {
	global known_bots
	global bottree_list

	set bot_index [bnl:search_bot $bot]
	if {$bot_index < 0} {
		lappend known_bots $bot
		lappend bottree_list [list $bot $hub $linktime $unlinktime $link_type]
	} else {
		set bottree_list [lreplace $bottree_list $bot_index $bot_index [list $bot $hub $linktime $unlinktime $link_type]]
	}
}
proc bnl:del_bot {bot} {
	global known_bots
	global bottree_list

	set bot_index [bnl:search_bot $bot]
	if {$bot_index >= 0} {
		set known_bots [ldelete $known_bots $bot_index]
		set bottree_list [ldelete $bottree_list $bot_index]
	}
}

proc bnl:list_downlinks {bot} {
	global bottree_list

	set sublist ""
	foreach botline $bottree_list {
		set rbot [lindex $botline 0]
		set lbot [lindex $botline 1]
		if {[string tolower $lbot] == [string tolower $bot]} {
			lappend sublist $rbot
		}
	}
	return $sublist
}

proc bnl:list_alldownlinks {bot} {
	global bottree_list
	global bottree-timeout

	set activelist ""
	set timeoutlist ""
	foreach botline $bottree_list {
		set rbot [lindex $botline 0]
		set lbot [lindex $botline 1]
		if {[string tolower $lbot] == [string tolower $bot]} {
			set unlink_time [lindex [bnl:read_bot $rbot] 3]
			if { ($unlink_time ==0) || ([expr [unixtime] - $unlink_time] < ${bottree-timeout})} {
				lappend activelist $rbot
			} else {
				lappend timeoutlist $rbot
			}
		}
	}
	return [list $activelist $timeoutlist]
}

proc bnl:list_subnet {bot} {
	global bottree_list

	set sublist [list [bnl:read_bot $bot]]
	foreach sbot [bnl:list_downlinks $bot] {
		set sublist [concat $sublist [bnl:list_subnet $sbot]]
	}
	return $sublist
}

### bottree
proc bnt:reset_depths {} {
	global bottree_depth
	global known_bots
	global timeout_bots
	
	set bottree_depth ""
	set timeout_bots ""
	foreach bot $known_bots {
		lappend bottree_depth [list $bot 0 0]
	}
}

proc bnt:get_depth {bot} {
	global bottree_depth
	global botnet-nick

	if {[string tolower $bot] == [string tolower ${botnet-nick}]} {
		return 0
	} else {
		return [lindex [lindex $bottree_depth [bnl:search_bot $bot]] 1]
	}
}

proc bnt:get_depthcounts {bot} {
	global bottree_depth
	global botnet-nick

	if {[string tolower $bot] == [string tolower ${botnet-nick}]} {
		return 1
	} else {
		return [lindex [lindex $bottree_depth [bnl:search_bot $bot]] 2]
	}
}

proc bnt:find_depths {bot} {
	global bottree_depth
	global timeout_bots

	set clevel [bnt:get_depth $bot]
	set cdepth_count [bnt:get_depthcounts $bot]
	set alldownlinks [bnl:list_alldownlinks $bot]
	set adownlinks [lindex $alldownlinks 0]
	set tdownlinks [lindex $alldownlinks 1]
	set timeout_bots [concat $timeout_bots $tdownlinks]
	set count [llength $adownlinks]
	foreach sbot $adownlinks {
		incr count -1
		set bot_index [bnl:search_bot $sbot]
		set depth_count $cdepth_count
		lappend depth_count $count
		set bottree_depth [lreplace $bottree_depth $bot_index $bot_index [list $sbot [expr $clevel + 1] $depth_count]]
		bnt:find_depths $sbot
	}
	foreach sbot $tdownlinks {
		set bot_index [bnl:search_bot $sbot]
		set depth_count $cdepth_count
		lappend depth_count 0
		set bottree_depth [lreplace $bottree_depth $bot_index $bot_index [list $sbot [expr $clevel + 1] $depth_count]]
		bnt:find_depths $sbot
	}
}

proc print_subtree {bot idx} {
	global botnet-nick
	global dcc.link_color
	global dcc.unlink_color
	global dcc.stop_color

	set tree_string ""
	set cdepth [bnt:get_depth $bot]
	set cdepth_count [bnt:get_depthcounts $bot]
	for {set sdepth 1} {$sdepth <= $cdepth} {incr sdepth} {
		if {[lindex $cdepth_count $sdepth] != 0} {
			append tree_string "       |"
		} elseif {$sdepth == $cdepth} {
			append tree_string "       `"
		} else {
			append tree_string "        "
		}
	}
	set botline [bnl:read_bot $bot]
	if {([lindex $botline 3] == 0) || ($bot == ${botnet-nick})} {
		set color ${dcc.link_color}
	} else {
		set color ${dcc.unlink_color}
	}
	putdcc $idx "${tree_string}[lindex $botline 4]${color}${bot}${dcc.stop_color}"
	foreach sbot [lindex [bnl:list_alldownlinks $bot] 0] {
		print_subtree $sbot $idx
	}
}

proc html_subtree {bot fd} {
	global botnet-nick
	global bottree-timeout
	global timeout_bots
	global html.branch_color
	global html.link_color
	global html.unlink_color
	global html.stop_color

	set tree_string ""
	set botline [bnl:read_bot $bot]
	set unlinktime [lindex $botline 3]
	if {$unlinktime == ""} {
		set unlinktime [unixtime]
	}
	set cdepth [bnt:get_depth $bot]
	set cdepth_count [bnt:get_depthcounts $bot]
	for {set sdepth 1} {$sdepth <= $cdepth} {incr sdepth} {
		if {[lindex $cdepth_count $sdepth] != 0} {
			append tree_string "</td><td></td><td bgcolor=\"${html.branch_color}\"><font color=\"${html.branch_color}\">|</font>"
		} elseif {$sdepth == $cdepth}  {
			append tree_string "</td><td></td><td bgcolor=\"${html.branch_color}\"><font color=\"${html.branch_color}\">`</font>"
		} else {
			append tree_string "</td><td></td><td>"
		}
	}
	if {([lindex $botline 3] == 0) || ($bot == ${botnet-nick})} {
		set color ${html.link_color}
	} else {
		set color ${html.unlink_color}
	}
	puts $fd "<tr><td>${tree_string}</td><td bgcolor=\"#070744\">[lindex $botline 4]${color}${bot}${html.stop_color}</td></tr>"
	foreach sbot [lindex [bnl:list_alldownlinks $bot] 0] {
		html_subtree $sbot $fd
	}
}

proc print_list {ilist title cols idx} {

	set ilist [lsort -dictionary $ilist]
	set listlength [llength $ilist]
	putdcc $idx $title
	for {set botcs 0} {$botcs < $listlength} {incr botcs $cols} {
		putdcc $idx "[lrange $ilist $botcs [expr $botcs - 1 + $cols]]"
	}
}

proc html_list {ilist title cols fd} {

	set ilist [lsort -dictionary $ilist]
	set listlength [llength $ilist]
	puts $fd "<table border=2 cellspacing=1 cellpadding=1>"
	puts $fd "<th colspan=$cols>$title</th>"
	for {set botcs 0} {$botcs < $listlength} {incr botcs $cols} {
		set col_string ""
		for {set boti $botcs} {$boti < [expr $botcs + $cols]} {incr boti} {
			append col_string "<td>[lindex $ilist $boti]</td>"
		}
		puts $fd "<tr>$col_string</tr>"
	}
	puts $fd "</table>"
}

proc print_tree {idx} {
	global botnet-nick
	global known_bots
	global linked_bots
	global timeout_bots
	global max_botcount
	global max_bottime
	global dcc.bold_color
	global dcc.link_color
	global dcc.unlink_color
	global dcc.stop_color

	bnt:reset_depths
	bnt:find_depths ${botnet-nick}
	print_subtree ${botnet-nick} $idx
	putdcc $idx "${dcc.bold_color}[llength $known_bots] bot(s) connu(s)${dcc.stop_color}"
	putdcc $idx "[llength $linked_bots] bot(s) ${dcc.link_color}linké(s)${dcc.stop_color} (max: $max_botcount bots le [fr_date $max_bottime])"
	putdcc $idx "[expr [llength $known_bots] - [llength $linked_bots]] bot(s) ${dcc.unlink_color}non linké(s)${dcc.stop_color} dont [llength $timeout_bots] non représentés "
	if {[llength $timeout_bots] > 0} {
		print_list $timeout_bots "Autres bots non linkés depuis plus d'un jour" 9 $idx
	}
}

proc html_tree {file} {
	global timezone
	global botnet-nick
	global known_bots
	global linked_bots
	global timeout_bots
	global max_botcount
	global max_bottime
	global knownbot-timeout
	global html.link_color
	global html.unlink_color
	global html.stop_color

	set fd [open $file "w"]
	bnt:reset_depths
	puts $fd "<html>"
	puts $fd "<head>"
	puts $fd "	<title>Le botnet vu de ${botnet-nick}</title>"
	puts $fd "	<meta http-equiv=\"Expires\" content=\"[ctime [expr [unixtime] + 333]] $timezone\">"
	puts $fd "	<meta http-equiv=\"Refresh\" content=\"999\">"
	puts $fd "	<meta generator=\"botstats.tcl by Noyga\">"
	puts $fd "</head>"
	puts $fd "<body bgcolor=\"black\" text=\"white\" link=\"yellow\" vlink=\"orange\" alink=\"red\">"
	puts $fd "Le botnet vu de <b>${botnet-nick}</b> le [fr_date [unixtime]]"
	bnt:find_depths ${botnet-nick}
	puts $fd "<p><b>[llength $known_bots] bot(s) connu(s)</b><br>"
	puts $fd "<b>${html.link_color}[llength $linked_bots] bot(s) link&eacute;(s)${html.stop_color}</b> (max: $max_botcount bots le [fr_date $max_bottime])<br>"
	puts $fd "<b>${html.unlink_color}[expr [llength $known_bots] - [llength $linked_bots]] bot(s) non link&eacute;(s)${html.stop_color}</b> dont [llength $timeout_bots] non repr&eacute;sent&eacute;s<br>"
	puts $fd "<table border=0 cellspacing=0 cellpadding=0>"
	html_subtree ${botnet-nick} $fd
	puts $fd "</table>"
	if {[llength $timeout_bots] > 0} {
		puts $fd "<p>"
		html_list $timeout_bots "Autres bots non link&eacute;s depuis plus d'un jour" 10 $fd
	}
	puts $fd "<p>Mise &agrave; jour toutes les 5 minutes<br>"
	puts $fd "<p>Dur&eacute;e de m&eacute;morisation des bots: [hr_time ${knownbot-timeout}]"
	puts $fd "<p><center><a href=\"http://bluebloup.free.fr/eggdrop/botstats.tcl\">botstats.tcl</a> &copy; <a href=\"mailto:Benoit.Timbert@free.fr\">Noyga</a>, 2001</center>"
	puts $fd "</body>"
	puts $fd "</html>"
	flush $fd
	close $fd	
}

### file interface
proc bnf:store_tree {file} {
	global max_botcount
	global max_bottime
	global bottree_list

	set fd [open $file "w"]
	puts $fd [list $max_botcount $max_bottime]
	foreach botline $bottree_list {
		puts $fd $botline
	}
	flush $fd
	close $fd
}


proc bnf:read_tree {file} {
	global max_botcount
	global max_bottime
	global bottree_list
	global known_bots

	set fd [open $file "r"]
	set known_bots ""
	set bottree_list ""
	set maxline [gets $fd]
	set max_botcount [lindex $maxline 0]
	set max_bottime [lindex $maxline 1]
	while {![eof $fd]} {
		set botline [gets $fd]
		if {$botline != ""} {
			lappend known_bots [lindex $botline 0]
			lappend bottree_list $botline
		}
	}
	close $fd
}

### botnet interface
proc bnn:get_bot {bot} {
	
	set botprop ""
	foreach botline [botlist] {
		set lbot [lindex $botline 0]
		if {[string tolower $lbot] == [string tolower $bot]} {
			return $botline
		}
	}
	return ""
}

proc bnn:list_downlinks {bot} {
	
	set sublist ""
	foreach botline [botlist] {
		set rbot [lindex $botline 0]
		set lbot [lindex $botline 1]
		if {[string tolower $lbot] == [string tolower $bot]} {
			set sublist [linsert $sublist end $rbot]
		}
	}
	return $sublist
}

### expire old bots
proc expire_old_bots {} {
	global known_bots
	global bottree_list
	global knownbot-timeout
	
	set botcount [llength $known_bots]
	for {set botindex 0} {$botindex < $botcount} {incr botindex} {
		set unlinktime [lindex [lindex $bottree_list $botindex] 3]
		if {$unlinktime != 0} {
			if {[expr [unixtime] - $unlinktime] > ${knownbot-timeout}} {
				putlog "obsolete bot: erasing [lindex $known_bots $botindex]"
				set known_bots [ldelete $known_bots $botindex]
				set bottree_list [ldelete $bottree_list $botindex]
				incr botcount -1
				incr botindex -1
			}
		}
	}
}

### init procs
proc init:fix_linked_bots {} {

	foreach bot [bots] {
		set nbotline [bnn:get_bot $bot]
		if {[bnl:search_bot $bot] < 0} {
			bnl:write_bot $bot [lindex $nbotline 1] [unixtime] 0 [lindex $nbotline 3] 
			putlog "Added $bot in my bottree (new bot)"
		} else {
			set lbotline [bnl:read_bot $bot]
			bnl:write_bot $bot [lindex $nbotline 1] [lindex $lbotline 2] [lindex $lbotline 3] [lindex $nbotline 3]
		}
	}
}

proc init:fix_subtree {bot} {
	global uptime
	
	foreach sbot [bnl:list_downlinks $bot] {
		set botline [bnl:read_bot $sbot]
		if {[islinked $sbot] == 1} {
			if {[lindex $botline 3] > 0} {
				set linktime $uptime
				putlog "fix: Added $sbot in my bottree"
			} else {
				set linktime [lindex $botline 2]
			}
			bnl:write_bot $sbot [lindex $botline 1] $linktime 0 [lindex $botline 4]
		} else {
			set unlinktime [lindex $botline 3]
			if {$unlinktime == 0} {
				set unlinktime $uptime
				putlog "fix: Deleted $sbot from my bottree"
			}
			bnl:write_bot $sbot [lindex $botline 1] [lindex $botline 2] $unlinktime [lindex $botline 4]
		}
		init:fix_subtree $sbot
	} 
}

### binds procs

proc link:addbots {bot hub} {
	global linked_bots
	global max_botcount
	global max_bottime

	if {[bnl:search_linked_bot $bot] < 0} {
		lappend linked_bots $bot
		set botcount [llength $linked_bots]
		if {$botcount > $max_botcount} {
			set max_botcount $botcount
			set max_bottime [unixtime]
		}
		bnl:write_bot $bot $hub [unixtime] 0 [lindex [bnn:get_bot $bot] 3] 
		#putlog "Added $bot (from $hub) in my bottree"
		foreach sbot [bnn:list_downlinks $bot] {
			link:addbots $sbot $bot
		} 
	} else {
		putlog "WARNING: loop detected when adding $bot from $hub in my bottree"
		unlink $bot "loop detected"
	}
}

proc disc:expirebots {bot} {
	global linked_bots

	if {[bnl:search_linked_bot $bot] < 0} {
		putlog "WARNING: $bot wasn't linked"
	} else {
		if {[bnl:search_bot $bot] < 0} {
			putlog "WARNING: $bot was linked, but unknown to me"
		} else {
			set linked_bots [ldelete $linked_bots [bnl:search_linked_bot $bot]]
			set botinfo [bnl:read_bot $bot]
			bnl:write_bot $bot [lindex $botinfo 1] [lindex $botinfo 2] [unixtime] [lindex $botinfo 4]
			foreach sbot [bnn:list_downlinks $bot] {
				disc:expirebots $sbot
			} 
			#putlog "Deleted $bot from my bottree"
		}
	}
}

proc bupd:updatebot {bot share} {

	if {[bnl:search_linked_bot $bot] < 0} {
		putlog "WARNING: $bot wasn't linked"
	} else {
		if {[bnl:search_bot $bot] < 0} {
			putlog "WARNING: $bot was linked, but unknown to me"
		} else {
			set botinfo [bnl:read_bot $bot]
			bnl:write_bot $bot [lindex $botinfo 1] [lindex $botinfo 2] [lindex $botinfo 3] $share
			#putlog "updated $bot : status $share"
		}
	}
}

proc time:pub {min hour day month year} {
	global bottree_url

	dccbroadcast "Bonjour je génère une page de visualisation du botnet sur $bottree_url"
}

proc time:store_tree {min hour day month year} {
	global bottree_file

	putlog "Writing bottree file..."
	bnf:store_tree $bottree_file
}

proc time:html_bigjob {min hour day month year} {
	global html_output
	global html_dest
	global ftp_server
	global ftp_login
	global ftp_passwd

	putlog "generating HTML file..."
	html_tree $html_output
	putlog "Transfering the file to the http server..."
	ftpsend $ftp_server $ftp_login $ftp_passwd $html_output $html_dest
	putlog "Launched in the background."
}

proc time:store_tree {min hour day month year} {
	global bottree_file

	putlog "Writing bottree file..."
	bnf:store_tree $bottree_file
}

proc time:expire_bots {min hour day month year} {
	global bottree_file

	putlog "Checking for old bots..."
	expire_old_bots
}

proc time:paranoid_resync {min hour day month year} {
	global bottree_file

	putlog "Paranoïa: resyncing..."
	botstats_reset
}

proc evnt:store_tree {type} {
	global bottree_file

	putlog "Writing bottree file..."
	bnf:store_tree $bottree_file
}

proc dcc:store_tree {handle idx args} {
	global bottree_file

	set file [lindex [join $args] 0]
	if {$file == ""} {
		set file $bottree_file
 	}
	putlog "Writing bottree file..."
	bnf:store_tree $file
	return 1
}

proc dcc:read_tree {handle idx args} {
	global bottree_file

	set file [lindex [join $args] 0]
	if {$file == ""} {
		set file $bottree_file
 	}
	bnf:read_tree $file
	return 1
}

proc dcc:xbottree {handle idx args} {
	global botnet-nick
	
	print_tree $idx
	return 1
}
proc dcc:hbottree {handle idx args} {
	global botnet-nick
	
	set file [lindex [join $args] 0]
	if {$file == ""} {
		putdcc $idx "Usage: hbottree <file>"
		return 0
 	}
	html_tree $file
	return 1
}

### init ...
proc botstats_reset {} {
	global bottree_file
	global linked_bots
	global botnet-nick
	
	
	bnf:read_tree $bottree_file
	set linked_bots [bots]
	expire_old_bots
	init:fix_linked_bots
	init:fix_subtree ${botnet-nick}
	bnt:reset_depths
}
botstats_reset

### binds

bind link - * link:addbots
bind disc - * disc:expirebots
bind bupd - * bupd:updatebot
bind dcc n|- store_tree dcc:store_tree
bind dcc n|- read_tree dcc:read_tree
bind dcc -|- xbottree dcc:xbottree
bind dcc n|- hbottree dcc:hbottree
bind time - "36 * * * *" time:store_tree
bind time - "37 17 * * *" time:expire_bots
bind time - "33 15 ?1 * *" time:paranoid_resync
bind time - "?2 * * * *" time:html_bigjob
bind time - "?7 * * * *" time:html_bigjob
bind time - "19 ?0 * * *" time:pub
bind evnt - prerehash evnt:store_tree
bind evnt - prerestart evnt:store_tree

putlog "Système de statistiques prêt"