int main(int argc, char *argv[]) { if( argc < 2 ) { std::cout << "Usage:" << std::endl; std::cout << argv[0] << " filename [stream-name [output-file]]" << std::endl; return 0; } char* filename = argv[1]; char* streamname = (argc<3) ? 0 : argv[2]; char* outfile = (argc<4) ? 0 : argv[3]; POLE::Storage* storage = new POLE::Storage( filename ); storage->open(); if( storage->result() != POLE::Storage::Ok ) { std::cout << "Error on file " << filename << std::endl; return 1; } if( !streamname ) visit( 0, storage, "/" ); else if( !outfile ) dump( storage, streamname ); else extract( storage, streamname, outfile ); delete storage; return 0; }
// Extract encryption data from Microsoft Word file // Place 48 bytes at record_out: // 16 byte Salt, followed by // 16 byte EncryptedVerifier, followed by // 16 byte EncryptedVerifierHash extern "C" void extract_doc(const char *file_name, unsigned char *record_out) { int n; // Used for number of bytes read POLE::Storage* storage = new POLE::Storage(file_name ); storage->open(); if( storage->result() != POLE::Storage::Ok ) { std::cout << "Error on file " << std::endl; exit(1); return; } // Check File Information Block to see if document is encrypted POLE::Stream* stream = new POLE::Stream( storage, "WordDocument" ); if (!stream || stream->fail() ) { std::cerr << "Could not open WordDocument stream\n"; exit(1); } // FibBase should be at the beginning of the WordDocument stream unsigned char wIdent[2]; n = stream->read(wIdent, 2); if (n != 2) return; if (! (wIdent[0] == 0xEC && wIdent[1] == 0xA5 )) { std::cerr << "FibBase not found\n"; exit(1); return; } // fEncrypted is in 12th byte of FibBase. 2 bytes have been read // already and 12 = 2 + 10. unsigned char byte; for (int i = 1; i <= 10; i++) { n = stream->read(&byte, 1); if (n != 1) { std::cerr << "Error reading FibBase\n"; exit(1); } } if ((byte & 0x01) == 0) { std::cerr << "File is not encrypted\n"; exit(1); } // Look for encryption header in 1Table or 0Table stream // See http://msdn.microsoft.com/en-us/library/dd923367(v=office.12).aspx // and http://msdn.microsoft.com/en-us/library/dd908560(v=office.12).aspx delete stream; stream = new POLE::Stream( storage, "1Table" ); if (!stream || stream->fail() ) { stream = new POLE::Stream( storage, "0Table" ); } if (!stream || stream->fail() ) { std::cerr << "Couldn't open 1Table or 0Table stream\n"; exit(1); } unsigned char EncryptionHeader[52]; n = stream->read(EncryptionHeader, 52); memcpy(record_out, EncryptionHeader + 4, 48); }