0% found this document useful (0 votes)
6 views

4 Classess Modules and Exception

Uploaded by

es169371
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

4 Classess Modules and Exception

Uploaded by

es169371
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 169

4.1.

Class Principles

4.2. Method Visibility

4.3. Subclassing and Inheritance

4.4. Modules

4.5. Exceptions

4.6. Conclusion

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


We have said many times that Ruby is an Object Oriented
programming language.

This means that any value is an object and any object has its own
class (it is an instance of that class).

A class defines what an object will look like, i.e. the set of methods
that the object accepts.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


This course does not cover object oriented principles and software
development techniques.

We will cover constructors and statements without going deep into


OO theory and programming styles.

Therefore if you do not know OO paradigms, we suggest you read


up on it.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Moreover we will mainly use the pry interpreter to explain classes,
module and exceptions.

But again, sometimes having the code in a real Ruby script is


required.

Therefore when you see a script, remember that it is available in


your Members Area. You can download and test any script without
rewriting it.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Penetration Testing Professional 5.0 – Caendra Inc. © 2018
Before continuing with the study of the course, be sure to
know the answers to the following questions:

• What is a class ?
• What is an object ?
• What is an instance of a class ?
• What is a method ?
• What is a subclass ?

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Let us now see how to define a class. We can use the following
syntax :
class <Name>
…<class body>…
end

Where <Name> must begin with a capital letter. This holds


because Ruby silently creates the constant <Name> to refer the
class, so the capital letter is required.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The following is a very simple example of a class named MyClass
which implements a simple method named hello.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In order to instantiate an object we can use the new construct
provided by all classes.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


To invoke an object method, simply
call it throughout your object. In other
words, we can use the object
instantiated followed by a dot (.)
and the method name.

object.method_name

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You should find the previous example very simple.

During the course, we have already used objects and methods


because we used a straightforward OO perspective about Ruby.

The only new concepts are class creation and object instantiation
but they are very simple.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Now we can move to study classes and objects deeply. You should
have all the prerequisites to learn them easily, especially if you are
familiar with the OO programming paradigm.

For further information on classes, please take a look at the


references here.

http://ruby-doc.org/core-1.9.3/Class.html

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Instance variables are variables available only to each instance of
the class, meaning that they change from object to object.

Since instance variables are encapsulated in any object of the class,


they are not visible outside of it.

Note they are defined within class definition using the special
character @.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Instance variables are only accessible via the instance’s public
methods. So you have to define accessors methods to read them
and setters methods to set them.

To initialize them, the default constructor method in Ruby is


initialize.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In the following example, we can see all of
these methods.

All instances of MyClass (defined in


MyClass.rb file) have their own instance
variable (@a) which is accessible thanks to
the getter and the setter method a.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The example shows how to load a
ruby file using pry or irb and how
to use the previous defined
constructor, getter and setter of
MyClass.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see from the previous example, each object has its
instance variable @a that is visible within the method of the
object.

NB: with OO methodology it is not a best practice to provide a


getter/setter for each instance variable. Use them only if they are
necessary.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Remember that instances variables can only
be accessed by the instance methods of the
object of that class.

Therefore the instruction @a = 4000 in the


following example would not compute as
expected.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In the previous example, the first @a is an instance variable that
belongs to the class object (WrongClass) while the others are
instance variables that belong to instances of WrongClass.

It is a substantial difference; instances variables are resolved in the


context of self. When we invoke a method, self refers to an
instance of a Class. Otherwise inside a class but outside any
method, self is the object that represents the class.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see the new does not
initialize the instance variable @a of
wobj.

It is created when we call the setter


(wobj.a = 100).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


But where is the @a of the class definition? It belongs to the class
object WrongClass.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


We suggest you get familiar with this concept in order to avoid
bugs or wrong code in your scripts.

A pentester should know the pragmatics of the languages that they


use.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Another powerful feature of Ruby is the ability to define
getter/setter using Metaprogramming. Metaprogramming allows
you to write, manipulate or generate programs (and their data) at
runtime.

We will not cover Metaprogramming in details but you should


know that it extends Ruby syntax to make programming easier.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


For example, with the attr_accessor
keyword, Ruby silently defines a getter
and a setter for us.

NB: It requires a symbol notation but it


defines real instance variables @x, @y.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


With the attr_reader keyword, Ruby
silently defines (only) a getter for us.

Note that the setter has not been


defined; if we try to set x, we get
“undefined method”.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Attr is another useful keyword.

