Skip to content
dmaloney-r7 edited this page Mar 31, 2017 · 24 revisions

Getting Started

Some things to do to get started contributing to this project:

  • Fork this Repo like you would any other Github project
  • Familiarise yourself with the SMB and SMB2 protocols
  • Familiarise yourself with the BinData Library as all packets are created using this library.

RubySMB Design Goals

Sockets should be made by the application, not the library

This means RubySMB should work with anything that responds to a certain interface, i.e., if it looks like a socket, it should work. To that end, the Dispatcher classes act as a wrapper for whatever socket you like.

Follow the spec by default

The RubySMB library should, by default, produce packets that conform to the spec.

Details on the packet specifications for the protocol can be found on MSDN:

SMB1 SMB2

In general, the library should attempt to look as close as possible to traffic produced by legitimate clients like Windows, OSX, or smbclient.

We recommend observing actual traffic in Wireshark while having clients perform the actions you are trying to implement. For example, if you were implementing writing to a file, open Wireshark on the server and then from a Windows client write a file to the share. Wireshark's SMB/SMB2 Dissectors are excellent, and will help you understand what is going on.

Allow deviating when necessary

RubySMB is being developed with an eye towards use in Metasploit. This means that we need to be able to send packets that do NOT confirm to the spec sometimes, in order to create certain exploit scenarios. Every packet can be individually crafted, and altered either as a BinData structure, or after it has been turned into a binary string, but before it is sent over the wire.

An Easy to use client

The RubySMB::Client should have easy simple to use interfaces that allow people to perform basic tasks over SMB without having to care about all of the underlying mechanisms. It should not, however, restrict access to those mechanisms. The Client is being built in such a way that a user can reach past the levels of abstraction as deeply or shallowly as they need for their own purposes.

Style Guidelines

All Ruby code should try to follow the ruby community style guide as much as possible.

All submitted code should have RSpec3 test coverage. All submitted code should have YARD docs. The top level YARD doc for a packet class should include a reference to the MSDN page on that packet structure.

For Example:

module RubySMB
  module SMB2
    module BitField
      # Represents a Security Mode BitField as defined by
      # [2.2.3 SMB2 NEGOTIATE Request](https://msdn.microsoft.com/en-us/library/cc246543.aspx)
      class Smb2SecurityMode < BinData::Record

Any bit flag fields should be set up as a separate class, and defined bit by bit so that users can easily tweak the value of the field without having to use binary operators. For example Let's look at the Smb2SecurityMode field again.

It is defined like this:

module RubySMB
  module SMB2
    module BitField
      # Represents a Security Mode BitField as defined by
      # [2.2.3 SMB2 NEGOTIATE Request](https://msdn.microsoft.com/en-us/library/cc246543.aspx)
      class Smb2SecurityMode < BinData::Record
        endian :little
        bit6    :reserved,          label: 'Reserved'
        bit1    :signing_required,  label: 'Signing Required'
        bit1    :signing_enabled,   label: 'Signing Enabled'
        uint8   :reserved2,         label: 'Reserved'
      end
    end
  end
end

This defines the field as its own type which can then be declared in a packet like the SMB2 NegotiateRequest

class NegotiateRequest < RubySMB::GenericPacket
        endian              :little
        smb2_header         :smb2_header
        uint16              :structure_size,      label: 'Structure Size', initial_value: 36
        uint16              :dialect_count,       label: 'Dialect Count'
        smb2_security_mode  :security_mode
        uint16              :reserved1, label: 'Reserved', initial_value: 0
        smb2_capabilities   :capabilities
        string              :client_guid,         label: 'Client GUID',        length: 16
        file_time           :client_start_time,   label: 'Client Start Time',  initial_value: 0
        array               :dialects,            label: 'Dialects',           type: :uint16, read_until: :eof

You can see our smb2_security_mode field declared in the middle of the packet there, and given a name of security_mode This allows a user to do something like this: packet.security_mode.signing_required = 1. It allows for the maximum power and flexibility when manipulating these packets later.

Short Term Goals

  • Complete all File CRUD(Create Read Update Delete) capabilities
  • Make sure we can support named pipes
  • Implement a basic File Server that allows users to register a resource on the server and assign a callback to be fired whenever that resource is required
  • smb_version module updated to use this library
  • psexec module updated to use this library
  • Meterpreter named pipe transport
  • Integrate the file server so that exploits can use it to serve files up

Long Term Goals

  • Circle back for SMB3 support
  • Add SMB3 Encryption