Skip to content

dmg: support AES-encrypted v2 key blobs - #6029

Open
kholia wants to merge 1 commit into
openwall:bleeding-jumbofrom
kholia:better-dmg-support
Open

kholia wants to merge 1 commit into
openwall:bleeding-jumbofrom
kholia:better-dmg-support

Conversation

@kholia

@kholia kholia commented Aug 13, 2026 •

Copy link
Copy Markdown
Member

Recent macOS releases can wrap v2 DMG key blobs with AES-192-CBC (CSSM_ALGID_AES) instead of 3DES. Teach both extractors to recognize this parameter set and emit a compact $dmg$3 hash, while rejecting unknown blob encryption combinations.

Add CPU and OpenCL verification by decrypting the final key-blob block and checking the CKIE marker and PKCS#7 padding. Include a known-password test vector and retain existing v1/v2 behavior.

Fixes #6028

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for modern macOS DMG v2 key blobs that are wrapped with AES-192-CBC (CSSM_ALGID_AES) by introducing a new compact $dmg$3 hash representation, updating both C and Python extractors to emit it (and reject unsupported parameter sets), and extending both CPU and OpenCL crackers with a verification step that decrypts the final key-blob block and checks for the CKIE marker plus PKCS#7 padding.

Changes:

  • Add $dmg$3 parsing and verification to both CPU (dmg_fmt) and OpenCL (opencl_dmg) formats.
  • Update dmg2john (C and Python) to detect AES-wrapped v2 key blobs, emit $dmg$3, and reject unknown blob-encryption combinations.
  • Add a known-password $dmg$3 test vector to prevent regressions.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/opencl_dmg_fmt_plug.c Extends OpenCL DMG format to accept headerver=3 and run a new dmg_final_v3 kernel; expands stored encrypted keyblob and carries key-bits.
src/dmg2john.c Detects AES-192-CBC-wrapped v2 blobs, emits $dmg$3, and errors out for unsupported blob-encryption parameter sets.
src/dmg_fmt_plug.c Adds $dmg$3 parsing and CPU-side verification by decrypting the last keyblob block and checking CKIE + PKCS#7 padding.
src/dmg_common_plug.c Adds a $dmg$3 test vector using the known password d3fc0n.
run/opencl/dmg_kernel.cl Adds OpenCL check_v3hash() and a new dmg_final_v3 kernel implementing the same last-block verification logic.
run/dmg2john.py Updates v2 header unpacking, detects AES-wrapped blobs, emits $dmg$3, and rejects unsupported blob-encryption parameter sets.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/dmg_common_plug.c Outdated
Comment thread src/dmg_fmt_plug.c
Comment thread run/opencl/dmg_kernel.cl
@openwall openwall temporarily blocked GraceWaddell Sep 21, 2026
@openwall openwall deleted a comment from GraceWaddell Sep 21, 2026
@kholia
kholia requested a review from solardiz September 26, 2026 11:40
@kholia

kholia commented Sep 30, 2026

Copy link
Copy Markdown
Member Author

The CI jobs are running into following 'prompt stalls':

Screenshot 2026-09-30 at 10 52 37 AM

@kholia
kholia force-pushed the better-dmg-support branch 2 times, most recently from 463222b to 9b25e02 Compare September 30, 2026 05:35
@kholia

kholia commented Sep 30, 2026

Copy link
Copy Markdown
Member Author

Patch to fix the apt prompt stalls problem:

diff --git a/.circleci/config.yml b/.circleci/config.yml
index 05d9ca0ba..0a1c7bba5 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -97,16 +97,16 @@ jobs:
   arm:
     machine:
       image: ubuntu-2204:current
-      environment:
-        DEBIAN_FRONTEND: "noninteractive"
     resource_class: arm.medium
+    environment:
+      DEBIAN_FRONTEND: "noninteractive"
     steps:
       - checkout
       - run:
           name: Preparing
           command: |
             uname -a
-            sudo apt update && sudo apt install -y zlib1g-dev libgmp-dev libpcap-dev libbz2-dev
+            sudo DEBIAN_FRONTEND=noninteractive apt update && sudo DEBIAN_FRONTEND=noninteractive apt install -y zlib1g-dev libgmp-dev libpcap-dev libbz2-dev

This change has been added to this PR to let the CI testing pass.

@solardiz solardiz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can merge this early - we need to get working CI for merging other PRs. My review feedback may be addressed separately. But it'd be good to move the added test vector to the end before we merge.

Comment thread src/dmg_common_plug.c Outdated
Comment thread src/dmg_fmt_plug.c Outdated
@kholia

kholia commented Sep 30, 2026

Copy link
Copy Markdown
Member Author

@solardiz I will open a new small PR to fix the CI pipeline(s) now and then we can work on this bigger PR later.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread run/dmg2john.py Outdated
Comment thread src/dmg2john.c
@kholia
kholia force-pushed the better-dmg-support branch from cdb68a1 to 542d7d9 Compare October 10, 2026 09:19
Recent macOS releases can wrap v2 DMG key blobs with AES-192-CBC
(CSSM_ALGID_AES) instead of 3DES. Teach both extractors to recognize this
parameter set and emit a compact $dmg$3 hash, while rejecting unknown blob
encryption combinations.

Add CPU and OpenCL verification by decrypting the final key-blob block and
checking the CKIE marker and PKCS#7 padding. Include a known-password test
vector and retain existing v1/v2 behavior.
@kholia
kholia force-pushed the better-dmg-support branch from 542d7d9 to b0cf3b7 Compare October 10, 2026 09:22
skippdot added a commit to skippdot/hashcat that referenced this pull request Oct 11, 2026
Modern macOS wraps the v2 disk-image key blob with AES-192-CBC (CSSM_ALGID_AES)
instead of 3DES, which no existing hashcat mode handles (issue hashcat#3774).

Verification derives a 24-byte KEK via PBKDF2-HMAC-SHA1, CBC-decrypts the final
key-blob block and checks for the "CKIE" marker followed by PKCS#7 padding.
aes192_decrypt returns little-endian output words here, so the marker and padding
are matched in that byte order only.

The identity digest is MD5 of the whole key blob, computed identically by the
decoder and reported by the comp kernel, so distinct blobs that share a salt and
a leading ciphertext block are not aliased in dedup/potfile.

- src/modules/module_38300.c: parse $dmg$3; validate declared salt length,
  AES-192 key bits and blob length; fixed 20-byte salt bounds; reuse the
  PBKDF2-HMAC-SHA1 init/loop from mode 24410; 64-byte esalt key blob.
- OpenCL/m38300-pure.cl: AES-192 key-blob unwrap + CKIE/PKCS#7 check in comp.
- tools/test_modules/m38300.py: edge coverage; the oracle re-derives the KEK and
  only reuses a blob that matches the candidate.

Hashes are produced by dmg2john from John the Ripper PR #6029 (openwall/john#6029).
skippdot added a commit to skippdot/hashcat that referenced this pull request Oct 12, 2026
Modern macOS wraps the v2 disk-image key blob with AES-192-CBC (CSSM_ALGID_AES)
instead of 3DES, which no existing hashcat mode handles (issue hashcat#3774).

Verification derives a 24-byte KEK via PBKDF2-HMAC-SHA1, CBC-decrypts the final
key-blob block and checks for the "CKIE" marker followed by PKCS#7 padding.
aes192_decrypt returns little-endian output words here, so the marker and padding
are matched in that byte order only.

The identity digest is MD5 of the whole key blob, computed identically by the
decoder and reported by the comp kernel, so distinct blobs that share a salt and
a leading ciphertext block are not aliased in dedup/potfile.

- src/modules/module_38300.c: parse $dmg$3; validate declared salt length,
  AES-192 key bits and blob length; fixed 20-byte salt bounds; reuse the
  PBKDF2-HMAC-SHA1 init/loop from mode 24410; 64-byte esalt key blob.
- OpenCL/m38300-pure.cl: AES-192 key-blob unwrap + CKIE/PKCS#7 check in comp.
- tools/test_modules/m38300.py: edge coverage; the oracle re-derives the KEK and
  only reuses a blob that matches the candidate.

Hashes are produced by dmg2john from John the Ripper PR #6029 (openwall/john#6029).
jsteube pushed a commit to hashcat/hashcat that referenced this pull request Oct 12, 2026
Modern macOS wraps the v2 disk-image key blob with AES-192-CBC (CSSM_ALGID_AES)
instead of 3DES, which no existing hashcat mode handles (issue #3774).

Verification derives a 24-byte KEK via PBKDF2-HMAC-SHA1, CBC-decrypts the final
key-blob block and checks for the "CKIE" marker followed by PKCS#7 padding.
aes192_decrypt returns little-endian output words here, so the marker and padding
are matched in that byte order only.

The identity digest is MD5 of the whole key blob, computed identically by the
decoder and reported by the comp kernel, so distinct blobs that share a salt and
a leading ciphertext block are not aliased in dedup/potfile.

- src/modules/module_38300.c: parse $dmg$3; validate declared salt length,
  AES-192 key bits and blob length; fixed 20-byte salt bounds; reuse the
  PBKDF2-HMAC-SHA1 init/loop from mode 24410; 64-byte esalt key blob.
- OpenCL/m38300-pure.cl: AES-192 key-blob unwrap + CKIE/PKCS#7 check in comp.
- tools/test_modules/m38300.py: edge coverage; the oracle re-derives the KEK and
  only reuses a blob that matches the candidate.

Hashes are produced by dmg2john from John the Ripper PR #6029 (openwall/john#6029).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dmg2john extracts uncrackable hashes from current DMG files

4 participants