If used alone, it defines a getter


while with true it defines a setter
too.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Ruby allows you to define methods that are called on the class
object instead of an instance object.

We have already said that self keyword always refers the current
object.

So we can define methods that belong to the class object using it.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see, the say method
belongs to the C1 object (we have
defined it with self). Available if we use C1,
but not if we
instantiate a C1 object
(obj).
Instances of C1 class do not have
such a method.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Since a Class is an object, we can define Class object instance
variables with getter and setter too.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In this example, the ClassObject
definition obscures two different scopes
for @a instance variable.

Try to find them by yourself before


continuing.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


There are two @a instance variables. One belongs to the class
object.

The second belongs to an arbitrary instance of ClassObject.

There are also getter/setter/constructor for each of them.

Can you find them?

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Now everything should be clear.

The next slide will better clarify this


concept.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see, there are two
different @a.

One belongs to the ClassObject


object and one belongs to an
instance of ClassObject (obj
object).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Class methods may be defined in a few other ways:

• Using the class name instead of self keyword

• Using the << notation

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The following is an example of the method definition.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The << notation is useful when you work with classes that have
been already defined. In the following example, we are adding the
method sub to the class object instance we created.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In the previous examples, the class object instance variable @a is
not shared among the class instances (objects created with new).

A class variable must start with special characters @@ and it is


shared among all class instances.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


It is accessible from instance methods, class methods and by the
class definition itself.

They are encapsulated in the object that represent the class; the
user of a class cannot access them from outside without
getter/setter.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


MyClass defines an instance variable @a
accessible through getter/setter created
thanks to attr and a class variable @@a
accessible through class_a getter/setter.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Loading the previous file, we can use MyClass and see what are
the differences of the two types of variables (instance and class).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You may find it useful to define
constants in your classes.

They are accessible from outside using


:: notation.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Constants can also be defined outside of a
class definition.

In the following example, we define a new


constant (C3) in the class named MyClass.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Classes are very flexible in Ruby. The following are some concepts
that a good Ruby programmer needs to known:
• Open Classes
• Operator methods
• Mutable / Immutable Objects and Methods

Let us inspect them one by one.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Generally in conventional OO languages, when you close the class
definition you cannot add anything else in it (generally methods,
variables,…) unless you use some advanced technique and tools
like reflection.

Ruby instead allows you to open a defined class in order to add


other methods, constants and so on.

https://en.wikipedia.org/wiki/Reflection_(computer_programming)

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Opening a class in Ruby is very simple; it is the same as defining a
new class. Ruby silently adds methods to the already defined class.

The following example shows how to add a method to obtain the


double if its size in the String class.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As we can see, it is very easy. The syntax
is the same as defining a class. Since the
String class already exists, the method
dsize is added to it.

This is a very powerful feature. Try it by


yourself. You can extend classes as much
as you want.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Classes are often used to define new user data types.

When you define new data types, you want to define operations
and operators for that type too, and you may want to use pre-
defined and easy syntax operator like +, -, *, etc.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The easiest example you may find in books and references is the
Point data type example. We use it too because we can show
better how to use operator methods.

Point class represent a simple point in Euclidean geometry. For


example: p1(1,2) – p2(10,20).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


We want an operation that sums two points. The standard
operator for sum is +. We want that if
p1(10,20) and p2(2,3)
than
p1 + p2 = > (10+2), (20+3) => p3(12,23)

The sum of two points will return a new point that contains the
sum of the coordinates x and y.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


This is our Point Class. As you can
see, a point has two coordinates
(x,y). Each of them has a getter.

Initialize creates a Point with


immutable x and y (there is no setter
or other method to change them).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The operator method is +. It returns a
new Point with the sum of the two
points.

Defining + as operator allows us to use


‘+’ in the traditional way (other is the
argument of the + method). You can
see this in the next slide.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


What will happen if we run the command p1 + p2?

The method ‘+’ of the object p1 will be called, meaning that @x


contains the x coordinate of p1 and other.x contains the x
coordinate of p2.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In the following example p1,p2,p3 are three instances of Point.
Note that p3 is automatically created.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You can define a lot of operator methods for your data type (for
example comparison operators such as ‘==’ ).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In the previous Point example, we used
Point as immutable values.

As you can see, there is no way to


change an object’s coordinate values
once it is initialized.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


This new Point class creates mutable object
value. Each coordinate has its own setter.

This time, the plus operator changes the first


object and returns it as a result. A Point value
can change its coordinate values using both the
setters and plus operation.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As expected, the sum modifies p1
object.

