home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / sci / crypt / 6058 < prev    next >
Encoding:
Text File  |  1992-12-22  |  12.0 KB  |  491 lines

  1. Xref: sparky sci.crypt:6058 alt.sources:2854
  2. Newsgroups: sci.crypt,alt.sources
  3. Path: sparky!uunet!paladin.american.edu!gatech!swrinde!zaphod.mps.ohio-state.edu!saimiri.primate.wisc.edu!ames!pacbell.com!network.ucsd.edu!qualcom.qualcomm.com!cancun!rdippold
  4. From: rdippold@cancun.qualcomm.com (Ron Dippold)
  5. Subject: WPCRACK.C
  6. Message-ID: <rdippold.725047417@cancun>
  7. Sender: news@qualcomm.com
  8. Nntp-Posting-Host: cancun.qualcomm.com
  9. Organization: Qualcomm, Inc., San Diego, CA
  10. Date: Tue, 22 Dec 1992 18:03:37 GMT
  11. Lines: 478
  12.  
  13. /*----------------------------------------------------------------------
  14. **  WPCRACK - Copyright (c) 1990, 91 Ron Dippold 10/11/91
  15. **  rdippold@qualcomm.com
  16. **
  17. **  Attempt to crack a Word Perfect 5.x file through some massive
  18. **  security holes.
  19. **
  20. **  This source code is hereby released for public use.  All I ask is
  21. **  that if you make some cool new additions or enhancements that you
  22. **  mail me the update.  And if you use the program or source code,
  23. **  give me a little credit.
  24. **
  25. **  There's at least one major enhancement that could be made to this
  26. **  that I can think of at the moment - frequency analysis on the
  27. **  actual document text.  Once you know the format, it's pretty easy.
  28. **
  29. **  I'm not claiming this is the best code you've ever seen, it's just
  30. **  a fast hack, but it works.  I tried to be generic as possible so
  31. **  that it will compile on almost any platform.  It was written under
  32. **  Borland C.
  33. **----------------------------------------------------------------------*/
  34.  
  35. #include <stdio.h>
  36.  
  37. #define MAX 18        /* Max number of chars to look for */
  38. #define N 5           /* Max number of repeats */
  39.  
  40. FILE *f;              /* File name */
  41.  
  42. typedef unsigned char byte;
  43. typedef unsigned int  word;
  44.  
  45. byte buf1[48];
  46. byte *buf;
  47.  
  48. word csum1, csum, missing, mi;
  49.  
  50. /* bytes in the plaintext we think we know - 0x00 means we don't know */
  51. byte known[32] = {
  52.     0xfb, 0xff, 0x05, 0x00, 0x32, 0x00, 0x99, 0x99,
  53.     0x00, 0x00, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00,
  54.     0x42, 0x00, 0x00, 0x00, 0x99, 0x00, 0x99, 0x00,
  55.     0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x99, 0x99 };
  56.  
  57. byte source[MAX][N][MAX];   /* source table from known bytes */
  58. char pass[MAX][N][MAX];     /* possible passwords */
  59. char tots[MAX][MAX];        /* totals and matches for each password position */
  60. char mats[MAX][MAX];
  61. int  conf[MAX];             /* confidence for each length */
  62.  
  63. char chr[N];                /* character and count for each char */
  64. byte cnt[N];
  65.  
  66. char fmt[N][MAX];           /* characters for output */
  67. byte cnts[N][MAX];
  68.  
  69. int order[MAX];             /* order by confidence */
  70. int thresh=80;              /* threshold of confidence */
  71. int num=0;                  /* number of lengths that beat threshold */
  72.  
  73. byte pp;
  74. char c;
  75.  
  76. byte idx[MAX];              /* current guess */
  77. char cur[MAX];
  78.  
  79. int i, j, k, l, t, len, tot, match, deep;
  80. int do_dec=0, do_table=0;
  81.  
  82. void docs() {
  83.     printf( " To attempt to crack a Word Perfect 5.x file, the syntax is:\n\n" );
  84.     printf( "   WPCRACK (-d) (-t) <filename> ( <threshold> )\n\n" );
  85.     printf( " <filename> is the Word Perfect file to crack.\n" );
  86.     printf( " <threshold> is the percentage confidence threshold over which\n" );
  87.   printf( "    a length is considered to be a possibility.\n" );
  88.     printf( "    From 0 (all) to 100 (exact match), default 80.\n" );
  89.     printf( " The -d switch will force WPCRACK to the decimal values of\n");
  90.     printf( "    each character of an answer as well.  Not pretty.\n");
  91.     printf( " The -t switch will force WPCRACK to print all answers in table\n");
  92.     printf( "    form with all possibilities, ignoring checksums.\n");
  93.     printf( "\n\n To decrypt the file with the password, run WPUNCRYP on it.\n");
  94.     exit( 1 );
  95. }
  96.  
  97. void main( int argc, char **argv )
  98. {
  99.     printf( "\nWPCRACK 1.0 - Copyright (c) 1990,91 Ron Dippold\n\n" );
  100.  
  101.     if( argc < 2 || argc > 5 ) {
  102.         docs();
  103.     }
  104.  
  105.     i=1;
  106.  
  107.     while( i<argc && argv[i][0] == '-' ) {
  108.         if( argv[i][1] == 'd' ) {
  109.             do_dec = 1;
  110.         } else {
  111.             if( argv[i][1] == 't' ) {
  112.                 do_table = 1;
  113.             } else {
  114.                 docs();
  115.             }
  116.         }
  117.         i++;
  118.     }
  119.  
  120.     if( i>= argc ) {
  121.         docs();
  122.     }
  123.  
  124.     if( i == argc-2  ) {
  125.         sscanf( argv[i+1], "%d", &thresh );
  126.         if( thresh<0 || thresh>100 ) {
  127.             docs();
  128.         }
  129.     }
  130.  
  131.     if( !( f = fopen( argv[i], "rb" ))) {
  132.         printf( "  Could not open file %s\n", argv[i] );
  133.         exit( 2 );
  134.     }
  135.  
  136.     fseek( f, 0L, SEEK_SET );
  137.     if( fread( buf1, 1, 4, f ) != 4) {
  138.         fclose( f );
  139.         printf( "  Couldn't read 4 bytes from file %s!\n", argv[i] );
  140.         exit( 3 );
  141.     }
  142.  
  143.     if( buf1[0]!=0xff || buf1[1]!=0x57 || buf1[2]!=0x50 || buf1[3]!=0x43 ) {
  144.         printf( "%x, %x, %x, %x\n", buf1[0], buf1[1], buf1[2], buf1[3] );
  145.         fclose( f );
  146.         printf( "  The identification bytes in this file are not those of a\n" );
  147.         printf( "  Word Perfect 5.x file.\n" );
  148.         exit( 4 );
  149.     }
  150.  
  151.     if( fread( &buf1[4], 1, 44, f ) != 44 ) {
  152.         fclose( f );
  153.         printf( "  Couldn't read the first 48 bytes of the file - garbaged!\n" );
  154.         exit( 5 );
  155.     }
  156.     fclose( f );
  157.  
  158.     if( buf1[12]==0 && buf1[13]==0 ) {
  159.         printf( "  The file claims it is not encrypted.\n" );
  160.         printf( "  We'll continue anyway, but take note!\n\n%c",7 );
  161.     }
  162.  
  163.     csum1 = (buf1[12]<<8) + buf1[13];
  164.  
  165.     buf = &buf1[16];
  166.  
  167. /*  printf( "Building known text table.\n" ); */
  168.     for( i=1; i<MAX; i++ ) {
  169.         for( j=0; j<N; j++ ) {
  170.             for( k=0; k<i; k++ ) {
  171.                 pp = j*i+k;
  172.                 while ( pp<= 31 ) {
  173.                     if( known[pp] == 0x99 ) {
  174.                         pp+=i; continue;
  175.                     }
  176.                     tot = 0;
  177.                     if( j>0 ) for( l=j-1; l>=0; l-- ) {
  178.                         if( pp == source[i][l][k] ) {
  179.                             tot++;
  180.                         }
  181.                     }
  182.                     if( tot ) {
  183.                         pp+=i;
  184.                     } else {
  185.                         break;
  186.                     }
  187.                 }
  188.                 if ( pp>31 ) pp = 0xFF;
  189.                 source[i][j][k] = pp;
  190.             }
  191.         }
  192.     }
  193.  
  194. /*  printf("Trying password lengths from 1 to %d\n", MAX-1 ); */
  195.     for( len=1; len<MAX; len++ ) {
  196. /* printf( "Len %2d:\n", len ); */
  197.     for( j=0; j<N; j++ ) {
  198.             for( k=0; k<len; k++ ) {
  199.                 l = source[len][j][k];
  200.                 if( l != 0xFF && known[l] != 0x99 ) {
  201.                     pp = ( len+l+1 ) ^ known[l] ^ buf[l];
  202.                     if( pp>127 || (pp>='a' && pp<='z')) pp = 0;
  203. /* putchar( pp ); */
  204.                 } else {
  205.                     pp = 0;
  206. /* putchar( '_'); */
  207.                 }
  208.                 pass[len][j][k] = pp;
  209.             }
  210. /* printf( "\n" ); */
  211.         }
  212.  
  213.     /* move all good choices to the top */
  214.         for( k=0; k<len; k++ ) {
  215.             for( j=0; j<N-1; j++ ) {
  216.                 if( pass[len][j][k] == 0 ) {
  217.                     for( l=j; l<N-1; l++ ) {
  218.                         pass[len][l][k] = pass[len][l+1][k];
  219.                     }
  220.                     pass[len][N-1][k] = 0;
  221.                 }
  222.             }
  223.         }
  224.  
  225.         tot=match=0;
  226.         for( k=0; k<len; k++ ) {
  227.             tots[len][k] = mats[len][k] = 0;
  228.             for( j=1; j<N; j++ ) {
  229.                 if( pass[len][j][k] != 0 ) {
  230.                     tots[len][k]+=j;
  231.                     for( i=0; i<j; i++ ) {
  232.                         if( pass[len][j][k] == pass[len][i][k] ) {
  233.                             mats[len][k]++;
  234.                         }
  235.                     }
  236.                 }
  237.             }
  238.             tot+=tots[len][k];
  239.             match+=mats[len][k];
  240.         }
  241.  
  242.         if( tot ) {
  243.             conf[len] = match*100 / tot ;
  244.         } else {
  245.             conf[len]=0;
  246.         }
  247.     }
  248.  
  249. /*  printf( "Sorting results\n\n" ); */
  250.     for( i=0; i<MAX; i++ ) {
  251.         order[i] = i;
  252.     }
  253.  
  254.   /* so it's a bubble sort.  It's small.  Deal with it. */
  255.     for( i=MAX-1; i>0; i-- ) {
  256.         for( j=1; j<i; j++ ) {
  257.             if( conf[order[j]] < conf[order[j+1]] ) {
  258.                 k = order[j]; order[j] = order[j+1]; order[j+1] = k;
  259.             }
  260.         }
  261.     }
  262.  
  263.     for( num=MAX-1; num>0; num-- ) {
  264.         if( conf[order[num]]>=thresh ) {
  265.             break;
  266.         }
  267.     }
  268.  
  269.     printf( "%d length%c meet%c the %d%% initial confidence threshold.\n",
  270.         num, num==1 ? ' ':'s', num==1 ? 's':' ', thresh );
  271.  
  272.     if( num == 0 ) {
  273.         printf( "  Try lowering the threshold.\n");
  274.         printf( "  Or maybe you need a new version of this to match a Word Perfect change.\n" );
  275.         exit( 2 );
  276.     }
  277.  
  278.     for( l=1; l<=num; l++ ) {
  279.         len = order[l];
  280.         printf( "\nPassword length of %d with %d%% confidence level:\n\n",
  281.             len, conf[len] );
  282.  
  283.         deep=0;
  284.     /* for each character */
  285.         for( k=0; k<len; k++ ) {
  286.             for( j=0; j<N; j++ ) {
  287.                 fmt[j][k]=' ';
  288.                 cnts[j][k]=0;
  289.             }
  290.  
  291.       /* run a character vote */
  292.             for( j=0; j<N; j++ ) {
  293.                 chr[j]=cnt[j]=0;
  294.             }
  295.             for( j=0; j<N; j++ ) {
  296.                 if( pass[len][j][k] != 0 ) for(i=0; i<N; i++ ) {
  297.                     if( !chr[i] ) {
  298.                         chr[i] = pass[len][j][k];
  299.                     }
  300.                     if( pass[len][j][k] == chr[i] ) {
  301.                         cnt[i]++;
  302.                         break;
  303.                     }
  304.                 }
  305.             }
  306.       for( i=N-1; i>0; i-- ) {      /* sort to find most popular */
  307.                 for( j=0; j<i; j++ ) {
  308.                     if( cnt[j] < cnt[j+1] ) {
  309.                         t = cnt[j]; cnt[j] = cnt[j+1]; cnt[j+1] = t;
  310.                         t = chr[j]; chr[j] = chr[j+1]; chr[j+1] = t;
  311.                     }
  312.                 }
  313.             }
  314.  
  315.       if( cnt[0] == 0 ) {           /* no letters */
  316.                 fmt[0][k]='_';
  317.                 cnts[0][k]=0;
  318.             } else {
  319.                 for( j=0; j<N; j++ ) {
  320.                     if( cnt[j] ) {
  321.                         cnts[j][k]=cnt[j];
  322.                         fmt[j][k]=chr[j];
  323.                         if( deep<j) deep = j;
  324.                     }
  325.                 }
  326.             }
  327.         }
  328.  
  329.     /* Find any missing letters */
  330.         missing = 0; mi=-1;
  331.         for( k=0; k<len; k++ ) {
  332.             if( !cnts[0][k] ) {
  333.                 missing++;
  334.                 mi = k;
  335.             }
  336.         }
  337.  
  338.         if( missing > 1 || do_table ) {
  339.             if( missing > 1) {
  340.                 printf("  More than one letter is missing - showing all possibilities.\n");
  341.             } else {
  342.                 printf("  Displaying table form as requested\n");
  343.             }
  344.  
  345.       /* show in table form */
  346.             for( j=0; j<=deep; j++ ) {
  347.                 printf( "   # of matches: " );
  348.                 for( k=0; k<len; k++ ) {
  349.                     putchar( cnts[j][k] ? cnts[j][k]+'0' : '0' );
  350.                 }
  351.                 if( j==0 ) {
  352.                     printf( "\n  Primary Guess: " );
  353.                 } else {
  354.                     printf( "\n     Alternates: " );
  355.                 }
  356.                 csum = 0;
  357.                 for( k=0; k<len; k++ ) {
  358.                     putchar( cnts[j][k] ? fmt[j][k] : ' ' );
  359.                     if( cnts[j][k] ) {
  360.                         csum = ( (csum >> 1) | ( csum << 15) ) ^ ( fmt[j][k]<<8 );
  361.                     }
  362.                 }
  363.         if( j==0 ) {
  364.                     if (missing) {
  365.                         printf("  (Incomplete!)");
  366.                     } else {
  367.                         if( csum == csum1 ) {
  368.                             printf("  Checksum good!");
  369.                         } else {
  370.                             printf("  Checksum bad!");
  371.                         }
  372.                     }
  373.                 }
  374.  
  375.                 if( do_dec ) {
  376.                     printf( "\n                 " );
  377.                     for(k=0; k<len; k++) {
  378.                         printf("%d ", cnts[j][k] ? fmt[j][k] : 0);
  379.                     }
  380.                 }
  381.  
  382.         /* if only one missing character, extrapolate */
  383.                 if( missing == 1 && j==0 ) {
  384.                     for( i=0; i<128; i++ ) {
  385.                         csum = 0;
  386.                         fmt[0][mi] = i;
  387.                         for( k=0; k<len; k++ ) {
  388.                             csum = ( (csum >> 1) | ( csum << 15) ) ^ ( fmt[0][k]<<8 );
  389.                         }
  390.                         if( csum == csum1 && ( i<'a' || i>='z' )) {
  391.                             printf( "\n   Extrapolated: " );
  392.                             for( k=0; k<len; k++ ) putchar( fmt[j][k] );
  393.                             printf( "   -- Good Checksum");
  394.                             if( do_dec ) {
  395.                                 printf( "\n                 " );
  396.                                 for(k=0; k<len; k++) printf("%d ", fmt[j][k]);
  397.                             }
  398.                         }
  399.                     }
  400.                 }
  401.  
  402.                 printf( "\n\n" );
  403.             }
  404.         } else {
  405.  
  406.             for( k=0; k<len; k++ ) {
  407.                 idx[k]=0;
  408.                 cur[k]=fmt[0][k];
  409.             }
  410.  
  411.             if( missing == 1 ) {
  412.                 cur[mi] = ' ';
  413.                 printf( "  " );
  414.                 for( k=0; k<len; k++ ) putchar( cur[k] );
  415.                 printf( "\n  ");
  416.                 for( k=0; k<len; k++ )
  417.                     putchar( k == mi ? '^' : ' ');
  418.                 printf( "\n The missing character will be extrapolated from the checksum\n\n");
  419.             } else {
  420.                 printf( " Only possibilities with good checksums will be listed.\n\n");
  421.             }
  422.  
  423.             do {
  424.                 if( missing == 0 ) {
  425.  
  426.           /* none missing - generate,  check checksum */
  427.                     csum = 0;
  428.                     for( k=0; k<len; k++ ) {
  429.                         csum = ( (csum >> 1) | ( csum << 15) ) ^ ( cur[k]<<8 );
  430.                     }
  431.                     if( csum == csum1 ) {
  432.                         printf( "  " );
  433.                         for( k=0; k<len; k++ ) {
  434.                             putchar( cur[k] );
  435.                         }
  436.                         printf( "   -- Good Checksum\n");
  437.                         if( do_dec ) {
  438.                             printf( "   Dec: " );
  439.                             for( k=0; k<len; k++ ) {
  440.                                 printf( "%d ", cur[k] );
  441.                             }
  442.                             printf( "\n");
  443.                         }
  444.                     }
  445.                 } else {
  446.  
  447.           /* checksum missing - generate */
  448.                     tot = 0;
  449.                     for( i=0; i<128; i++ ) {
  450.                         csum = 0;
  451.                         cur[mi] = i;
  452.                         for( k=0; k<len; k++ ) {
  453.                             csum = ( (csum >> 1) | ( csum << 15) ) ^ ( cur[k]<<8 );
  454.                         }
  455.                         if( csum == csum1 && ( i<'a' || i>='z' )) {
  456.                             tot++;
  457.                             printf( "  " );
  458.                             for( k=0; k<len; k++ ) putchar( cur[k] );
  459.                             printf( "   -- Good Checksum\n");
  460.                             if( do_dec) {
  461.                                 printf("  ");
  462.                                 for( k=0; k<len; k++ ) printf("%d ",cur[k]);
  463.                                 printf("\n");
  464.                             }
  465.                         }
  466.                     }
  467.                     if( !tot ) {
  468.                         printf("  No valid passwords found\n" );
  469.                     }
  470.                 }
  471.  
  472.         /* next combination */
  473.                 k=len-1;
  474.                 while( k>=0 ) {
  475.                     if( cnts[idx[k]+1][k]==0 || cur[k]== N-1 ) {
  476.             idx[k]=0;
  477.                         k--;
  478.                     } else {
  479.                         idx[k]++;
  480.                         break;
  481.                     }
  482.                 }
  483.  
  484.             } while( k>=0 );
  485.         } /* table or checksum */
  486.     }
  487. }
  488.  
  489. -- 
  490. Cthulhu cthucks, but does he cthwallow?
  491.