Browse files

Services

  • Loading branch information...
1 parent bd2a0de commit 066007551d8ff60e39eb880fc8194d7b96eb7e14 @txus committed Jan 6, 2011
View
1 .gitignore
@@ -1,3 +1,4 @@
pkg/*
*.gem
.bundle
+*.log
View
12 bin/micetrap
@@ -1,6 +1,7 @@
#!/usr/bin/env ruby -w
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
+require 'trollop' unless defined?(Trollop)
require 'micetrap'
require 'micetrap/version'
@@ -32,19 +33,20 @@ opts = Trollop::options do
Running it with sudo will allow you to use default, unsuspicious ports,
which may give you advantage at tricking a smart attacker.
- The available options are are:
- #{SERVICES.join('\n')}
+ The available services are are:
+ #{SERVICES.join(', ')}
Usage:
[sudo] micetrap <service> [options]
where [options] are:
EOS
- opt :port, "A specific port to use", :default => nil
+ opt :port, "A specific port to use", :default => nil, :type => :integer
stop_on SERVICES
end
-service = ARGV.shift
+puts opts.inspect
+service = ARGV.shift.to_sym
Trollop::die "You need to specify a service, which must be one of the following: #{SERVICES.join(', ')}\n\nMaybe you just feel a bit lost.." unless SERVICES.include?(service)
-Micetrap::Server.new(opts).fire!
+Micetrap::Server.new(opts.update(:service => service)).fire!
View
7 lib/micetrap.rb
@@ -1,12 +1,17 @@
require 'micetrap/services/exceptions'
require 'micetrap/services/base'
+
require 'micetrap/logger'
require 'micetrap/server'
module Micetrap
class << self
def services
- []
+ [:ftp, :torrent, :samba, :http, :mysql]
end
end
end
+
+Micetrap.services.each do |service|
+ require "micetrap/services/#{service}"
+end
View
16 lib/micetrap/logger.rb
@@ -13,15 +13,23 @@ def initialize(service_name)
end
def file
- @file ||= File.open(@filename, 'w')
+ @file ||= File.new(@filename, 'a')
end
- def log_probe(line, addr, remote_host, remote_port)
- file.write "\n#{Time.now} Recorded a probe coming from #{remote_host} - #{addr}:#{remote_port} containing the following:\n\t\t#{line}"
+ def log_probe(line, remote_host, remote_port)
+ logged = "\n#{Time.now} Recorded a probe coming from #{remote_host}:#{remote_port} containing the following:\n\t\t#{line}"
+ puts "About to write there"
+ file.write logged
+ puts "wrote to #{file.inspect}"
+ puts logged
end
def log_message(line)
- file.write "\n#{Time.now} ::: #{line} :::"
+ logged = "\n#{Time.now} ::: #{line} :::"
+ puts "About to write there"
+ file.write logged
+ puts "wrote to #{file.inspect}"
+ puts logged
end
end
View
2 lib/micetrap/server.rb
@@ -10,7 +10,7 @@ def initialize(options)
@service =
eval("Micetrap::Services::#{options[:service].to_s.capitalize}").new
@port = options[:port] # Optional
- rescue NameError
+ rescue NameError=>e
raise Services::UnrecognizedServiceException.new("Service #{options[:service].to_s.capitalize} is not recognized")
end
View
26 lib/micetrap/services/base.rb
@@ -7,23 +7,33 @@ class ClientQuitError < RuntimeError; end
attr_reader :logger
def initialize
- @logger = Logger.new self.class.name.downcase.to_sym
+ @logger = Logger.new self.name.downcase.to_sym
end
def fire port = nil
- server = TCPServer.open(port || default_ports.sample || 0)
+ port = port.to_i if port
+ begin
+ server = TCPServer.open(port || default_ports.sample || 0)
+ rescue Errno::EACCES
+ puts "Seems that you are trying to use a system port, for which you need root privileges.\n\nRun micetrap with a custom port if you don't want to sudo!\n"
+ exit(1)
+ end
@port = server.addr[1]
@addrs = server.addr[2..-1].uniq
- logger.log_message "#{@name} micetrap listening on #{@addrs.collect{|a|"#{a}:#{port}"}.join(' ')}"
+ logger.log_message "#{name} micetrap listening on #{@addrs.collect{|a|"#{a}:#{port}"}.join(' ')}"
+ listen(server)
+ end
+ def listen(server)
# Handle Ctrl-C to exit!
interrupted = false
trap("INT") { interrupted = true }
while not interrupted do
+ socket = server.accept
Thread.start do
- read_from(server.accept)
+ read_from(socket)
end
end
end
@@ -39,13 +49,13 @@ def read_from(socket)
while line = s.gets # read a line at a time
raise ClientQuitError if line =~ /^die\r?$/
- logger.log_probe line, addr, name, port
+ logger.log_probe line, name, port
if line.strip == ""
s.write response
logger.log_message "Responded misleadingly: let's drive those hackers nuts!"
s.close
- exit(0)
+ Kernel.exit(0)
end
end
rescue ClientQuitError
@@ -60,6 +70,10 @@ def read_from(socket)
def default_ports; []; end;
def response; ""; end;
+ def name
+ self.class.name.split('::').last
+ end
+
end
end
end
View
22 lib/micetrap/services/ftp.rb
@@ -0,0 +1,22 @@
+module Micetrap
+ module Services
+ class Ftp < Base
+
+ protected
+
+ def default_ports
+ [21]
+ end
+
+ def response
+ @response ||=
+ [
+ "220-FTP server (lukemftpd 1.1) ready.\r\n",
+ "220 Welcome to Pure-FTPd 1.8\r\n",
+ "220--------------------------------------------------------------------------------\r\n220-This is the \"Banner\" message for the Mac OS X Server's FTP server process.\r\n",
+ ].sample
+ end
+
+ end
+ end
+end
View
20 lib/micetrap/services/http.rb
@@ -0,0 +1,20 @@
+module Micetrap
+ module Services
+ class Http < Base
+
+ protected
+
+ def default_ports
+ [80, 8080]
+ end
+
+ def response
+ @response ||=
+ [
+ "HTTP/1\.0 200 OK\r\nContent-Type: text/html\r\n\r\n<html>\n<body>\n<ul><li>\n<i>com\.apple\.KernelEventAgent</i>\n",
+ ].sample
+ end
+
+ end
+ end
+end
View
20 lib/micetrap/services/mysql.rb
@@ -0,0 +1,20 @@
+module Micetrap
+ module Services
+ class Mysql < Base
+
+ protected
+
+ def default_ports
+ [3306]
+ end
+
+ def response
+ @response ||=
+ [
+ ".\0\0\0\n4.0.13\0...\0",
+ ].sample
+ end
+
+ end
+ end
+end
View
20 lib/micetrap/services/samba.rb
@@ -0,0 +1,20 @@
+module Micetrap
+ module Services
+ class Samba < Base
+
+ protected
+
+ def default_ports
+ [135, 139, 445]
+ end
+
+ def response
+ @response ||=
+ [
+ "smbd: error while loading shared libraries: libattr.so.1: cannot open shared object file: No such file or directory\n",
+ ].sample
+ end
+
+ end
+ end
+end
View
20 lib/micetrap/services/torrent.rb
@@ -0,0 +1,20 @@
+module Micetrap
+ module Services
+ class Torrent < Base
+
+ protected
+
+ def default_ports
+ []
+ end
+
+ def response
+ @response ||=
+ [
+ "\x13BitTorrent protocol\0\0\0\0\0\0\0\0",
+ ].sample
+ end
+
+ end
+ end
+end
View
10 spec/micetrap/logger_spec.rb
@@ -20,7 +20,7 @@ module Micetrap
describe "#file" do
it 'returns the log file' do
file = double('file')
- File.stub(:open).and_return file
+ File.stub(:new).and_return file
subject.file.should be(file)
end
end
@@ -30,14 +30,14 @@ module Micetrap
file = double('file')
now = Time.now
Time.stub(:now).and_return now
- File.stub(:open).and_return file
+ File.stub(:new).and_return file
- expected_string = "\n#{now} Recorded a probe coming from hackerz.com - 234.43.14.35:5978 containing the following:\n\t\t###EVILPROBE###"
+ expected_string = "\n#{now} Recorded a probe coming from hackerz.com:5978 containing the following:\n\t\t###EVILPROBE###"
subject.file.should_receive(:write)
.with expected_string
- subject.log_probe "###EVILPROBE###", "234.43.14.35", "hackerz.com", 5978
+ subject.log_probe "###EVILPROBE###", "hackerz.com", 5978
end
end
@@ -46,7 +46,7 @@ module Micetrap
file = double('file')
now = Time.now
Time.stub(:now).and_return now
- File.stub(:open).and_return file
+ File.stub(:new).and_return file
expected_string = "\n#{now} ::: Warning! :::"
View
88 spec/micetrap/services/base_spec.rb
@@ -4,34 +4,108 @@ module Micetrap
module Services
describe Base do
describe "#fire" do
+
+ before(:each) do
+ subject.stub(:listen)
+ end
+
context 'when given a port' do
it 'fires up the service on that port' do
-
+ server = double('server', :addr => [1,2,3])
+ TCPServer.should_receive(:open).with(5900).and_return server
+ subject.fire 5900
end
end
context 'when port is nil' do
it 'fires up the service on one of the default ports' do
-
+ server = double('server', :addr => [1,2,3])
+ subject.stub_chain('default_ports.sample') { 445 }
+ TCPServer.should_receive(:open).with(445).and_return server
+
+ subject.fire
end
context 'but when no default ports are specified' do
it 'uses the port 0' do
-
+ server = double('server', :addr => [1,2,3])
+ subject.stub(:default_ports) { [] }
+ TCPServer.should_receive(:open).with(0).and_return server
+
+ subject.fire
end
end
end
it 'logs a message telling the trap is listening' do
-
+ server = double('server', :addr => [1,2,3])
+ TCPServer.stub(:open).and_return server
+ subject.logger.should_receive(:log_message).with do |arg|
+ arg.should include('Base micetrap listening')
+ end
+ subject.fire
end
+ end
+ describe "#listen", :blocking => true do
it 'calls read_from every time a connection is accepted' do
connection = double('connection')
server = double('server', :addr => [1,2,3], :accept => connection)
- TCPServer.should_receive(:open).and_return server
- subject.logger.stub(:log)
subject.should_receive(:read_from).with(connection).any_number_of_times
puts "Press Ctrl-C to resume specs! Don't worry, it's all under control :)"
- subject.fire
+ subject.listen(server)
+ end
+ end
+ describe "#read_from" do
+ let(:peeraddr) { [ nil, 4983, 'hackerz.com', '293.13.23.32'] }
+ let(:socket) do
+ double :socket, :peeraddr => peeraddr
+ end
+ before(:each) do
+ socket.should_receive(:close).any_number_of_times
end
+
+ context 'when the socket contains a line with die' do
+ it 'dies' do
+ socket.should_receive(:gets).and_return 'die'
+ subject.logger.should_not_receive(:log_probe)
+ subject.logger.should_receive(:log_message).with("hackerz.com:4983 disconnected")
+
+ subject.read_from(socket)
+ end
+ end
+
+ context 'otherwise' do
+ it 'logs the probe' do
+ socket.should_receive(:gets).and_return 'some probe', nil
+ subject.logger.should_receive(:log_probe).with 'some probe', 'hackerz.com', 4983
+
+ subject.read_from(socket)
+ end
+ context 'when the line is blank' do
+ it 'does respond with the appropriate response' do
+ Kernel.stub(:exit)
+ socket.should_receive(:gets).and_return '', nil
+ subject.logger.stub(:log_probe)
+ appropriate_response = double :response
+ subject.should_receive(:response).and_return appropriate_response
+
+ socket.should_receive(:write).with(appropriate_response)
+ subject.logger.should_receive(:log_message)
+
+ subject.read_from(socket)
+ end
+ end
+ context 'when the line contains any other thing' do
+ it 'does not respond' do
+ socket.should_receive(:gets).and_return 'some evil probe', nil
+ subject.logger.stub(:log_probe)
+
+ subject.should_not_receive(:response)
+ socket.should_not_receive(:write)
+
+ subject.read_from(socket)
+ end
+ end
+ end
+
end
end
end
View
24 spec/micetrap/services/ftp_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+module Micetrap
+ module Services
+ describe Ftp do
+
+ describe "#default_ports" do
+ it 'returns the default ports' do
+ Ftp.new.send(:default_ports).should include(21)
+ end
+ end
+ describe "#response" do
+ it 'returns a response' do
+ Ftp.new.send(:response).should be_a(String)
+ end
+ it 'caches the response for cohesion' do
+ service = Ftp.new
+ response = service.send(:response)
+ service.instance_variable_get(:@response).should == response
+ end
+ end
+ end
+ end
+end
View
24 spec/micetrap/services/http_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+module Micetrap
+ module Services
+ describe Http do
+
+ describe "#default_ports" do
+ it 'returns the default ports' do
+ Http.new.send(:default_ports).should =~ [80, 8080]
+ end
+ end
+ describe "#response" do
+ it 'returns a response' do
+ Http.new.send(:response).should be_a(String)
+ end
+ it 'caches the response for cohesion' do
+ service = Http.new
+ response = service.send(:response)
+ service.instance_variable_get(:@response).should == response
+ end
+ end
+ end
+ end
+end
View
24 spec/micetrap/services/mysql_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+module Micetrap
+ module Services
+ describe Mysql do
+
+ describe "#default_ports" do
+ it 'returns the default ports' do
+ Mysql.new.send(:default_ports).should include(3306)
+ end
+ end
+ describe "#response" do
+ it 'returns a response' do
+ Mysql.new.send(:response).should be_a(String)
+ end
+ it 'caches the response for cohesion' do
+ service = Mysql.new
+ response = service.send(:response)
+ service.instance_variable_get(:@response).should == response
+ end
+ end
+ end
+ end
+end
View
24 spec/micetrap/services/samba_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+module Micetrap
+ module Services
+ describe Samba do
+
+ describe "#default_ports" do
+ it 'returns the default ports' do
+ Samba.new.send(:default_ports).should =~ [135, 139, 445]
+ end
+ end
+ describe "#response" do
+ it 'returns a response' do
+ Samba.new.send(:response).should be_a(String)
+ end
+ it 'caches the response for cohesion' do
+ service = Samba.new
+ response = service.send(:response)
+ service.instance_variable_get(:@response).should == response
+ end
+ end
+ end
+ end
+end
View
24 spec/micetrap/services/torrent_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+module Micetrap
+ module Services
+ describe Torrent do
+
+ describe "#default_ports" do
+ it 'returns the default ports' do
+ Torrent.new.send(:default_ports).should == []
+ end
+ end
+ describe "#response" do
+ it 'returns a response' do
+ Torrent.new.send(:response).should be_a(String)
+ end
+ it 'caches the response for cohesion' do
+ service = Torrent.new
+ response = service.send(:response)
+ service.instance_variable_get(:@response).should == response
+ end
+ end
+ end
+ end
+end

0 comments on commit 0660075

Please sign in to comment.