12/2005 by Zadig.

Tools needed:

  • bdb.
  • reveng.

Introduction:

To use Zeta R1 you have to register your copy to yellowtab. If you do not, a nag application reminds you that you must do it. You have several ways to register but you will most probably end up by using internet since it is the most convenient solution.
We can understand that yellowtab wants to ensure that people really bought there copy but it can also be a good way for them to get information from users. In this document I will present an analyse of the registration process to see what is really doing Zeta, and what kind of information it sends to yellowtab. We will then see if it is possible to register a copy legally without network connection. This may be usefull if you use like me a test install that is often deleted/reinstalled.


I- The registration process in Zeta R1.

1- Activate.

2- The App server.

3- Global diagram.

II- The registration process in Zeta R1 SP1.

1- Activate.

2- The App server.

3- Global diagram.

III- Registering without network.

1- Fake registering execs.

2- Fake registration server.

3- Registration script.

4- Just backup your install.

IV- Conclusion.


I- The registration process in Zeta R1.

Just after Zeta's installation you are asked to register you copy. The application that asks for it let you choose between two ways of doing this: If you have an internet connection you just have to enter your serial number and activation key, and let the process goes on through internet. If you do not have an internet connection must must either send a mail to yellowtab, either phone them so that you get 2 activation codes. If you do not register, this application will appear periodically.

1- Activate.

"activate" is the application that asks for the serial number. It is located at "/boot/beos/bin/" (or /bin this is the same). After disassembling it we find one interesting class:

Class BRegistration
0000FA54: BRegistration::BRegistration(void)
0000FACC: BRegistration::Init(void)
0000FAD4: BRegistration::Invoke(void)
0000FAE8: BRegistration::IsRegistered(void)
00010174: BRegistration::Perform(int, int)
0000FB28: BRegistration::Register(char const *, long, long)
0000FADC: BRegistration::ShowRegisterWindow(void)
0000FA88: BRegistration::~BRegistration(void)
Let's first look at the "IsRegistered" method. There is almost nothing in it. This function is entirely based on a call to "BApplication::Perform(0x4d6, 0)". This function is in libbe.so. The "0x4d6" message is handled at the begining of the function. Here is the partial call graph of this function:
+BApplication::Perform(unsigned long, void *)
   +_BAppServerLink_::_BAppServerLink_(void)
      +_BAppServerLink_::Init(bool)
         +BApplication::connect_to_app_server(void)  
   +BPrivate::AppSession::swrite(long, void const *)
   +BPrivate::AppSession::flush(void)
   +BPrivate::AppSession::sread(long, void *)
   +_BAppServerLink_::~_BAppServerLink_(void)
We see here that we connect the the app_server, send datas and read datas. So it is the app server that tells if we are registered or not. Thus we will have a deeper look at it but later. For now we will continue to see what is happening in "activate". The other interesting method of BRegistration is "Register".

Its 3 parameters are the serial number and the 2 activation codes. Looking at this function's dead-listing you can guess that there are important things in it because the strings contruction is more or less obfuscated. In fact this function is just adding attributes to some files:

  • "/boot/beos/app/People": Attribute "code12" is added (type int). This is the first activation code.
  • "/boot/beos/system/servers/app_server": Attribute "code24" is added (type int). This is the second activation code.
  • "/boot/beos/system/kernel_intel": Attribute "sser1762" is added (type string). This is the serial number.
You can check this easily by typing the commands:
listattr /boot/beos/apps/People | grep code
listattr /boot/beos/system/servers/app_server | grep code
listattr /boot/beos/system/kernel_intel | grep sser
So registering your copy of Zeta is just adding an attribute to 3 files. There are several important things that all users should be aware of:
  • If you delete the "People" application then your copy will not be registered anymore (this also apply to the other files but Zeta will not boot without them :p)
  • Never send your kernel file to anybody since you will also send your serial number. If you have to do this remove the "sser1762" attribute to the file you send.

Now we know what is done to set your install as registered but not how we get the activation codes. The "Register" method is called at two places:

  • ActLooper::PhoneActivate(BMessage *).
  • ActLooper::InetActivate(BMessage*).
The first function extracts the 2 activation codes and the serial number from the BMessage sent as argument. These datas are just the ones filled in the gui of the phone activation part.
The second method is more interesting because it is where is done the net request. The function starts by calling "/bin/notice --busy 'connecting to server'". This little tool is showing a message with an animation on the screen. It then builds an http url. The way it is constructed is also obfuscated and ends with the string: "http://activate.yellowtab-support.com/register.php?key=your-activation-key&serial=your-serial-number". The http request is implicitly sent by using the "Stream" class. When the request is completed, The function expects the following attributes of the "Stream" handle to exist: code, code1, code2, error. Then the "Register" method is called.

So the only personnal information that is sent to yellowtab is your ip address. This is both few and a lot of information since several insteresting things can be extracted from it. When you bought your copy they had a link between the serial number and a name/address. With the registration process they also have a link with an ip adress.

2- The App server.

Know that we saw what is doing "activate" let's see what is in the app server. As we saw previously, "activate" uses the app server to know if Zeta is registered. So let's look at its disassembly, and the class list:

Class BRegistration
0008F4E4: BRegistration::BRegistration(void)
0008F5A0: BRegistration::Init(void)
0008F5D0: BRegistration::Invoke(void)
0008F7A4: BRegistration::IsRegistered(void)
00090694: BRegistration::Perform(int, int)
0009003C: BRegistration::Register(char const *, long, long)
0008F5FC: BRegistration::ShowRegisterWindow(void)
0008F558: BRegistration::~BRegistration(void)
These are exactly the same methods than on the activate application. However we will see that the code of the IsRegistered method is quite different. Still looking at interesting functions we can see this:
00079C40: TServer::RegistrationLaunch(TServer *)
00079B64: TServer::RegistrationThread(void)
Let's first look at the "TServer::RegistrationThread(void)" method. It consists of a loop that checks if Zeta is registered:
while(1)
{
   snooze();
   if(b_IsRegistered == false)
      BRegistration::Perform();
   if(BRegistration::IsRegistered == false)
   {
      BRegistration::Perform();
      BRegistration::Invoke();
      b_Isregistered = true;
   }
}
This is not the exact code but it represents more or less what is done in it. We see that the "b_IsRegistered" flag is cached in memory, probably to avoid disks accesses once the thread knows that we are registered. Now let's look at the different functions. "BRegistration::Invoke" just calls "ShowRegisterWindow", "ShowRegisterWindow" tries to launch "/boot/beos/bin/activate". If the activate application could not be lauched, "/boot/beos/bin/reinstallactivate.sh" is executed. This script just shows a modal alert that invite you to insert Zeta's install cd and then copies "activate" where it should be. But what is happening if "reinstallactivate" is also missing ? In fact this is not tested. The app_server assumes that it exists and then calls "ShowRegisterWindow" again. Thus you can see that we should end up in an infinite loop if both "activate" and "reinstallactivate" are missing (however I did not try it).

Finally the "IsRegistered" method is in some way the most interesting one since it extracts the 2 activation codes of the serial number to check that the 3 file attributes are correct. I will not give details on this here since it is not the purpose of this text. I will just say that the serial number is hashed to extract these two codes.

3- Global diagram.

Now we have a global view of the registration process. The different parts of it are shown below:



                ______________________________________
               |                                      |
               |              app_server              |
               |______________________________________|
                  |        /|\             |         |
                  |         |              |         |
                  |starts   |IsResigtered  |         |
                  |         |(libbe.so)    |         |
                _\|/________|____          |         |
               |                 |         |         |
               |     activate    |         |         |
               |_________________|         |         |
                   |          |            |         |
                   |          |wr attr     |rd attr  |
                   |          |            |         |
                __\|/___    _\|/__________\|/___    \|/________
               |        |  |Filesystem:         |  |           |
               | notice |  |- app_server        |  | reinstall |
               |________|  |- kernel_intel      |  |___________|
                           |- People            |
                           |____________________|

II- The registration process in Zeta R1 SP1.

Now let's see what has changed in the service pack 1. At first I did not intend to present this but I was quite forced to do it. When I started to study the registration I had Zeta R1 installed. I then installed SP1 before having finished to study all parts because I did not thought that the app_server would have changed (big mistake from me!). So I used the old app_server dead-listing and debugged the new one... and I saw very strange things. I almost got headakes until I realized that the binary had changed, and especially the registration part.

1- Activate.

The binary has changed but it seems that the registration part has not changed at all. By the way the code size of the new version (.text section) is only bigger of 48 bytes from the old one. So almost nothing changed here.

2- The App server.

As I said previously the app server has evolved. In fact I saw this when I removed both "activate" and "reinstallactivate" to check that there was an infinite loop. A big surprise appeared: There was no infinite loop but the activation app was started! nethertheless "/bin/activate" was not there. So how could it be executed ? After a little search you can see that it exists in the "/tmp" directory.
I spent a lot of time to find where this came from because I used the old dead-listing. At one time I also thought that the "activate" app was crypted somewhere before being flush on "/tmp", and that the app server was patched at runtime to do this! But in fact things are much simple when you use the correct disassembly.
What has changed here is the "ShowRegisterWindow" method. Now it does the following things:

  • Generate a temporary name "/tmp/filexxx" where xxx is random.
  • Copy the "activate" zip archive from memory to "/tmp/filexxx". The zip archive of "activate" is stored inside the app server elf file.
  • execute "cd /tmp && /bin/unzip -o filexxx" to extract activate and ovewrite the existing one if it exists.
  • execute "/tmp/activate"
So since SP1 the registration app is no more necessary in "/bin". It seems that the reinstallactivate script is not used anymore (by the way it is no more nedded since activate generated before being launched) although its code is also embedded in the app server elf file.

3- Global diagram.

So now the global view of the registration process is:


                ________________________________________________________
               |                                                        |
               |__________    app_server                                |
               | activate |                                             |
               |  zipped  |  __________                                 |
               |__________|_|__________|________________________________|
                   |        |          |    |       /|\             |
                   |copy    |unzip     |    |        |              |
                   |        |          |    |starts  |IsResigtered  |
                   |        |          |    |        |(libbe.so)    |
                __\|/_______|__      _\|/__\|/_______|_____         |
               |               |    |                      |        |
               | /tmp/filexxxx |    |  /tmp/activate       |        |
               |_______________|    |______________________|        |
                                             |          |           |
                                             |          |wr attr    |rd attr
                                             |          |           |
                                          __\|/___    _\|/_________\|/____
                                         |        |  |Filesystem:         |
                                         | notice |  |- app_server        |
                                         |________|  |- kernel_intel      |
                                                     |- People            |
                                                     |____________________|

III- Registering without network.

Now that we know exactly how is done the registration we can see how to register it when you do not have an internet connection.

1- Fake registering execs.

Before the SP1 there was a very easy way to use Zeta without registering it: You just had to replace the "activate" binary with an empty script. So the file exists, it is executed, but does nothing. However by doing this your copy is never considered as registered by the app server and it will do disk accesses regularily. I suppose that the app server changed in SP1 to avoid this trick.
However there is still a way to do this easily in SP1. But since this is just a quick and dirty hack I will not detail it here.

2- Fake registration server.

The first elegant solution that I thought about was using a fake registration server. We have all necessary apps with Zeta to do it. The issue with it is that the "register.php" script must send back the 2 activation codes. I first thought that these keys were computed by the app server and that the php script just had to return "ok". If it was true then we would just have to:

  • add "127.0.0.1 activate.yellowtab-support.com" to the file "/etc/hosts".
  • install and configure robinhood with php support
  • add an empty "register.php" file at robinhood root dir.
  • start robin hood!
With all these steps you will make "activate" connect to your machine "127.0.0.1" instead of yellowtab's server. Then the php script will tell "ok" to "activate". But unfortunatelly this does not work because the php script must return the 2 activation codes. So if we have to know them there are much more simple solutions to register.

3- Registration script.

If you already have your activation codes, there is obviously a very simple way to register Zeta: Adding the correct attributes to the correct files will just do what "activate" is doing. This can be done with this shell script:

#!/bin/env sh

rmattr code12 /boot/beos/apps/People
rmattr code24 /boot/beos/system/servers/app_server
rmattr sser1762 /boot/beos/system/kernel_intel

addattr -t int32 code12 your-activation-code1 /boot/beos/apps/People
addattr -t int32 code24 your-activation-code2 /boot/beos/system/servers/app_server
addattr -t string sser1762 your-serial-number  /boot/beos/system/kernel_intel
The problem here is that you must at least register once to yellowtab to get the activation codes.

4- Just backup your install.

Finally there is a last solution to reinstall Zeta without having to register: Once you are registered, just backup your installed copy on a cd and do your next installs from this cd. The new installs will be already registered.

IV- Conclusion.

As we saw yellowtab is only sending the minimum necessary information through internet to register a copy. So it seems that this is not a way to spy users. But I am not convinced that this is usefull anyway: When you buy your copy the registration process could have been done locally. We can imagine that if someone releases a cracked version of Zeta he would anyway remove all registration information in it (unless he is really stupid or stoled his copy to somebody).

This network registration may be usefull for yellowtab to see how many times a user installs its copy. I did not see on how many machines they allow to install Zeta with one license. I assume that if they see 60 registration requests for one serial number, they will send a little mail to this user.

I will finish with the most important thing in my opinion: Never send you kernel file as is to anybody. I know that it could seem strange to do such a thing but I did received a lot of these files when we worked on the xp patch and the 1Gb memory patch for R5. So this may occur sometime.

Zadig.