コンテンツにスキップ

NTHash(NT hash)

NTHash(NT hash)は Windows のパスワード表現(password representation)で、NTLM/NTLMv2 の鍵(key)として使われます。パスワード文字列を UTF-16LE(Unicode)に変換し、MD4 でハッシュ化した 16 バイトの値です。

  1. パスワードを UTF-16LE に変換(大文字化などの正規化(normalization)は行わない)。
  2. 変換後のバイト列に MD4 を適用。
  3. 出力 16 バイトが NTHash。

式で表すと以下です。 NTHash = MD4(UTF-16LE(password))

  • ローカルアカウント(local account)では SAM に保存されます。
  • ドメインアカウント(domain account)では NTDS(NTDS.dit)に保存されます。
  • NTLMv1/NTLMv2 の応答生成や pass-the-hash の前提情報として使われます。
  • ソルト(salt)が無く、同一パスワードは同一 NTHash になります。
  • MD4 はレガシーなハッシュ関数(hash function)であり、オフライン解析(offline cracking)に弱いです。
  • ポリシーで LM/NTLMv1 を無効化し、資格情報の露出を抑える運用が重要です。
[dependencies]
md-4 = "0.10"
hex = "0.4"
use md4::{Digest as Md4Digest, Md4};
fn utf16le_bytes(input: &str) -> Vec<u8> {
let mut out = Vec::with_capacity(input.len() * 2);
for unit in input.encode_utf16() {
out.extend_from_slice(&unit.to_le_bytes());
}
out
}
pub fn nthash(password: &str) -> [u8; 16] {
let mut hasher = Md4::new();
hasher.update(utf16le_bytes(password));
let digest = hasher.finalize();
let mut out = [0u8; 16];
out.copy_from_slice(&digest);
out
}
fn main() {
let nth = nthash("Passw0rd!");
println!("NTHash: {}", hex::encode(nth));
}