Hashcat capture file: Ruby parsing library

Native format of Hashcat password "recovery" utility

Application

["Hashcat", "aircrack-ng"]

File extension

hccapx

KS implementation details

License: Unlicense

This page hosts a formal specification of Hashcat capture file using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Runtime library

All parsing code for Ruby generated by Kaitai Struct depends on the Ruby runtime library. You have to install it before you can parse data.

The Ruby runtime library can be installed from RubyGems:

gem install kaitai-struct

Code

Parse a local file and get structure in memory:

data = Hccapx.from_file("path/to/local/file.hccapx")

Or parse structure from a string of bytes:

bytes = "\x00\x01\x02..."
data = Hccapx.new(Kaitai::Struct::Stream.new(bytes))

After that, one can get various attributes from the structure by invoking getter methods like:

data.records # => get records

Ruby source code to parse Hashcat capture file

hccapx.rb

# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

require 'kaitai/struct/struct'

unless Gem::Version.new(Kaitai::Struct::VERSION) >= Gem::Version.new('0.9')
  raise "Incompatible Kaitai Struct Ruby API: 0.9 or later is required, but you have #{Kaitai::Struct::VERSION}"
end


##
# Native format of Hashcat password "recovery" utility
# @see https://hashcat.net/wiki/doku.php?id=hccapx Source
class Hccapx < Kaitai::Struct::Struct
  def initialize(_io, _parent = nil, _root = self)
    super(_io, _parent, _root)
    _read
  end

  def _read
    @records = []
    i = 0
    while not @_io.eof?
      @records << HccapxRecord.new(@_io, self, @_root)
      i += 1
    end
    self
  end
  class HccapxRecord < Kaitai::Struct::Struct
    def initialize(_io, _parent = nil, _root = self)
      super(_io, _parent, _root)
      _read
    end

    def _read
      @magic = @_io.read_bytes(4)
      raise Kaitai::Struct::ValidationNotEqualError.new([72, 67, 80, 88].pack('C*'), magic, _io, "/types/hccapx_record/seq/0") if not magic == [72, 67, 80, 88].pack('C*')
      @version = @_io.read_u4le
      @ignore_replay_counter = @_io.read_bits_int_be(1) != 0
      @message_pair = @_io.read_bits_int_be(7)
      @_io.align_to_byte
      @len_essid = @_io.read_u1
      @essid = @_io.read_bytes(len_essid)
      @padding1 = @_io.read_bytes((32 - len_essid))
      @keyver = @_io.read_u1
      @keymic = @_io.read_bytes(16)
      @mac_ap = @_io.read_bytes(6)
      @nonce_ap = @_io.read_bytes(32)
      @mac_station = @_io.read_bytes(6)
      @nonce_station = @_io.read_bytes(32)
      @len_eapol = @_io.read_u2le
      @eapol = @_io.read_bytes(len_eapol)
      @padding2 = @_io.read_bytes((256 - len_eapol))
      self
    end
    attr_reader :magic

    ##
    # The version number of the .hccapx file format.
    attr_reader :version

    ##
    # Indicates if the message pair matching was done based on
    # replay counter or not.
    # 
    # Whenever it was set to 1 it means that the replay counter
    # was ignored (i.e. it was not considered at all by the
    # matching algorithm).
    # 
    # Hashcat currently does not perform any particular action
    # based on this bit, but nonetheless this information could be
    # crucial for some 3th party tools and for
    # analysis/statistics. There could be some opportunity to
    # implement some further logic based on this particular
    # information also within hashcat (in the future).
    attr_reader :ignore_replay_counter

    ##
    # The message_pair value describes which messages of the 4-way
    # handshake were combined to form the .hccapx structure. It is
    # always a pair of 2 messages: 1 from the AP (access point)
    # and 1 from the STA (client).
    # 
    # Furthermore, the message_pair value also gives a hint from
    # which of the 2 messages the EAPOL origins. This is
    # interesting data, but not necessarily needed for hashcat to
    # be able to crack the hash.
    # 
    # On the other hand, it could be very important to know if
    # "only" message 1 and message 2 were captured or if for
    # instance message 3 and/or message 4 were captured too. If
    # message 3 and/or message 4 were captured it should be a hard
    # evidence that the connection was established and that the
    # password the client used was the correct one.
    attr_reader :message_pair
    attr_reader :len_essid
    attr_reader :essid
    attr_reader :padding1

    ##
    # The flag used to distinguish WPA from WPA2 ciphers. Value of
    # 1 means WPA, other - WPA2.
    attr_reader :keyver

    ##
    # The final hash value. MD5 for WPA and SHA-1 for WPA2
    # (truncated to 128 bit).
    attr_reader :keymic

    ##
    # The BSSID (MAC address) of the access point.
    attr_reader :mac_ap

    ##
    # Nonce (random salt) generated by the access point.
    attr_reader :nonce_ap

    ##
    # The MAC address of the client connecting to the access point.
    attr_reader :mac_station

    ##
    # Nonce (random salt) generated by the client connecting to the access point.
    attr_reader :nonce_station

    ##
    # The length of the EAPOL data.
    attr_reader :len_eapol
    attr_reader :eapol
    attr_reader :padding2
  end
  attr_reader :records
end