Moreover, p1 and p3 are two


variables that reference the same
object.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


We show mutable and immutable objects because Ruby has a lot
of operators and methods that act as immutable or mutable
operators/methods.

Do you remember bang methods (methods that ends with


exclamation mark !)?

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


They allow you to treat an object as a mutable or immutable one.
Without an exclamation mark, the method returns a new value; in
the other case, it modifies the original object.

This is a feature that Ruby programmers must know and use


(properly) in their scripts.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Do not use mutable objects if they are not necessary. You may
introduce bugs or something not expected.

The use of immutable object is more of a programming philosophy


than a feature. Use it in an appropriate manner.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Penetration Testing Professional 5.0 – Caendra Inc. © 2018
In the previous examples, we used only public methods (since they
are public by default) but Ruby allows you to define protected and
private methods too.

If you are familiar with protected/private concepts in Java (and


other programming languages), you should be aware that Ruby has
some differences.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You can define both private instance methods and private class
methods.

Private instance methods can only be called by other instance


methods of the class (and subclass). You cannot call them from
outside an object.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


A famous Ruby private instance method is initialize. You cannot
call it from outside:

obj.initialize -> it is not possible

Note: initialize is an exception because in Ruby all methods are


public by default.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Private instance methods are defined using
the private keyword.

If used without arguments (like in the


example), all the methods below this
keyword are private.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


There is another way to define private
methods. You can use the private
keyword with arguments. This allows
you to specify which of the methods to
treat as private.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In both cases, instances of Aclass can
access only getName Only the class
object (Aclass) can access the method
privateName.

In this code, getName calls privateName.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Sometimes it may be useful to specify class methods as private.

For example, if you want to use particular design patterns that


must use this feature.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


To do this, you can use the
private_class_method keyword.

Remember that with the self


keyword, we are setting methods
for the Aclass class object (not for
instances of Aclass).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see from the class object,
only getName can be called.

Once again, it is a method of the object


that represents the class (it is not a
“AClass” instance).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Protected methods work as private methods but protected
methods may be called by any instance of the defining class or its
subclasses.

We know that this definition may be unclear. The following


example explain its meaning.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see, we can explicitly call a
protected method if its caller is an
instance of the defining class.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


When you define a complex class with
private/protected methods (instance and
class), it should look like the following
screenshot.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Visibility keyword does not apply to constants, instance or class
variables.

Constants are public while instance/class variables are private.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You can use private/protected methods as key for a good
programming style.

Do not think that private methods is a secure way to hide


something private. A different technique such as meta-
programming (via send method) or reflection API allows to bypass
private/protected methods.

https://en.wikipedia.org/wiki/Reflection_(computer_programming)

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


We encourage you to use them in order to avoid something not
desirable in your program and as an index of good programming
capabilities.

Remember that scripts with meta-programming or (not required)


reflection are not welcome. A good programming style is always
appreciated.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Penetration Testing Professional 5.0 – Caendra Inc. © 2018
Ruby provides a mechanism to extend a class in order to modify its
behavior or add new functionalities.

This is what is called (in all other languages) subclassing.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


A class may have multiple subclasses but classes in general can
only extend one class (a class has only one superclass).

When you define a new class, if nothing is specified, it


automatically extends the Object Class.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


This means that any class is a descendant of Objects and
respectively any class has Objects in its ancestors.

Curiosity: Object Class extends another Ruby utility Class:


BasicObject.

Therefore the root class in ruby is BasicObject.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Extending a class is very simple, just use the < operator. A class
inherits all superclass methods.

As we can see in the example, Italian extends Person, therefore it


can use Person methods.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Italian class has inherited all Person methods and the initialize
constructor too. This may be strange if you come from an OO
language like Java.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can imagine, we can specialize a class in Ruby in order to
define new methods or override existing methods.

You can override all methods: public, protected and private


(initialize constructor too).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Pay attention; subclassing in Ruby is strongly discouraged if you do
not properly know the superclass that you want to extend.

You might override some private methods that are fundamental


for the class to work properly.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Note: in Java you can use a superclass as an API, without taking
into account the implementation and what are the
private/protected methods.

Do not use this style of programming in Ruby. You may introduce


bugs extending classes that you do not yet know well.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


To override a method, simply define it in the subclass. Ruby will do
the rest.

A very common overridden method is to_s (the same as toString in


Java).

Remember that by default, a class extends the Object class and


that to_s is a method that Object class hold.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


