Skip to content

Socket Code Template

tqbf edited this page Sep 13, 2010 · 2 revisions

We could waste a lot of time building “publishing” plugins to send Ruckus fuzz messages across the network, but what would be the point?

  1. Ruby already has good libraries for that
  2. You’d still be no closer to fuzzing a DeviceIoControl call
  3. The plugin would still only handle 70-80% of the network cases
  4. You still wouldn’t have serverside support.

8 times out of 10 if you’re fuzzing something, it’s the serverside of a network protocol. For that case, here’s a template in our recommended network programming environment, EventMachine:


%w[ rubygems eventmachine ruckus my_protocol ].each {|x| require x}

Everything you care about is in my_protocol. I have no idea what it might be.


# Boilerplate common to all network clientside code
module Clientside
    def post_init
        @buf = ""
        @timeout = 1
        go
    end

    def tx(buf, &block) 
        watchdog  
        send_data(buf)
        @handler = block if block_given?
    end

    def watchdog
        @timer.try(:cancel)
        @timer = EventMachine::Timer.new(@timeout) { close_connection } 
    end

    def receive_data(buf)
        @buf << buf
        @handler.try(:call)
    end

    def unbind; go; end
end

An EventMachine-ism: every connection is defined by a Module, which is how you tell EventMachine what to do with the connections it makes.

For our purposes, we need to define three handler functions in that module:

  1. post_init – “initialize”. We arrange to call “go” when initialization is done.
  2. receive_data – called any time one or more bytes of data arrives at our socket. Here, we just buffer and delegate.
  3. unbind – called when we lose the connection. Here, we just ask for another connection.

We also define a couple more methods.

Our tx wraps send_data, which will deliver 1, 10, or 10,000,000 bytes across a socket gracefully without locking up I/O.

Here, we’ve extended that with a watchdog timer that will fire if we don’t get anything back from the server.

More importantly, we gave send_data a block argument, which will be called as soon as we get a response from the server.


# Enough handler code to get you past login
module Login; include Clientside
    attr_accessor :user, :pass
    def go
        tx(MyProtocol::Login.new :user => @user, :pass => @pass) do
             resp, @buf = MyProtocol::LoginResponse.factory(@buf)
             if(resp.kind_of? MyProtocol::LoginFailure)
                fail(resp)
             else
                ok(resp)
             end
        end
    end

    def fail(resp)
        raise resp.reason.str.value
    end
end

On “go”, we send a login message with a block that gets called when the login response appears. We check the response and delegate to “ok” if it succeeded.


# Attack a specific message type
module AttackMessage; include Login
    def ok
        tx(MyProtocol::Message :data => fuzz.next) 
    end
end

You could put all the preceding code up to “AttackMessage” into a file and “require” it, and just define these 5 lines of code to implement an attack. “ok” was called because our login succeeded.


def go; EventMachine::connect("localhost", 7777, AttackMessage); end

EventMachine::run {
    10.times { go }
}

More boilerplate. This program is going to land in the EventMachine::run loop and never leave it. Run is going to call select() and dispatch I/O. We are running 10 concurrent connections with no threads, resupplying connections every time “unbind” is called on one of them.

Clone this wiki locally