Introduction
Is it possible to recover a forgotten password for a Microsoft Office file using automation? The answer is yes, by the brute force via automation/Interop, the multithreading and a lot of quantifiable CPU time.
The main goal of this software is verify the capability of Interop to open the password protected file and also to check when a password is strong enough to resist attacks. But this software can be also used in a real world, to find a forgotten password about your owned files. In fact, it was written to open a file that the owner forgive the exact password.
Where to Get It?
The form with algorithm can be downloaded from here (^) and inserted in a your new Visual Studio project.
Why Use Interop / Automation ?
Microsoft Interop allows developers to manage the MS Office files and makes it easy to create a program that uses brute force to find a forgotten password:
- It works very well on the Microsoft Office documents.
- It's easy to implement.
- It permits to avoid studying the cryptographic algorithm (and its eventually non-standard implementation) or to spend time studying and understanding the file structure of each kind (Excel .xls and .xlsx, Word .doc and .docx and so on).
On the opposite side:
- It's not a time performant on the open file password protected operations.
Software Requirements
To use the software developed by Visual Studio 2017. It is required to have installed the Microsoft Office (or Excel or Word, according to the file type to work on) on the target computer .
If you have the error CS0234 , it means you need to reference the Office library. Open the menu Project, Add reference... and select the tab COM and scroll the list to Microsoft Word 16.0 Object Library or other version you have.
Time Needed to Accomplish the Job
The brute force attack has a predictable amount of time needed to accomplish the job. It can be computed as combinations of ammissible char
s powered by the maximum password testable length.
For example, if we work on a password composed just by uppercase letters and having the length in range between 1 and 6, then we have 26 chars to test, repeating them from 'A
' to 'ZZZZZZ
'.
The total combinations (mathematically more correctly term is dispositions) to be tested are:
- 1 char ('A' to 'Z') : 26 ^ 1 = 26;
- 2 chars ('AA' to 'ZZ': 26 ^ 2 = 676;
- 3 chars ('AAA' to 'ZZZ'): 26 ^ 3 = 17.576;
- 4 chars ('AAAA' to 'ZZZZ'): 26 ^ 4 = 456.976;
- 5 chars ('AAAAA' to 'ZZZZZ'): 26 ^ 5 = 11.881.376;
- 6 chars ('AAAAAA' to 'ZZZZZZ'): 26 ^ 6 = 308.915.776;
The sum is 321.272.406
of possible passwords.
Now, the last step for computing the time, is adding the time factor.
The old hardware used for testing obtained c.a. 1.500 test/minute. Then:
- 321.272.406 combinations / 1.500 test/minute = 214.182 minutes
- 214.182 minutes / 60 min/h = 3.570 hours
- 3.570 hours / 24 h/day = 148 days (or 5 months).
The situation of 148 days in the worst case is represented by 'ZZZZZZ
'. The best one is the password filled by just 'A
' that is immediately tested and found.
It is possible to skip too short a password, starting, for example, from a 4 char length passwords (i.e., 'AAAA
')
Of course, if we know the password length, it's a great improvement about the time we can save.
Reduced combinations avoiding the absolute unlikely password as 'RKWLPG
' or 'TMQNTZ
' (just because those are meaningless, then hard to remember or located in a nonsense order of the keyboards -to the opposite to 'QWERTY' that is it-) is not possible by algorithm and is a concrete risk to jump over the right one.
Standard Set of Chars to be Tested
To complete the information, it is useful to remember the real combinations have to be based on the set of char
s that include all the possibilities. At least:
- lowercase: 'a' to 'z': 26
- uppercase 'A' to 'Z': 26
- numbers: '0' to '9': 10
- special chars: parenthesis (six), space, currency symbols (three or more), interpunctuation (six or more) and other: more than 20.
It sum up to 26+26+10+10 over 70 chars. then, if the password have a size of 5 chars, we obtain 70^1 +70^2 +70 ^3 +70^4 +70^5 =1.680.700.000 possible passwords to test (against 308.915.776 if used a single alphabet set as seen before).
I have to underline this software can useful if it will be used on your files, because you can reduce the complexity of all the possibilities. In fact, you know:
- which
char
set is or is not applicable (for example, if you never used some special char
or the uppercase set, you can exclude them from testing). - the minimum length of the password (for example, if you use password of 8 or more
char
s, it means you start the elaboration from that length saving a lot ot time)
Dreaming More CPU Speed
The test was conducted by a very old Intel i5 760 2.80GHz 4 cores. For those who need performance, around the end of 2018, it is planned processor Intel® Core™ i9 Extreme Edition having 18 cores and 36 threads, with a speed that can be represented by one teraflop (1012 FLOPS): the proposed computation time will be incredibly shrunk. I suppose from 1 month, it became 1 week.
Just to smile if you have no time to wait, now exists a a new supercomputer that can release 200,000 trillion calculations per second (200 petaflops, 200x 1015 FLOPS). I suppose the time will be shortened from a month to a single day or less.
What Can Be Parametrized
The software presented provides the possibility to choose:
- The kind of characters that can be tried to guess the password: uppercase, lowercase, numbers. Actually, special characters are not inserted as available
char
set. - The password length range: the minimum and the maximum length to check: it is very useful to avoid to trash time to verify the too short passwords.
- The number of core to be used: this feature is intended to limit the payload on the CPU, to maintain an every day responsible computer. More, the jobs are executed in a low priority mode, then they don't affect the regular usage.
Using the Code
The software uses a single form, that creates and starts multiple threads: each one loop tests sequentially a password obtained by the function PasswordNext()
until the StopSearch()
is false
. When the password is achieved, a flag will be set by StopSearch(true)
.
Testing Char Set
The set of admitted char
s is defined in the form through some checkboxes and it will be returned by the function AllowedCharsToString()
: actually can manage:
- lowercase letters
- uppercase letters
- numbers
Creating Non Invasive Threads
Brute force is a heavy CPU resource consumer and it transforms the computer in zombie. To allow you to continue to use it in almost normal conditions, the threads are created with a lowest priority. The CPU remains busy to 100% all the time along, but your interaction by other software or works have the priority: the operating system will serve you and will suspend the brute force until necessary.
Below is the code that creates and starts all the threads: they will be inserted in a List<Thread>
to reference them further. The instruction T.Priority
is used to set the thread to the lowest priority.
TTCll = new System.Collections.Generic.List<System.Threading.Thread>();
for (int numt = 0; numt < ThreadToUse; numt++)
{
TextBox NumTxt = (TextBox)(EsecuzioneTLP.Controls
["NumThread" + numt.ToString("00") + "Txt"]);
var T = new System.Threading.Thread(() => { Runner(NumTxt); });
T.Priority = System.Threading.ThreadPriority.Lowest;
T.Start();
TTCll.Add(T);
}
Showing the Running Status
When we face with a very long running loops, it is very important to inform the user that everything is working and is not stuck. The software can use a selectable number of cores, then will be used TableLayoutPanel
in the form that will contain startup generated Labels
and Textboxes
: each one will be bound to a different thread and they will be used to show the currently tested passwords.
int ThreadToUse = int.Parse(MaxTasksTxt.Text);
ThreadPanel_Create(ThreadToUse );
Here, the form when it is running. At the bottom, with a more gray background, is visible the TableLayoutPanel
with four threads numbered from '00
' to '03
', displaying the password they are currently testing: '6K
', '6L
', '6J
', '6M
'.
Suggestions
If you will start a test, remember to disable the sleep/stand by function of your computer, otherwise the day after you could find the computer stopped.
The thread Function: Runner()
The main function, used by each thread, is named Runner()
. Using the parameter NumTxt t
hat is a TextBox
, the loop can update the form about the current password to be tested. That TextBox
was dynamically created in the TableLayoutPanel
.
Creating Instance
The thread creates an instance of the software to be used to try to open the file protected password:
var WApp = new Microsoft.Office.Interop.Word.Application();
The Main Loop
The loop that tests the various possible password is a while
that checks, by StopSearch()
, if the thread must stop because the right password was found.
The function's core call Open()
with a password obtained by PasswordNext()
.
If It is the Right Password
If the tested password can open the file, then the routine performs those steps:
StopSearch(true)
is called to set a flag. Achivied()
is called using the password as parameter to update the user interface.
Then, the resource WDoc
can be released.
try
{
WDoc = WApp.Documents.Open(FileName, PasswordDocument: test , ReadOnly: true);
StopSearch(true);
Achivied(test);
WDoc.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(WDoc);
}
If It is Not the Right One
Calling WApp.Documents.Open()
on a password protected file using a wrong one, raise an exception. This is the reason to wrap that instruction by try
/catch
.
Inside the catch
is not necessary to perform any operation. In fact, WDoc
is null
. In case you want to do something with exception, the ex.Message
string
comparison must be changed according to the language used on the computer.
if (ex.Message.Contains("La password non è corretta. Word non può aprire il documento."))
The Thread Ends
Last job of the routine is to release the Interop instance using the instruction:
ReleaseComObject(WApp);
To make it more robust, the ReleaseComObject()
is backed by a try
/catch
.
Which Password Next?
The function named PasswordNext()
returns the password to be tested next. The first value is 'A
' and will be followed by each single letter to arrive to 'Z
'; after, will starts form 'a
' to 'z
' and '0
' to '9
' (the type of char
s that compose the series come out from AllowedCharsToString().
private char [] PasswordNext()
{
char[] GiveBack;
lock (SyncLockerobjNewPassword)
{
GiveBack = new char[PasswordToVerify.Length];
PasswordToVerify.CopyTo(GiveBack,0);
bool riporto = false;
for (int i = PasswordToVerify.Length - 1; i >= 0; i--)
{
if (PasswordToVerify[i] != AllowedCC[AllowedlattertIdx])
{
PasswordToVerify[i] =
AllowedCC[(ammessistr.IndexOf(PasswordToVerify[i]) + 1)];
riporto = false ;
break;
}
else
{
PasswordToVerify[i] = AllowedCC[0];
riporto = true;
}
}
if ( riporto)
{
char [] tmp = new char[PasswordToVerify.Length ];
PasswordToVerify.CopyTo( tmp,0) ;
PasswordToVerify = new char[PasswordToVerify.Length + 1];
PasswordToVerify[0] = AllowedCC[0];
tmp.CopyTo(PasswordToVerify, 1);
}
}
return GiveBack ;
}
I Got It !
Here, the form at the end of elaboration, when the password is found. It reports information about:
- the last password tested by each thread (it is useless)
- the password found (in this case, is "
AB0
") - the start time
- the end time
- the elapsed time to accomplish the job
The start button remains disabled to prevent the user from inadvertently launching another run. To run another test, the software has to be restarted.
Change File to Target
To use the code against an Excel file, the line to modify is the WApp
declaration, changing it to:
var WApp = new Microsoft.Office.Interop.Excel.Application();
Secondary Points of Interest
For new developer using the TableLayoutPanel
, ThreadPanel_Create()
can be a useful function to understand how to create columns at runtime, inserting controls like Label
and TextBox
. To note this control have always a column.
For who approach the Threading, there is nice example about the creation and synchronization to stop them according to a situation that became true in one of them.
Conclusions
The Microsoft password protection is strong enough if it respects the simple rule of any password: length (more than 8 chars), the usage of a large set of chars: uppercase and lowercase, numbers and special char
s. But if you are looking for your lost password, you have a good change to recover it. If you are not in hurry, of course!
History
- 14th June, 2018: Initial version