Announcing Ninja-Patching!
Sure, monkey patching is great and all. That period of disbelief, followed by increasing exasperation as the -victim- maintenance programmer discovers that an object is behaving differently than it’s source code says it should, is satisfying. But sooner or later he or she wises up and greps through the codebase, discovers where you re-opened the class in question, and the game is up.
The fact of the matter is that monkeys simply aren’t very stealthy. They are easy to find when you know what you are looking for. When you really want to catch a coder by surprise, a monkey doesn’t cut it. What you need is a “*Ninja*”:http://www.realultimatepower.net/index4.htm.
And so, today I’m unleashing the technique of Ninja-Patching, along with a reference implementation. Ninja-Patching is silent, untraceable, precise, unpredictable, and always deadly. And unlike monkey patching, which usually happens at startup, Ninja-Patching happens _when you least expect it_. Here’s an example use:
require 'ninja'
Ninja.hire(Enumerable) do def self.to_s "PWNED by Ninjas!!!" end
That’s all you have to do. A silent assassin has been hired, and will ruthlessly hunt down its target. In this case, the target is the first object found in @ObjectSpace@ which is a kind of Enumerable. Which one? Hard to say. Ninjas are, like I said, unpredictable. Once the target is acquired, the Ninja will wait some random amount of time in order to throw off the trail and instill a false sense of security. Then, without warning, the Ninja will attack! The block given to @Ninja.hire@ will be executed in the context of the target object. And then it’s all over but the crying.
Here’s the implementation:
CODE = <<'END_CODE'
class Ninja
def self.hire(target_description, &instructions)
self.new(target_description, instructions)
end
private
# target_description can be either an object which responds to +#===+, or a
# Proc which returns true or false.
def initialize(target_description, instructions)
@target_description = if target_description.kind_of?(Proc) then
target_description
else
lambda {|obj| target_description === obj}
end
@instructions = instructions
@target = acquire_target(@target_description)
if @target.equal?(self)
$stderr.puts "Never double-cross a Ninja!"
exit
elsif @target
stalk(@target)
else
raise "No such object found!"
end
end
def acquire_target(target_description)
ObjectSpace.each_object do |object|
if target_description.call(object)
return object
end
end
nil
end
def stalk(target)
Thread.new do
sleep(rand(60))
attack!(target)
end
end
def attack!(target)
target.instance_eval(&@instructions)
end
end
END_CODE
# Using eval conceals the Ninja in the stack trace
eval CODE
This code is released under the Ninja Public License (NPL), which releases me from all liability should ninja.rb turn on you and assasinate you in your @Kernel#sleep()@. Warning: ninja.rb has a known vulnerability to chosen_one.rb.

This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.
Related posts:
