35 months ago, when I joined Borland, I had to create a MSN account so that I can communicate with my colleagues overseas. And so, I created an account and a unique password.

Unfortunately, I've forgotten the password since I've never had to enter my password since then.

So... what to do? A little spelunking to figure out how Trillian encodes password, and I came up with the following application. Once I came up with the appropriate decoding mechanism, I had to write a function to reverse the process as well, and so I came up with EncodePassword as well, otherwise, I wouldn't be able to blog about this, since I would really have to provide my actual password hash... ;o)

// Recovers passwords stored in Trillian
program RecoverTrillianPassword;


{$APPTYPE CONSOLE}

uses
  SysUtils;
const
  XORPassword: array[0..83] of Byte = (
   243, 038, 129, 196, 057, 134, 219, 146, 113, 163, 185, 230, 083, 122, 149,
   124, 000, 000, 000, 000, 000, 000, 255, 000, 000, 128, 000, 000, 000, 128,
   128, 000, 255, 000, 000, 000, 128, 000, 128, 000, 128, 128, 000, 000, 000,
   128, 255, 000, 128, 000, 255, 000, 128, 128, 128, 000, 085, 110, 097, 098,
   108, 101, 032, 116, 111, 032, 114, 101, 115, 111, 108, 118, 101, 032, 072,
   084, 084, 080, 032, 112, 114, 111, 120, 000
  );

// Obtained from password= field in msn.ini under Program Files\Trillian\users\default
function DecodePassword(const PasswordHash: string): string;
var
  S: string;
  C: Char;
  B: Byte;
  I, J: Integer;
begin
  Result := '';
  I := 1; J := 0;
  while I < Length(PasswordHash) do
    begin
      S := Copy(PasswordHash, I, 2);
      B := StrToInt('$'+S);
      C := Chr(B xor XORPassword[J]);
      Result := Result + C;
      Inc(J); Inc(I, 2);
    end;
end;

function EncodePassword(const Password: string): string;
var
  I: Integer;
  B: Byte;
  C: Char;
begin
  Result := '';
  I := 0;
  for C in Password do
    begin
      B := Ord(C) xor XORPassword[ I ];
      Result := Result + IntToHex(B,2);
      Inc(I);
    end;
end;

begin
  WriteLn(DecodePassword('BB43EDA856D1B4E01DC7'));
end.

// V - CA11B9F100B4
// A - C110B2F3