Skip to main content

You are here

Ruby

Working with Ruby obfuscated code: Finding all classes available in a module

As a follow up to my HashiCorp Rocks! blog post. Up until now, I've never directly worked with any obfuscated code. HashiCorp obfuscates their VMware Fusion and Workstation commercial Vagrant plugins.

Like Vagrant, the plugins themselves are written in Ruby.

alpha03:lib tony$ file vagrant-vmware-fusion.rb
vagrant-vmware-fusion.rb: ASCII text, with very long lines, with CRLF, LF line terminators

However, if you try to read the source all you'll see is a bunch of encoded text. Since my Vagrant plugin has some functionality that only works after a certain action gets executed by the proprietary plugins. This is why I needed to know the exact name of that particular action (class name) exactly how it's defined inside the VMware Fusion and Workstation plugins. This was a serious problem because I can't read their source code!

Luckily, this wasn't as difficult as it seems. Finding the classes (or methods but in the case of mine I didn't need too) available in Ruby is fairly simple process. To my luck somebody had already asked and answered this question in StackOverflow.

In my case, first step was needing to know the name of the actual module itself. I found the easiest way to get the name of the module that's obfuscated, is to intentionally have it spit out an exception. In doing that, I found that the module names whose namespace I'll be searching were HashiCorp::VagrantVMwarefusion and HashiCorp::VagrantVMwareworkstation.

Once I knew the modules's name, I was able to use Ruby to view what additional modules I have within the particular module namespace. I was able to accomplish that using the following

 
t = HashiCorp::VagrantVMwareworkstation.constants.select {|c| 
HashiCorp::VagrantVMwareworkstation.const_get(c).is_a? Module
}
puts t

The above sample code spit out a bunch of modules inside HashiCorp::VagrantVMwareworkstation, but since I know the Vagrant plugin API and it's coding standards/practices. I was able to verify that the module I'm searching for is HashiCorp::VagrantVMwareworkstation::Action. Once again, looking at Plugin API and other examples, I knew that this is where the class is I'm looking is stored in. So I used the following to get the corresponding class name within HashiCorp::VagrantVMwareworkstation::Action

p = HashiCorp::VagrantVMwareworkstation::Action.constants.select { |c|
HashiCorp::VagrantVMwareworkstation::Action.const_get(c).is_a? Class
}
 puts p

I repeated the above tests for HashiCorp::VagrantVMwarefusion and I was also able to find the corresponding class name that it's defined inside the obfuscated Ruby code.

In the end I was able to get the classes HashiCorp::VagrantVMwareworkstation::Action::Suspend and HashiCorp::VagrantVMwarefusion::Action::Suspend, and everything worked as expected.

Programming: 

Awesome Applications: 

Python if __name__ == '__main__' Ruby equivalent

Python is by no chance my favorite language to work in, however I always loved the way you can beautifully write your modules and easily test them via if __name__ == '__main__' statement. I've been doing a lot of Ruby programing these past few weeks, and I came across a situation were I needed this exact feature in Ruby.

My problem:
I needed to run some unit tests to a Ruby based TCP server that gets spawn as daemon. The program is completely command line, and once spawned, their isn't any code to communicate with its child process. The unit tests itself aren't exactly to complicated. I simply need to make sure that the TCP server starts, verify the status of it using its PID, and be able to kill the process. I needed to run the unit tests without heavily modifying the existing program, and the best best to accomplished it was using a similar if __name__ == '__main__' Python approach. Lucky for me, in the Ruby world we can accomplish the awesome if __name__ == '__main__' Python statement via if __FILE__ == $0

Example:
Here is a test module called test-module.rb

#!/usr/bin/env ruby

if __FILE__ == $0
  puts "Executed via command line."
else
  puts "Included."
end

Now, if we run this test-module.rb from the command line, the if __FILE__ == $0 block will evaluate to true.

alpha03:tests $ ./test-module.rb
Executed via command line.

If the module gets included the if __FILE__ == $0 block will evaluate to false. Example script called test.rb

#!/usr/bin/env ruby

require './test-module'

Running the test.rb script that required test-module.rb

alpha03:tests tony$ ./test.rb
Included.

Conclusion:
Ruby rocks!

Programming: 

Custom Nagios mdadm monitoring: check_mdadm-raid

Simple Nagios mdadm monitoring plugin.

#!/usr/bin/env ruby

# Tony Baltazar. root[@]rubyninja.org

OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3

# Note to self, mdadm exit status:
#0 The array is functioning normally.
#1 The array has at least one failed device.
#2 The array has multiple failed devices such that it is unusable.
#4 There was an error while trying to get information about the device.

raid_device = '/dev/md0'

get_raid_output = %x[sudo mdadm --detail #{raid_device}].lines.to_a


get_raid_status = get_raid_output.grep(/\sState\s:\s/).to_s.match(/:\s(.*)\\n\"\]/)
raid_state = get_raid_status[1].strip



if raid_state.empty?
 print "Unable to get RAID status!"
 exit UNKNOWN
end

if /^(clean(, checking)?|active)$/.match(raid_state) 
 print "RAID OK: #{raid_state}"
 exit OK
elsif /degraded/i.match(raid_state)
 print "WARNING RAID: #{raid_state}"
 exit WARNING
elsif /fail/i.match(raid_state)
 print "CRITICAL RAID: #{raid_state}"
 exit CRITICAL
else
 print "UNKNOWN RAID detected: #{raid_state}"
 exit UNKNOWN
end

Programming: 

Awesome Applications: 

301 URL redirect on Ruby on Rails

In your respective controller, specify the method of the view in questioned that needs to be redirected.

def code
   headers["Status"] = "301 Moved Permanently"
   redirect_to "https://www.example.com/alpha01"
 end

Programming: 

Awesome Applications: 

Building mysql2 gem in Ubuntu issue

Installing mysql2 (0.3.11) with native extensions
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

/home/tony/.rvm/rubies/ruby-1.9.3-p125/bin/ruby extconf.rb
checking for rb_thread_blocking_region()... yes
checking for rb_wait_for_single_fd()... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lmygcc... no
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.

Provided configuration options:
--with-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/home/tony/.rvm/rubies/ruby-1.9.3-p125/bin/ruby
--with-mysql-config
--without-mysql-config
--with-mysql-dir
--without-mysql-dir
--with-mysql-include
--without-mysql-include=${mysql-dir}/include
--with-mysql-lib
--without-mysql-lib=${mysql-dir}/lib
--with-mysqlclientlib
--without-mysqlclientlib
--with-mlib
--without-mlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-zlib
--without-zlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-socketlib
--without-socketlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-nsllib
--without-nsllib
--with-mysqlclientlib
--without-mysqlclientlib
--with-mygcclib
--without-mygcclib
--with-mysqlclientlib
--without-mysqlclientlib

FIX

sudo apt-get install libmysqld-pic

Programming: 

Awesome Applications: 

Premium Drupal Themes by Adaptivethemes