So let us suppose that a generic class named Person (defined
without < ) extends the Object method to_s as follows.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The following code shows how the Italian subclass overrides the
to_s method of Person.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Often when you extend a class, you want to specialize the
behaviors of some methods.

The super keyword helps us avoid the complete redefinition of


method behavior.

With super, you can call the method of the superclass.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You can use super with or without arguments according to the
superclass method called.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Let us see how the previous classes
work.

As you can see, both initialize and


to_s of Car class use the super
version of those methods (I am a
#{@type} vehicle is printed).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Ruby allows you to specialize both instance methods (like the
previous examples) and class methods.

Just use the proper notation (explained earlier) to define a class


method.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Inheritance does not affect instance variables.

This holds because an instance variable by definition is created by


the methods that first initialize it; it belongs to the scope of self.

In Ruby, a class does not define the set of fields for its object
instances like Java or other OO languages.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The following code (same of the previous example) is perfectly
legal. Car initialization defines instance variable @type . Therefore
@type is not inherited.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Inheritance does not affect instance variables. Remember this.

Therefore if you use an instance variable defined in a superclass,


you must pay attention because other superclass methods can use
the same variables and you might introduce bugs or change the
superclass method behavior.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Do you remember? Class variables are shared and visible from
instance methods, class methods and by the class definition itself.

These rules apply to both classes and its subclasses.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Therefore if a class A defines a global variable @@a and B is an
subclass of A, B and its instances can use the same @@a variable:
• @@a is shared among A and B (class and instances). Any @@a
changes affect all the objects that may use it.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The following is a simple example:

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Constants have a particular behavior when used with inheritance.
They are inherited and they can be overridden.

What if when you try to override an inherited constant? Ruby


creates a new one with the same name but available only for the
subclass.

The redefinition does not affect the superclass and its object.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The following is a simple example.

As you can see, each class has its own


constant CONST.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can imagine, if you do not
override a constant in the subclass then
it is simply inherited and usable by the
subclass.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Note there is another strange behavior when we use inherited
constants.

Ruby first looks up a class constant in its lexical scope rather then
in the inherited chain. An inherited method (not overridden)
always uses the superclass constant even if it is overridden in the
subclass.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see, inherited getCONST uses the superclass CONST.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Do you remember the private keyword? We saw that it can be
used to hide a method from the outside.

When you work with inheritance, you must know that private
keyword works in a similar way as the protected Java keyword.

This means that private methods can be used inside inherited


classes.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Private methods are inherited.

This code may seem incorrect for a Java


programmer.

It is perfectly legal in Ruby.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


As you can see, the subclass can use
private methods of the superclass.

Attention: superPrivate is a subclass


public method that use a superclass
private method.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In Ruby, protected methods work like private methods. They are
inherited and can be used similar to private methods.

The only difference is that you have to use them in an explicit way
(object.method notation) when used inside (and not outside) a
class or subclass.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The easiest way to understand protected
behavior is with an example.

Inside a class or a subclass, you can use


obj.method notation (obj.getA).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Let us see the previous code at work.

As you can see, protected method getA


cannot be used outside classes; getAB uses
it internally with obj.getA notation.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


So what happens if we change the
previous example’s protected keyword
with private keyword?

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The main difference between protected and private is that we
cannot use the explicit notation obj.getAB notation inside the A
class or any of its subclasses (B).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Now you should be able to manage classes, subclasses and objects
in a proper way.

You have all the prerequisites to go further in your study of Ruby.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Penetration Testing Professional 5.0 – Caendra Inc. © 2018
A module is used in Ruby to define namespaces and mixins. We
will explain both of them soon.

A module is essentially a collection of methods, constants and class


variables with a name.

Module official references are available here.

http://ruby-doc.org/core-1.9.3/Module.html

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The main differences between classes and modules are:

• Modules cannot be instantiated

• They cannot be subclassed, therefore there is not a


module hierarchy

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Semantically, a module object is an instance of the Module class.

Class is a subclass of Module, therefore all classes are modules too


but not vice versa.

These concepts are simply a curiosity for a standard programmer


but they may be useful for fully understand Ruby pragmatics.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Modules can be used to define a new custom namespace for
methods and constants.

A namespace is a way to collect and bind related methods and


constants, giving them a name that helps you to use them.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Math is the most suitable example of modules used as namespace.

It is a collection of mathematical constants (PI and E) and methods,


especially for basic trigonometric and transcendental functions.

http://ruby-doc.org/core-2.1.0/Math.html

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


