Hashcat capture file (old version): Nim parsing library

Native format of Hashcat password "recovery" utility.

A sample of file for testing can be downloaded from https://web.archive.org/web/20150220013635if_/http://hashcat.net:80/misc/example_hashes/hashcat.hccap

Application

["Hashcat", "aircrack-ng"]

File extension

hccap

KS implementation details

License: Unlicense

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

Nim source code to parse Hashcat capture file (old version)

hccap.nim

import kaitai_struct_nim_runtime
import options

type
  Hccap* = ref object of KaitaiStruct
    `records`*: seq[Hccap_HccapRecord]
    `parent`*: KaitaiStruct
  Hccap_HccapRecord* = ref object of KaitaiStruct
    `essid`*: seq[byte]
    `macAp`*: seq[byte]
    `macStation`*: seq[byte]
    `nonceStation`*: seq[byte]
    `nonceAp`*: seq[byte]
    `eapolBuffer`*: Hccap_EapolDummy
    `lenEapol`*: uint32
    `keyver`*: uint32
    `keymic`*: seq[byte]
    `parent`*: Hccap
    `rawEapolBuffer`*: seq[byte]
    `eapolInst`*: seq[byte]
  Hccap_EapolDummy* = ref object of KaitaiStruct
    `parent`*: Hccap_HccapRecord

proc read*(_: typedesc[Hccap], io: KaitaiStream, root: KaitaiStruct, parent: KaitaiStruct): Hccap
proc read*(_: typedesc[Hccap_HccapRecord], io: KaitaiStream, root: KaitaiStruct, parent: Hccap): Hccap_HccapRecord
proc read*(_: typedesc[Hccap_EapolDummy], io: KaitaiStream, root: KaitaiStruct, parent: Hccap_HccapRecord): Hccap_EapolDummy

proc eapol*(this: Hccap_HccapRecord): seq[byte]


##[
Native format of Hashcat password "recovery" utility.

A sample of file for testing can be downloaded from https://web.archive.org/web/20150220013635if_/http://hashcat.net:80/misc/example_hashes/hashcat.hccap

@see <a href="https://hashcat.net/wiki/doku.php?id=hccap">Source</a>
]##
proc read*(_: typedesc[Hccap], io: KaitaiStream, root: KaitaiStruct, parent: KaitaiStruct): Hccap =
  template this: untyped = result
  this = new(Hccap)
  let root = if root == nil: cast[Hccap](this) else: cast[Hccap](root)
  this.io = io
  this.root = root
  this.parent = parent

  block:
    var i: int
    while not this.io.isEof:
      let it = Hccap_HccapRecord.read(this.io, this.root, this)
      this.records.add(it)
      inc i

proc fromFile*(_: typedesc[Hccap], filename: string): Hccap =
  Hccap.read(newKaitaiFileStream(filename), nil, nil)

proc read*(_: typedesc[Hccap_HccapRecord], io: KaitaiStream, root: KaitaiStruct, parent: Hccap): Hccap_HccapRecord =
  template this: untyped = result
  this = new(Hccap_HccapRecord)
  let root = if root == nil: cast[Hccap](this) else: cast[Hccap](root)
  this.io = io
  this.root = root
  this.parent = parent

  let essidExpr = this.io.readBytes(int(36))
  this.essid = essidExpr

  ##[
  The BSSID (MAC address) of the access point
  ]##
  let macApExpr = this.io.readBytes(int(6))
  this.macAp = macApExpr

  ##[
  The MAC address of a client connecting to the access point
  ]##
  let macStationExpr = this.io.readBytes(int(6))
  this.macStation = macStationExpr

  ##[
  Nonce (random salt) generated by the client connecting to the access point.
  ]##
  let nonceStationExpr = this.io.readBytes(int(32))
  this.nonceStation = nonceStationExpr

  ##[
  Nonce (random salt) generated by the access point.
  ]##
  let nonceApExpr = this.io.readBytes(int(32))
  this.nonceAp = nonceApExpr

  ##[
  Buffer for EAPOL data, only first `len_eapol` bytes are used
  ]##
  let rawEapolBufferExpr = this.io.readBytes(int(256))
  this.rawEapolBuffer = rawEapolBufferExpr
  let rawEapolBufferIo = newKaitaiStream(rawEapolBufferExpr)
  let eapolBufferExpr = Hccap_EapolDummy.read(rawEapolBufferIo, this.root, this)
  this.eapolBuffer = eapolBufferExpr

  ##[
  Size of EAPOL data
  ]##
  let lenEapolExpr = this.io.readU4le()
  this.lenEapol = lenEapolExpr

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

  ]##
  let keyverExpr = this.io.readU4le()
  this.keyver = keyverExpr

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

  ]##
  let keymicExpr = this.io.readBytes(int(16))
  this.keymic = keymicExpr

proc eapol(this: Hccap_HccapRecord): seq[byte] = 
  if this.eapolInst.len != 0:
    return this.eapolInst
  let io = this.eapolBuffer.io
  let pos = io.pos()
  io.seek(int(0))
  let eapolInstExpr = io.readBytes(int(this.lenEapol))
  this.eapolInst = eapolInstExpr
  io.seek(pos)
  if this.eapolInst.len != 0:
    return this.eapolInst

proc fromFile*(_: typedesc[Hccap_HccapRecord], filename: string): Hccap_HccapRecord =
  Hccap_HccapRecord.read(newKaitaiFileStream(filename), nil, nil)

proc read*(_: typedesc[Hccap_EapolDummy], io: KaitaiStream, root: KaitaiStruct, parent: Hccap_HccapRecord): Hccap_EapolDummy =
  template this: untyped = result
  this = new(Hccap_EapolDummy)
  let root = if root == nil: cast[Hccap](this) else: cast[Hccap](root)
  this.io = io
  this.root = root
  this.parent = parent


proc fromFile*(_: typedesc[Hccap_EapolDummy], filename: string): Hccap_EapolDummy =
  Hccap_EapolDummy.read(newKaitaiFileStream(filename), nil, nil)