We continue publishing set of articles about interesting technology areas and solutions we have implemented or encountered in our projects.
This article briefly describes our experience in implementing MS Outlook storage (.pst) encryption through file virtualization using BoxedApp.
Encrypt data which MS Outlook stores in .pst files.
Outlook has possibility to use password protection for storage files, but it is not secure and can be easily broken, for example by such utility http://www.nirsoft.net/utils/pst_password.html
Also Outlook provides API to handle events when user performs some operations with entities – creates, changes, receives, deletes and so on. But such possibilities were not enough for our task – processing on deeper level was required.
In order to encrypt data of personal storage files direct access to bytes which Outlook reads/writes was needed. At first we tried to hook standard Win32 API functions which work with files: CreateFile, ReadFile, WriteFile. But after some experiments we found that it’s not enough – read/write operations of Outlook were not handled. After some additional researches it was determined that Outlook is using mapping of file into memory with Win32 API CreateFileMapping and MapViewOfFile.
Under these circumstances there was no fast and easy way to capture read/write operations so it was made decision to try using BoxedApp.
After studying possibilities of BoxedApp was found that it provides solution for our problem by method
HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileBasedOnIStreamW( LPCWSTR szPath, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, LPSTREAM pStream )
It allows passing of own implementation of interface IStream for callbacks on read-write operations.
As a result all what had to be done is to implement IStream and put all encryption operations just in two methods:
virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead); virtual HRESULT STDMETHODCALLTYPE Write(const void* pv, ULONG cb, ULONG* pcbWritten);
and correctly implement some data navigation methods:
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pstatstg, DWORD grfStatFlag); virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition); virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize);
We got access to all bytes which Outlook was reading/writing and successfully implemented encryption/decryption.