Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/proto/ntlm/base.rb
Views: 11704
# -*- coding: binary -*-1#2# An NTLM Authentication Library for Ruby3#4# This code is a derivative of "dbf2.rb" written by yrock5# and Minero Aoki. You can find original code here:6# http://jp.rubyist.net/magazine/?0013-CodeReview7# -------------------------------------------------------------8# Copyright (c) 2005,2006 yrock9#10# This program is free software.11# You can distribute/modify this program under the terms of the12# Ruby License.13#14# 2011-02-23 refactored by Alexandre Maloteaux for Metasploit Project15# -------------------------------------------------------------16#17# 2006-02-11 refactored by Minero Aoki18# -------------------------------------------------------------19#20# All protocol information used to write this code stems from21# "The NTLM Authentication Protocol" by Eric Glass. The author22# would thank to him for this tremendous work and making it23# available on the net.24# http://davenport.sourceforge.net/ntlm.html25# -------------------------------------------------------------26# Copyright (c) 2003 Eric Glass27#28# Permission to use, copy, modify, and distribute this document29# for any purpose and without any fee is hereby granted,30# provided that the above copyright notice and this list of31# conditions appear in all copies.32# -------------------------------------------------------------33#34# The author also looked Mozilla-Firefox-1.0.7 source code,35# namely, security/manager/ssl/src/nsNTLMAuthModule.cpp and36# Jonathan Bastien-Filiatrault's libntlm-ruby.37# "http://x2a.org/websvn/filedetails.php?38# repname=libntlm-ruby&path=%2Ftrunk%2Fntlm.rb&sc=1"39# The latter has a minor bug in its separate_keys function.40# The third key has to begin from the 14th character of the41# input string instead of 13th:)424344module Rex45module Proto46module NTLM47# The base type needed for other modules like message and crypt48class Base4950CONST = Rex::Proto::NTLM::Constants5152# base classes for primitives53class Field54attr_accessor :active, :value5556def initialize(opts)57@value = opts[:value]58@active = opts[:active].nil? ? true : opts[:active]59end6061def size62@active ? @size : 063end64end6566class String < Field67def initialize(opts)68super(opts)69@size = opts[:size]70end7172def parse(str, offset=0)73if @active and str.size >= offset + @size74@value = str[offset, @size]75@size76else77078end79end8081def serialize82if @active83@value84else85""86end87end8889def value=(val)90@value = val91@size = @value.nil? ? 0 : @value.size92@active = (@size > 0)93end94end9596class Int16LE < Field97def initialize(opt)98super(opt)99@size = 2100end101102def parse(str, offset=0)103if @active and str.size >= offset + @size104@value = str[offset, @size].unpack("v")[0]105@size106else1070108end109end110111def serialize112[@value].pack("v")113end114end115116class Int32LE < Field117def initialize(opt)118super(opt)119@size = 4120end121122def parse(str, offset=0)123if @active and str.size >= offset + @size124@value = str.slice(offset, @size).unpack("V")[0]125@size126else1270128end129end130131def serialize132[@value].pack("V") if @active133end134end135136class Int64LE < Field137def initialize(opt)138super(opt)139@size = 8140end141142def parse(str, offset=0)143if @active and str.size >= offset + @size144d, u = str.slice(offset, @size).unpack("V2")145@value = (u * 0x100000000 + d)146@size147else1480149end150end151152def serialize153[@value & 0x00000000ffffffff, @value >> 32].pack("V2") if @active154end155end156157# base class of data structure158class FieldSet159class << FieldSet160def define(&block)161klass = Class.new(self) do162def self.inherited(subclass)163proto = @proto164165subclass.instance_eval do166@proto = proto167end168end169end170171klass.module_eval(&block)172173klass174end175176def string(name, opts)177add_field(name, String, opts)178end179180def int16LE(name, opts)181add_field(name, Int16LE, opts)182end183184def int32LE(name, opts)185add_field(name, Int32LE, opts)186end187188def int64LE(name, opts)189add_field(name, Int64LE, opts)190end191192def security_buffer(name, opts)193add_field(name, SecurityBuffer, opts)194end195196def prototypes197@proto198end199200def names201@proto.map{|n, t, o| n}202end203204def types205@proto.map{|n, t, o| t}206end207208def opts209@proto.map{|n, t, o| o}210end211212private213214def add_field(name, type, opts)215(@proto ||= []).push [name, type, opts]216define_accessor name217end218219def define_accessor(name)220module_eval(<<-End, __FILE__, __LINE__ + 1)221def #{name}222self['#{name}'].value223end224225def #{name}=(val)226self['#{name}'].value = val227end228End229end230end #self231232def initialize233@alist = self.class.prototypes.map{ |n, t, o| [n, t.new(o)] }234end235236def serialize237@alist.map{|n, f| f.serialize }.join238end239240def parse(str, offset=0)241@alist.inject(offset){|cur, a| cur += a[1].parse(str, cur)}242end243244def size245@alist.inject(0){|sum, a| sum += a[1].size}246end247248def [](name)249a = @alist.assoc(name.to_s.intern)250raise ArgumentError, "no such field: #{name}" unless a251a[1]252end253254def []=(name, val)255a = @alist.assoc(name.to_s.intern)256raise ArgumentError, "no such field: #{name}" unless a257a[1] = val258end259260def enable(name)261self[name].active = true262end263264def disable(name)265self[name].active = false266end267end268269Blob = FieldSet.define {270int32LE :blob_signature, {:value => CONST::BLOB_SIGN}271int32LE :reserved, {:value => 0}272int64LE :timestamp, {:value => 0}273string :challenge, {:value => "", :size => 8}274int32LE :unknown1, {:value => 0}275string :target_info, {:value => "", :size => 0}276int32LE :unknown2, {:value => 0}277}278279SecurityBuffer = FieldSet.define {280int16LE :length, {:value => 0}281int16LE :allocated, {:value => 0}282int32LE :offset, {:value => 0}283}284285286class SecurityBuffer287attr_accessor :active288def initialize(opts)289super()290@value = opts[:value]291@active = opts[:active].nil? ? true : opts[:active]292@size = 8293end294295def parse(str, offset=0)296if @active and str.size >= offset + @size297super(str, offset)298@value = str[self.offset, self.length]299@size300else3010302end303end304305def serialize306super if @active307end308309def value310@value311end312313def value=(val)314@value = val315self.length = self.allocated = val.size316end317318def data_size319@active ? @value.size : 0320end321end322end323end324end325end326327328