home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR8 / WORDUNP.ZIP / WU.CPP < prev    next >
C/C++ Source or Header  |  1993-01-26  |  6KB  |  220 lines

  1. // wu.cpp        -- Unprotect Microsoft Word/Winword Document
  2.  
  3.  
  4. //    Marc Thibault <marc@tanda.isis.org>
  5.  
  6. // Word protects a document by XOR'ing a 16-byte key repetitively
  7. //    through the document file, starting at byte 40. The header (0x180 bytes)
  8. //    is filthy with zeros including what appears to be over 48 of them at
  9. //    the end of the header. This program hopes that the last 32 are zeros
  10. //    (it checks) and extracts the key from this area. Improvements can be
  11. //    made to this if it ever turns out that these bytes are used for
  12. //    something.
  13.  
  14. // The encryption key is derived from the user's passphrase by some means
  15. //  I have not attempted to discover. It is unnecessary, since the
  16. //    encryption key can be directly discovered and applied.
  17.  
  18. // Call:
  19. //            wu infile outfile
  20.  
  21. // Exit Status:
  22. //    1    too few arguments
  23. //    2    can't open given file for input
  24. //    3    can't open given file for output
  25. //    4    can't find a key (last two rows of header aren't the same)
  26. //    5    too short to be a Word file
  27. //    6    Problem writing to output file
  28.  
  29.  
  30. #include <stdio.h>
  31. #include <process.h>
  32. #ifdef __TURBOC__
  33.     #include <iostream.h>
  34. #endif
  35. #ifdef __ZTC__
  36.     #include <stream.h>
  37. #endif
  38.  
  39. #define Version "1.2"
  40. #define VersionDate "26 January 1993"
  41. #define keyLength 0x10
  42. #define bufferLength 0x180
  43. #define headerLength 0x180
  44.  
  45.  
  46. int  findKey(unsigned char buffer[], unsigned char key[]);
  47. void fixHeader(unsigned char buffer[], unsigned char key[]);
  48. void fixBuffer(unsigned char buffer[], unsigned char key[]);
  49.  
  50. #ifdef debug
  51. void showBuffer(unsigned char buf[]);
  52. #endif
  53.  
  54. char *copyLeft[] = {"\nMarc Thibault <marc@tanda.isis.org>\n",
  55.                     " Oxford Mills, Ontario \n",
  56.                     " This work is released to the public domain. \n",
  57.                     " It may be copied and distributed freely \n",
  58.                     " with appropriate attribution to the author.\n"};
  59.  
  60.  
  61. void main(int argc, char *argv[])
  62. {
  63.     unsigned char buffer[bufferLength];        // data buffer
  64.     unsigned char key[keyLength];            // encryption key
  65.     size_t count, check;
  66.     int i;
  67.  
  68.     FILE *crypt, *plain;
  69.  
  70.     // ----------------------
  71.  
  72.     if( argc < 3)                             // file names must be present
  73.     {
  74.         cout << "\n Word Unprotect -- Version " << Version;
  75.         cout << "\n   by Marc Thibault, " << VersionDate;
  76.         cout << "\n Syntax: wu infile outfile \n";
  77.         exit (1);
  78.     }
  79.  
  80.     // Open files
  81.  
  82.     if( NULL == (crypt = fopen(argv[1], "rb")))
  83.     {
  84.         cout << "\n wu error: can't open the input file\n";
  85.         exit (2);
  86.     }
  87.  
  88.     if( NULL == (plain = fopen(argv[2], "wb")))
  89.     {
  90.         cout << "\n wu error: can't open the output file\n";
  91.         exit (3);
  92.     }
  93.  
  94.     // Read header from input file
  95.  
  96.     count = fread(buffer,1,headerLength,crypt);
  97.     if(count != bufferLength)
  98.     {
  99.         cout << "\n wu error: Input file too short to be a Word File\n";
  100.         exit(5);
  101.     }
  102.  
  103.     // Extract the encryption key
  104.  
  105.     if(findKey(buffer,key))
  106.     {
  107.         cout << "\n wu error: Couldn't find a key \n";
  108.         exit(4);
  109.     }
  110.  
  111. #ifdef debug
  112.     cout << "\n Key in hexadecimal is";
  113.     for (i=0; i<keyLength; i++) printf(" %02X", key[i]);
  114.     cout << "\n";
  115. #endif
  116.  
  117.     // Decrypt/fixup the header and
  118.     // write it to the output file
  119.  
  120.     fixHeader(buffer,key);
  121.     check = fwrite(buffer, 1, headerLength, plain);
  122.     if (check != headerLength)
  123.     {
  124.         cout << "\n wu error: Problem writing to output file";
  125.         exit(6);
  126.     }
  127.  
  128.     // decrypt the rest of the file
  129.  
  130.     do
  131.     {
  132.         count = fread(buffer,1,bufferLength,crypt);
  133.         if (count != 0)
  134.         {
  135.             fixBuffer(buffer, key);
  136.             check = fwrite(buffer, 1, count, plain);
  137.             if (check != count)
  138.             {
  139.                 cout << "\n wu error: Problem writing to output file";
  140.                 exit(6);
  141.             }
  142.         }
  143.     } while (count == bufferLength); 
  144. }
  145.  
  146. // --------------------------------------------------------------------------
  147. #ifdef debug
  148. void showBuffer(unsigned char buf[])
  149. {
  150.     for( int i=0; i<bufferLength; i += 16)
  151.     {
  152.     printf("\n");
  153.     for(int j=0; j<16; j++) printf (" %2X", buf[i+j]);
  154.     }
  155.     printf("\n");
  156. }
  157. #endif
  158.  
  159. // --------------------------------------------------------------------------
  160. // findKey -- Find key in protected Word File
  161. // entered with everything initialized, including the initial buffer
  162.  
  163. int findKey(unsigned char buffer[], unsigned char key[])
  164. {
  165.     int i,check;
  166.  
  167.     // make sure the header looks ok, with 32 bytes of zeros (two copies
  168.     // of the key) at the end of the header.
  169.  
  170.     check=0;
  171.     for (i=0; i<keyLength; i++) check |= (buffer[0x160+i]^buffer[0x170+i]); 
  172.     if (check != 0) return(1);
  173.  
  174.     // If there's ever a problem, this is a place
  175.     // to put a scanner for majority
  176.     // vote on each key byte. The header
  177.     // is so full of zeros, this should work.
  178.  
  179.     // In the meantime, just move one copy to the key buffer.
  180.  
  181.     for (i=0; i<keyLength; i++) key[i] = buffer[0x160+i];
  182.     return(0);
  183. }
  184.  
  185. // --------------------------------------------------------------------------
  186. // fixHeader -- Fix the header block after finding key
  187.  
  188.  
  189. void fixHeader(unsigned char buffer[], unsigned char key[])
  190. {
  191.     int i, j;
  192.  
  193.     // reset the protect flag
  194.     buffer[11] &= 0xfe;
  195.  
  196.     // reset bytes 14-17 (key hash?)
  197.     for( i=14; i<18; i++) buffer[i] = 0;
  198.  
  199.     // decrypt partial row at 0x24
  200.     for( i=4; i<16; i++) buffer[0x20+i] ^= key[i];
  201.  
  202.     // decrypt rest of header
  203.     for( i=0x30; i < headerLength; i += keyLength)
  204.     {
  205.         for( j=0; j < keyLength; j++) buffer[i+j] ^= key[j];
  206.     }
  207. }
  208.  
  209. // --------------------------------------------------------------------------
  210. // fixBuffer -- Decrypt the buffer contents as a whole
  211.  
  212.  
  213. void fixBuffer(unsigned char buffer[], unsigned char key[])
  214. {
  215.     for( int i=0; i < bufferLength; i += keyLength)
  216.     {
  217.         for( int j=0; j < keyLength; j++) buffer[i+j] ^= key[j];
  218.     }
  219. }
  220.