tinyapps.org / docs / Cracking Microsoft Office password protection via hashcat, locally or in the cloud


This guide covers cracking a password-protected DOCX file1 created with Word for Mac 2011 (which employs the same protection algorithm as Microsoft Word 2010). It also largely applies to cracking any hash supported by hashcat (MD5, SHA1, NTLM, etc).

1. Cracking locally

Test platform: a wildly unsuitable mid-2010 iMac with an Intel Core i3 processor and 256MB ATI Radeon HD 4670 graphics card, running macOS 10.12. We won't bother attempting a brute force / mask attack, since even a simple 6-character lowercase password could take as long as 19 years to crack on this hardware.

1.1 Retrieve hash

Download and run office2hashcat.py to retrieve and save the encrypted hash of our password-protected Word document (foo.docx) to hash.txt:2

$ office2hashcat.py foo.docx > hash.txt
$ cat hash.txt
$office$*2010*100000*128*16*a1688e8975694550a7a61b5...

The hash is identified as MS Office 2010, which is assigned the hash mode number 9500 by hashcat (see hashcat --help for a list of all hash modes).

1.2 Get hashcat and OpenCL-Headers

$ git clone https://github.com/hashcat/hashcat.git
$ cd hashcat
$ git submodule update --init
$ make

1.3 Get wordlist

Download merged.txt.tar.gz from Daniel Miessler's SecLists/Passwords and extract to merged.txt:

$ curl -LO https://github.com/danielmiessler/SecLists/raw/601038eb4ea18c97177b43a757286d3c8a815db8/Passwords/merged.txt.tar.gz
$ tar xf merged.txt.tar.gz

1.4 Start cracking

We'll pass the following arguments to hashcat:

-a 0 = set attack mode to straight / dictionary attack
-m 9500 = set hash mode to MS Office 2010
--status = automatically update status screen
-o found.txt = output recovered password to found.txt
hash.txt = the hash we saved in step 1.1
merged.txt = our wordlist from step 1.3

$ ./hashcat -a 0 -m 9500 --status -o found.txt hash.txt merged.txt

Here's the output:

hashcat (v3.6.0-386-gc8da13c3) starting...

* Device #2: This device does not support base atomics.

* Device #2: This device does not support byte-addressable store.

* Device #2: This device's local mem size is too small.

No devices found/left.

Started: Thu Aug 17 23:08:08 2017
Stopped: Thu Aug 17 23:08:08 2017

What happened? The GPU is unsupported3 and hashcat halts immediately. We can force hashcat to use the CPU with --opencl-device-types 1:

$ ./hashcat -a 0 -m 9500 --opencl-device-types 1 --status -o found.txt hash.txt merged.txt

which cracked the hash for what turned out to be a 6 character lowercase password in about 12.5 hours:

Session..........: hashcat
Status...........: Cracked
Hash.Type........: MS Office 2010
Hash.Target......: $office$*2010*100000*128*16*a1688e8975694550a7a61b5...2ed49a
Time.Started.....: Thu Aug 17 23:09:08 2017 (12 hours, 27 mins)
Time.Estimated...: Fri Aug 18 11:36:44 2017 (0 secs)
Guess.Base.......: File (merged.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.Dev.#1.....:      352 H/s (7.32ms)
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 15771648/19922208 (79.17%)
Rejected.........: 0/15771648 (0.00%)
Restore.Point....: 15770624/19922208 (79.16%)
Candidates.#1....: piccia2 -> pichincho

Started: Thu Aug 17 23:08:59 2017
Stopped: Fri Aug 18 11:36:45 2017

2. Cracking in the cloud

Test platform: An Amazon AWS EC2 P2 instance sporting 16 NVIDIA Tesla K80 GPUs, totaling 192GB of video memory. Since we'll have a smidge more computing power this time, let's test both dictionary and brute force attacks.

2.1 Create AWS EC2 p2.16xlarge instance

  1. Sign in to AWS account
  2. Services > Compute > EC2
  3. "Launch Instance"
  4. Quick Start > scroll down to "Ubuntu Server 16.04 LTS (HVM), SSD Volume Type - ami-6e1a0117" > Select
  5. Scroll down to "p2.16xlarge" > click the checkbox next to "GPU compute" > "Review and Launch"4
  6. Launch
  7. "Create a new key pair" > assign a key pair name (e.g., "p2xl") > "Download Key Pair" > p2xl.pem.txt will be downloaded
  8. "Launch Instances"

2.2 Enable inbound SSH and connect from Mac

  1. Services > Computer > EC2 > Resources > Security Groups > default > Inbound > Edit
  2. Type: SSH, Source: My IP > Save
  3. EC2 Dashboard > Running Instances
  4. Note your Public DNS
  5. On the Mac:
    $ mv p2xl.pem.txt p2xl.pem
    $ chmod 400 p2xl.pem
    $ ssh -i p2xl.pem ubuntu@YOUR_PUBLIC_DNS

2.3 Setup server

2.3.1 Update Ubuntu

$ sudo apt-get update && sudo apt-get install build-essential linux-image-extra-virtual

2.3.2 Disable Nouveau driver

$ echo "blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off" | sudo tee -a /etc/modprobe.d/blacklist-nouveau.conf >/dev/null
$ echo options nouveau modeset=0 | sudo tee -a /etc/modprobe.d/nouveau-kms.conf >/dev/null
$ sudo update-initramfs -u

2.3.3 Install NVIDIA driver

$ sudo apt-get install linux-source linux-headers-`uname -r`
$ wget http://us.download.nvidia.com/XFree86/Linux-x86_64/384.59/NVIDIA-Linux-x86_64-384.59.run
$ chmod +x NVIDIA-Linux-x86_64-384.59.run
$ sudo ./NVIDIA-Linux-x86_64-384.59.run
$ sudo reboot

2.3.4 Optimize GPU settings

$ sudo nvidia-smi -pm 1
$ sudo nvidia-smi -acp 0
$ sudo nvidia-smi --auto-boost-permission=0
$ sudo nvidia-smi -ac 2505,875

2.4 Get hashcat, OpenCL-Headers, and wordlist

$ git clone https://github.com/hashcat/hashcat.git
$ cd hashcat/
$ git submodule update --init
$ make
$ wget https://github.com/danielmiessler/SecLists/raw/601038eb4ea18c97177b43a757286d3c8a815db8/Passwords/merged.txt.tar.gz
$ tar xf merged.txt.tar.gz

2.5 Upload hash from Mac to p2.16xlarge instance

  1. Retrieve DOCX hash locally as explained in section 1.1 above (Why risk sending a potentially sensitive document into the cloud?)
  2. $ scp -i p2xl.pem hash.txt ubuntu@YOUR_PUBLIC_DNS:~/hashcat/

2.6 Dictionary / wordlist / straight attack

(Options and arguments explained in section 1.4 above)

$ ./hashcat -a 0 -m 9500 --status -o found.txt hash.txt merged.txt

A touch faster than the iMac:

Session..........: hashcat
Status...........: Cracked
Hash.Type........: MS Office 2010
Hash.Target......: $office$*2010*100000*128*16*a1688e8975694550a7a61b5...2ed49a
Time.Started.....: Tue Aug 22 05:31:34 2017 (1 min, 21 secs)
Time.Estimated...: Tue Aug 22 05:32:55 2017 (0 secs)
Guess.Base.......: File (merged.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.Dev.#1.....:    13195 H/s (10.22ms)
Speed.Dev.#2.....:    13193 H/s (11.03ms)
Speed.Dev.#3.....:    14517 H/s (10.16ms)
Speed.Dev.#4.....:    13196 H/s (11.21ms)
Speed.Dev.#5.....:    14514 H/s (10.02ms)
Speed.Dev.#6.....:    13196 H/s (10.83ms)
Speed.Dev.#7.....:    14515 H/s (10.17ms)
Speed.Dev.#8.....:    13195 H/s (10.77ms)
Speed.Dev.#9.....:    14518 H/s (10.20ms)
Speed.Dev.#10.....:    13199 H/s (10.79ms)
Speed.Dev.#11.....:    13196 H/s (10.42ms)
Speed.Dev.#12.....:    13198 H/s (10.60ms)
Speed.Dev.#13.....:    13197 H/s (10.56ms)
Speed.Dev.#14.....:    13202 H/s (10.94ms)
Speed.Dev.#15.....:    13203 H/s (10.75ms)
Speed.Dev.#16.....:    13204 H/s (10.64ms)
Speed.Dev.#*.....:   216.4 kH/s
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 17465344/19922208 (87.67%)
Rejected.........: 0/17465344 (0.00%)
Restore.Point....: 14163968/19922208 (71.10%)
Candidates.#1....: phretts -> playa#11
Candidates.#2....: s421 -> samsloanolp
Candidates.#3....: senaatsvergaderings -> shamalagu
Candidates.#4....: samslone -> scanteea
Candidates.#5....: scanteesorin -> senaatsvergadering
Candidates.#6....: redblows1 -> rhinoqueen
Candidates.#7....: shamalah -> shuff1
Candidates.#8....: rhinorac -> robduber
Candidates.#9....: shuff13 -> skinheaw2
Candidates.#10....: robdukes3 -> roxacxx
Candidates.#11....: playa#16$ -> posada25
Candidates.#12....: quarry55 -> ralysia1
Candidates.#13....: posada2526 -> pse64911
Candidates.#14....: roxad03 -> s420k818
Candidates.#15....: pse731 -> quarry420
Candidates.#16....: ralyy -> redblossom123
HWMon.Dev.#1.....: Temp: 76c Util: 99% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#2.....: Temp: 65c Util: 98% Core: 784MHz Mem:2505MHz Bus:16
HWMon.Dev.#3.....: Temp: 82c Util: 99% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#4.....: Temp: 71c Util: 99% Core: 771MHz Mem:2505MHz Bus:16
HWMon.Dev.#5.....: Temp: 79c Util: 97% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#6.....: Temp: 65c Util: 99% Core: 797MHz Mem:2505MHz Bus:16
HWMon.Dev.#7.....: Temp: 78c Util: 99% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#8.....: Temp: 69c Util: 88% Core: 810MHz Mem:2505MHz Bus:16
HWMon.Dev.#9.....: Temp: 78c Util: 99% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#10.....: Temp: 65c Util: 99% Core: 849MHz Mem:2505MHz Bus:16
HWMon.Dev.#11.....: Temp: 78c Util: 99% Core: 823MHz Mem:2505MHz Bus:16
HWMon.Dev.#12.....: Temp: 66c Util:100% Core: 849MHz Mem:2505MHz Bus:16
HWMon.Dev.#13.....: Temp: 81c Util: 99% Core: 849MHz Mem:2505MHz Bus:16
HWMon.Dev.#14.....: Temp: 66c Util: 99% Core: 797MHz Mem:2505MHz Bus:16
HWMon.Dev.#15.....: Temp: 79c Util: 99% Core: 810MHz Mem:2505MHz Bus:16
HWMon.Dev.#16.....: Temp: 66c Util:100% Core: 797MHz Mem:2505MHz Bus:16

Started: Tue Aug 22 05:30:32 2017
Stopped: Tue Aug 22 05:32:59 2017

2.7 Brute-force / mask attack

We'll cheat a bit and restrict the attack to a maximum of just 8 lowercase letters. Arguments that differ from section 1.4 above:

-a 3 = set attack mode to brute-force / mask
?l?l?l?l?l?l?l?l = set mask to 8 lowercase letters
--increment = start with 1 character and attack up to max of 8 set by mask

$ ./hashcat -m 9500 --status -o found.txt hash.txt -a 3 ?l?l?l?l?l?l?l?l --increment

Not much longer than the dictionary attack:

Session..........: hashcat
Status...........: Cracked
Hash.Type........: MS Office 2010
Hash.Target......: $office$*2010*100000*128*16*a1688e8975694550a7a61b5...2ed49a
Time.Started.....: Tue Aug 22 05:47:55 2017 (50 secs)
Time.Estimated...: Tue Aug 22 05:48:45 2017 (0 secs)
Guess.Mask.......: ?l?l?l?l?l?l [6]
Guess.Queue......: 6/8 (75.00%)
Speed.Dev.#1.....:    12866 H/s (10.22ms)
Speed.Dev.#2.....:    12900 H/s (10.95ms)
Speed.Dev.#3.....:    15383 H/s (10.11ms)
Speed.Dev.#4.....:    12940 H/s (10.82ms)
Speed.Dev.#5.....:    15303 H/s (9.94ms)
Speed.Dev.#6.....:    12873 H/s (10.61ms)
Speed.Dev.#7.....:    15380 H/s (10.10ms)
Speed.Dev.#8.....:    12880 H/s (10.59ms)
Speed.Dev.#9.....:    12832 H/s (10.10ms)
Speed.Dev.#10.....:    12857 H/s (10.32ms)
Speed.Dev.#11.....:    12873 H/s (10.43ms)
Speed.Dev.#12.....:    12847 H/s (10.56ms)
Speed.Dev.#13.....:    12861 H/s (10.56ms)
Speed.Dev.#14.....:    12879 H/s (10.76ms)
Speed.Dev.#15.....:    12888 H/s (10.76ms)
Speed.Dev.#16.....:    12866 H/s (10.58ms)
Speed.Dev.#*.....:   213.4 kH/s
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 10543104/308915776 (3.41%)
Rejected.........: 0/10543104 (0.00%)
Restore.Point....: 0/11881376 (0.00%)
Candidates.#1....: parier -> pqppon
Candidates.#2....: pakdje -> pqxgen
Candidates.#3....: laedpo -> lqtywa
Candidates.#4....: paiool -> pqyhch
Candidates.#5....: laduwa -> lqfnit
Candidates.#6....: pajcka -> pqrbbe
Candidates.#7....: lappon -> lqatce
Candidates.#8....: pammra -> pqnawo
Candidates.#9....: pazius -> pqmbxx
Candidates.#10....: pasuon -> pqkyel
Candidates.#11....: pawswa -> pqirse
Candidates.#12....: paouga -> pqlrhi
Candidates.#13....: papfys -> pqajdi
Candidates.#14....: pabsme -> pqzlge
Candidates.#15....: parjal -> pqpfys
Candidates.#16....: pamvdi -> pqnxju
HWMon.Dev.#1.....: Temp: 73c Util: 97% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#2.....: Temp: 59c Util: 99% Core: 797MHz Mem:2505MHz Bus:16
HWMon.Dev.#3.....: Temp: 77c Util: 97% Core: 849MHz Mem:2505MHz Bus:16
HWMon.Dev.#4.....: Temp: 65c Util: 97% Core: 797MHz Mem:2505MHz Bus:16
HWMon.Dev.#5.....: Temp: 75c Util: 97% Core: 849MHz Mem:2505MHz Bus:16
HWMon.Dev.#6.....: Temp: 59c Util: 97% Core: 810MHz Mem:2505MHz Bus:16
HWMon.Dev.#7.....: Temp: 75c Util: 80% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#8.....: Temp: 63c Util: 97% Core: 875MHz Mem:2505MHz Bus:16
HWMon.Dev.#9.....: Temp: 76c Util: 76% Core: 849MHz Mem:2505MHz Bus:16
HWMon.Dev.#10.....: Temp: 59c Util: 74% Core: 862MHz Mem:2505MHz Bus:16
HWMon.Dev.#11.....: Temp: 76c Util: 96% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#12.....: Temp: 61c Util: 97% Core: 810MHz Mem:2505MHz Bus:16
HWMon.Dev.#13.....: Temp: 80c Util: 97% Core: 849MHz Mem:2505MHz Bus:16
HWMon.Dev.#14.....: Temp: 61c Util: 85% Core: 836MHz Mem:2505MHz Bus:16
HWMon.Dev.#15.....: Temp: 78c Util: 97% Core: 810MHz Mem:2505MHz Bus:16
HWMon.Dev.#16.....: Temp: 61c Util: 70% Core: 875MHz Mem:2505MHz Bus:16

Started: Tue Aug 22 05:44:38 2017
Stopped: Tue Aug 22 05:48:50 2017

2.8 Terminate instance

  1. Services > Compute > EC2 > Running Instances
  2. Highlight your p2.16xlarge instance
  3. Actions > Instance State > Terminate > "Yes, Terminate"

3. Footnotes

  1. Unrelated to the trivial "Restrict Editing" or "locking" feature.

  2. Or use office2john.py, but you'll then need to specify --username in the command line arguments to ignore the filename and colon that office2john prepends to the output.

  3. A cursory attempt at tweaking /hashcat/src/opencl.c by removing the if statements for base atomics, byte-addressable store, and local mem size did indeed allow the GPU to be utilized along with the CPU, halving the run time. Alas, the result was less than desirable:

    Session..........: hashcat                                
    Status...........: Exhausted
    Hash.Type........: MS Office 2010
    Hash.Target......: $office$*2010*100000*128*16*a1688e8975694550a7a61b5...2ed49a
    Time.Started.....: Sun Aug 20 14:50:19 2017 (8 hours, 17 mins)
    Time.Estimated...: Sun Aug 20 23:07:33 2017 (0 secs)
    Guess.Base.......: File (merged.txt)
    Guess.Queue......: 1/1 (100.00%)
    Speed.Dev.#1.....:      236 H/s (0.25ms)
    Speed.Dev.#2.....:      329 H/s (6.56ms)
    Speed.Dev.#*.....:      565 H/s
    Recovered........: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
  4. For a lengthier process (albeit with more options, including Security Groups), click "Next: Configure Instance Details" instead.

4. Sources

5. More info

Cloud-based hash cracking

Microsoft Office Encryption

Wordlists

OpenCL


created: 2017.08.22, updated: 2017.08.23