Advertisement
Guest User

Untitled

a guest
Oct 12th, 2024
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.52 KB | None | 0 0
  1. // wu.cpp -- Unprotect Microsoft Word/Winword Document
  2.  
  3.  
  4. // Marc Thibault <[email protected]>
  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 <iostream>
  32.  
  33. using namespace std;
  34.  
  35. #define Version "1.2"
  36. #define VersionDate "26 January 1993"
  37. #define keyLength 0x10
  38. #define bufferLength 0x180
  39. #define headerLength 0x180
  40.  
  41.  
  42. int findKey(unsigned char buffer[], unsigned char key[]);
  43. void fixHeader(unsigned char buffer[], unsigned char key[]);
  44. void fixBuffer(unsigned char buffer[], unsigned char key[]);
  45.  
  46. #ifdef debug
  47. void showBuffer(unsigned char buf[]);
  48. #endif
  49.  
  50. char *copyLeft[] = {"\nMarc Thibault <[email protected]>\n",
  51. " Oxford Mills, Ontario \n",
  52. " This work is released to the public domain. \n",
  53. " It may be copied and distributed freely \n",
  54. " with appropriate attribution to the author.\n"};
  55.  
  56.  
  57. int main(int argc, char *argv[])
  58. {
  59. unsigned char buffer[bufferLength]; // data buffer
  60. unsigned char key[keyLength]; // encryption key
  61. size_t count, check;
  62. int i;
  63.  
  64. FILE *crypt, *plain;
  65.  
  66. // ----------------------
  67.  
  68. if( argc < 3) // file names must be present
  69. {
  70. cout << "\n Word Unprotect -- Version " << Version;
  71. cout << "\n by Marc Thibault, " << VersionDate;
  72. cout << "\n Syntax: wu infile outfile \n";
  73. exit (1);
  74. }
  75.  
  76. // Open files
  77.  
  78. if( NULL == (crypt = fopen(argv[1], "rb")))
  79. {
  80. cout << "\n wu error: can't open the input file\n";
  81. exit (2);
  82. }
  83.  
  84. if( NULL == (plain = fopen(argv[2], "wb")))
  85. {
  86. cout << "\n wu error: can't open the output file\n";
  87. exit (3);
  88. }
  89.  
  90. // Read header from input file
  91.  
  92. count = fread(buffer,1,headerLength,crypt);
  93. if(count != bufferLength)
  94. {
  95. cout << "\n wu error: Input file too short to be a Word File\n";
  96. exit(5);
  97. }
  98.  
  99. // Extract the encryption key
  100.  
  101. if(findKey(buffer,key))
  102. {
  103. cout << "\n wu error: Couldn't find a key \n";
  104. exit(4);
  105. }
  106.  
  107. #ifdef debug
  108. cout << "\n Key in hexadecimal is";
  109. for (i=0; i<keyLength; i++) printf(" %02X", key[i]);
  110. cout << "\n";
  111. #endif
  112.  
  113. // Decrypt/fixup the header and
  114. // write it to the output file
  115.  
  116. fixHeader(buffer,key);
  117. check = fwrite(buffer, 1, headerLength, plain);
  118. if (check != headerLength)
  119. {
  120. cout << "\n wu error: Problem writing to output file";
  121. exit(6);
  122. }
  123.  
  124. // decrypt the rest of the file
  125.  
  126. do
  127. {
  128. count = fread(buffer,1,bufferLength,crypt);
  129. if (count != 0)
  130. {
  131. fixBuffer(buffer, key);
  132. check = fwrite(buffer, 1, count, plain);
  133. if (check != count)
  134. {
  135. cout << "\n wu error: Problem writing to output file";
  136. exit(6);
  137. }
  138. }
  139. } while (count == bufferLength);
  140. }
  141.  
  142. // --------------------------------------------------------------------------
  143. #ifdef debug
  144. void showBuffer(unsigned char buf[])
  145. {
  146. for( int i=0; i<bufferLength; i += 16)
  147. {
  148. printf("\n");
  149. for(int j=0; j<16; j++) printf (" %2X", buf[i+j]);
  150. }
  151. printf("\n");
  152. }
  153. #endif
  154.  
  155. // --------------------------------------------------------------------------
  156. // findKey -- Find key in protected Word File
  157. // entered with everything initialized, including the initial buffer
  158.  
  159. int findKey(unsigned char buffer[], unsigned char key[])
  160. {
  161. int i,check;
  162.  
  163. // make sure the header looks ok, with 32 bytes of zeros (two copies
  164. // of the key) at the end of the header.
  165.  
  166. check=0;
  167. for (i=0; i<keyLength; i++) check |= (buffer[0x160+i]^buffer[0x170+i]);
  168. if (check != 0) return(1);
  169.  
  170. // If there's ever a problem, this is a place
  171. // to put a scanner for majority
  172. // vote on each key byte. The header
  173. // is so full of zeros, this should work.
  174.  
  175. // In the meantime, just move one copy to the key buffer.
  176.  
  177. for (i=0; i<keyLength; i++) key[i] = buffer[0x160+i];
  178. return(0);
  179. }
  180.  
  181. // --------------------------------------------------------------------------
  182. // fixHeader -- Fix the header block after finding key
  183.  
  184.  
  185. void fixHeader(unsigned char buffer[], unsigned char key[])
  186. {
  187. int i, j;
  188.  
  189. // reset the protect flag
  190. buffer[11] &= 0xfe;
  191.  
  192. // reset bytes 14-17 (key hash?)
  193. for( i=14; i<18; i++) buffer[i] = 0;
  194.  
  195. // decrypt partial row at 0x24
  196. for( i=4; i<16; i++) buffer[0x20+i] ^= key[i];
  197.  
  198. // decrypt rest of header
  199. for( i=0x30; i < headerLength; i += keyLength)
  200. {
  201. for( j=0; j < keyLength; j++) buffer[i+j] ^= key[j];
  202. }
  203. }
  204.  
  205. // --------------------------------------------------------------------------
  206. // fixBuffer -- Decrypt the buffer contents as a whole
  207.  
  208.  
  209. void fixBuffer(unsigned char buffer[], unsigned char key[])
  210. {
  211. for( int i=0; i < bufferLength; i += keyLength)
  212. {
  213. for( int j=0; j < keyLength; j++) buffer[i+j] ^= key[j];
  214. }
  215. }
  216.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement