1PasswordSuite
Blog
https://posts.specterops.io/1password-secret-retrieval-methodology-and-implementation-6a9db3f3c709
1PasswordExtract
This .NET application is built on the same version of the CLR (4.7.2) the latest 1Password binary uses at the time of upload (8/13/21). This binary gets function pointers to various critical functions responsible for decrypting secrets within the 1Password SQLite database and waits until the 1Password application is unlocked by the user. Once unlocked, it writes the results as a JSON array to C:\Users\Public\1Password.log for you to view and parse.
1PasswordInject
This unmanaged application acquires a process handle to the 1Password process and adjusts the Discretionary Access Control List (DACL) on it to allow for full access rights to the process. Once those access rights have been adjusted, a new handle is opened with PROCESS_ALL_ACCESS
to inject the 1PasswordExtract shellcode blob generated by @TheWover's donut. This shellcode is embedded as a byte array in the RawData.h
header if you choose to modify the 1PasswordExtract code.
sc.py
Simple python script that leverages @TheWover's donut to generate shellcode from a .NET binary. This is placed into loader.bin
, which is then copied as a C byte array into RawData.h
of 1PasswordInject
. This process is manual and not automated at this time, meaning you'll need to copy paste this shellcode into the header file yourself if you choose to make modifications.
Future Development
There's more to look at here. Not included in this project is a way to retrieve the user's proxy credentials from the application. Other avenues that have been explored in the past (but not currently verified) is the retrieval of the master password. Lastly, the ability to decrypt the SQLite database directly instead of using injection is promising, but since this works, I chose to stop working on it any further.
Special Thanks
- @tifkin, for helping me figure out why I couldn't acquire a process handle to 1Password.