Fun With Fortres

by Amatus

Through my high school career, I have developed an animosity towards a certain piece of security software for Microsoft Windows.  Fortres Grand Corporation (www.fortres.com) sells this software - named Fortres101 - mostly to schools, libraries, and similar institutions.

Access to the computer is limited in several ways by Fortres.  It can be configured to control access to icons on the desktop, the Start menu, context menus, Explorer menus, Windows hotkeys, reading, writing, and executing the filesystem, reading and writing the registry, and even web browsing.  As you may have already guessed, this usually interferes with the normal operation of many applications.  At my old high school the teacher would disable Fortres on request because it interfered with our regular school work.  A good friend of mine found that a fake password dialog was an effective way of getting the admin password in this situation.

All versions of Fortres (that I know of) have a configuration dialog that can be accessed by pressing "CTRL+ALT+SHIFT+ESC".  You are then presented with the password dialog box.  If backdoor passwords are enabled, a supposedly random number appears in the dialog box caption.  A one time use password, also a number, can be generated from the backdoor key.  A call to technical support can supply you with the backdoor password or to this function, take your pick.

Backdoor Method

Fortres has an option to provide a backdoor key in case the admin has forgotten the password.  This key appears as a number in the title bar of the password dialog.  If the number begins with "5-" then you are using a version of Fortres I haven't cracked yet.  Normally the admin would call up tech-support or something and they would use the backdoor key to calculate the backdoor password, which the admin would then use in place of the actual password.  At least that's what I've heard.  In practice, I have found that this supposedly random key is actually based on the system clock.  This little snippet of code will derive the backdoor password for you:

// key - the backdoor key
// The return value is the backdoor password
unsigned short backdoor_password(unsigned long key)
{
  short x;

  x = ((short) (key * -1.2456) + 1) * 65533;
  x = (x / 2 + 7) * 3;
  x /= 2;
  return x * x;
}

If you can't do this in your head, a "circumvention device" can do it for you in a matter of microseconds.  I'm currently working on software for TI calculators.  I have not yet looked into writing software for any other handheld devices, as I do not have any.  If you are interested in something like this, cross your fingers and hope I have a web server running at amatus.doesnotexist.com.

The backdoor key is not there?  Don't worry.  Through some testing, I have found that the file containing the Fortres password is always readable, no matter how Fortres is configured.  This means that if you have the ability to execute your own programs on the computer, you can read the configuration/password file and decipher the password.  Almost every computer I have seen in a high school has a CD-ROM drive and will allow you to execute programs through the use of a CD with \AUTORUN.INF.  Fortres versions 3.x and 4.x passwords can be expunged using these functions.

When Fortres is misconfigured, there are many many ways to disable it.  This article is meant to help attack the more secure installations.  At my old high school we had a DOS version of AutoCAD installed on Microsoft Windows 95 machines.  The sysadmin had the computers setup to boot in DOS mode for this application.  AutoCAD has a file managing tool that allowed an attacker to overwrite CONFIG.SYS and AUTOEXEC.BAT with backups.  This is an example of a misconfiguration in the favor of usability, something every sysadmin has to do at one point or another.

The code for generating backdoor passwords was obtained by reverse engineering a program sent to me by a friend.  I'm pretty sure he grabbed it off some warez site or something.  The code for deciphering Fortres 3.x passwords was written exclusively by my reverse engineering of FORTRES.EXE.

When I began I knew no assembly - now I can blindly patch binaries without the help of a compiler, thanks to Fortres Grand Corporation.  All the credit for the Fortres 4.x code goes to Frost_Byte (packetstorm.securify.com/0004-exploits/Fortres4-analysis.txt).  I only transcribed it into C and optimized it a little.  All symbols needed are defined in windows.h.

I hope all of you find this information interesting.  Doubt should form in your mind whenever hearing the words "security" and "Windows" in the same sentence.  As always, the information expressed within this article is purely for hacking purposes.  I do not make any claim to the accuracy or correctness of any of it.  This information is provided "as is" and I am not responsible for any damages caused by the misuse of it.  In fact, forget you ever read this article.

(I love you Steph.)

Fortres v3.x

Under the default install, Fortres v3.x saves the password in a configuration file named DEFAULT.FG3 in the path C:\FORTRES.101\

I took the initiative to reverse engineer Fortres v3.x to figure out how to get the password out of this file.  I got myself a disassembler and a book on assembly and started cracking.  It didn't take long to find the bit of code that performed the decoding but rewriting it into C was a new challenge for me.  It took about a year of working off and on to finally reduce it to these two simple functions.

// Rotate left
unsigned char rotl(unsigned char x, unsigned long pos)
{
  return x << pos % 8 | x >> 8 - pos % 8;
}

// fd - an open file descriptor to DEFAULT.FG3
// password - a pointer to a buffer to be filled with the password
// len - the length of the buffer pointed to by password
// The return value is true if the password was successfully deciphered
int fortres3(FILE * fd, char *password, unsigned long len)
{
  unsigned long i, j;
  unsigned char buff[648], key[103];

  fseek(fd, 234, SEEK_SET);
  if (fread(key, 1, 103, fd) != 103)
    return -1;
  if (fread(buff, 1, 648, fd) != 648)
    return -1;
  for (i = 0, j = 0; i < 648; i++)
    buff[i] =
      rotl((unsigned char) (rotl(buff[i], i) ^ key[j = (j + 1) % 103]), i) ^ 0xB2;
  buff[16] = buff[97];
  buff[18] = buff[109];
  buff[20] = buff[73];
  buff[21] = buff[57];
  for (i = 0; i < len && buff[i + 16]; i++)
    password[i] = buff[i + 16] + 0x1B;
  if (password[i - 1] != 'C')
    return -1;
  password[i - 1] = '\0';
  return 0;
}
Return to $2600 Index