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.
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.
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
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.
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.
- @tifkin, for helping me figure out why I couldn't acquire a process handle to 1Password.