For example, let us write our own Math namespace - MyMath. In
the following example, we are defining two constants (PI and E)
and a function (exp).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Modules and namespaces allow you to define custom Libraries:
collection of constants, methods, classes, other modules and so
on.

Note that modules and classes are handled by Ruby by looking at


their name. These names are constants so you can define classes
and modules inside a module and create hierarchies of libraries.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


This strategy is often used by third-party libraries.

You use them by including the third party custom module and they
provide you a hierarchy of methods, constants, classes and more.

This avoids collisions between their function and yours. It is an


appropriate style of code architecture management.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Mixin is a powerful feature implemented in Ruby.

Mixin means that if a module defines instance methods (instead of


class methods), those instance methods can be mixed into another
class; the implementation of the class and the module are joined.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In other words, any instance of the destination class includes
module methods as their instance methods.

To mix a module into a class, simply use the include keyword.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Let us see a simple example. Module B is mixed with A class. The
method hello is available inside instances of A class as a simply
instance method.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Two useful Ruby modules designed for mixin are Comparable and
Enumerable.

If your class defines the operator <=>, you can include Comparable
to get for free operation like <, <=, ==, >, >= and between?.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Same thing with Enumerable. If it is mixed with your class, it gives
you sort, find, min, max, etc.. without the need to implement
them.

The Ruby platform provides other usable classes as well. Each one
requires that your target class implements some methods in order
to work correctly. For example, Enumerable requires the method
each and <=> for some operations.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Nothing prevents the use of a module both as a namespace and as
a mixin; just provide both instance and class methods to the
module.

Math is a classical example of a module that can be used both as


namespace and as a mixin.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Let us see how to use Math as a
namespace and as a mixin.

Once we include Math, we do not need


to specify Math:: to access its constants,
methods and so on.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Penetration Testing Professional 5.0 – Caendra Inc. © 2018
Another very important class that you need to know is Exception.

Sometimes, something can go wrong in a program. Imagine a


division by 0; it will generate an error.

A good programmer should know if a program may go to


unwanted states. We should provide some code to execute when
these errors happen in order to retrieve a correct execution flow.
http://ruby-doc.org/core-1.9.3/Exception.html

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Exceptions are used for this type of situation.

We have already seen a lot of Exceptions during this course. If you


have experience with OO languages (like Java or PHP), you have
already identified them.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


An exception will be generated if we divide a number by 0 or if we
use undefined constants, undefined objects and much more.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


When any of the previous errors occur, Ruby raises an exception.
Normally when an exception is raised, the program terminates its
execution.

But as with almost all OO languages. Ruby allows you to handle the
error and execute some arbitrary code.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Exception in Ruby are object instances of the Exception class (or
one of its subclasses).

Usually subclasses of Exception are used to add information about


the type of Exception raised or to distinguish different exceptions.

Please refer to references to see the full Ruby Exception hierarchy.

http://ruby-doc.org/core-1.9.3/Exception.html

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Exceptions are objects but they are usually created with the
method raise (instead of new). Nothing prevents you from creating
them with new but good programming styles suggests avoiding it.

Raise alone creates a


RuntimeError.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


RuntimeError objects can be created using raise. Note that you can
specify a string argument to associate them.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


With raise, you can specify the Error type too. Just use the name of
the Exception Class and the message to display.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The following is a simple example that uses ArgumentError. In this
case, if a or b are not integer an ArgumentError occurs.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


ArgumentError, RuntimeError, ZeroDivisionError are subclasses of
StandardError.

If you want to use a custom error and non pre-defined errors are
ideal, it is best practice to create your Error class that is inherited
from StandardError.

Please consult the following reference for the full hierarchy of pre-
defined Error classes.
http://ruby-doc.org/core-1.9.3/Exception.html

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Let us see now how to define a custom NoIntError.

It is useful to handle the ArgumentError seen in the previous


example.

First, we shall define the new class NoIntError that is inherited


from StandardError. It is our custom error class. It is really simple.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Then we can use it to raise a more specific exception when we
have found an argument that is not an integer.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Attention: in our examples, we used the interpreter. Remember
that if an exception is not handled, the program terminates.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


In the previous example, the second int_sum invocation cause an
Exception because the first argument is not an integer. Therefore
the program terminates its execution without executing the last
int_sum invocation.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


If you want to handle an exception and execute some arbitrary
code when it happens, you can use rescue.

References defines rescue as a clause that can be attached to


other statements (begin is the most common).

