Ruby of wisdom

 

Hello.rb

#!/usr/bin/ruby

puts 'Hello World!"

Classes

Ruby knows the following classes:

  • Integer
  • Float
  • String

Methods

A method is something you can do with a class.

  • foo.to_i convert to integer
  • foo.to_f convert to float
  • foo.to_s convert to string

Variables

Warnung: Variablennamen dürfen nicht mit einem Großbuchstaben beginnen.

stadt = "Berlin"

Working with Numbers

Math

var = var + 2
var += 2

var = var - 3
var -= 3

var = var * 6
var *= 6

var = var / 2
var /= 2

var = var** 3
var **=3

var = var % 4
var %= 4

Working with Strings

String Manipulation

name = name.chomp
number = gets.chomp.to_i

Data Structures

Working with Arrays

Defining Arrays

item = Array.new
@item = Array.new

$a = `ls`
=> "bin\nDATA\nDesktop\nvmware\n"

$a = `ls`.split
=> ["bin", "DATA", "Desktop", "vmware"]

zahlen = [ "null", "eins", "zwei", "drei", "vier" ]

Accessing Arrays

zahlen = [ "null", "eins", "zwei", "drei", "vier" ]

zahlen.lenght        # Anzahl der Array-Elemente
freunde = ["Jim", "Jeff", "Tim", "Rob"]

freunde.each do |freund|
    puts "Ich habe einen Freund, der " + freund + " heißt"
end

# same as

4.times do |i|
    puts "Ich habe einen Freund, der " + freunde[i] + " heißt"
end

# same as

freunde.length.times do |i|  # 'i' für 'index'.
  puts "Ich habe einen Freund, der " + freunde[i] + "heißt"
end

Working with Hashes

Defining Hashes

data = Hash.new

freund = {
  "vorname"    => "Herbert",
  "nachname"   => "Maier",
  "adresse"    => "Auf Maien 69",
  "stadt"      => "Neunkirchen",
  "bundesland" => "Saarland"
}

Accessing Hashes

freund.each do |key, value|
  puts key + " => " + value
end

# same as

freund.each_key do |key|
  puts freund[key]
end
freund.each_key do |key|
  puts key
end
h = { "a" => 100, "b" => 200 }
h.each_pair {|key, value|
  puts "#{key} is #{value}"
}
=> a is 100
=> b is 200

Working with Hashes of Hashes

Creating HOH in Ruby is a bit quiet strange IMHO.

The “default_proc” Method

int = Hash.new{|h,k| h[k]=Hash.new &h.default_proc}
int[:eth0][:ip]   = "10.0.0.1"
int[:eth0][:mask] = "255.255.255.0"
int[:eth0][:cidr] = "24"
int[:eth1][:ip]   = "10.0.1.1"
int[:eth1][:mask] = "255.255.255.0"
int[:eth1][:cidr] = "24"

puts "IP of eth0 is:"+int[:eth0][:ip]

The “ostruct” Method

require 'ostruct'

int = Hash.new{|h,k| h[k]=OpenStruct.new}

int[:eth0].ip   = "10.0.0.1"
int[:eth0].mask = "255.255.255.0"
int[:eth0].cidr = "24"
int[:eth1].ip   = "10.0.1.1"
int[:eth1].mask = "255.255.255.0"
int[:eth1].cidr = "24"

puts int[:eth1].cidr

Loops

Counted Loop

count = 0
5.times do
    count += 1
    puts "count = " + count.to_s
end
count = 1
count = 2
count = 3
count = 4
count = 5
count = sum = 0
11.times do
  count += 1
  sum += count
  puts "Summe to " + count.to_s + " = "+ sum.to_s
end
Summe to 1 = 1
Summe to 2 = 3
Summe to 3 = 6
Summe to 4 = 10
Summe to 5 = 15
Summe to 6 = 21
Summe to 7 = 28
Summe to 8 = 36
Summe to 9 = 45
Summe to 10 = 55
Summe to 11 = 66
count=10
count.times do
  count-=1
  puts count.to_s
end
9
8
7
6
5
4
3
2
1
0

Conditional Statements

IF THEN ELSE

stadt="zh"
if stadt == "Berlin"
   drinking_age = 18
else
   drinking_age = 21
end

WHILE

count=0
while count < 10
  puts "count = " + count.to_s
  count +=1
end

Methodes (functions)

Methodes are in Ruby what you would call a function in Bash or Perl.

A simple Methode looks like:

def showme(message)
  puts message
end

message="ruby says hello"
showme(message)

Task specific solutions

Networking

# Lets try a simple banner grabber in ruby
#
require 'socket'
socket = TCPSocket.new("www.heise.de", "80")
socket.write("GET / HTTP/1.0\n\n")
print socket.read + " - soso \n"

Get MAC and IP from network interface

require 'socket'

# From bits/ioctls.h
SIOCGIFHWADDR  = 0x8927          # Get hardware address
SIOCGIFADDR    = 0x8915          # get PA address

class String
	def to_ipaddr4
		self.unpack("CCCC").join(".")
	end
	def to_etheraddr
		self.unpack("H2H2H2H2H2H2").join(":")
	end
end

class Interface

	def self.hw_address(iface)
		sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM,0)
		buf = [iface,""].pack('a16h16')
		sock.ioctl(SIOCGIFHWADDR, buf);
		sock.close
		return buf[18..24].to_etheraddr
	end

	def self.ip_address(iface)
		#sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM,0)
		sock = UDPSocket.new
		buf = [iface,""].pack('a16h16')
		sock.ioctl(SIOCGIFADDR, buf);
		sock.close
		# Another way
		# Socket::unpack_sockaddr_in(buf[16..256])[1]
		buf[20..24].to_ipaddr4
	end

end

if $0 == __FILE__
	puts Interface.hw_address('eth0')
	puts Interface.ip_address('eth0')
end

Set NIC into promiscuous mode

You have to install the bit-struct library from: http://raa.ruby-lang.org/project/bit-struct/

Installation:

tar xvfz bit-struct-0.10.tgz
cd bit-struct-0.10
ruby install.rb config
ruby install.rb setup
sudo ruby install.rb install
require 'socket'
require 'bit-struct'

AF_PACKET = 17
ETH_P_ALL = 3

# From bits/socket.h
SOL_PACKET = 263

# From netpacket/packet.h
PACKET_ADD_MEMBERSHIP  = 1
PACKET_MR_PROMISC      = 1

# Equivalent C htons function
def htons(h)
  [h].pack("S").unpack("n")[0]
end

# Struct in linux/if_packet.h
class MReq < BitStruct
	signed   :mr_ifindex, 32, :endian => :native
	unsigned :mr_type, 16, :endian => :native
	unsigned :mr_alen, 16, :endian => :native
	char		 :mr_address, 64
end

mreq = MReq.new do |m|
	m.mr_ifindex = 2
	m.mr_type = PACKET_MR_PROMISC
	m.mr_alen = 0
	m.mr_address = 0
end

begin
  ssock = Socket.open(AF_PACKET, Socket::SOCK_RAW, htons(ETH_P_ALL))
	ssock.setsockopt(SOL_PACKET, PACKET_ADD_MEMBERSHIP, mreq)
rescue Errno::EPERM
  $stderr.puts "Must run #{$0} as root."
  exit!
end
This entry was posted in Programing, Ruby. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.