WhatWeb源码分析之开篇

      WhatWeb是一款非常著名的指纹扫描器,在平时渗透测试用的也比较多。从这一篇开始,陆陆续续来分析它的源码,领会其中精髓。写这篇博客的当下,我对ruby并不熟悉,所以开篇就一边看着源码一遍熟悉ruby语法吧。

      开始看whatweb这个文件的源码熟悉语法:

 
  
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless
    $:.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
$LOAD_PATH << "/usr/share/whatweb/"

      $LOAD_PATH是Ruby读取外部文件的一个环境变量,返回值是一个路径的数组。Ruby会在这个环境变量的路径中读取需要的require文件,如果在环境变量中找不到自己想要的文件,就会报LoadError错误。$LOAD_PATH和$:指的都是同一个环境变量。$LOAD_PATH.unshift是把括号里面得到的路径加到现在已经存在所有环境变量之前。<<会把后续给定对象附加到数组的末尾。里面涉及的文件操作就不在这里描述了。

 
  
if RUBY_VERSION =~ /^1\.9/
	require 'digest/md5'
    require 'lib/extend-http_ruby1.9.rb'   

      看一下这个=~符号是将字符串与正则表达式进行匹配。如果匹配成功,返回匹配子串在字符串中的偏移,如果不成功返回nil。

 
  
gems = %w|json mongo rchardet |
 
  
gems.each do |thisgem|
	begin
		require 'rubygems' # rubygems is optional
		if gem_available?(thisgem) #
			require thisgem			
		else
		end
	rescue LoadError
		# that failed.. no big deal
		raise if $WWDEBUG==true
	end
end

      上面%w||这个语法是赋值一个数组,具体可以看这里。

 
  
PLUGIN_DIRS=[ "plugins", "my-plugins"].map {|x| $LOAD_PATH.map {|y| y+"/"+x if File.exists?(y+"/"+x) } }.flatten.compact

      这里主要涉及到map函数,这个函数是针对每个元素进行变换并返回整个修改后的数组。后面的flatten是使数组一维化,并返回新的数组。compact是去掉数组中nil部分,返回新的一个数组。

 
  
def randstr
	rand(36 ** 8).to_s(36)
end 

      这个产生随机字符串的方法比较有意思,可以看这里。rand(进制**length).to_s(进制)产生a-z和0-9组成的长度为length的随机字符串。36代表进制(a-z、0-9的数目加起来正好36)。但是有讨论说这个可能产出长度小于length的随机字符串。

 
  
while t = next_target
		Thread.new(t) do |thistarget|
			begin
				target = Target.new(thistarget) # we set the target within the thread
			rescue => err
				error(err)
				next
			end
 
  
			puts Thread.current.to_s + " started for " + target.to_s if $verbose>1
			sleep $WAIT unless $WAIT.nil? # wait
 
  
			# follow redirects
			no_redirects =false
			num_redirects = 0
			while no_redirects == false do
				no_redirects=true if target.is_file?
				# if we redirect 10 times we give up
				if num_redirects == $MAX_REDIRECTS
					error("ERROR Too many redirects: #{target.to_s}")
					no_redirects=true
					next
				end
 
  
				begin
					target.open
				rescue => err
					error("ERROR Opening target: #{target.to_s} - #{err}")
					no_redirects = true # without this we can get stuck in a loop
					raise if $WWDEBUG
					next
				end
 
  
				if target.is_url? and target.status.nil?
					# assume all HTTP sites return a status
					no_redirects=true
					next
				end
 
  
				results = run_plugins(target)
 
  
				# reporting
				# multiple output plugins simultaneously, some stdout, some files
				output_list.each do |o|
					begin
						o.out(target, target.status, results)
					rescue => err
						#srsly, logging failed
						error("ERROR Logging failed: #{target.to_s} - #{err}")
						raise if $WWDEBUG==true
					end
				end
 
  
				# REDIRECTION
				unless no_redirects
					begin
						if newtarget = target.get_redirection_target		
							num_redirects+=1 
							target=Target.new(newtarget)
						else
							no_redirects=true 
						end
					rescue => err
						error("ERROR Redirection broken: #{target.to_s} - #{err}")
						no_redirects=true
						raise if $WWDEBUG==true
					end
				end
			end # while no_redirects
		end # Thread.new
 
  
	while Thread.list.size>($MAX_THREADS+1)
		puts "Thread list full, passing control" if $verbose>1
		#sleep 0.5
		Thread.pass
	end
end # targets.each

      上面的代码涉及到多线程的知识。下面是由do…end组成的ruby代码块。

 
  
		Thread.new(t) do |thistarget|
		省略的部分代码
		end # Thread.new

      |thistarget|接收一个参数,新创建的线程执行代码块里面的代码。下面有个示例说明这种语法。

 
  
require 'net/http'  
  
pages = %w(www.iteye.com www.csdn.net www.sina.com.cn www.google.cn)  
threads = []  
  
for page in pages  
  threads << Thread.new(page) do |url|  
    h = Net::HTTP.new(url, 80)  
    puts "The URL is #{url} "  
    resp = h.get('/', nil)  
    puts "The #{url} response : #{resp.message}"  
  end  
end  
  
threads.each { |t|t.join  }  

      运行结果:

WhatWeb源码分析之开篇_第1张图片

      好了,一边看代码一边学习语法,做点小笔记。后续会继续更新WhatWeb源码分析系列。

 

 

你可能感兴趣的:(Ruby,Programming)