http://ruby-doc.org/core-1.9.3/Exception.html

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Attaching rescue to begin gives us the easiest
way to explain how rescue works. In Ruby, $!
refers the last Exception object.

If you call the fact method with an integer less


than 0, it is executed infinite times because
return statements are always
false. Therefore at some point, the script
spends all its memory.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


At some point, an exception is raised by Ruby because the stack is
full. Rescue catches the exception object and global variable $!
stores it.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You have seen that $! Refers to the last Exception object. You can
also use a personal variable with rescue. In the example, we use
exc instead of $!.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


You can use different rescue clauses and handle exceptions by their type.
In the example, the ARGV[0] is used to call int_sum method with wrong
arguments.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Rescue can follow any statement. If an exception occurs, the body of
rescue is executed. In the example, the last int_sum causes an exception.

Therefore the rescue body is executed, printing 0 to stdout.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Raise and rescue are not the only exception clauses available in
Ruby. Let us see :
• retry

• else

• ensure

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Retry is a clause that can be used inside a rescue clause to re-
execute the block of code that has caused the exception.

It is a very useful feature. Imagine that you want to update a


database and an exception occurs (a network error, a DB error,
etc.). You may simply try it again (the network may be available
now). With retry you can do that.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Let us see a very simple example. When b is 0, a ZeroDivisionError
occurs. Rescue captures it, changes b to 1 and then retry the begin
block.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Attention: with retry, you might introduce an infinite loop of retry
block execution. It is a feature that you should use carefully.

Usually programmers use retry with an appropriate strategy based


on their needs. For example, using an ' exponential backoff '
between retry attempts.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Else is another clause provided by Ruby. It is used to execute some
arbitrary code when rescue does not catch any exception.

Using else is similar to putting the else block at the end of the
begin clause. Note that any exception raised in the else block will
not be handled by the rescue clause!

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Else may be put after a rescue clause. It is not a very used feature
but you should know it exists.

begin
# code You may need it when
rescue
# code you become a Ruby
else
# code guru.
end

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Ensure is another clause that is used to specify some code that is
always executed at the end of the begin flow.

The code is always executed even if an exception occurs inside the


main control flow.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Ensure may be inserted after all rescue and else clauses. A
complete view is:
begin
# normal flow
rescue
# exception handling
else
# no exception occur
ensure
# always executed
end

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


For simplicity, in the previous example, we saw exception handling
using the begin statement.

You can use all the previous concepts and clauses with methods,
classes and modules as well without the need of begin keyword.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


For example, you can write a method like the following one:

def my_method(a,b,c)
# normal flow
rescue
# exception handling
else
# no exception occur
ensure
# always executed
end

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The same holds for classes and modules.

Exceptions are a very powerful Ruby feature. You can write elegant
and semantically correct code that are able to handle all type of
errors and exceptions.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Penetration Testing Professional 5.0 – Caendra Inc. © 2018
We have reached the end of the basic Ruby course.

Now you should be able to understand how Ruby works and you
should be able to write simple and rich Ruby program.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


We have seen Data types, control flows (basic statement and
methods), variables, classes, objects, modules and much more.

You have everything you need to start programming with Ruby


using an OO style and a correct programming structure
methodology (readable, manageable and semantically correct
code).

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


The next step is to learn how to use Ruby in real penetration
testing environments.

Therefore in the next sections, you will learn system and network
programming with Ruby.

You will also see how to use Ruby in order to write a custom
Metasploit module and much more.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Note that there also are many other statements, techniques and
features that we have not seen in this module. Some of them are:
• Proc and Lamba abstraction
• Closures
• Functional programming and higher order function
• Reflection
• Metaprogramming

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


To fully understand them, some high knowledge of programming
paradigms in general are required.

Therefore we have decided to skip them. Usually a pentester does


not use them. If you are interested, they are explained in one of
the best Ruby books:
“The Ruby Programming Language”.

Penetration Testing Professional 5.0 – Caendra Inc. © 2018


Penetration Testing Professional 5.0 – Caendra Inc. © 2018
The Ruby Programming Language Ruby Language Official References
https://www.amazon.com/Ruby-
Programming-Language-David- http://ruby-doc.org/
Flanagan/dp/0596516177
Ruby Essentials Ruby Programming Wikibook

https://www.techotopia.com/index.php/Rub https://en.wikibooks.org/wiki/Ruby_Program
y_Essentials ming

Penetration Testing Professional 5.0 – Caendra Inc. © 2018

You might also like