Recovering Lupa's back up file password.
A friend of mine is using the authoring software Lupa to create a family album. Lupa helps you author albums and then receive a printed copy of the album you created in the software. The software is given for free. Lupa makes its business from the printed albums people order.
My friend then used Lupa's backup feature to back-up his work. He noticed the Lupa back-up file is actually a zip file! He was happy, because that meant that he now had one zip with all the content he created. As he was the one that created the content, it seems logical that he can export it, and use it as he wants to.
Unfortunately, the zip file was password protected! That's when my friend called me to assist him. So we went on to discover the lost password of the zip file!
When you look at lupa's folder, you notice a file called delzip179.dll:
When you look at this dll in depends, you see the interesting Dz_UnzExec function. Interesting!!
When we open the backup file created using Lupa, it will probably use this function to unzip it, and provide it with the password as input. A quick test with windbg, confirms that this function is indeed used, so the question that remaines is where is the password?!
Now instead of opening IDA and trying to figure this out the hard way, we googled this DLL. apparently it's open source! Took us a little while to find a not broken link to the sources, but eventually, we got the signature of the function. It received one parameter, a struct named UnZipParms:
typedef struct
{
HWND fHandle;
void *fCaller;
long fVersion;
ZFunctionPtrType ZCallbackFunc;
BOOL fTraceEnabled;
unsigned fWantedCodePage;
unsigned fPromptToOverwrite;
char *pZipPassword;
BOOL fTest;
BOOL fComments;
BOOL fConvert;
BOOL fQuiet;
BOOL fVerboseEnabled;
BOOL fUpdate;
BOOL fFreshen;
BOOL fDirectories;
BOOL fOverwrite;
long fArgc;
char *pZipFN;
UnzFileData *fUFDS;
struct UnzExFileData *fXUDFS;
BOOL fUseOutStream; // Use Memory stream as output.
void *fOutStream; // Pointer to the start of streaam data.
unsigned long fOutStreamSize; // Size of the output data.
BOOL fUseInStream; // Use memory stream as input.
void *fInStream; // Pointer to the start of the input stream data.
unsigned long fInStreamSize; // Size of the input data.
unsigned long fPwdReqCount; // PasswordRequestCount, How many times a password will be asked per file
char *fExtractDir;
long fNotUsed[8];
long fSeven;
}UnZipParms;
Do notice the 7th parameter, called pZipPassword. Bingo!
Now, all that is left to do, is to open lupa, attach windbg to it and get the password and:
Wait for the zip to load: *sxe ld delzip179*
Open the backup file in Lupa
Print the password: *bp delzip179!DZ_UnzExec "db poi(poi(esp+4)+1c)"*
break on the unzip function
dereference (poi) the first parameter
then dereference the 7th (7*4=28 = 0x1c) member in that structure
display the bytes in that address.
(windbg commands are bold and italic)
This revealed the password:
As you may notice, it is a 22 bytes binary password (in hex: "6c 6b 32 33 33 f6 30 2c 2e 6c 6f 70 32 65 73 33 33 33 34 fb fc df"
). We tried to copy (programmatically) and paste it to winzip, and that didnt work. So we used python's zipfile module, that did the job just fine, and extracted the files inside the zip.
My friend had hoped to see XML files there, but unfortunately for him, this was not the case... Anyway the rest is left for him to figure out ;-)
Note that we found the password hardcoded in the EXE. this makes sense - as Lupa can open backup files that other people made. This probably means that the password is the same for all Lupa's out there. Not even sure of what's the point of encryption here... even DRM is no excuse, as the content does not belong to them... Do they try to protect the user's data from the user himself?!
This was relatively an easy task, but any program that tries to hide\encrypt data that belongs to user from the user himself can be cracked. that's a fact... so why even bother with it?